core: Lazy loaded module is not adding the new custom translateLoader
I’m submitting a … (check one with “x”)
[x] bug report => check the FAQ and search github for a similar issue or PR before submitting
[ ] support request => check the FAQ and search github for a similar issue before submitting
[ ] feature request
Current behavior When a lazy loaded module is being loaded it triggers the factory for create the new TranslateHttpLoader however it is not adding the translations in the file
Expected/desired behavior Load the translations of the lazy loaded module
Reproduction of the problem I can’t provide a plnkr because but this is the code that i’m using
export function translateFactory(http: Http) {
return new TranslateHttpLoader(http, '/metro-apps/maintenances/i18n/', '.json');
}
[...]
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
useFactory: translateFactory,
deps: [Http]
}
})
Please tell us about your environment: Kubuntu 16.04
-
ngx-translate version: core=6.0.0 loader: 0.0.3
-
Angular version: 2.4.7
-
Browser: all
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 20
- Comments: 26 (8 by maintainers)
Just bumped into this as well.
I wanted my app module to fetch translations from “/assets/i18n/{lang}.json” and my lazy loaded modules to fetch from “/assets/i18n/{feature}/{lang}.json” but was unable to get this to work.
The custom loader configured by forChild(…) was ignored.
@atiertant i can’t set isolate to true because i’ll need the parent translations, i was expecting to be able to add more translations based on my current module (lazy)
I never managed to do it. So I created my own service to add translations to the root translateModule. I have a resolver for the routes accessing the lazyloaded module calling loadTranslationModule() before resolving.
@atiertant no exactly, because what about keeping the same instance? what the forChild method needs to do is only insert the new translations keeping the same instance of the TranslateService
I’ve implemented a solution for this issue which seems to work. Being relatively a newbie in Angular, I would appreciate your comments.
The solution loads the translation for lazy loaded modules (once they are loaded) and merges that into a single translation service. It supports switching languages before and after lazy loaded modules are loaded.
I’m using a service (LazyAPIService) which is used to collect data from every loaded module. It can be used to get notification anywhere when any lazy module is loaded, but I primarily use it to load translations.
Each module calls the Add function to add itself in the module constructor, with a unique name and the translation asset path to the list (modules might be loaded more then once when used as child modules of lazy loaded modules, so we do not add a module if the name already exists)
MultiTranslateHttpLoader is used as the translation loader. It loads the translation for each module added to the LazyAPIService. It uses the deepmerge “all” function to merge the loaded JSON translations into a single JSON object.
Since the loader holds the injected singleton LazyAPIService, loading other languages (which will call getTranslation) will load the language from all the added modules so far (including the lazy loaded ones).
The MultiTranslateHttpLoader marks a flag once it finishes it’s initial load on the app.module startup. This means that any module added afterwards is a lazy loaded module. So, any module added after the flag is set, also calls AddTranslation to load and merge just the translation file for the added module (for all languages already loaded. I could not find a way to not load the module translation for languages that are NOT the current, but already loaded, but still make them load if that language is selected later on. Let me know if you solve that. I also tried to reset the other languages, but that did not trigger loading them again when used)
Since LazyAPIService is constructed before the TranslationService, I use the Injector service to manually retrieve the TranslateService when needed in the AddTranslation.
Don’t forget to add the assests in angular.json: “src/assets”, { // add this for every module that has translation “glob”: “**/*”, “input”: “./src/app/packages/admin/assets/”, “output”: “./assets/” }
I wrote a article about how to have 1 json file per lazy loaded module without having to write a new Custom Loader etc… it’s quiet simple, only the documentation is not clear in fact: https://medium.com/@TuiZ/how-to-split-your-i18n-file-per-lazy-loaded-module-with-ngx-translate-3caef57a738f
I worked around this issue with a custom MissingTranslationHandler as the correct currentLoader is set on the lazily loaded module translate service.
In my lazy loaded module
and the common missing translation handler: