Search code examples
javascriptngx-translate

No array operations work on getLangs() from ngx-translate/core TranslateService


I work on an Angular (v13) project which uses ngx-translate/core for i18n. There are multiple languages (15 currently) configured. I find the following very strange behaviour (TranslateService is injected as this.translateService):

  1. Calling this.translateService.getLangs() returns an array with the 15 language codes as expected. I can log this value or e.g. configure a dropdown select with these values.
  2. However, I can do absolutely no array operations on this value, including indexing [0] (says undefined), .length (returns 0), or for-in or for-of. No ... operator to create a new array or object with the values, no Object.assign([], langs), no Array.from() - they just return empty arrays. Let alone .map(), .forEach(), etc.
  3. typeof says object, Array.isArray() says true.

Some basic example code:

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')
    );
}

shows in the console:

[] 0 undefined false false

and if I expand the [] it shows the 15 codes (including 'en'), and length: 15.

Questions

  1. Am I reading the ngx-translate documentation wrong (that what is there)?
  2. Am I using it wrong somehow due to not understanding something?
  3. Is this a bug in ngx-translate?
  4. Is this a bug in JavaScript?
  5. Is there any workaround?

Solution

  • Thank you to Amer for his comment pointing me in the right direction.

    • The problem occurs because this.translateService.getLangs() is called before languages have been loaded via this.translateService.addLangs(). The language values are obtained via a HttpClient.get() request, which returns an Observable and calls addLangs() once the results are received (refer Observable.subscribe(...)). (So no funny happenings, just a wrong understanding.)
    • The simple solution is to only do any operations on the array of languages in the complete callback of the Observable returned by HttpClient.get() (or use one of the other synchronization mechanisms available). This was a bug in the original code and has now been fixed.
    • The browser (Chrome) logging [] (which could then be expanded to the full array) was a confusion on my part. When the array is available at logging time, it is logged as expanded, e.g. [ "ar", "en", .... ]. (By the time I clicked on the expansion widget in the console, the array had obviously been loaded in the mean time, which enables it to be shown on expansion.)
    • I strongly advise against synchronization via timeouts as someone may wrongly read from Amer's comment, where it is suggested only for problem detection. One should always use one of the synchronization methods (Promises, Observables, events, etc. etc.) in final code to synchronize between asynchronous processes.