How to split your i18n file per lazy loaded module with ngx-translate?
I am currently rewriting this article with the latest version of Angular and answers to all comments. Meanwhile check this repository for a working example using Angular 8: https://github.com/Tuizi/i18n-split-example
tl;dr Check the summary section at the end
After a few months of working on my Angular app, my i18n files have more than 800 lines each, almost impossible to maintains and will become more and more difficult with time. The best solution to this problem would be to have one i18n file per module (in fact 2, I have to support French and English).
Environment:
@angular/core@4.4.3
@ngx-translate/core@8.0.0
@ngx-translate/http-loader@2.0.0
The principle
To be able to load a json file along with a lazy loaded module you have to use the property isolate
as the documentation suggests. Isolating your TranslateModule will allow you to create a new instance of TranslateService, and, with it, a new HttpLoader instance with a different path to i18n files.
Now, the biggest difference you have to keep in mind is that when you change the language you have to change it for all instanceof TranslateService. This will tell the service fetch the json file of each lazy loaded module for the language you want.
In my code, I use Redux (ngrx-platform) to communicate the language change between all my modules.
Multiple requests?
Note: You have to keep that in mind: this will significantly increase the amount of request made to your server! if you have 10 modules, it’s 10 requests only for translations!
But in 2017, that’s not a problem anymore…
- Use Http 2
- Use sw-precache from Google to generate a manifest file
- Use Idle-Preload as lazy loading strategy
- Use server side rendering if you are still not happy
The impact on your performance should will be insignificant.
Folder structure
My assets folder for i18n files looks like this:
assets/
└── i18n/
├── app/
│ ├── en.json
│ └── fr.json
└── home/
├── en.json
└── fr.json
app contains core i18n translations, like: menu, header, footer, and other folders like home, which contain i18n translations for lazy loaded module.
Code
AppModule
First prepare your AppModule to call forRoot()
of TranslateModule and to load your core i18n files app/(en|fr).json
AppComponent
AppComponent is your root component, where the user can set the language by clicking on a button in the header. Then you dispatch the language information to your store to let your other modules know that the language has changed and they must change the language of their TranslateService instance.
HomeModule (lazy loaded module)
In this module, declare a new instance of TranslateHttpLoader to get your i18n files home/(en|fr).json
HomeComponent
The only thing left is to call use()
of its TranslateService instance, each time the language changes, in all your lazy loaded modules’ components by subscribing to the current language property of your store.
Summary
That’s it! You are now setup to split your big i18n file into more smaller one that will help you to easily maintain your translations file.
To summarize:
- In your AppModule call
forRoot()
- In all your lazy loaded modules call
forChild()
withisolated: true
and create a new instance of TranslateHttpLoader with the path to the i18n files for the module - In all your lazy loaded module’s main component call
use()
of TranslateService each time the user changes the language