Angular Translation Setup
Introduction
Adding multi-language support to your Angular application makes it accessible to users from different regions and language backgrounds. This process, known as internationalization (i18n), allows your application to adapt to different languages without changing its core functionality.
In this tutorial, we'll learn how to set up translations in an Angular application using the popular @ngx-translate/core
library. This library provides a simple way to manage translations and switch between languages dynamically.
Prerequisites
Before we start, make sure you have:
- Basic knowledge of Angular
- An existing Angular project or a new one created with Angular CLI
- Node.js and npm installed
Installing @ngx-translate/core
Let's start by installing the required packages:
npm install @ngx-translate/core @ngx-translate/http-loader --save
The @ngx-translate/core
package contains the core functionality, while @ngx-translate/http-loader
allows loading translation files using HTTP requests.
Setting Up the Translation Module
1. Create a Translation Files Structure
First, we'll create a folder structure for our translation files. In your Angular project, create the following structure:
src/
└── assets/
└── i18n/
├── en.json
├── es.json
└── fr.json
2. Add Translation Content
Let's add some basic translations to our JSON files:
en.json (English):
{
"HEADER": {
"TITLE": "My Application",
"HOME": "Home",
"ABOUT": "About",
"CONTACT": "Contact"
},
"WELCOME": {
"TITLE": "Welcome to My Application",
"MESSAGE": "This is an internationalized Angular application.",
"LANGUAGE_SELECT": "Select a language:"
},
"BUTTONS": {
"SUBMIT": "Submit",
"CANCEL": "Cancel"
}
}
es.json (Spanish):
{
"HEADER": {
"TITLE": "Mi Aplicación",
"HOME": "Inicio",
"ABOUT": "Acerca de",
"CONTACT": "Contacto"
},
"WELCOME": {
"TITLE": "Bienvenido a Mi Aplicación",
"MESSAGE": "Esta es una aplicación Angular internacionalizada.",
"LANGUAGE_SELECT": "Selecciona un idioma:"
},
"BUTTONS": {
"SUBMIT": "Enviar",
"CANCEL": "Cancelar"
}
}
fr.json (French):
{
"HEADER": {
"TITLE": "Mon Application",
"HOME": "Accueil",
"ABOUT": "À propos",
"CONTACT": "Contact"
},
"WELCOME": {
"TITLE": "Bienvenue sur Mon Application",
"MESSAGE": "C'est une application Angular internationalisée.",
"LANGUAGE_SELECT": "Sélectionnez une langue:"
},
"BUTTONS": {
"SUBMIT": "Soumettre",
"CANCEL": "Annuler"
}
}
3. Configure the Translation Module
Now, let's configure the translation module in our app. First, create a function to load the translation files:
// src/app/translation.loader.ts
import { HttpClient } from '@angular/common/http';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
Then, update your app.module.ts
to include the TranslateModule:
// src/app/app.module.ts
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 { AppComponent } from './app.component';
import { createTranslateLoader } from './translation.loader';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule,
TranslateModule.forRoot({
defaultLanguage: 'en',
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient]
}
})
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Using Translations in Components
1. Setting Up the Root Component
First, let's update our app.component.ts
to initialize the translate service:
// src/app/app.component.ts
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 {
availableLanguages = [
{ code: 'en', name: 'English' },
{ code: 'es', name: 'Español' },
{ code: 'fr', name: 'Français' }
];
currentLang: string;
constructor(private translate: TranslateService) {
// Get browser language or default to English
const browserLang = translate.getBrowserLang();
this.currentLang = browserLang.match(/en|es|fr/) ? browserLang : 'en';
// Set default language
translate.setDefaultLang('en');
// Use current language
translate.use(this.currentLang);
}
changeLanguage(langCode: string): void {
this.translate.use(langCode);
this.currentLang = langCode;
}
}
2. Update the Template
Now, let's update the app.component.html
to use our translations:
<!-- src/app/app.component.html -->
<header>
<h1>{{ 'HEADER.TITLE' | translate }}</h1>
<nav>
<ul>
<li><a href="#">{{ 'HEADER.HOME' | translate }}</a></li>
<li><a href="#">{{ 'HEADER.ABOUT' | translate }}</a></li>
<li><a href="#">{{ 'HEADER.CONTACT' | translate }}</a></li>
</ul>
</nav>
</header>
<main>
<div class="welcome-section">
<h2>{{ 'WELCOME.TITLE' | translate }}</h2>
<p>{{ 'WELCOME.MESSAGE' | translate }}</p>
<div class="language-selector">
<label>{{ 'WELCOME.LANGUAGE_SELECT' | translate }}</label>
<select [(ngModel)]="currentLang" (change)="changeLanguage(currentLang)">
<option *ngFor="let lang of availableLanguages" [value]="lang.code">
{{ lang.name }}
</option>
</select>
</div>
</div>
<div class="action-buttons">
<button>{{ 'BUTTONS.SUBMIT' | translate }}</button>
<button>{{ 'BUTTONS.CANCEL' | translate }}</button>
</div>
</main>
Don't forget to add the FormsModule to your app.module.ts
for the select element to work:
import { FormsModule } from '@angular/forms';
@NgModule({
// ...
imports: [
BrowserModule,
HttpClientModule,
FormsModule,
TranslateModule.forRoot({
// ...
})
],
// ...
})
Advanced Translation Techniques
1. Using Translation Parameters
The @ngx-translate/core
library allows you to pass parameters to your translations. Let's update our translation files to include parameters:
en.json (add this):
{
"GREETINGS": {
"HELLO": "Hello, {{name}}!",
"ITEMS_COUNT": "You have {{count}} items in your cart."
}
}
Similar updates should be made to the other language files.
In your component, you can pass parameters like this:
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-greeting',
template: `
<div>
<p>{{ 'GREETINGS.HELLO' | translate:{ name: userName } }}</p>
<p>{{ 'GREETINGS.ITEMS_COUNT' | translate:{ count: itemsCount } }}</p>
</div>
`
})
export class GreetingComponent {
userName = 'John';
itemsCount = 5;
constructor(private translate: TranslateService) {}
}
2. Programmatic Translation
Sometimes you need to translate strings programmatically, not just in the template. Here's how:
import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-programmatic-example',
template: `
<div>
<p>{{ translatedText }}</p>
<p>{{ translatedGreeting }}</p>
</div>
`
})
export class ProgrammaticExampleComponent implements OnInit {
translatedText: string;
translatedGreeting: string;
constructor(private translate: TranslateService) {}
ngOnInit() {
// Get a simple translation
this.translate.get('WELCOME.TITLE').subscribe((res: string) => {
this.translatedText = res;
});
// Get a translation with parameters
this.translate.get('GREETINGS.HELLO', { name: 'Sarah' }).subscribe((res: string) => {
this.translatedGreeting = res;
});
}
}
3. Translation in Services
You can also use translations in your services:
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
@Injectable({
providedIn: 'root'
})
export class NotificationService {
constructor(private translate: TranslateService) {}
showSuccessMessage(userName: string): string {
let message = '';
this.translate.get('NOTIFICATIONS.SUCCESS', { name: userName })
.subscribe((res: string) => {
message = res;
});
return message;
}
}
Real-World Example: Multi-Language Form
Let's create a practical example of a contact form with multi-language support:
First, add the necessary translations to our JSON files:
en.json (add this):
{
"CONTACT_FORM": {
"TITLE": "Contact Us",
"NAME_LABEL": "Full Name",
"EMAIL_LABEL": "Email Address",
"MESSAGE_LABEL": "Your Message",
"SUBMIT_BUTTON": "Send Message",
"SUCCESS_MESSAGE": "Your message has been sent successfully!",
"ERROR_MESSAGE": "There was an error sending your message. Please try again.",
"NAME_REQUIRED": "Name is required",
"EMAIL_REQUIRED": "Email is required",
"EMAIL_INVALID": "Please enter a valid email address",
"MESSAGE_REQUIRED": "Message is required"
}
}
Now, let's create a contact form component:
// src/app/contact-form/contact-form.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-contact-form',
templateUrl: './contact-form.component.html',
styleUrls: ['./contact-form.component.css']
})
export class ContactFormComponent {
contactForm: FormGroup;
formSubmitted = false;
formSuccess = false;
formError = false;
constructor(
private fb: FormBuilder,
private translate: TranslateService
) {
this.createForm();
}
createForm() {
this.contactForm = this.fb.group({
name: ['', Validators.required],
email: ['', [Validators.required, Validators.email]],
message: ['', Validators.required]
});
}
onSubmit() {
this.formSubmitted = true;
if (this.contactForm.valid) {
// Simulate form submission
setTimeout(() => {
this.formSuccess = true;
this.formError = false;
this.contactForm.reset();
this.formSubmitted = false;
}, 1000);
}
}
getErrorMessage(controlName: string): string {
const control = this.contactForm.get(controlName);
if (control.hasError('required')) {
return `CONTACT_FORM.${controlName.toUpperCase()}_REQUIRED`;
}
if (controlName === 'email' && control.hasError('email')) {
return 'CONTACT_FORM.EMAIL_INVALID';
}
return '';
}
}
The HTML template would look like:
<!-- src/app/contact-form/contact-form.component.html -->
<div class="contact-form-container">
<h2>{{ 'CONTACT_FORM.TITLE' | translate }}</h2>
<div *ngIf="formSuccess" class="success-message">
{{ 'CONTACT_FORM.SUCCESS_MESSAGE' | translate }}
</div>
<div *ngIf="formError" class="error-message">
{{ 'CONTACT_FORM.ERROR_MESSAGE' | translate }}
</div>
<form [formGroup]="contactForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="name">{{ 'CONTACT_FORM.NAME_LABEL' | translate }}</label>
<input type="text" id="name" formControlName="name">
<div *ngIf="formSubmitted && contactForm.get('name').invalid" class="validation-error">
{{ getErrorMessage('name') | translate }}
</div>
</div>
<div class="form-group">
<label for="email">{{ 'CONTACT_FORM.EMAIL_LABEL' | translate }}</label>
<input type="email" id="email" formControlName="email">
<div *ngIf="formSubmitted && contactForm.get('email').invalid" class="validation-error">
{{ getErrorMessage('email') | translate }}
</div>
</div>
<div class="form-group">
<label for="message">{{ 'CONTACT_FORM.MESSAGE_LABEL' | translate }}</label>
<textarea id="message" formControlName="message" rows="5"></textarea>
<div *ngIf="formSubmitted && contactForm.get('message').invalid" class="validation-error">
{{ getErrorMessage('message') | translate }}
</div>
</div>
<button type="submit" class="submit-button">
{{ 'CONTACT_FORM.SUBMIT_BUTTON' | translate }}
</button>
</form>
</div>
Don't forget to add ReactiveFormsModule to your app.module.ts:
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
// ...
imports: [
// ...
ReactiveFormsModule
],
// ...
})
Persisting Language Preferences
A good user experience includes remembering the user's language preference. Let's add that functionality:
// src/app/app.component.ts
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
availableLanguages = [
{ code: 'en', name: 'English' },
{ code: 'es', name: 'Español' },
{ code: 'fr', name: 'Français' }
];
currentLang: string;
constructor(private translate: TranslateService) {
// Check for saved language preference
const savedLang = localStorage.getItem('preferred-lang');
// If no saved preference, get browser language or default to English
if (!savedLang) {
const browserLang = translate.getBrowserLang();
this.currentLang = browserLang.match(/en|es|fr/) ? browserLang : 'en';
} else {
this.currentLang = savedLang;
}
// Set default language
translate.setDefaultLang('en');
// Use current language
translate.use(this.currentLang);
}
changeLanguage(langCode: string): void {
this.translate.use(langCode);
this.currentLang = langCode;
// Save language preference
localStorage.setItem('preferred-lang', langCode);
}
}
Summary
In this tutorial, we've covered:
- Setting up
@ngx-translate/core
in an Angular application - Creating and organizing translation files
- Using the translate pipe in templates
- Passing parameters to translations
- Using translations programmatically
- Creating a real-world example with a multi-language form
- Persisting user language preferences
With this setup, your Angular application can now support multiple languages, providing a better experience for international users. As your application grows, you can easily add more languages and translation keys to support your expanding user base.
Additional Resources
Exercises
- Add a new language to the application (e.g., German or Japanese)
- Create a language switcher component that shows flags for each available language
- Implement a "translator mode" that shows the translation key alongside the translated text (useful for debugging)
- Create a service to automatically detect and set the user's language based on their browser settings
- Implement lazy loading of translation files to improve initial load performance
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)