Search code examples
angulartransloco

Angular, Transloco service is not translating, but inside setTimeout it is translating


If I use this.translocoService.translate(title) inside setTimeout, it is translating. But without setTimeout, it says there is no translation.

import { Injectable } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { RouterStateSnapshot, TitleStrategy } from '@angular/router';
import { TranslocoService } from '@ngneat/transloco';

@Injectable({
  providedIn: 'root',
})
export class CustomTitleStrategyService extends TitleStrategy {
  override updateTitle(snapshot: RouterStateSnapshot): void {
    setTimeout(() => {
      const title = this.buildTitle(snapshot);
      const translation = this.translocoService.translate(title);
      this.title.setTitle(translation);
    }, 500);
  }

  constructor(
    private title: Title,
    private translocoService: TranslocoService,
  ) {
    super();
  }
}

Is there a way to remove setTimeout? because to me it looks like not proper solution


Solution

  • Instead of relying on fixed amount of time that your app takes to load translation files, you can use selectTranslate, which returns observable, to translate the key when the translation is available.

    selectTransalate method of TranslateService returns an observable that when subscribed loads the translation file and emits the translation of the given key.

    source

    You can use it in that way:

    this.translocoService.selectTranslate(title).subscribe(translatedTitle => {
       this.title.setTitle(translatedTitle);
    });
    

    In order to prevent some jiggle behavior when changing title many times, I'd suggest something like this:

    @Injectable({
      providedIn: 'root',
    })
    export class CustomTitleStrategyService extends TitleStrategy {
      private readonly _title$ = new Subject<string>('');
    
      override updateTitle(snapshot: RouterStateSnapshot): void {
        this._title$.next(this.buildTitle(snapshot));
      }
    
      constructor(
        private title: Title,
        private translocoService: TranslocoService,
      ) {
        super();
        this._title$.pipe(
          takeUntilDestroyed(), 
          distinctUntilChanged(),
          switchMap(title => this.translocoService.selectTranslate(title))
        ).subscribe(translatedTitle => {
          this.title.setTitle(translatedTitle);
        });
      }
    }