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 if something drives me nuts are 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?
1. Enable the translation service:
import { TranslateModule, TranslateLoader, TranslateService } from '@ngx-translate/core';
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.
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); }
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) {
this.translations = this.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 app development in Android or Windows.
This post has some inspiration from Yaser's blog:
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
Comments
Post a Comment