3

I have a service that provides the global app language as follows:

export class LanguageService {
  private currentLanguage$ = new ReplaySubject < string > ();

  getCurrentLanguage(): Observable < string > {
    return this.currentLanguage$.asObservable();
  }
}

I use this service to provide language switching on the fly throughout the app. All components respect the language provided by the function above ('en', 'fr', etc.) and I wanted the CurrencyPipe to also do so.

As I understood I can provide this via LOCALE_ID, but I cannot find examples or guidance on how to do so in the docs, and especially not on how to provide it using an observable.

Sammy
  • 3,395
  • 7
  • 49
  • 95
  • The question isn't clear enough on what are your expectations. Is the language supposed to be changed during lifetime of the app? – Estus Flask Jun 25 '17 at 21:22
  • Thank you, I edited my question for clarity. – Sammy Jun 25 '17 at 21:36
  • Angular built-in i18n isn't suitable for changing languages on the fly. As any other provider, `LOCALE_ID` is a singleton (within root injector) and its value cannot be changed after instantiation. Use third-party solutions for dynamic languages, like ngx-translate. See https://medium.com/thorstens-thoughts/i18n-in-angular-apps-c0ed022c8a02 for example. – Estus Flask Jun 25 '17 at 22:38
  • But I AM using ngx-translate!! All I want is that CurrencyPipe respect the current user language instead of always taking the browser locale as a default even if the user explicitly changed their language. – Sammy Jun 25 '17 at 23:02
  • Then you need to create a pipe that wraps CurrencyPipe transform method, like it's shown in the article above. – Estus Flask Jun 25 '17 at 23:25

3 Answers3

2

Based on a solution from here: Changing LOCALE_ID in runtime does no change formatting of pipes #15039

Main module configuration:

@NgModule({
  imports: [
    ...
    TranslateModule.forRoot({
        loader: {
            provide: TranslateLoader,
            useFactory: MyAsyncTranslateLoader,
            deps: [HttpClient, ModuleConfig],
        },
    }),
  ],
  providers: [
    {
        provide: LOCALE_ID,
        deps: [TranslateService],
        useClass: DynamicLocaleId,
    },
    ...
  ]
...

And the class itself:

import { TranslateService } from '@ngx-translate/core';
    
export class DynamicLocaleId extends String {
  constructor(protected service: TranslateService) {
    super('');
  }
    
  toString() {
    return this.service.currentLang;
  }
}
Sargon
  • 262
  • 1
  • 9
0

The solution according to Angular is to create multiple builds using i18n. Ofcourse this might not be possible for some reason.

I almost got the same problem with a datepipe, the only diffence was that I was using a local variable.

First I tried to provide this in my appModule:

{
  provide: LOCALE_ID, deps: [WindowRef], useFactory(windowRef: WindowRef) {
    return windowRef.ln;
  }
}

The service:

@Injectable()
export class WindowRef {
  get nativeWindow(): any {
    return _window();
  }

  public ln = 'en';


  constructor() {
    try {
      if (!isNullOrUndefined(this.nativeWindow.navigator.language) && this.nativeWindow.navigator.language !== '') {
        this.ln = this.nativeWindow.navigator.language;
      }
    }finally {}
  }
}

But this didn't work for me when using AOT. My solution was the create my own datepipe which extended the angular datepipe.

This was the result:

@Pipe({name: 'datepipe', pure: true})
export class MyDatePipe extends DatePipe implements PipeTransform {
  constructor(private win: WindowRef) {
    super(win.ln);
  }

  transform(value: any, pattern?: string): string | null {
    return super.transform(value, pattern);
  }
}

You can do almost the same, but then extend the currencyPipe.

Robin Dijkhof
  • 18,665
  • 11
  • 65
  • 116
-1

Just add this declaration to the provider's list.

{
  provide: LOCALE_ID,
  deps: [LanguageService],   
  useFactory: (languageService) => languageService.getLanguage() 
}

Plus, you might need to return a Promise from your getLanguage method as they don't support Observable (as far as i'm aware of).

Omri L
  • 739
  • 4
  • 12