Angular: Localization in to multiple languages

7.5k Views Asked by At

I have an Angular 6 application that has already been built. Now we are planning to support it in to multiple languages. I am able to create multiple xlf files and get the target strings replaced with the language. My locale file has three files like messages.en.xlf, messages.es.xlf and messages.fr.xlf each for English, Spanish and French.

Based on the language of the browser, the app should pick up the required language file. If the browser is set in French, it should automatically pickup messages.fr.xlf and display the app in French.

Initially my build command will be ng build --prod --output-hashing all, but with the localization changes, I need to use --aot=false and --build-optimizer=false and my app's performance and load time became worse.

ng build  --prod --output-hashing all --aot=false --build-optimizer=false

My main.ts file is like below:

declare const require;
var userLang;

window.addEventListener('languagechange', function () {
  // callLangugae();
  location.reload(true);
});

function callLangugae() {
  userLang = navigator.language;
  userLang = userLang.split("-")[0];
  switch (userLang) {
    case 'es': {
      registerLocaleData(localeEs);
      break;
    }
    case 'fr': {
      registerLocaleData(localeFr);
      break;
    }
    case 'en': {
      registerLocaleData(localeEn);
      break;
    }
    default: {
      userLang = 'en';
      registerLocaleData(localeEn);
      break;
    }
  }

}

callLangugae();

const translations = require(`raw-loader!./locale/messages.${userLang}.xlf`);

platformBrowserDynamic().bootstrapModule(AppModule, {
  providers: [
    { provide: TRANSLATIONS, useValue: translations },
    { provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }
  ]
})
  .catch(err => console.log(err));

I am wondering is there a proper way to load the xlf file based on the language of the browser without the performance problems and without making AOT false.

2

There are 2 best solutions below

3
On

You have a 3 main options of how you can go about using translations in your application.

AoT Build per Language

You can use the angular built in i18n functionality and create an AoT build per language. You then need to ensure that the correct language dependent build files are loaded at run time when the web page loads. The general practice is to have each language dependent build in their own folder which is named with the ISO code of the locale/language. You can then point to this folder and then the contained index.html on page navigation (or load the contained .js files in whatever host page you are using). Depending on the number of locales you want to support this cause your build time to increase significantly. On the positive side you get all the runtime performance benifits of AoT.

One JiT build and resource file per language

You can use the angular built in i18n functionality and create a single JiT build and point to the appropriate translation file at run time. Your build time will be much faster (when you publish your app) but the clients will take a performance hit when they load the app and possibly also during execution of the app. The positive is that this structure could be easier to maintain when you are dealing with multiple languages especially if the number of languages is expected to grow.

External tool (like @ngx-translate)

This is my preferred method when dealing with a growing number of languages that need to be supported. This external tool allows you to use a single AoT build. You then define the translation keys in your templates and configure the tool to retrieve the translations from some (presumably) external source (like a server or file on disk). There are probably others out there as well but I am not going to include them in this answer.


A note about JiT vs AoT. There is already a fairly well written answer that compares JiT build vs an AoT build that can be found on StackOverflow: Angular 2 : Just-in-Time (JiT) vs Ahead-of-Time (AoT) compilation. I will not re-summarize those answers here.

0
On

With Angular 9 and Ivy, run-time, single build translations are coming closer to reality. Ivy already has capabilities to load translations at run-time as explained here:

https://angular.fun/post/2020-01-11-angular-ivy-localize/

and also here:

https://jaxenter.com/angular-9-ivy-167934.html

However, it does not seem to be production ready as external tools are needed to extract the strings.

Considering how painful it is to create one build one language, I am tempted to try this new approach.