Solvedangular cli [Discussion] angular-cli and i18n (ng-xi18n + ngc)

With angular's i18n working quite good now, I wanted to start a general discussion about how the angular-cli will be supposed to work with it.

According to this statement on StackOverflow from @Brocco, angular-cli will eventually make use of AOT compilation. This means, that ngc will be used, which in turn will respect xlf files for translations. For JIT builds (development builds), we could make use of a raw webpack loader, which loads a xlf file as string and provides this as translation.

Here are some questions which come to my mind and I think need to be considered in future development:

  • Currently, for a production build, everything (vendor's code + application code) is bundled into one single bundle.js file. With multiple translations, will we be supposed to have one complete bundle for each language? This seems to be a very inpractical approach. Bundling every translation into the bundle.js is not practical either, as in maybe 99% of all cases, one language is sufficient. Imagine a popular app, built with angular, which is used from people all over the world. We 1) don't want to ship a bundle.js containing all possible translations, because eventually they will blow up the bundle size. We 2) don't want to have hundrets of bundles, each for one language. Maybe it would be good to split the bundle.js into two separate bundles: 1) vendors library code, 2) NgFactory code. For each language, a dedicated ngfactory-bundle.lang-LANG.js would then be created.
  • What about libraries that support localization? For example a library which supplies some input components (like a calendar) which needs to be localized.
  • How can we reliably detect the language and load the app accordingly? At the moment, this has to occur during bootstrap, but what about detecting the browser locale or maybe the users preference (this means: much later than bootstrap time; after a database request, fetching the user settings after auth)?
  • As ng is a façade: would we need an ng i18n command to hide the possibly rather complex ng-xi18n call (regarding hiding passed parameters... a call could otherwise look like this: ./node_modules/.bin/ng-xi18n -p src/tsconfig.json ......)? Or could this be automated with some kind of watch (I don't think so, as ng-xi18n takes some time to complete, even with a small app)?
  • Where would we store the localization files? Maybe src/i18n/ would be a good place for the start. If we would like to encourage a set of localization files for each module, it should be located at src/<module-name>/i18n/ or maybe src/i18n/<module-name>/. The latter approach would be better for translator-teams, or translation-tools I think
50 Answers

✔️Accepted Answer

@rolandoldengarm are you using i18n + Angular CLI + Ahead of Time Compilation? If so, I would very much appreciate any hints on how to get this working.

For people struggling with i18n + Angular CLI: It took me a while to figure out the correct way to call ng-xi18n (although it is mentioned in this issue's description, actually):

./node_modules/.bin/ng-xi18n -p src/tsconfig.json

Or in package.json:

  ...
  "scripts": {
    "i18n": "ng-xi18n -p src/tsconfig.json"
  }
  ...

Other Answers:

I agree with @itsnotvalid. Compiling complete bundles for each language is bs. Point. End of story.

I suggest you take a look at Mozilla's L20n localization framework (MDN: Introducing L20n). The framework basically observes DOM trees using the MutationObserver API, and also uses an "industry standard" translation source file format

import "l20n/dist/bundle/web/l20n";

export function getTranslationProvider(): Promise<{}> {
  return new Promise((resolve) => {
    document.addEventListener('readystatechange', () => resolve(document.l10n.ready));
  });
}

getTranslationProvider().then(() => platformBrowserDynamic().bootstrapModule(AppModule));
@Component({
  selector: 'foo',
  template: `
    <h1 data-l10n-id="bar"></h1>
  `
})
export class FooComponent {}

locale.ja.ftl

bar = めぐみん

the configuration goes into your html

<!DOCTYPE html>
  ...
  <meta name="defaultLanguage" content="ja"/>
  <meta name="availableLanguages" content="en,fr,ja"/>

  <link rel="localization" href="public/locales/locale.{locale}.ftl"/>

where {locale} will be replaced by navigator.language automatically.

@sayedrakib please don't hijack this Github issue, furthermore this is a support question.
And angular CLI doesn't use SystemJS anymore at all.

To run ng-xi18n I just remove the imports from my scss files and add them back after the messages have been extracted It is a bit of a hassle that I have to do this, but since I'm not generating the messages every day I can live with it for now.

As for AOT + i18n: I made a PR #3098 to expose the i18nFormat, i18nFile and locale options of the angular compiler. With that branch I can build my app with AOT and have it translated.

The only downside is that you have to run the build command for every locale and you get a bundle for every command. For now I just deploy each bundle in a separate directory and redirect the user according to his browser language or a cookie from a previous visit to the correct directory/locale.

Combined with #1253 this is an irksome bug. We have to manually import colors/fonts/etc in every scss file across the app but we have to use non-standard syntax to do it if we want i18n to work.

More Issues: