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¶
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 | 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¶
| | ||||||
|---|---|---|---|---|---|---|
|
Except where otherwise noted, content on this site is licensed under MIT License.