来自 ngx-translate/core TranslateService 的 getLangs() 没有数组操作工作

问题描述 投票:0回答:2

我正在开发一个 Angular (v13) 项目,该项目使用

ngx-translate/core
表示 i18n。配置了多种语言(当前有 15 种)。我发现以下非常奇怪行为(TranslateService 被注入为
this.translateService
):

  1. 调用
    this.translateService.getLangs()
    将返回一个包含 15 种语言代码的数组(如预期)。我可以记录这个值或者例如使用这些值配置下拉选择。
  2. 但是,我绝对不能对此值执行任何数组操作,包括索引
    [0]
    (表示
    undefined
    )、
    .length
    (返回 0)、
    for-in
    for-of
    。没有
    ...
    运算符来创建带有值的新数组或对象,没有
    Object.assign([], langs)
    ,没有
    Array.from()
    - 它们只是返回空数组。更不用说
    .map()
    .forEach()
    等等
  3. typeof
    表示对象,
    Array.isArray()
    表示真实。

一些基本示例代码:

ngOnInit(): void {
    console.log(
      this.translateService.getLangs(),
      this.translateService.getLangs().length,
      this.translateService.getLangs()[0],
      this.translateService.getLangs().includes('en'),
      this.translateService.getLangs().includes('aa')
    );
}

在控制台显示:

[] 0 undefined false false

如果我展开

[]
,它会显示 15 个代码(包括“en”)和
length: 15

问题

  1. 我阅读的 ngx-translate 文档是否错误(那里有什么)?
  2. 我是否因为不理解某些东西而使用错误?
  3. 这是
    ngx-translate
    中的错误吗?
  4. 这是 JavaScript 中的错误吗?
  5. 有什么解决办法吗?
javascript ngx-translate
2个回答
1
投票

感谢Amer的评论为我指明了正确的方向。

  • 出现问题的原因是在通过 this.translateService.getLangs()
     加载语言之前调用 
    this.translateService.addLangs()
    。语言值是通过
    HttpClient.get()
    请求获取的,该请求返回
    Observable
    并在收到结果后调用
    addLangs()
    (请参阅
    Observable.subscribe(...)
    )。 (所以没有什么有趣的事情,只是错误的理解。)
  • 简单的解决方案是仅在
    complete
    返回的
    Observable
    HttpClient.get()
    回调中对语言数组执行任何操作(或使用其他可用的同步机制之一)。这是原始代码中的一个错误,现已修复。
  • 浏览器(Chrome)日志记录
    []
    (然后可以扩展到整个数组)对我来说是一个困惑。当数组在记录时可用时,它会被记录为已扩展,例如
    [ "ar", "en", .... ]
    。 (当我单击控制台中的扩展小部件时,该数组显然已同时加载,这使得它可以在扩展时显示。)
  • 我强烈建议不要通过超时进行同步,因为有人可能会错误地阅读 Amer 的评论,其中建议仅用于问题检测。人们应该始终在最终代码中使用其中一种同步方法(Promises、Observables、事件等)来在异步进程之间进行同步。

0
投票

我可以通过将其保存在稍后初始化的字段中来解决完全相同的问题。

protected availableLanguages: string[] = [];

constructor(protected translateService: TranslateService, protected dataService: DataService, protected userConfigurationService: UserConfigurationService<string>)
{
  this.translateService.store.onLangChange.pipe(takeUntilDestroyed()).subscribe((_: LangChangeEvent): void => {
    this.availableLanguages = this.translateService.store.langs;
    this.availableLanguages.sort();
  });
}

可以进行测试,例如在像这样的 jasmine 中,关键是重新创建组件,以便在覆盖事件发射器后再次调用构造函数:

it('should handle default language change', () =>
{
  const eventEmitter: EventEmitter<LangChangeEvent> = new EventEmitter<LangChangeEvent>();
  component['translateService'].store.onLangChange = eventEmitter;
  component['translateService'].store.langs = ['de', 'en'];

  fixture = TestBed.createComponent(HeaderComponent);
  component = fixture.componentInstance;

  expect(component['availableLanguages']).toEqual(arrayContaining([]));

  eventEmitter.emit({
    lang: 'de',
    translations: {}
  });

  expect(component['availableLanguages']).toEqual(arrayContaining(['de', 'en']));
});
© www.soinside.com 2019 - 2024. All rights reserved.