Pure version angular for internalization (i18n).
Translations are static. If you change language you must refresh the page or use bootstrap extension.
Use EasyI18 Js library https://github.com/gabrie-allaigre/easy-i18n-js
Install using npm:
npm install easy-i18n-js @ngx-easy-i18n-js/core --save
Open angular.json and under allowedCommonJsDependencies add:
"allowedCommonJsDependencies": [
"easy-i18n-js"
]
Usage in app.module.ts, add imports
import localeFr from '@angular/common/locales/fr';
import localeEn from '@angular/common/locales/en';
imports: [
EasyI18nModule.forRoot({
options: {
logging: false
},
ngLocales: {
'fr': localeFr,
'en': localeEn,
},
defaultLanguage: 'en-US'
})
]
export interface EasyI18nModuleConfig {
// Options fo easy i18 js library
options?: EasyI18nOptions;
// Use specific loader
loader?: Provider;
// Add Angular locale <code>import localeFr from '@angular/common/locales/fr';</code>
ngLocales?: { [key: string]: any; };
// Use browser language
useBrowserLanguage?: boolean;
// Default fallback language use if current language not found
defaultLanguage?: string;
// <code>exact</code> only fr-FR, <code>minimum</code> only fr, <code>all</code> fr-FR and fr
discover?: 'exact' | 'minimum' | 'all';
}
In child module
imports: [
EasyI18nModule
]
For change current locale use EasyI18nService
export class MyComponent {
constructor(
private easyI18nService: EasyI18nService
) {
}
public doChangeLanguage(locale: string): void {
this.easyI18nService.registerCulture('fr');
}
}
Force reload if change culture
this.easyI18nService.registerCulture('fr', { reload: true });
In HTML, uses locales pipes to get dates, numbers in locale format
pipe | description | example |
---|---|---|
localeDate |
Same as date |
{{ mydate | localeDate:'short' }} |
localeNumber |
Same as number |
{{ mydate | localeNumber }} |
localeCurrency |
Same as currency |
{{ mydate | localeCurrency }} |
localePercent |
Same as percent |
{{ mydate | localePercent }} |
Main function for translate your language keys
In HTML template, with pipe, parameter is TrOptions
{{ 'hello' | tr }}
{{ 'hello_with_genre' | tr: { gender: 'male' } }}
{{ 'My name is {}' | tr: { args: ['Gabriel'] } }}
TrOptions arguments
Name | type | example |
---|---|---|
args | string[] |
['Gabriel', '20'] |
namedArgs | { [key: string]: string; } } |
{ name : 'Gabriel', age : '20' } |
namespace | string |
'common' |
gender | 'male' | 'female' | 'other' |
gender: 'other' |
Directives
There are 2 differents directives
First is simple, translate [tr]
Directive | description | example |
---|---|---|
tr |
Active directive translate | <span tr>hello</span> |
trNamespace |
Add namespace | <span tr trNamespace="common">hello</span> |
trKey |
Set key (if empty use content) | <span tr trKey="hello" trNamespace="common"></span> |
trGender |
Gender | <span tr trGender="male">hello_with_genre</span> |
trArgs |
Arguments | <span tr [trArgs]="['Gabriel']">hello</span> |
trNamedArgs |
Named arguments | <span tr [trNamedArgs]="{ name: 'Gabriel' }">hello</span> |
Second, use HTML named arguments [trContent]
, replace {namedArg}
with child element *trElement
Directive | description |
---|---|
trContent |
Active content directive translate, get a key |
trNamespace |
Add namespace |
trGender |
Gender |
trArgs |
Arguments |
trNamedArgs |
Named arguments |
demarc |
Change token start, end identifier |
Examples
<!-- "hello_name": "My name is {name}" -->
<div trContent="hello_name">
<span *trElement="'name'" style="color: red; font-size: 2rem; font-weight: bold">Gabriel</span>
</div>
<div trContent="My name is {name} and I live in {country}" style="color: blue;">
<span *trElement="'name'" style="color: red; font-size: 2rem; font-weight: bold">Gabriel</span>
<span *trElement="'country'">{{ var_country }}</span>
</div>
You can use extension methods of [String], you can also use tr() as a static function.
In typescript file, there is no need to inject EasyI18nService
'hello'.tr();
'hello_with_genre'.tr({ gender: 'male' });
tr('hello');
tr('hello_with_genre', { gender: 'male' });
You can translate with pluralization. To insert a number in the translated string, use {}.
In HTML template, with pipe, first parameter is number and second PluralOptions
{{ 'money' | plural:10 }}
{{ 'money_with_args' | plural:3: { args: ['Gabriel'] } }}
PluralOptions arguments
Name | type | example |
---|---|---|
args | string[] |
['Gabriel', '20'] |
namedArgs | { [key: string]: string; } } |
{ name : 'Gabriel', age : '20' } |
namespace | string |
'common' |
name | string |
money |
numberFormatterFn | (value: number) => string |
(value) => value.Precision(3) |
gender | 'male' | 'female' | 'other' |
gender: 'other' |
Directives
There are 2 different directives
First is simple, translate plural [plural]
Directive | description | example |
---|---|---|
plural |
Active directive translate | <span [plural]="10">money</span> |
pluralNamespace |
Add namespace | <span [plural]="100" pluralNamespace="common">money</span> |
pluralKey |
Set key (if empty use content) | <span [plural]="100" pluralKey="money" pluralNamespace="common"></span> |
pluralGender |
Gender | <span [plural]="1" pluralGender="male">money_with_genre</span> |
pluralArgs |
Arguments | <span [plural]="5" [pluralArgs]="['Gabriel']">money</span> |
pluralNamedArgs |
Named arguments | <span [plural]="13" [pluralNamedArgs]="{ name: 'Gabriel' }">money</span> |
pluralName |
Name value | <span [plural]="4" pluralName="value">money</span> |
pluralNumberFormatterFn |
Formatter function | <span [plural]="10000" [pluralNumberFormatterFn]="myFn">money</span> |
Second, use HTML named arguments [pluralContent]
, replace {namedArg}
with child element *pluralElement
Directive | description |
---|---|
pluralContent |
Active content directive translate, get a key |
pluralValue |
Active content directive translate, get a value |
pluralNamespace |
Add namespace |
pluralGender |
Gender |
pluralArgs |
Arguments |
pluralNamedArgs |
Named arguments |
pluralName |
Name value |
pluralNumberFormatterFn |
Formatter function |
demarc |
Change token start, end identifier |
Examples
<!-- "money_content": {
"zero": "{name} not have money",
"one": "{name} have {money} dollar",
"two": "{name} have {money} dollars",
"many": "{name} have {money} dollars",
"other": "{name} have {money} dollars"
} -->
<div pluralContent="money_content" [pluralValue]="var_money" class="fst-italic text-gray-500">
<span *pluralElement="'name'" style="color: red; font-size: 2rem; font-weight: bold">Gabriel</span>
<span *pluralElement="'money'" style="color: blueviolet; font-weight: bold"
[style.font-size]="(var_money / 10) + 'vw'">{{ var_money }}</span>
</div>
You can use extension methods of [String], you can also use plural() as a static function.
In typescript file, there is no need to inject EasyI18nService
'money_args'.plural(0, { args: ['Gabriel'] });
'money_args'.plural(1.5, { args: ['Gabriel'] });
plural('money_args', { args: ['Gabriel'] });
Default store is EmptyEasyI18nStore
Use localStorage
store, usage in app.module.ts, add provider
providers: [
{
provide: EasyI18nStore,
useFactory: () => new LocalStorageEasyI18nStore('current-lang')
}
]
Load messages with HttpClient
Install using npm:
npm install @ngx-easy-i18n-js/http-loader --save
Usage in app.module.ts, add provider
providers: [
{
provide: EasyI18nLoader,
deps: [HttpClient],
useFactory: (httpClient: HttpClient) => new HttpEasyI18nLoader(httpClient)
}
]
Change prefix or suffix with options
new HttpEasyI18nLoader(httpClient, {
prefix: 'assets/',
suffix: '.json5'
});
new HttpEasyI18nLoader(httpClient, {
prefix: ['assets/common/i18n', 'assets/i18n'],
suffix: '.json5'
});
Load multiples files with scope
Usage in app.module.ts, add provider
providers: [
{
provide: EasyI18nLoader,
deps: [HttpClient],
useFactory: (httpClient: HttpClient) => new ScopedHttpEasyI18nLoader(httpClient, [
{ prefix: `/assets/i18n/` },
{ prefix: ['assets/common/i18n', 'assets/i18n/common'], scope: 'common' },
{ prefix: `/assets/i18n/errors/`, scope: 'errors' }
])
}
]
{{ 'common.save' | tr }}
{{ 'errors.internal_server_error' | tr }}
Change suffix
new ScopedHttpEasyI18nLoader(httpClient, [
{ prefix: `/assets/i18n/` }
], {
suffix: '.json5'
});
Append scoped loader for lazy routes
const routes: Routes = [
{
path: 'login',
loadChildren: () => import('./login/login.module').then(m => m.LoginModule),
canActivate: [
appendScopedHttpEasyI18nLoader([
{ prefix: `/assets/i18n/login/`, scope: 'login' }
])
]
}
];
Bootstrap application, refresh application when culture change without reload page
Install using npm:
npm install @angular/cdk @ngx-easy-i18n-js/bootstrap --save
Usage
imports: [
EasyI18nBootstrapModule.forRoot({
bootstrap: AppComponent
})
]
bootstrap: [EasyI18nBootstrapComponent]
And in index.html
, replace <app-root></app-root>
by <ngx-easy-i18n></ngx-easy-i18n>
For custom loading component
imports: [
EasyI18nBootstrapModule.forRoot({
bootstrap: AppComponent,
loadingComponent: MyLoadingComponent
})
]
bootstrap: [EasyI18nBootstrapComponent]