Angular - NgxTranslate - 条件下缺少翻译处理程序
Angular - NgxTranslate - Missing Translation Handler on condition
我创建了一个丢失的翻译处理程序,它在外部 api 中查找翻译,如果找不到,则 returns 原始密钥。
export class MyMissingTranslationHandler implements MissingTranslationHandler {
constructor(public injector: Injector) {}
handle(params: MissingTranslationHandlerParams): string {
const result = ApiCallToFindTheKey(params.key)
return result ? result : params.key;
}
}
我还有一些 json 翻译文件(用于静态应用程序翻译),这些文件也是通过 api 调用请求的。
export class MultiTranslateHttpLoader implements TranslateLoader {
constructor(private http: HttpClient) {}
public getTranslation(lang: string): Observable<any> {
const resources: string[] = [
'_global.json',
...
];
const requests = resources.map(resource => {
const path = 'i18n/' + lang + '/' + resource;
return this.http.get(path).pipe(
catchError(res => {
console.error(res.message);
return of({});
})
);
});
return forkJoin(requests).pipe(map(response => merge.all(response)));
}
}
翻译管道配置为使用这些json文件,如果找不到翻译,它就会落入我丢失的翻译处理程序.
export function HttpLoaderFactory(http: HttpClient): TranslateLoader {
return new MultiTranslateHttpLoader(http);
}
@NgModule({
imports: [
TranslateModule.forRoot({
defaultLanguage: 'fr',
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
},
missingTranslationHandler: {
provide: MissingTranslationHandler,
useClass: MyMissingTranslationHandler
}
}),
...
]
有时,json 文件花费的时间有点太长,| translate pipe 认为翻译不存在并去查找丢失的翻译处理程序,而不是等待 json 文件加载。
所以翻译的结果是缺少的翻译处理程序 returns 而不是真正的翻译。 如何让翻译管道等待 json 文件加载然后翻译? 我考虑过使用某种 flag 但是不知道有没有更优雅的方案
根据@KanishkAn 的建议,我使用 APP_INITIALIZER。
/**
* Application won't load until the translations have been downloaded
*/
export function initializeTranslations(translationLoadedService: TranslationLoadedService): () => Promise<void> {
return async (): Promise<void> => {
return new Promise(resolve => {
translationLoadedService.loaded$().subscribe(() => resolve());
});
};
}
@NgModule({
imports: [
TranslateModule.forRoot({
defaultLanguage: 'fr',
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient, TranslationLoadedService]
},
missingTranslationHandler: {
provide: MissingTranslationHandler,
useClass: MyMissingTranslationHandler
}
}),
...
],
exports: [TranslateModule],
providers: [
...,
{ provide: APP_INITIALIZER, useFactory: initializeTranslations, deps: [TranslationLoadedService], multi: true }
],
entryComponents: ... ,
declarations: ...
})
我创建了一个中间服务,它将在加载所有翻译后解析承诺。
@Injectable({
providedIn: 'root'
})
export class TranslationLoadedService {
private translationLoaded: Subject<void> = new Subject<void>();
loaded$(): Subject<void> {
return this.translationLoaded;
}
}
因此,一旦我下载了所有翻译,我就会通知订阅者。
export class MultiTranslateHttpLoader implements TranslateLoader {
constructor(private http: HttpClient, private translationLoaded: TranslationLoadedService) {}
public getTranslation(lang: string): Observable<any> {
const resources: string[] = [
'_global.json',
...
];
const requests = resources.map(resource => {
const path = 'i18n/' + lang + '/' + resource;
return this.http.get(path).pipe(
catchError(res => {
console.error('Something went wrong for the following translation file:', path);
console.error(res.message);
return of({});
})
);
});
return forkJoin(requests).pipe(
map(response => {
**this.translationLoaded.loaded$().next();**
return merge.all(response);
})
);
}
}
我创建了一个丢失的翻译处理程序,它在外部 api 中查找翻译,如果找不到,则 returns 原始密钥。
export class MyMissingTranslationHandler implements MissingTranslationHandler {
constructor(public injector: Injector) {}
handle(params: MissingTranslationHandlerParams): string {
const result = ApiCallToFindTheKey(params.key)
return result ? result : params.key;
}
}
我还有一些 json 翻译文件(用于静态应用程序翻译),这些文件也是通过 api 调用请求的。
export class MultiTranslateHttpLoader implements TranslateLoader {
constructor(private http: HttpClient) {}
public getTranslation(lang: string): Observable<any> {
const resources: string[] = [
'_global.json',
...
];
const requests = resources.map(resource => {
const path = 'i18n/' + lang + '/' + resource;
return this.http.get(path).pipe(
catchError(res => {
console.error(res.message);
return of({});
})
);
});
return forkJoin(requests).pipe(map(response => merge.all(response)));
}
}
翻译管道配置为使用这些json文件,如果找不到翻译,它就会落入我丢失的翻译处理程序.
export function HttpLoaderFactory(http: HttpClient): TranslateLoader {
return new MultiTranslateHttpLoader(http);
}
@NgModule({
imports: [
TranslateModule.forRoot({
defaultLanguage: 'fr',
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
},
missingTranslationHandler: {
provide: MissingTranslationHandler,
useClass: MyMissingTranslationHandler
}
}),
...
]
有时,json 文件花费的时间有点太长,| translate pipe 认为翻译不存在并去查找丢失的翻译处理程序,而不是等待 json 文件加载。
所以翻译的结果是缺少的翻译处理程序 returns 而不是真正的翻译。 如何让翻译管道等待 json 文件加载然后翻译? 我考虑过使用某种 flag 但是不知道有没有更优雅的方案
根据@KanishkAn 的建议,我使用 APP_INITIALIZER。
/**
* Application won't load until the translations have been downloaded
*/
export function initializeTranslations(translationLoadedService: TranslationLoadedService): () => Promise<void> {
return async (): Promise<void> => {
return new Promise(resolve => {
translationLoadedService.loaded$().subscribe(() => resolve());
});
};
}
@NgModule({
imports: [
TranslateModule.forRoot({
defaultLanguage: 'fr',
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient, TranslationLoadedService]
},
missingTranslationHandler: {
provide: MissingTranslationHandler,
useClass: MyMissingTranslationHandler
}
}),
...
],
exports: [TranslateModule],
providers: [
...,
{ provide: APP_INITIALIZER, useFactory: initializeTranslations, deps: [TranslationLoadedService], multi: true }
],
entryComponents: ... ,
declarations: ...
})
我创建了一个中间服务,它将在加载所有翻译后解析承诺。
@Injectable({
providedIn: 'root'
})
export class TranslationLoadedService {
private translationLoaded: Subject<void> = new Subject<void>();
loaded$(): Subject<void> {
return this.translationLoaded;
}
}
因此,一旦我下载了所有翻译,我就会通知订阅者。
export class MultiTranslateHttpLoader implements TranslateLoader {
constructor(private http: HttpClient, private translationLoaded: TranslationLoadedService) {}
public getTranslation(lang: string): Observable<any> {
const resources: string[] = [
'_global.json',
...
];
const requests = resources.map(resource => {
const path = 'i18n/' + lang + '/' + resource;
return this.http.get(path).pipe(
catchError(res => {
console.error('Something went wrong for the following translation file:', path);
console.error(res.message);
return of({});
})
);
});
return forkJoin(requests).pipe(
map(response => {
**this.translationLoaded.loaded$().next();**
return merge.all(response);
})
);
}
}