Angular中Transloco服务非setTimeout环境下无法翻译,求替代方案
问题根源
直接调用this.translocoService.translate()同步获取翻译失败,是因为路由切换触发updateTitle时,Transloco对应的语言包可能还未加载完成——同步方法会立即返回结果,此时翻译键还没有对应的翻译值;而setTimeout只是通过延迟执行侥幸等到了语言包加载完毕,但这种方式不可靠(比如网络慢时500ms可能不够)。
解决方案
利用Transloco提供的异步API确保翻译加载完成后再设置标题,以下是两种可靠实现方式:
方式一:使用selectTranslate订阅翻译结果
selectTranslate返回Observable,会在翻译值准备好时发出数据,是Transloco推荐的异步获取翻译的方式:
import { Injectable } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { RouterStateSnapshot, TitleStrategy } from '@angular/router'; import { TranslocoService } from '@ngneat/transloco'; import { take } from 'rxjs/operators'; @Injectable({ providedIn: 'root', }) export class CustomTitleStrategyService extends TitleStrategy { override updateTitle(snapshot: RouterStateSnapshot): void { const titleKey = this.buildTitle(snapshot); if (!titleKey) return; this.translocoService.selectTranslate(titleKey) .pipe(take(1)) // 只取一次结果后取消订阅,避免内存泄漏 .subscribe(translation => { this.title.setTitle(translation); }); } constructor( private title: Title, private translocoService: TranslocoService, ) { super(); } }
方式二:确保语言包加载完成后再获取翻译
如果需要明确等待当前语言的翻译包加载完毕,可以结合langLoaded$ observable:
import { Injectable } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { RouterStateSnapshot, TitleStrategy } from '@angular/router'; import { TranslocoService } from '@ngneat/transloco'; import { take, switchMap } from 'rxjs/operators'; @Injectable({ providedIn: 'root', }) export class CustomTitleStrategyService extends TitleStrategy { override updateTitle(snapshot: RouterStateSnapshot): void { const titleKey = this.buildTitle(snapshot); if (!titleKey) return; this.translocoService.langLoaded$(this.translocoService.getActiveLang()) .pipe( take(1), switchMap(() => this.translocoService.selectTranslate(titleKey)) ) .subscribe(translation => { this.title.setTitle(translation); }); } constructor( private title: Title, private translocoService: TranslocoService, ) { super(); } }
说明
以上两种方式遵循Angular响应式编程模式,无需依赖不可靠的延迟时间,能确保翻译值就绪后再设置页面标题,同时通过take(1)避免不必要的订阅内存泄漏。
内容的提问来源于stack exchange,提问作者Maksat Madeniyetov
相关产品推荐
相关产品推荐

