DEV Community

Cover image for How to build painless multi-language apps with Angular and ngx-translate
Federico Navarrete
Federico Navarrete

Posted on • Edited on • Originally published at supernovaic.blogspot.com

How to build painless multi-language apps with Angular and ngx-translate

I'm sure if you're reading this post is because either you're curious or you understand the pain of supporting multiple languages in Angular.

I love Angular and it's my main JS Modern Framework, but there is something that drives me nuts its poor multi-lingual support. It's extremely over-complicated to my taste.

I have developed multiple websites and over 11 apps for Windows and Android and I cannot understand how the creators couldn't be inspired by Google's most important OS, Android.

In Android, you only need a couple of XMLs (en, es, etc.), minor adjustments in the UI XMls, or code something in Java/Kotlin and magically, you have an app that supports multiple languages.

After several attempts, I found ngx-translate, which leveraged my work significantly. So, how to use it?

npm install @ngx-translate/core @ngx-translate/http-loader --save
Enter fullscreen mode Exit fullscreen mode

Next, configure your app.module.ts

1. Enable the translation service:

import { TranslateModule, TranslateLoader, TranslateService } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { HttpClient, HttpClientModule } from '@angular/common/http';
Enter fullscreen mode Exit fullscreen mode

2. Configure the loader:

a. Root domain (www.mydomain.com):

export function translateHttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}
Enter fullscreen mode Exit fullscreen mode

b. Sub-domains (myself.github.io/myapp):

export function translateHttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
Enter fullscreen mode Exit fullscreen mode

In this option, you are going to configure the location of your JSON files.

3. Configure your constructor (my version auto-detects the browser language and set it by default):

availableLng = ['en', 'es'];

//start the translation service
constructor(private translateService: TranslateService) {
    //defines the default language
    let tmpLng = 'en';

    //gets the default browser language
    const currentLng = window.navigator.language.substring(0,2);

    if (this.availableLng.includes(currentLng))
       tmpLng = currentLng;

    translateService.setDefaultLang(tmpLng);
}
Enter fullscreen mode Exit fullscreen mode

4. Add to your imports:

    HttpClientModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: translateHttpLoaderFactory,
        deps: [HttpClient]
      }
    })
Enter fullscreen mode Exit fullscreen mode

Your final app.module.ts might look like this one:

import { HttpClientModule, HttpClient } from '@angular/common/http';
//configure translation service
import { TranslateModule, TranslateLoader, TranslateService } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

/* IMPORTANT:
   This only works if you are setting your app in your main domain: www.mydomain.com
*/
export function translateHttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}

/*
   For sub-domains like myself.github.io/myapp
   You need to use this code or a variation with the location of your assets:
*/

/*
export function translateHttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
*/

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: translateHttpLoaderFactory,
        deps: [HttpClient]
      }
    })
  ],
  providers: [],
  bootstrap: [AppComponent]
})

export class AppModule {
  //define available languages
  availableLng = ['en', 'es'];

  //start the translation service
  constructor(private translateService: TranslateService) {
    //defines the default language
    let tmpLng = 'en';

    //gets the default browser language
    const currentLng = window.navigator.language.substring(0,2);

    if (this.availableLng.includes(currentLng))
           tmpLng = currentLng;

    translateService.setDefaultLang(tmpLng);
  }
}
Enter fullscreen mode Exit fullscreen mode

After, create a new folder in assets called i18n. Inside of it, you are going to create the language assets like en.json:

{
  "Title": "Translation demo",
  "WelcomeMessage": "Welcome to the international demo application"
}
Enter fullscreen mode Exit fullscreen mode

And es.json:

{
  "Title": "Demo de traducción",
  "WelcomeMessage": "Bienvenido a la aplicación de demostración internacional"
}
Enter fullscreen mode Exit fullscreen mode

Now, inside the HTML part of your components, you can call it like this:

<h1 translate>Title</h1>
Enter fullscreen mode Exit fullscreen mode

Where translate indicates the tag that is going to be translated and Title the JSON key.

Can this be extended beyond HTML tags?

Definitely, what if you have a placeholder in an input?

You can use it like this:

<input placeholder="{{'Title' | translate}}" />
Enter fullscreen mode Exit fullscreen mode

Or how do you use it from the TypeScript file?

First, enable it from the component constructor:

constructor(private translateService: TranslateService) { }
Enter fullscreen mode Exit fullscreen mode

Now, you can access it with a simple piece of code like this one (synchronous, but might return the same key if it hasn't loaded yet):

console.log(this.translateService.instant('WelcomeMessage'));
Enter fullscreen mode Exit fullscreen mode

The best option would be to use the async option:

this.translateService.get('WelcomeMessage').subscribe((data: any) => { console.log(data); });
Enter fullscreen mode Exit fullscreen mode

The greatest benefit in my experience with ngx-translate is that it works and looks similar to common Apps development in Android or Windows.

This post has some inspiration from Yaser's blog:

https://yashints.dev/blog/2018/01/17/multi-language-angular-applications

Plus, if you want to see a full action app using this framework, you can check it here:

https://fanmixco.github.io/gravitynow-angular

Also, here is its repository:

https://github.com/FANMixco/gravitynow-angular

Follow me on:

Personal LinkedIn YouTube Instagram Cyber Prophets Sharing Your Stories
Personal LinkedIn YouTube Instagram RedCircle Podcast RedCircle Podcast

sponsor me

Top comments (0)