34

I am compiling my project with:

ng serve --aot --i18nFile=client/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr

How can I access the locale ID at runtime? I want to show/hide elements based on the locale.

PS. I do realise that using JIT compilation I can simply do this:

providers: [ { provide: LOCALE_ID, useValue: 'fr' } ]

But I'm looking for a AOT solution. I also would rather not infer locale based on hostname or anything like that.

Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
williamsandonz
  • 15,864
  • 23
  • 100
  • 186
  • Can you please clarify the question as to whether you want the user's locale, or if you just want to access the static LOCAL_ID value? – inorganik Jan 18 '21 at 17:51

3 Answers3

85

Simply inject LOCALE_ID in your constructor, e.g.

import { LOCALE_ID, Inject } from '@angular/core';

...

constructor(
  @Inject(LOCALE_ID) public locale: string
) { }
Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
williamsandonz
  • 15,864
  • 23
  • 100
  • 186
  • 2
    import { Component, Inject, LOCALE_ID } from '@angular/core'; – Javier Larios Nov 22 '18 at 17:08
  • 7
    The better is to say: *"Simply do this in your **constructor**"*. – Mir-Ismaili Feb 01 '19 at 14:47
  • 10
    You might consider deleting this answer because LOCALE_ID doesn't get the user's locale or language, it is static – inorganik Mar 04 '20 at 13:52
  • 6
    @inorganik You might consider deleting your comment (and answer), because LOCALE_ID provides exactly what the OP asks and yours doesn't. window.navigator language will provide incorrect answer when user if the user switches the language of the angular application without also switching their browser locale. Your solution will also provide incorrect result for users who use locale unsupported by the app, who would otherwise prefer to use a different locale than the one you as developer consider the default (e.g. user's language `nl` is not supported by app, user wants `de`, app default is `en`) – Tamius Han Feb 25 '22 at 10:06
23

The injection token LOCALE_ID does not provide your user's language or locale, it is static and defaults to 'en-US' unless you provide a different value for it (docs):

providers: [{provide: LOCALE_ID, useValue: 'en-GB' }]

Here's a method that gets the user's preferred language and locale:

  getUsersLocale(defaultValue: string): string {
    if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {
      return defaultValue;
    }
    const wn = window.navigator as any;
    let lang = wn.languages ? wn.languages[0] : defaultValue;
    lang = lang || wn.language || wn.browserLanguage || wn.userLanguage;
    return lang;
  }
Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
inorganik
  • 24,255
  • 17
  • 90
  • 114
  • I think you should mention more clearly, that your function returns either the users locale or the language, not always the language alone (f.e. 'en-US' OR 'en'). To get the language, we need to parse it from the locale. A not so experienced user could misunderstand this. – Jan Feb 02 '20 at 16:04
  • @Jan it returns both. As stated "Here's a method that gets the user's preferred language/locale" – inorganik Mar 04 '20 at 13:52
  • @inorganik A forward slash in formal or informal language usually indicates the word 'or', so your statement is most likely to be interpreted as "Here's a method that gets the user's preferred language OR locale". Jan is correct to suggest that you should clarify your statement. Ref: https://www.grammarly.com/blog/slash/ – Scopperloit Aug 13 '20 at 14:22
  • 5
    This does not answer the question. The question is how you get the initialized app LOCALE_ID not the browser's default language. – unitario Dec 18 '20 at 08:41
  • 1
    @unitario But the OP's question implies they want the user's locale - "I also would rather not infer locale based on hostname or anything like that." – inorganik Dec 18 '20 at 21:03
  • 2
    @inorganik it implies that he/she doesn’t want the locale from the hostname or browser (“anything like that”). The app is being served with a specific locale (LOCALE_ID) which he/she want to access at runtime. Your solution will not provide that. – unitario Dec 23 '20 at 06:13
6

This question is on very tol of google search, so i add here another solution. If you are using compile time translations (default for Angular) so global

console.log($localize.locale); // statically replaced to its value by Angular compiler

Would return current locale without involving a dependency injector and etc

Timofey Yatsenko
  • 758
  • 10
  • 14