Core: How to know when the translation bundles are loaded

Created on 3 Mar 2017  路  11Comments  路  Source: ngx-translate/core

I'm submitting a ... (check one with "x")

[ ] bug report => check the FAQ and search github for a similar issue or PR before submitting
[x] support request => check the FAQ and search github for a similar issue before submitting
[ ] feature request

Current behavior
I have the necessity to know then the translation bundle is loaded and only then do some extra work.
In my case I need to load other modules translations (not lazy-loaded) and I noticed that when a bundle is loaded it completely overrides existing translations instead of merging like setTranslation does with shouldMerge. (Probably related to this line of code, I'll make a PR if necessary.)
Therefore I need a way to know when the AppModule bundle is loaded with the specified loader. For the time being I resolved subscribing translate.use() and setting a custom AsyncSubject, but I'm not sure it's the correct Observable to subscribe to.
Another way would be maybe creating a custom loader with an AsyncSubject, but wouldn't be very different from the former solution I suppose.

  • ngx-translate version: 6.0.0

  • Angular version: 2.4.x

feature request

Most helpful comment

I needed the same functionality.
Why not just check translateService.store.translations if it's empty or not.

All 11 comments

I agree with @jiayihu, determining if the translations are loaded or not could be very useful.

In my case, I'm developing a TranslateLoader for an utility, getting translations using ngx-translate. If there was an injection token (such as TRANSLATIONS_LOADED), I could rather leverate the use of it rather than subscribing to translate.use().

I needed the same functionality.
Why not just check translateService.store.translations if it's empty or not.

no updates on this yet? pretty sad!

I think this is a must fix to use ngx-translate. Client code need to know if things are loaded or not.

I check it in this way.

  ngOnInit() {
    if (this.translateService.store.translations[this.translateService.currentLang]) {
      this.inicializar();
    } else {
      this.suscripcionLangChange = this.translateService.onLangChange.subscribe(() => {
        this.inicializar();
      });
    }
  }

Just use one of the following observables:

  • onDefaultLangChange
  • onLangChange
  • onTranslationChange

You would probably want to pipe it with a take(1) operator to avoid triggering your code multiple times (and also release memory by having the observable complete after one emission):

import { take } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';

export class SomeComponentOrService
{
    constructor(private translate: TranslateService)
    {
        this.translate.onDefaultLangChange.pipe(take(1)).subscribe(_ => doWhatYouWant());
    }
}

I am having trouble detecting when my translations have been loaded.
I am using the instant function but I have to check when the loader is finished.
Subscribing to onLangChange only works once when the page is first loaded, but if I am in another page that languageChange will not emit any more value so that doesnt work either.

I noticed that

constructor(
  private translate: TranslateService,) {
    console.log('-->',JSON.stringify(translate.store.translations[translate.currentLang]));
   console.log(this.translate.instant('ORGANISATION.TABLE'));

is logging as

--> {"HEADINGS":{"ORGANISATION":"Organisation","ORGANISATIONS":"Organisations AU"},"BUTTONS":{"CREATE_ORG":"Create Org"},"FOO":"HELLO","TABLE":{"ORGANISATION":"Organisation"}}
list.component.ts:74 ORGANISATION.TABLE

which means the translation was already available, but still the instant function is not returning the translation.

Why is this?

Seems like you're translation id is reversed. It should match your data hierarchy.
Try this.translate.instant('TABLE.ORGANISATION').

Yeah, that was a stupid mistake in my console.log. I did use the correct hierarchy in the actual code.
I am just creating a wrapper service that will check if the store exists, if not it will return an observable based on language changed. If the store does exist it will also return an Observable.
So then I can just subscribe to this combined Observable to execute the instant function.

Shame there is no generic translationsLoaded observable you can subscribe to.

So I did this:

import { Injectable, OnDestroy } from '@angular/core';
import { Observable, of } from 'rxjs';
import { TranslateService } from '@ngx-translate/core';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class I18NService  {

  constructor(
    private translate: TranslateService
  ) {}

  translationsLoaded(): Observable<boolean> {

    if (this.translate.store.translations[this.translate.currentLang]) {
      return of(true);
    } else {
      return this.translate.onLangChange
        .pipe(
          map(res => !!res)
        );
    }
  }
}

and then in my controller I can do

    this.i18NService.translationsLoaded().subscribe(res => {
      // just update some labels that will go into the headers of a dynamic table 
      this.columns.map(col => {
        if (col.label) {
          col.label = this.translate.instant(col.label);
        }
        return col;
      })
    });

A simple solution would be to expose a promise in your service and extract its resolve() function:

class YourLangService
{
    public isReady: Promise<string>;

    private resolveIsReady: (locale: string) => void;

    constructor(...)
    {
        this.isReady = new Promise<string>(resolve => this.resolveIsReady = resolve);
    }
}

Then subscribe to onLangChange() or find any other convenient place to resolve the promise.

Now you could simply inject your service and query the promise:

class SomeComponent
{
    constructor(private lang: YourLangService)
    {
        this.lang.isReady.then(...);
    }
}

You could replace the promise with a BehaviorSubject, but I find the promise easier to work with than an observable in this case.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

egornoveo picture egornoveo  路  4Comments

louisdoe picture louisdoe  路  3Comments

crebuh picture crebuh  路  3Comments

ryanki1 picture ryanki1  路  4Comments

IterationCorp picture IterationCorp  路  3Comments