ngx-easy-i18n-js
December 18, 2023 ยท View on GitHub
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
Download and Installation
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'
})
]
Configuration
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 });
Locale pipes
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 }} |
Translate
Main function for translate your language keys
HTML file
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>
Typescript file
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' });
Translate Plural
You can translate with pluralization. To insert a number in the translated string, use {}.
HTML file
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>
Typescript file
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'] });
Store
Default store is EmptyEasyI18nStore
Use localStorage store, usage in app.module.ts, add provider
providers: [
{
provide: EasyI18nStore,
useFactory: () => new LocalStorageEasyI18nStore('current-lang')
}
]
Add HttpLoader
Standard
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'
});
Scoped loader
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' }
])
]
}
];
Add Bootstrap
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]