At some point, your web application may require serving a multilingual user base. Internationalization, or i18n for short, is the process by which you make your app usable for those with a different native language.
While Angular has some built-in i18n functionality, ngx-translate
is a third-party package that offers some functionality that might be better suited for your use case.
In this article, you will use ngx-translate
in an Angular application.
To complete this tutorial, you will need:
This tutorial was verified with Node v16.4.0, npm
v7.19.0, @angular/core
v12.1.0, @ngx-translate/core
v13.0.0, and @ngx-translate/http-loader
v6.0.0.
Create a brand new Angular application and add some dependencies.
Open your terminal and use @angular/cli
to create a new project:
- ng new angular-ngx-translate-example --skip-tests
Then navigate to the newly created project directory:
- cd angular-ngx-translate-example
Next, run the following command to add the package to your application:
- npm install @ngx-translate/core@13.0.0
Now import the TranslateModule
in your AppModule
:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
TranslateModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
This will provide access to the core of the translate service, pipe, and directives.
However, unless you plan on adding each and every translation yourself manually via code, you will probably want to add a little bit of configuration at this stage in order to make loading your translations a little easier.
TraslateHttpLoader
Probably the most common way to load translations is to include your translation files as assets and load them via the TranslateHttpLoader
, which is available in a separate npm package.
- npm install @ngx-translate/http-loader@6.0.0
Now import the TranslateHttpLoader
in your AppModule
:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { AppComponent } from './app.component';
// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
You are free to create your own loader. You will need to implement the TranslateLoader
interface and provide it in your module like above.
Creating the translation loader in this way expects you to have a file in your project under an /assets/i18n/
folder, called {lang}.json
, where {lang}
is the language of the file you are using for translations. For English, this file may be en.json
, for example.
You can change the default path and file extension by providing extra parameters to the new TranslateHttpLoader()
constructor.
The translation file is a JSON object of key-value pairs, where the key describes the text that is translated, and the value is the actual text in the language specified by the file.
{
"welcomeMessage": "Thanks for joining, {{ firstName }}! It's great to have you!",
"login": {
"username": "Enter your user name",
"password": "Password here"
}
}
The value may also be another object, which allows you to group your translations however you would like.
In the text of your translation value, you can also include double curly braces around a variable name, which will later allow you to interpolate strings dynamically into your translations.
Before you can access these translations in your application, you have to initialize some properties in the TranslateService
.
Probably the best place to do this is in your bootstrapped AppComponent
.
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(translate: TranslateService) {
translate.addLangs(['en', 'klingon']);
translate.setDefaultLang('en');
translate.use('en');
}
}
First, translate.addLangs([])
tells the service which languages are available to use for translations.
The method translate.setDefaultLang('en')
allows you to specify a fallback set of translations to use in case there are missing translations for the current language.
translate.use('en')
tells the service which is the current language to use for translations.
The parameter for all of these is the language you want to pull translations from - these should match the names of the JSON files that define the translations for those languages.
With that setup, you have three ways to access the translations. Which one you use at any given time will be up to your needs and preferences.
TranslateService
Using the service, there are two methods to get your translations.
The first, and recommended, method is to use:
get(key: string|Array<string>, interpolateParams?: Object)`
This returns an Observable, and as such, is asynchronous, which guarantees that the translation file will be loaded before using the value. This Observable then completes as soon as the value is retrieved.
The second method is to use:
instant(key: string|Array<string>, interpolateParams?: Object)`
This is synchronous. If the translation file isn’t finished loading at the time you use this method, you won’t get a translation at all.
Remember, we told the service to use en
as the current lang, so all translation results will come from en.json
initially.
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
user!: { firstName: string; lastName: string; };
welcome!: string;
usernameLabel!: string;
passwordLabel!: string;
constructor(translate: TranslateService) {
translate.addLangs(['en', 'klingon']);
translate.setDefaultLang('en');
translate.use('en');
}
ngOnInit() {
// hardcoded example
this.user = { firstName: 'Sammy', lastName: 'Shark' };
// synchronous. Also interpolate the 'firstName' parameter with a value.
this.welcome = this.translate.instant('welcomeMessage', { firstName: this.user.firstName });
// asynchronous - gets translations then completes.
this.translate.get(['login.username', 'login.password'])
.subscribe(translations => {
this.usernameLabel = translations['login.username'];
this.passwordLabel = translations['login.password'];
});
}
}
You can implement your own method in your application to switch between languages - whether through a select box, URL route, or some other method, call the use(lang: string)
method on the TranslateService
to set the current language.
TranslatePipe
You can use the translate pipe much like you’d use any other pipe in Angular. The input into the pipe is the key of the translation you need. The optional parameter is an object which defines any interpolation strings that the translation is expecting.
In the example below, the component has a user
object, with a property of firstName
:
<p>{{ 'welcomeMessage' | translate: user }}</p>
This code will produce a message of: "Thanks for joining, Sammy! It's great to have you!"
.
This matches the interpolation that is expected by the value of welcomeMessage
.
<input type="password" placeholder="{{ 'login.password' | translate }}">
This code will produce an input with a placeholder of: "Password here"
.
TranslateDirective
You can also place a directive on any HTML element to get translations.
There are a couple of different ways to do this.
<label translate='login.username'></label>
This code will produce a label of: "Enter your user name"
.
You can also set the key of the translation as the content of the element.
<p translate [translateParams]="{ firstName: user.firstName }">welcomeMessage</p>
This code will produce a message of: "Thanks for joining, Sammy! It's great to have you!"
.
In this article, you used ngx-translate
in an Angular application.
Continue your learning by reading about the built-in i18n support in Angular.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
The link to ngx-translate is broken. It now leads to a spam page…
Please update it to https://ngx-translate.org
This comment has been deleted
Complementary to “ngx-translate”, I believe that additional tools for synchronizing translation-files are required. I was disappointed by many commercial tools, which is why I wrote the free tool “attranslate”: https://github.com/fkirc/attranslate You may give “attranslate” a try if you are seeking a free tool for synchronizing your Angular-translations.