core icon indicating copy to clipboard operation
core copied to clipboard

Subsequent calls to translateService.use(language) may change to an older language

Open beradrian opened this issue 7 years ago • 6 comments

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

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

Current behavior Let's suppose you call translateService.use("de") and then translateService.use("en"). Now, if de.json takes 500ms to load and en.json takes 100ms to load, in the end the current language will be "de".

Expected/desired behavior The current language should be the one of the last .use() call, in the example above en.

Reproduction of the problem If the current behavior is a bug or you can illustrate your feature request better with an example, please provide the steps to reproduce and if possible a minimal demo of the problem via https://plnkr.co or similar. You can use this template as a starting point: http://plnkr.co/edit/tpl:XXwyUYS6ZL7qVD9I2l0g

What is the expected behavior?

What is the motivation / use case for changing the behavior?

Please tell us about your environment:

  • ngx-translate version: x.x.x 9.0.1

  • Angular version: 2.x.x 5.0.0

  • Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ] Chrome

If needed I can provide a PR with the fix.

beradrian avatar Dec 07 '17 12:12 beradrian

It looks similar to #224. @beradrian what would be your fix here?

bagage avatar Jun 14 '18 13:06 bagage

You have this method in TranslateService

public use(lang: string): Observable<any> {
// don't change the language if the language given is already selected
if (lang === this.currentLang) {
  return of(this.translations[lang]);
}

let pending: Observable<any> = this.retrieveTranslations(lang);

if (typeof pending !== "undefined") {
  // on init set the currentLang immediately
  if (!this.currentLang) {
    this.currentLang = lang;
  }

  pending.pipe(take(1))
    .subscribe((res: any) => {
      this.changeLang(lang);
    });

  return pending;
} else { // we have this language, return an Observable
  this.changeLang(lang);

  return of(this.translations[lang]);
}
}

I would modify it to

private currentLangSubscription: Subscription;

public use(lang: string): Observable<any> {
// don't change the language if the language given is already selected
if (lang === this.currentLang) {
  return of(this.translations[lang]);
}

let pending: Observable<any> = this.retrieveTranslations(lang);

if (typeof pending !== "undefined") {
  // on init set the currentLang immediately
  if (!this.currentLang) {
    this.currentLang = lang;
  }

  if (this.currentLangSubscription) {
    this.currentLangSubscription.unsubscribe();
  }
 
  this.currentLangSubscription = pending.pipe(take(1))
    .subscribe((res: any) => {
      delete this.currentLangSubscription;
      this.changeLang(lang);
    });

  return pending;
} else { // we have this language, return an Observable
  this.changeLang(lang);

  return of(this.translations[lang]);
}
}

Similarly you can do the same for default language.

beradrian avatar Jun 15 '18 10:06 beradrian

Looking good, thanks for sharing! Maybe it would ease integration if PR was submitted? Would you like to submit it or should I?

@ocombe any thoughts?

bagage avatar Jun 15 '18 12:06 bagage

Yes, sure I can submit a PR if you want. Just let me know. Thanks!

beradrian avatar Jun 16 '18 16:06 beradrian

Is it scheduled to fix this bug in a future version?

andresbm05 avatar Oct 04 '19 09:10 andresbm05

Hi,

is there any update or workaround for this?

Thank you!

Mek89 avatar Oct 28 '21 11:10 Mek89