Skip to content

Localization

Localization or internationalization (i18n) is the process of designing and preparing your app to be usable in different locales around the world. Localization includes the support for different languages as well as different formats for entities like dates, time, decimals, currency, etc.

This guide covers locale selection and formatting. For translating Element component text, see translation.

Angular supports localization as described in the i18n guide and is supported by pipes. Angular applies a compile time localization concept. It does not support the change of locales (language and formats) at runtime. Instead, for each locale it generates a new web application that supports exactly one locale. It replaces text in the HTML templates with the translations and sets a fixed LOCALE_ID which is used by the pipes. Changing locales is realized by changing the web application.

With a runtime translation framework such as ngx-translate, Element supports a single web application with many languages and formats. We localize formats by following the angular pipes concept and reuse the locale and region definitions from Angular common locales. This is sufficient and standard conform for most applications. For example, if you want to display a date in a compact format use the date pipe like {{ date | date:'short' }}. You will get the format 'M/d/yy' (6/15/15) for English. If required, applications may extend and specialize the formats and pipes.

The Angular pipes that uses the locale information like the DatePipe, CurrencyPipe, DecimalPipe and PercentPipe are pure pipes. Pure pipes only re-render when the inputs changes. This means they do not re-render when the LOCALE_ID changes. They load the LOCALE_ID only once at load time and caches the value.

We recommend to follow the same behavior as users changes to locales are seldom. As a consequence we need to reload the web application on locale changes.

Locales in Element

Element provides the service SiLocaleService to set the current locale like en, fr or a variant like fr-CA or en-GB as well as the available locales of the application. The service is configured by an in injected SiLocaleConfig object in the main module.

In addition you need to register and initialize the locale packages for Angular. The following shows a generic example that only loads the selected Angular locale into the applications.

Note, the /* webpackInclude: /(en|de|fr)\.js$/ */ statement that need to match the supported locales.

// On locale change, we dynamically reload the locale definition
// for angular. With this configuration, we only load the current
// locale into the client and not all application locales.
const genericLocaleInitializer = (localeId: string): Promise<any> => {
  console.log('Registering locale data for ' + localeId);
  return import(
    // The following trick only includes en, de and fr.
    // Applications need to set their locales in the regex.
    // note: the `/node_modules/` is due to a webpack bug: webpack/webpack#13865
    /* webpackInclude: /(en|de|fr)\.m?js$/ */
    `/node_modules/@angular/common/locales/${localeId}`
  ).then(module => {
    registerLocaleData(module.default);
  });
};

const localeConfig: SiLocaleConfig = {
  availableLocales: ['en', 'de', 'fr'],
  defaultLocale: 'en',
  localeInitializer: genericLocaleInitializer,
  dynamicLanguageChange: false,
  fallbackEnabled: false
};

export const APP_CONFIG: ApplicationConfig = {
  providers: [
    { provide: LOCALE_ID, useClass: SiLocaleId, deps: [SiLocaleService] },
    { provide: SI_LOCALE_CONFIG, useValue: localeConfig }
    // , { provide: APP_INITIALIZER, useFactory: appLoadFactory, multi: true, deps: [DemoLocaleService] },
    // { provide: SiLocaleStore, useClass: DemoLocaleService }
  ]
};

In addition, fallbackEnabled enables ngx-translate to use the translation from the defaultLocale language when a translate value is missing. This is separate from Element's default text fallback.

Persisting locales using SiLocaleStore

Setting the SiLocaleService.locale = 'fr' changes the language and forces a reload of the browser window. The service uses the SiLocaleStore to persist the new locale. After reloading the application, the service uses the SiLocaleStore to load the changed locale. By default, a localStorage implementation is used. You can implement your own store to load and persist the user preferred locale from a setting backend that is shared across applications.

We implemented a demo store that loads a locale from a backend before the angular application initializes. The store is configured in the providers of the main module definition. In the following you find the key code snippets.

// Load the locale from a backend service before the app initializes
export function appLoadFactory(service: DemoLocaleService) {
  return () => service.loadConfig().toPromise();
}
// Configure the APP_INITIALIZER provider and configure to use the
// DemoLocaleService as a locale store.
export const APP_CONFIG: ApplicationConfig = {
  providers: [
    { provide: LOCALE_ID, useClass: SiLocaleId, deps: [SiLocaleService] },
    { provide: SI_LOCALE_CONFIG, useValue: localeConfig },
    {
      provide: APP_INITIALIZER,
      useFactory: appLoadFactory,
      multi: true,
      deps: [DemoLocaleService]
    },
    { provide: SiLocaleStore, useClass: DemoLocaleService }
  ]
};

You can also combine a Store that caches the last value in the localStore and loads in parallel the current value from a backend.

Runtime locales changes using impure pipes

If you need to support locale changes without reloading, we recommend to extend the Angular pipes and set the pure property to false.

@Pipe({
  name: 'dateImpure',
  pure: false // eslint-disable-line @angular-eslint/no-pipe-impure
})
export class DateImpurePipe extends DatePipe implements PipeTransform {}

SiLocaleService API Documentation

provided in root
✓

Attributes and Methods

Name Type Default Description
config
SiLocaleConfig ... The config for the local service.
hasLocale(...)
(locale: string) => boolean Test if the given locale is part of the available locales.

Parameters
  • locale: string  The locale to be tested.
locale
string Sets a new locale to the locale service and also to the translate service.
Throws An error if the new value is not configured in the available locales or if the new locale cannot be saved, an error is thrown.
(readonly) locale$
BehaviorSubject<string> Holds the used locale definition like en, de, or en-US.
(readonly) localePackageLoaded$
ReplaySubject<void> ... Emits to indicate that the localization package (e.g. @angular/common/locales/${localeId}) is loaded and registered. Emits after calling localeInitializer from the config object.

Types Documentation

Properties
The list of available locales (e.g. en, fr, de, en-GB, de-AT)
availableLocales?: string[]
The default locale to be used, when no user preference available and the browser language is not part of the available languages.
defaultLocale?: string
Default is false and defines that on setting a new locale, the locale is stored and the browser is reloaded. When changing to true, window reload is not invoked, but angular pure pipes like DatePipe will not work.
dynamicLanguageChange?: boolean
Set to true to also enable the default language on ngx-translate. When true, ngx-translate will use a translate value from the default language when a required value is not available in the current language. But note, this will also enforce to load the default language translation file into the application, even if a different locale is active. In other words, the application start time increases.
fallbackEnabled?: boolean
The localeInitializer function is invoked on every locale change. Make sure to invoke registerLocaleData with the locale to enable the Angular localization.
localeInitializer?: (localeId: string) => Promise<any>

Except where otherwise noted, content on this site is licensed under MIT License.