- Choosing a i18n strategy
- Install
angular-cli
- Bootstrap the Angular App
- Serve the App in the Browser
- Create a New Component
- Install
@ngx-translate
- Declare
@ngx-translate
in the App's Parent Module - Automatically Extract Texts Marked for Translation
- Add
ngx-translate-extract
as anpm
Script - Inject
translate
Into the Main App Component - Mark Texts for Translation
- Switch Languages
- Enjoy! 😎
The official Angular i18n solution is Enterprise-oriented and built to work with the industry standard translation source file format.
Traditionally, SPA apps use .json
files for storing/loading reading locale data. @ngx-translate
provides an accessible way of achieving that purpose.
Reasons I chose @ngx-translate
over the official Angular i18n solution:
- The official Angular i18n solution forces you to build and deploy a separate version of the application for each supported language.
@ngx-translate
offers a HTTP Loader.@ngx-translate
offers a string extractor tool that crawls all project source files and extracts texts marked for translation. In my opinion, this considerabily eases the locale files mainteinance.
Note:
@ngx-translate
loads the.json
files dynamically (during runtime) on a per-need basis. This means that when the app first loads, only the default locale file is downloaded. (This means that new locale files will be requested only when the language is changed.)
2. Install angular-cli
npm i -g @angular/cli
Note:
npm i -g
is syntactic sugar fornpm install --global
.
ng new i18nExample
cd i18nExample
ng s
Note:
ng s
is syntactic sugar forng serve
.
ng generate component sayHi
npm i -s @ngx-translate/core @ngx-translate/http-loader
Note:
npm i -s
is syntactic sugar fornpm install --save
.
// app.module.ts
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { HttpClientModule, HttpClient } from '@angular/common/http';
// ...
export const createTranslateLoader = (http: HttpClient) => {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
};
// ...
imports: [
// ...
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient]
}
})
]
npm i -g @biesbjerg/ngx-translate-extract
ngx-translate-extract -i ./src -o ./src/assets/i18n/{de,en}.json --clean --format namespaced-json
Since we'll be using the string extractor tool during development, we should add it as a npm
script:
// package.json
// ...
"scripts": {
// ...
"i18n:update": "ngx-translate-extract -i ./src -o ./src/assets/i18n/{de,en}.json --clean --format namespaced-json"
},
// ...
Now we can conveniently run:
npm run i18n:update
In order to gain access to the Translation Service, we need to include it into the app:
// app.component.ts
// ...
import { TranslateService } from '@ngx-translate/core';
// ...
export class AppComponent {
// ...
constructor(translate: TranslateService) {
translate.setDefaultLang('en');
}
}
This is possible because we have previously declared that our app.module.ts
imports the TranslateModule
.
@ngx-translate
offers 3 ways of accessing the Translation Service:
- TranslateService
- TranslatePipe
- TranslateDirective
For more information on these, please consult the @ngx-translate
documentation.
For the purpose of this tutorial, we will be using TranslatePipe
.
Now that we are able to access the Translation Service, let's mark a text for translation using TranslatePipe
.
// app.component.html
<h1>
{{ "welcome" | translate }}
</h1>
Reloading the application results in the text "welcome"
being rendered. That happens because there's no value specified for the "welcome"
key in our locale files.
Let's add some translation values to the English locale file:
// src/assets/i18n/en.json
{
"welcome": "Welcome!",
...
}
And to the German locale file:
// src/assets/i18n/de.json
{
"welcome": "Willkomen!",
...
}
Reloading the app will reveal the correct text being rendered for the "welcome"
i18n key.
Note:
Marking more texts for translation and running
npm run i18n:update
will cause new keys to be added to the.json
files.In the same manner, removing a text from the template and running
npm run i18n:update
will cause the key to be removed (along with its value) from the.json
files.
@ngx-translate
provides a helper method for switching languages: translate.use()
.
In order to switch the language dynamically, we need to call Translate Service's use()
method.
In order to do that, we declare a new private property translate
in AppComponent
:
// app.component.ts
// ...
import { TranslateService } from '@ngx-translate/core';
// ...
export class AppComponent {
translate: TranslateService; // <-- defining translate as a private property
switchLanguage = (lang: string) => { // <-- creating a new method
this.translate.use(lang); // <-- invoking `use()`
}
constructor(translate: TranslateService) {
this.translate = translate; // <-- binding the injected `TranslatedService` to the local `translate` property
translate.setDefaultLang('en');
}
}
And in our template, we add two buttons for invoking switchLanguage()
:
// app.component.html
// ...
<button (click)="switchLanguage('en')">EN</button>
<button (click)="switchLanguage('de')">DE</button>
// ...
Loading the app will look like this:
And switching to DE will look like this:
You can find the final version of the code for this tutorial in this repository. 👍