I'm submitting a ... (check one with "x")
[ ] bug report => check the FAQ and search github for a similar issue or PR before submitting
[x] support request => check the FAQ and search github for a similar issue before submitting
[ ] feature request
Expected/desired behavior
Our application is very large and we don't want the user to download all translations when they may only use a subset of the available modules. In some places the user must also be able to switch languages. Is there a way to load only the translations for the modules the user has access to? I've seen #22, but it doesn't seem to have arrived at a final solution.
@nchutchind / @ollwenjones, I would love to hear about either of your solutions if you ever arrived at one?
What is the motivation / use case for changing the behavior?
To prevent users from downloading resources they don't require and allow dynamically switching languages at runtime
Please tell us about your environment:
[email protected] generated so no access to webpack config etc
Hello, this will be possible in the next release 6.0.0 (there's a beta available) for lazy loaded modules and components using the "providers" property (in both cases a new injector is created that allows to create a new instance of the service).
You can try the beta 1 if you want.
Great, i'll take a look. Thanks!
@ocombe i'm already using the beta-1 but seems that the module is not making the ajax request for load the module translations
@uberspeck could you achieve it ? if so, provide link so get know how to use it.
@AlwaysAbhl001, i've created a simple service to load translations for each module/component...
/app/shared/services/translation-loader.service.ts
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
export interface ILocale {
lang: string;
data: Object;
}
@Injectable()
export class TranslationLoaderService {
constructor(
private translate: TranslateService
) { }
public loadTranslations(...args: ILocale[]): void {
const locales = [...args];
locales.forEach( (locale) => {
/*
use setTranslation() with the third argument set to true to append
translations instead of replacing them
*/
this.translate.setTranslation(locale.lang, locale.data, true);
});
}
}
...then create the language files. You could use a different shape here if you wish.
/app/app.en.ts
export const locale = {
"lang": "en",
"data": {
"app": { // <= namespace for module/component translations
"title": "My Big Title",
"archived": "Archived",
"inactive": "Inactive",
"delete":"Delete",
...
}
}
}
}
...I then configure translation in the root module and load the root translation files...
/app/app.module.ts
...
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { TranslationLoaderService } from './shared/services/translation-loader.service';
/* Import language files in each module/component as needed */
import { locale as english } from './app.en';
import { locale as spanish } from './app.es';
@NgMoudule({
...,
/* use forRoot() in the main app module only */
imports: [TranslateModule.forRoot(), ...],
...
});
export class AppModule {
constructor(
private translate: TranslateService,
private translationLoader: TranslationLoaderService
) {
/* Config translation in root module */
this.translate.addLangs(['en', 'es']);
this.translate.setDefaultLang('en');
this.translate.use('en');
/* Load translations in each module/component as needed */
this.translationLoader.loadTranslations(english, spanish);
}
}
...and set up translation in each feature module/component as necessary...
/app/feature-module/feature.module.ts
...
import { TranslateModule } from '@ngx-translate/core';
import { TranslationLoaderService } from '../shared/services/translation-loader.service';
import { locale as english } from './feature.module.en';
import { locale as spanish } from './feature.module.es';
@NgModule({
imports: [TranslateModule, ...],
...
})
export class FeatureModule {
constructor(
private translationLoader: TranslationLoaderService
) {
this.translationLoader.loadTranslations(english, spanish);
}
}
...and finally, in a component...
<h1 translate>app.title</h1>
I'm sure this solution isn't perfect, but it works for us. If you come up with improvements I'd love to hear them! Something to watch out for. You can't rely on translations from lazy loaded sibling or child modules to be present so make sure any translations needed across lazy loaded modules are available to a parent of those modules. Hope that helps!
@uberspeck i did something similar but using require on each lazy loaded module i have this
export class UsersModule {
constructor(translate: TranslateService) {
let lang = translate.getBrowserLang();
let i18n = require(`./i18n/${lang}.json`);
translate.setTranslation(lang, i18n, true);
}
}
BTW for do that i did a PR for allow deep merge of objects
I like your solution @jiberrocal, i'll have to play with that. Thx for sharing!
You're welcome :)
I am facing some issue with setTranslation. Can you please help me in this #627. Thanks in advance
@ocombe You said that it's possible to use the 'providers' property to create a new instance of the TranslateService per module. Do you have an example/documentation on how to do this?
@jlberrocal, @uberspeck do I understand correctly, that main difference in examples is with what typo of storage one uses. In first example translations are in TS file and that requires additional moves, in other it is in plat JSON file? Or am I missing something?
@jeserkin in the example i provided is just a JSON file, but i use require in order to force webpack to include it as part of the bundle otherwise you'll need to create a loader or a rule for preserve the json files and then request them with lazy loading
Is it possible with @uberspeck example to use json as storage for translations as well?
im facing problem
i have multiple modules like
Main App module
Shared Module (Translation inside this module as per as library instructed https://github.com/ngx-translate/core)
User Module (language is accesible not giving error if i remove shared moidule then it is geving translation error but not converting)
Pls help
Example: https://stackblitz.com/edit/angular-w2afh1
If you click home login or register and change the language it will be change but not in profile page
Most helpful comment
@AlwaysAbhl001, i've created a simple service to load translations for each module/component...
/app/shared/services/translation-loader.service.ts...then create the language files. You could use a different shape here if you wish.
/app/app.en.ts...I then configure translation in the root module and load the root translation files...
/app/app.module.ts...and set up translation in each feature module/component as necessary...
/app/feature-module/feature.module.ts...and finally, in a component...
I'm sure this solution isn't perfect, but it works for us. If you come up with improvements I'd love to hear them! Something to watch out for. You can't rely on translations from lazy loaded sibling or child modules to be present so make sure any translations needed across lazy loaded modules are available to a parent of those modules. Hope that helps!