diff --git a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.html b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.html
index 6f90c11..92949bd 100644
--- a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.html
+++ b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.html
@@ -39,6 +39,16 @@
+
+ {{ 'userLanguage' | translate }}
+
+
+ {{ lang.label }}
+
+
+ {{ 'userLanguageHint' | translate }}
+
+
{{ 'clientsPerPage' | translate }}
diff --git a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts
index 308da61..b90e7f3 100644
--- a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts
+++ b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts
@@ -36,6 +36,11 @@ export class AddUserModalComponent implements OnInit {
{ value: 'list', name: 'Listado' },
];
+ get availableLanguages() {
+ const langs = this.configService.languages;
+ return Object.keys(langs).map(code => ({ code, label: langs[code] }));
+ }
+
constructor(
public dialogRef: MatDialogRef,
@Inject(MAT_DIALOG_DATA) public data: any,
@@ -52,6 +57,7 @@ export class AddUserModalComponent implements OnInit {
role: ['', Validators.required],
groupsView: ['card', Validators.required],
clientsPerPage: [null, [Validators.min(1)]],
+ language: ['es'],
organizationalUnits: [[]]
});
@@ -87,7 +93,8 @@ export class AddUserModalComponent implements OnInit {
role: response.userGroups.length > 0 ? response.userGroups[0]['@id'] : null,
organizationalUnits: organizationalUnitIds,
groupsView: response.groupsView,
- clientsPerPage: response.clientsPerPage ?? null
+ clientsPerPage: response.clientsPerPage ?? null,
+ language: response.language ?? 'es'
});
this.userId = response['@id'];
@@ -114,7 +121,8 @@ export class AddUserModalComponent implements OnInit {
enabled: true,
userGroups: [this.userForm.value.role],
groupsView: this.userForm.value.groupsView,
- clientsPerPage: this.userForm.value.clientsPerPage || null
+ clientsPerPage: this.userForm.value.clientsPerPage || null,
+ language: this.userForm.value.language || null
};
if (!this.userId && this.userForm.value.password) {
diff --git a/ogWebconsole/src/app/layout/header/header.component.ts b/ogWebconsole/src/app/layout/header/header.component.ts
index 4196b4f..7c19339 100644
--- a/ogWebconsole/src/app/layout/header/header.component.ts
+++ b/ogWebconsole/src/app/layout/header/header.component.ts
@@ -6,6 +6,7 @@ import { BreakpointObserver } from '@angular/cdk/layout';
import { AuthService } from '@services/auth.service';
import { TranslateService } from '@ngx-translate/core';
import { ConfigService } from '@services/config.service';
+import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-header',
@@ -28,13 +29,21 @@ export class HeaderComponent implements OnInit {
constructor(
public dialog: MatDialog,
public auth: AuthService,
- private breakpointObserver: BreakpointObserver
+ private breakpointObserver: BreakpointObserver,
+ private http: HttpClient
) { }
ngOnInit(): void {
this.breakpointObserver.observe(['(max-width: 576px)']).subscribe((result) => {
this.isSmallScreen = result.matches;
- })
+ });
+
+ // Aplicar idioma guardado: el del JWT (servidor) tiene prioridad sobre localStorage
+ const jwtLang = this.auth.language;
+ const localLang = localStorage.getItem('language');
+ const langToApply = jwtLang || localLang || 'es';
+ this.translate.use(langToApply);
+ localStorage.setItem('language', langToApply);
}
get availableLanguages() {
@@ -66,6 +75,18 @@ export class HeaderComponent implements OnInit {
switchLanguage(lang: string) {
this.translate.use(lang);
localStorage.setItem('language', lang);
+
+ // Persistir en servidor si el usuario está autenticado
+ const uuid = this.auth.uuid;
+ if (uuid) {
+ this.http.patch(
+ `${this.config.apiUrl}/users/${uuid}`,
+ { language: lang },
+ { headers: { 'Content-Type': 'application/merge-patch+json' } }
+ ).subscribe({
+ error: (err) => console.error('Error saving language preference:', err)
+ });
+ }
}
getCurrentLanguage(): string {
diff --git a/ogWebconsole/src/app/services/auth.service.ts b/ogWebconsole/src/app/services/auth.service.ts
index 3c18231..c88d1b0 100644
--- a/ogWebconsole/src/app/services/auth.service.ts
+++ b/ogWebconsole/src/app/services/auth.service.ts
@@ -18,6 +18,7 @@ interface JwtPayload {
uuid: string;
groupsView: string;
clientsPerPage: number | null;
+ language: string | null;
}
@Injectable({ providedIn: 'root' })
@@ -103,6 +104,11 @@ export class AuthService {
return this.tokenPayload?.clientsPerPage ?? null;
}
+ /** Idioma preferido del usuario */
+ get language(): string | null {
+ return this.tokenPayload?.language ?? null;
+ }
+
/**
* Devuelve el rol principal del usuario según prioridad.
*/
diff --git a/ogWebconsole/src/locale/cat.json b/ogWebconsole/src/locale/cat.json
index 973cc78..76153a0 100644
--- a/ogWebconsole/src/locale/cat.json
+++ b/ogWebconsole/src/locale/cat.json
@@ -238,6 +238,8 @@
"clientSelectStepText": "Selecciona un client per veure les traces associades.",
"clientsPerPage": "Clients per pàgina",
"clientsPerPageHint": "Nombre de clients mostrats per pàgina al llistat",
+ "userLanguage": "Idioma preferit",
+ "userLanguageHint": "Idioma de la interfície per a aquest usuari",
"clientSuccessfullyRemovedFromThe": "Client eliminat de la xarxa correctament",
"clientsViewStepText": "Visualització dels clients de la unitat organitzativa seleccionada",
"clientUpdatedSuccessfully": "Client actualitzat correctament",
diff --git a/ogWebconsole/src/locale/en.json b/ogWebconsole/src/locale/en.json
index a1f3b36..f91ed17 100644
--- a/ogWebconsole/src/locale/en.json
+++ b/ogWebconsole/src/locale/en.json
@@ -238,6 +238,8 @@
"clientSelectStepText": "Select a client to see the associated traces.",
"clientsPerPage": "Clients per page",
"clientsPerPageHint": "Number of clients shown per page in the list",
+ "userLanguage": "Preferred language",
+ "userLanguageHint": "Interface language for this user",
"clientSuccessfullyRemovedFromThe": "Client successfully removed from the network",
"clientsViewStepText": "Display of the selected organizational unit's clients",
"clientUpdatedSuccessfully": "Client updated successfully",
diff --git a/ogWebconsole/src/locale/es.json b/ogWebconsole/src/locale/es.json
index f77a672..b6b5511 100644
--- a/ogWebconsole/src/locale/es.json
+++ b/ogWebconsole/src/locale/es.json
@@ -238,6 +238,8 @@
"clientSelectStepText": "Selecciona un cliente para ver las trazas asociadas.",
"clientsPerPage": "Clientes por página",
"clientsPerPageHint": "Número de clientes mostrados por página en el listado",
+ "userLanguage": "Idioma preferido",
+ "userLanguageHint": "Idioma de la interfaz para este usuario",
"clientSuccessfullyRemovedFromThe": "Cliente eliminado de la red con éxito",
"clientsViewStepText": "Visualización de los clientes de la unidad organizativa seleccionada",
"clientUpdatedSuccessfully": "Cliente actualizado con éxito",