Translating Text Using i18n in Angular

Angular, being a versatile framework, offers powerful tools to create applications that cater to diverse audiences. One essential feature for global accessibility is multi-language support. This blog will guide you through implementing multi-language translation using ngx-translate in an Angular application.

In my recent Angular project, I encountered a fascinating challenge — implementing localization in an app that required dynamic language switching and integration with existing components.

In easy and simple steps.

So here is everything we are going to discuss in this blog:

Step 1: Create a new angular app .

Create a new app using angular cli using this command.

ng new i18n

Step 2: Installing ngx-translate Packages

1) Open Command Line Interface (CLI):

Open your preferred command line interface (such as Terminal, Command Prompt, or PowerShell) within your Angular project directory.

2)Run npm Install Command:

Use the following command to install the required ngx-translate packages:

npm install @ngx-translate/core
npm install @ngx-translate/http-loader@6.0.0

3)Explanation of the Command:

  • npm install: Initiates the npm package installation process.

  • @ngx-translate/core: The core package for ngx-translate, providing translation functionalities.

  • @ngx-translate/http-loader: An optional package for loading translation files via HTTP requests.

Step 3:

a) To keep things simple, I’m going to remove everything from app.component.html and also I am using tailwind css for styling within the project. Here I am creating a simple shopping app which switches to different languages.

Firstly I removed all the tags and content in app.component.html and then imported the translation modules in app.module.ts.

app.component.html

<header class="text-center bg-orange-400 px-3 py-5">
  <h1 class="text-4xl font-bold text-gray-900">
    {{ "HOME.TITLE" | translate }}
  </h1>

  <div class="flex items-center justify-center mt-4">
    <label class="mr-2 text-gray-700">
      {{ "HOME.SELECT" | translate }}
      <select #langSelect (change)="translate.use(langSelect.value)" 
      class="px-2 py-2 border rounded"  
      >
        <option
          *ngFor="let lang of translate.getLangs()"
          [value]="lang"
          [selected]="lang === translate.currentLang"
        >
          {{ lang }}
        </option>
      </select>
    </label>
  </div>
</header>
<div class="bg-gray-400"> 
<div class="text-center" [innerHTML]="'HELLO.MESSAGE' | translate"></div>
<div class="flex justify-center">
  <input type="text" [placeholder]="'HOME.PLACEHOLDER' | translate"  
   class="w-full md:w-1/2 lg:w-1/3 px-3 py-2 border rounded-lg text-center mt-5"/>
</div>
  <app-shopping-card-list></app-shopping-card-list>
</div>

This HTML structure represents a webpage with a header section styled using Tailwind CSS classes (text-center, bg-orange-400, etc.). Inside the header, there's a large, bold title fetched dynamically through translation using Angular's TranslatePipe.

Below the header, there’s a gray-colored section housing dynamic content retrieved through translation ('HELLO.MESSAGE' | translate). Additionally, there's a text input field (<input>) styled using Tailwind CSS classes for responsiveness (w-full, md:w-1/2, etc.). Lastly, an Angular component <app-shopping-card-list> is included, displaying a shopping card list. Overall, this HTML file structures a webpage with translation-integrated content and styled elements.

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import { ShoppingCardListComponent } from './shopping-card-list/shopping-card-list.component';

export function HttpLoaderFactory(httpClient: HttpClient) {
  return new TranslateHttpLoader(httpClient);
}

