4

When I first change the language of my application the translation service makes a request for the file that represents the new language, My 'smart' components strings reflect the update correctly BUT any 'pure/dumb' components do not, they stay in the previous language. However, once the new language file has been loaded into cache and I continue to change languages everything seems to work fine.

It seems that any pure component is not resolving updates from the ajax response for the new language file, it will only change language correctly when the file has already been loaded into cache. Again, this is only for components that are using ChangeDetectionStrategy.OnPush

I understand the changeDetection using Inputs and Observables in dumb components but I'm not so familiar when it comes to pipes in this case. Possibly I'm missing something?

UDPATE

I've managed to hack a fix, it's not great but it works. This is the constructor in my service that wraps the Translate service.

I check to see if I have the language json file already in cache for the language I'm about to select. If I don't have it I use the 'reloadLang' method in ng2-translate to go and get it. Once I have it I use an empty timeout and then call 'translate.use'. There's a timing issue somewhere because If I take out the timeout it doesn't work. If I already have the translation file I'm about to switch to I just use translate.use as normal and all works fine.

constructor(private translate: TranslateService, public store: Store<any>) {
// this language will be used as a fallback when a translation isn't found in the current language
translate.setDefaultLang('en');
// subscribe to changes
store.select('i18n').subscribe((state: MultilingualStateI) => {
  // update ng2-translate which will cause translations to occur wherever the TranslatePipe is used in the view
  if (this.translate.getLangs() && (this.translate.getLangs().indexOf(state.lang) > -1)) {
    this.translate.use(state.lang)
  } else {
    this.translate.reloadLang(state.lang).take(1).subscribe(() => {
      setTimeout(() => this.translate.use(state.lang), 0);
    });
  }
});

}

I'm not totally sure what's going on here but it seems to be a mix between using ChangeDetectionStrategy.OnPush and a fresh response from requesting the translation file. If anyone else is seeing this please add your input.

HomeBrew
  • 849
  • 2
  • 12
  • 25

1 Answers1

4

I was stuck with this problem. I have some graphs (I'm using ng2-charts) and when I changed language (for example, from en to es), all labels where updated except the chart related ones. For having my charts updated with the new language, I had to change again the laguage to es (so, double click to change language first time).

After reading your issue and workaround, I checked it and the problem is, as you pointed out, the cache. The first time you change language, the JSON is loaded, but as it wasn't in cache not all components get translated (in my case, charts weren't properly updated). The second time you change to the same language, the labels are already in cache so it works properly.

I fixed it by loading all available languages when I initialise the service:

constructor(private translate: TranslateService) {
    var navigatorLanguage = (window.navigator.userLanguage || window.navigator.language).toLowerCase().split("-")[0];
    // this language will be used as a fallback when a translation isn't found in the current language
    translate.setDefaultLang(navigatorLanguage);
    // the lang to use, if the lang isn't available, it will use the current loader to get them
    translate.use(navigatorLanguage)
    // Hack to load all languages
    // If we don't do this, the first time we change language not all elements are properly translated
    translate.reloadLang('en')
    translate.reloadLang('es')
}

In my case, I only have those two languages. If there are more, maybe some for loop would be useful to reload every lang :)

Isthar
  • 433
  • 3
  • 14