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
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';
2. Configure the loader:
a. Root domain (www.mydomain.com):
export function translateHttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
b. Sub-domains (myself.github.io/myapp):
export function translateHttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
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);
}
4. Add to your imports:
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: translateHttpLoaderFactory,
deps: [HttpClient]
}
})
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);
}
}
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"
}
And es.json:
{
"Title": "Demo de traducción",
"WelcomeMessage": "Bienvenido a la aplicación de demostración internacional"
}
Now, inside the HTML part of your components, you can call it like this:
<h1 translate>Title</h1>
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}}" />
Or how do you use it from the TypeScript file?
First, enable it from the component constructor:
constructor(private translateService: TranslateService) { }
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'));
The best option would be to use the async option:
this.translateService.get('WelcomeMessage').subscribe((data: any) => { console.log(data); });
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
Top comments (0)