angular - 在启动时从 Angular 8 应用程序中的 API 在运行时延迟加载和设置 LOCALE_ID
问题描述
我们有一种从 API 延迟加载和设置 Angular 应用程序的 LOCALE_ID 的方法(通过在启动时加载用户配置文件数据)。这在 Angular 7 上运行良好,但是当我升级到 Angular 8 时它停止工作。当 localeFactory 被调用(见下文)时localeService.getLocale()
,它是未定义的,它还没有被初始化。我们将它初始化在 a SharedResolver
which is in a SharedModule
which 包含在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 {}
共享解析.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);
解决方案
是的,这是 Ivy i18n 中的问题v8.x.x
。我已将其发布在 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]
}
...
]
...
推荐阅读
- http - 如何与 Arduino 网络服务器建立多个连接?
- twitter-bootstrap - 如何更改按钮导航栏的对齐方式?
- r - 如何使用 R 计算特定事件的概率
- powershell - 如何仅从 html 网页中的 powershell 脚本显示服务器名称和 ping 结果
- docker - jenkins 无法正确启动,尽管没有错误输出
- java - 通过 getResources 和 getIdentifier 检索时,资源字符串设置为“0”
- python - 如何使用 for 循环在新行上打印 Numpy 数组中的元素?
- python - 如何使用 for 循环保存所有输入数据
- ios - 如何向未运行的 iOS 应用程序发送 BLE 消息?
- python - openGL(pyglet) 3d 场景无法在 AMD 显卡上正确渲染