Nous avons une approche pour le chargement paresseux et la définition de LOCALE_ID de l'application Angular à partir de l'API (en chargeant les données du profil utilisateur lors du démarrage). Cela a bien fonctionné sur Angular 7 mais quand j'ai mis à niveau vers Angular 8, cela a cessé de fonctionner. Lorsque la localeFactory est appelée (voir ci-dessous), la localeService.getLocale()
n'est pas définie, elle n'a pas encore été initialisée. Nous l'initialisons dans un SharedResolver
qui est dans un SharedModule
qui est inclus dans les importations du AppModule
. Quelle est la bonne approche pour ce faire dans Angular 8? Je n'ai rien vu de spécifique dans la documentation des changements, donc je suppose que c'est quelque chose indirect. Avez-vous des commentaires sur l'approche à adopter ici? Merci
Veuillez consulter le code correspondant ci-dessous:
app.module.ts
export function localeFactory(localeService: LocaleService) {
console.log('locale factory called');
// This is `undefined` here now for some reason
console.log(localeService.getLocale());
return localeService.getLocale() || 'en';
}
...
const APP_LOCALE_ID = {
provide: LOCALE_ID,
deps: [LocaleService],
useFactory: localeFactory
};
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
BrowserAnimationsModule,
AppRoutingModule,
SharedModule.forRoot(), // <- in this module we have the SharedResolver
AccountModule,
ApiModule,
GenesysSubprojectModule
],
declarations: [AppComponent],
providers: [
AppRouteGuard,
BreadcrumbService,
{
provide: APP_INITIALIZER,
useFactory: appInitializerFactory,
deps: [PlatformLocation, BootstrapService],
multi: true
},
{ provide: ErrorHandler, useClass: GlobalErrorHandler },
AppRouteGuard,
BreadcrumbService,
// TODO - This doesn't work anymore!
APP_LOCALE_ID
],
bootstrap: [AppComponent]
})
export class AppModule {}
shared-resolution.ts
export class SharedResolve implements Resolve<any> {
...
resolve(route: ActivatedRouteSnapshot) {
...
const observables = forkJoin(
this.authService.getPermissions(),
this.authService.getCurrentProfileFromApi(),
this.languageApi.getActiveLanguages(), // TODO - cache
this.tenantSettingsApi.getLogo(logoLastModificationTime),
this.dashboardApi.getDashboardSettings(),
this.reportApi.getReportSettings(),
this.publicSettingsApi.getSettings(),
this.tenantSettingsApi.getInitializationSettings()
) as Observable<any[]>;
return observables
.pipe(
flatMap(result => {
...
const profile: CurrentUserProfileExtEditDto = result[1];
...
const languageName =
profile.languageName || navigator.language; // browser default language
console.log('Set locale to languageName=' + languageName);
this.storageService.setLocale(languageName);
this.localeService.setLocale(languageName);
Ce que nous faisons dans notre projet, c'est que nous avons en fait des modules chargés en lazylé pour chaque mutation (lang) ou "marché". Cela signifie que vous utilisez Angular routage et injection de dépendances pour séparer les éléments liés à i18n à <lang>.module.ts
donc vous en avez un pour chacun et toutes les choses liées au "site" sont traitées dans site.module.ts
qui contient réellement l'application elle-même
Vous pouvez voir la solution ici (mais elle n'inclut pas le LOCALE_ID
fournir, mais vous pouvez facilement l'ajouter ici)
https://stackblitz.com/github/vmasek/angular-typed-translations-demo
J'ai écrit un article de blog sur cette approche alternative i18n et en tapant les traductions. Vous pouvez en savoir plus à ce sujet ici https://blog.angularindepth.com/angular-typed-translations-29353f0a60bc