我们有一种从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);
是的,这是 v8.x.x
年的常春藤 i18n 问题。我已经将其发布在 Angular 存储库中,并得到了 @Ocombe(正在开发 Ivy i18n(的确认。
如果您赶时间,作为解决方法,您可以这样做:
由于 Ivy 正在搜索运行时区域设置,您只需在AppModule
中提供默认语言,如下所示,然后提供您的APP_INITIALIZER
:
...
providers: [
...
{ provide: LOCALE_ID, useValue: 'en' }
{
provide: APP_INITIALIZER,
useFactory: initializeAppSettings,
deps: [AppInitializerService],
multi: true
}
...
]
...
这将首先设置默认区域设置,然后运行您的APP_INITIALIZER
。接下来,在您的CoreModule
(仅加载一次(中,只需提供从后端获取的新LOCALE_ID
:
...
providers: [
...
{
provide: LOCALE_ID,
useFactory: (localeService: LocaleService) => localeService.getCurrentLocale(),
deps: [LocaleService]
}
...
]
...
我们在项目中所做的是,我们实际上为每个(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