web-dev-qa-db-ja.com

Angular 8起動時のアプリケーションのAPIから実行時にLOCALE_IDを遅延して読み込み、設定する

APIからAngularアプリケーションのLOCALE_IDを遅延読み込みして設定する方法があります(起動時にユーザープロファイルデータを読み込むことにより)。これはAngular 7では問題なく機能しましたが、Angular 8にアップグレードすると機能しなくなりました。 localeFactoryが呼び出されたとき(以下を参照)、localeService.getLocale()は未定義であり、まだ初期化されていません。 SharedResolverのインポートに含まれるSharedModuleにあるAppModuleで初期化します。 Angular 8でこれを行うための正しいアプローチは何ですか?変更のドキュメントにこれに固有のものは何も見られなかったので、それは間接的なものだと思います。ここで私が取るべきアプローチについて何か意見はありますか?ありがとう

以下の関連コードを参照してください:

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-resolve.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);
15
Botond Béres

私たちのプロジェクトで行っていることは、実際には各(lang)ミューテーションまたは「マーケット」に対してレイジーロードされたモジュールがあるということです。これは、Angularルーティングと依存性注入を使用して、i18n関連のものを<lang>.module.tsに分離するため、「サイト」関連のものがすべてsite.module.tsで処理され、実際にアプリケーション自体を保持します

ここで解決策を見ることができます(ただし、LOCALE_IDは含まれていませんが、簡単に追加できます)。

https://stackblitz.com/github/vmasek/angular-typed-translations-demo


私はこの代替i18nアプローチと翻訳の入力についてブログ投稿を書きました。詳細はこちら https://blog.angularindepth.com/angular-typed-translations-29353f0a60bc

0
Vojtech