feat(i18n): use user preferred language
Try to load the locale from the apiman user profile. Use the default language from the config as fallback.
Closes:
MODIFY
src/app/app.component.ts
src/app/app.component.ts
/*
- * Copyright 2021 Scheer PAS Schweiz AG
+ * Copyright 2022 Scheer PAS Schweiz AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,14 @@ import { HeroService } from './services/hero/hero.service';
import { IHero, INavigation } from './interfaces/IConfig';
import { NavigationService } from './services/navigation/navigation.service';
import { SpinnerService } from './services/spinner/spinner.service';
+import { KeycloakService } from 'keycloak-angular';
+import { BackendService } from './services/backend/backend.service';
+import { EMPTY, from, Observable, of } from 'rxjs';
+import { map, switchMap } from 'rxjs/operators';
+import { TranslateService } from '@ngx-translate/core';
+import { ICurrentUser } from './interfaces/ICommunication';
+import { HttpErrorResponse } from '@angular/common/http';
+import { ConfigService } from './services/config/config.service';
@Component({
selector: 'app-root',
@@ -29,19 +37,78 @@ import { SpinnerService } from './services/spinner/spinner.service';
export class AppComponent implements OnInit {
@ViewChild('content') content!: ElementRef;
title = 'devportal';
+ defaultLocale = 'en';
constructor(
private router: Router,
private heroService: HeroService,
private navigationService: NavigationService,
- public loadingSpinnerService: SpinnerService
+ public loadingSpinnerService: SpinnerService,
+ private keycloak: KeycloakService,
+ private backend: BackendService,
+ private translate: TranslateService,
+ private config: ConfigService
) {}
ngOnInit(): void {
+ this.defaultLocale = this.config.getLanguage();
+
+ this.loadUserLocale();
this.initHeroEmitter();
this.initNavigationEmitter();
}
+ /**
+ * This method changes the language of the application based on the users/browsers locale.
+ * If the user is not logged in or a preferred browser language is not available the default (en) will be used.
+ */
+ private loadUserLocale(): void {
+ from(this.keycloak.isLoggedIn())
+ .pipe(
+ switchMap((isLoggedIn: boolean) => {
+ if (isLoggedIn) {
+ return this.getUserLanguage();
+ } else {
+ return of(this.translate.getBrowserLang());
+ }
+ }),
+ switchMap((language: string | undefined) => {
+ if (language) {
+ console.info('Trying to load language: %s', language);
+ // currently no support for locales like en_US
+ return this.translate.use(language.substring(0, 2).toLowerCase());
+ } else {
+ console.info(
+ 'No preferred locale is configured, using default (%s)',
+ this.defaultLocale
+ );
+ return EMPTY;
+ }
+ })
+ )
+ .subscribe({
+ next: () => console.info('Language successfully loaded'),
+ error: (err: HttpErrorResponse) =>
+ console.error(
+ 'No language is matching the requested locale, using default (%s): %s',
+ this.defaultLocale,
+ err.message
+ )
+ });
+ }
+
+ /**
+ * Gets the locale of a user
+ * @returns the locale (string) as observable
+ */
+ private getUserLanguage(): Observable<string> {
+ return this.backend.getCurrentUser().pipe(
+ map((user: ICurrentUser) => {
+ return user.locale;
+ })
+ );
+ }
+
private initHeroEmitter(): void {
this.heroService.heroChanged.subscribe((hero: IHero) => {
if (hero.large) {

MODIFY
src/app/interfaces/ICommunication.ts
src/app/interfaces/ICommunication.ts
@@ -965,7 +965,7 @@ export interface ICurrentUser {
username: string;
fullName: string;
email: string;
-
+ locale: string;
/** @format date-time */
joinedOn: string;
admin: boolean;

feat(i18n): use user preferred language

Try to load the locale from the apiman user profile. Use the default language from the config as fallback.

Closes: #55