@NgModule({
  declarations: [
    AppComponent,
    ShoppingCardListComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    TranslateModule.forRoot({
      loader:{
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient] 
      }
    })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

In this Angular app’s AppModule, there's a special part called TranslateModule from @ngx-translate/core. This part helps with using many languages. It gets the different language words from the internet using something called TranslateHttpLoader and the internet tool HttpClient. It's set up in a way that when you change languages, it gets the right words without needing to refresh the page. This makes it easy to use the app in different languages without any extra work.

b) The Angular AppComponent imports Component and TranslateService from @ngx-translate/core. It initializes the translation service, adds supported languages, sets the default language to English, and dynamically chooses the app's language based on the browser's preference or defaults to English.

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 {
  title = 'i18n';
  roles = 'admin'
  constructor(public translate: TranslateService) {
    translate.addLangs(['en', 'fr','ar',"hi","de"]);
    translate.setDefaultLang('en');

    let browserLang : any;
    browserLang = translate.getBrowserLang();
    translate.use(browserLang.match(/en|fr|ar|hi|de/) ? browserLang : 'en');
  }
}

Here is a step by step explanation :

The constructor within the Angular AppComponent initializes the translation service (TranslateService) and configures language settings:

  1. translate.addLangs(['en', 'fr','ar',"hi","de"]): Adds supported languages ('en', 'fr', 'ar', 'hi', 'de') to the translation service.

  2. translate.setDefaultLang('en'): Sets the default language to English ('en').

  3. let browserLang : any; browserLang = translate.getBrowserLang(): Retrieves the preferred language from the user's browser.

  4. translate.use(browserLang.match(/en|fr|ar|hi|de/) ? browserLang : 'en'): Sets the app's language based on the browser's preferred language, selecting from the supported languages or defaulting to English if the browser's language doesn't match. This ensures the app's language aligns with the user's browser settings when possible.

Step 4 : Shopping card component

shopping-card-list.component.html

<div class="flex flex-wrap justify-center">
    <div *ngFor="let item of items" class="w-full sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/5 p-4">
      <div class="bg-white rounded-lg shadow-md">
        <div class="border border-gray-200 p-4 rounded">
          <img [src]="item.image" alt="Product Image" class="w-full h-auto mb-2" />
          <h2 class="text-xl font-bold mb-2">{{ 'PRODUCT.NAME' | translate }} - {{item.name}}</h2>
          <p class="text-gray-700 mb-2">{{ 'PRODUCT.DESCRIPTION' | translate }} - {{item.description}}</p>
          <p class="text-gray-900 font-semibold mb-2">{{ 'PRODUCT.PRICE' | translate }}: {{ item.price }}</p>
          <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg ">
            {{ 'PRODUCT.ADD_TO_CART' | translate }}
          </button>
        </div>
      </div>
    </div>
  </div>

shopping-card-list.component.ts

import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Component({
  selector: 'app-shopping-card-list',
  templateUrl: './shopping-card-list.component.html',
  styleUrls: ['./shopping-card-list.component.css']
})
export class ShoppingCardListComponent {
  items = [
    {
      id: 1,
      image: './assets/bag.avif',
      name: 'bag',
      description: "A bag",
      price: 100
    },
    {
      id: 2,
      image: './assets/shirt.avif',
      name : "shirt",
      description: "Men shirt",
      price: 150,
    },
    {
      id: 3,
      image: './assets/jeans.jpg',
      name: "jeans",
      description :"men jeans",
      price: 250,
    },
    {
      id: 4,
      image: './assets/samsung.jpg',
      name: "mobile",
      description :"samsung m11",
      price: 10000,
    },

    // Add more items as needed
  ];
  constructor(public translate: TranslateService) {}
}

The HTML snippet exhibits a product display grid styled using Tailwind CSS. The Angular component ShoppingCardListComponent renders product details fetched dynamically from items array, populating each card with an image, name, description, and price. The use of Angular's TranslateService ensures language translation for elements like product names and descriptions using the TranslatePipe.

The TypeScript code defines items with various product details, such as image paths, names, descriptions, and prices. To indicate adding more items, ellipsis ("...") is shown within the object, signifying the potential addition of further product entries within the array.

Step 5: Translation files

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

They’re basically json files with key-value pairs.
So, for our example, I created 2 files for both languages, en.json and fr.json, and here is the code.

en.json :

{
    "HOME": {
      "TITLE": "Translating text using i18n in Angular",
      "SELECT": "Change language",
      "PLACEHOLDER": "Search"
    },
}

fr.json


  {
    "HOME": {
      "TITLE": "Traduire du texte en utilisant i18n dans Angular",
      "SELECT": "Changer la langue",
      "PLACEHOLDER": "Recherche"
    },
}

Both the translation files and HTML file use identical keys, allowing seamless value replacement. These keys serve as references to determine the corresponding translated content.

Now run the application using

ng serve

How is the language switch is happening:-

The language change occurs when a user selects a different language from the <select> dropdown menu in the HTML file. The <select> element is bound to a method in the component that interacts with the TranslateService from @ngx-translate/core.

Here’s a general overview of how the language change happens:

  1. The <select> element's (change) event triggers the translate.use(langSelect.value) method.

  2. This event-driven function (translate.use) is connected to the TranslateService.

  3. The langSelect.value fetches the chosen language value from the dropdown.

  4. When a new language is selected, translate.use() updates the app's language to the chosen one.

  5. The TranslateService then dynamically loads and displays the content in the selected language, updating the translated text throughout the application.

This way, the app reacts to the language selection event, initiating the translation service to switch and display content in the chosen language in real-time.

Here is the gif showcasing how the language switching is happening.

The source code of this blog post is on GitHub.