1

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.

Andrew Hill
  • 2,165
  • 1
  • 26
  • 39
indra257
  • 66
  • 3
  • 24
  • 50
  • 2
    For performance it is usually better to create 1 bundle set per language if you are using the built in i18n for translation. Alternatively you can use [@ngx-translate](https://github.com/ngx-translate/core) which dynamically can switch the language without even needing to reload the window. – Igor Aug 29 '19 at 20:38
  • We need to create only 1 build package. we can't create one for each language. I have seen ngx-translate but I am wondering is there a angular built in way to do it – indra257 Aug 29 '19 at 20:41
  • You can create 1 build package that contains bundles for each language. – Martin Aug 29 '19 at 21:00
  • @Martin I am not sure how it is possible. Also I am using nginx for the routing so I am not sure how to create bundles for each language and load the required bundles based on the language. – indra257 Aug 30 '19 at 14:32
  • 1
    `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 with out making aot false.` ← You must choose either aot with different application files per language *or* jit which can bootstrap the locale at run time. There is no hybrid approach if using the built in i18n translations. – Igor Sep 06 '19 at 20:10
  • 1
    Personally I prefer to use [`@ngx-translate`](https://github.com/ngx-translate/core) especially if you have multiple translations or the number of languages will grow. This will allow you to compile using AOT and supports dynamic replacement of texts (ie. translations) in your component. – Igor Sep 06 '19 at 20:12
  • 1
    The reason no one had provided an answer up until this point has nothing to do with motivation (ie. adding a bounty), the question is not answerable because the solution you desire does not exist. You have to choose between dynamic translation loading in the browser and run angular as JIT, create bundles per translation and run as AOT, or using a library like [`@ngx-translate`](https://github.com/ngx-translate/core). – Igor Sep 06 '19 at 20:15
  • @Igor Will there be a performance problem because of using --aot=false --prod --build-optimizer=false – indra257 Sep 06 '19 at 20:26
  • AOT will offer more compact builds (less download time over the wire) and are also optimized so yes, an aot build will load faster than a jit build. If they run any faster once loaded is another question and here you *might* not really see any difference but that depends on what the app actually does. – Igor Sep 06 '19 at 20:48
  • See also [Angular 2 : Just-in-Time (JiT) vs Ahead-of-Time (AoT) compilation](https://stackoverflow.com/q/41450226/1260204) – Igor Sep 06 '19 at 20:52
  • take a look to Transloco from Netanel Basal https://netbasal.com/good-things-come-to-those-who-wait-whats-new-in-transloco-5dadf886b485 – Eliseo Sep 09 '19 at 09:06
  • you can use xliffmerge and use this library [@ngx-i18nsupport](https://www.npmjs.com/package/ngx-i18nsupport) – Savaj Patel Sep 10 '19 at 07:48
  • @indra257 - have you had a chance to read over my answer yet? I hope it is satisfactory. – Igor Sep 12 '19 at 10:47
  • @Igor yes. I have decided to use AOT as the performance got reduced a lot after using JIT. So I am planning to create 3 bundles based on the language. We are using nginx in our application and wondering is there a way to redirect to the package based on the browser language. – indra257 Oct 15 '19 at 00:39

2 Answers2

7

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.

Igor
  • 60,821
  • 10
  • 100
  • 175
  • 1
    Or just wait for Ivy - they've suggested that we'll be able to dynamically internationalise our apps at runtime, with AOT. – hevans900 Sep 11 '19 at 09:40
  • 1
    @ngx-translate is the most preferable for me also. It supports adding or removing at run-time also without re-deployment. – khush Sep 13 '19 at 13:31
  • I agree with @khush, ngx-translate is a good choice. I had to use it on a project and it's pretty easy to use. – Hadrien Delphin Sep 13 '19 at 14:19
1

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.

Sarang
  • 2,143
  • 24
  • 21