core
core copied to clipboard
translate.use(langCode) is not working in some cases
Current behavior
In app.component.ts
I have set up the TranslateService
as follows:
translate.addLangs(['en', 'bn']);
translate.use('en');
translate.onLangChange.subscribe((change) => {
console.log('langChange', change);
})
In another module, I'm doing this to change the current language,
this.translate.use(langCode);
When I change the language to bn
, it does not work.
BUT, if I write translate.use('bn');
in app.component.ts
, language change starts working.
What I've noticed is that, when I set en
as the language in app.component.ts
the onLangChange
prints an empty object as the translations
property.
// in onLangChange callback
Object { lang: "bn", translations: {} }
Expected behavior
Changing language should work regardless of what language was set during initialization
How do you think that we should fix this?
Minimal reproduction of the problem with instructions
Environment
ngx-translate version: 13.0.0
Angular version: 10.1.5
Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ x] Firefox version 81
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
For Tooling issues:
- Node version: 12.16
- Platform: Windows
Others:
This workaround works for me (angular 11 et ionic 5) :
I force to load all possible language in app.components :
this.translate.addLangs(['fr', 'en', 'es', 'de'])
this.translate.use('en') this.translate.use('es') this.translate.use('de') this.translate.use('fr')
then in other component, i can call again this.translate.use('xxx')
This issue was not present in previous version for angular 8
Same problem for me, the workaround of @sguilly worked. But this wasn't a problem previously.
Hi guys! I also noticed this "issue". After a few attempts, I got it by using same loader config in forChild
as in forRoot
:
app.module.ts
(can be core.module
or whatever):
export const HttpLoaderFactory = (httpClient: HttpClient) => {
return new ...
};
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
...,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient],
},
}),
],
providers: [
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
],
bootstrap: [AppComponent],
})
export class AppModule {}
app.component.ts
:
export class AppComponent {
constructor(private readonly translateService: TranslateService) {
this.setDefaultLang();
}
private setDefaultLang() {
this.translateService.addLangs(['en', 'fr', 'es-ES', 'es-419']); // array of available langs
this.translateService.setDefaultLang('es-ES');
}
}
lang-test-module.ts
(the module from where we want to change lang):
import { HttpClient } from '@angular/common/http';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { HttpLoaderFactory } from 'src/app/app.module.ts';
...
@NgModule({
imports: [
...,
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient],
},
}),
],
declarations: [LangTestPage],
})
export class LangTestModule {}
I don't know if it is a good solution...
@joseph-navant : your tip don't work in my code
@joseph-navant : your tip don't work in my code
Can I help you?
- I have the
TranslateModule.forRoot()
(with loader) in mycore.module
(core.module
is imported inapp.module
) - My
HttpLoaderFactory
is usingMultiTranslateHttpLoader
(https://github.com/denniske/ngx-translate-multi-http-loader) - I added available langs and default lang in
app.component-ts
(as u can see in the code above) - I have the
TranslateModule.forChild()
(with loader) in the module from I want to change lang (this module is lazy loaded) - The
HttpLoaderFactory
i'm using in this module is imported from mycore.module
(can beapp.module
or whatever) - In
LangTestPage
I get available langs and render it inradio-buttons
- When I click in one of them, it calls
use()
fromtranslateService
and voilá
lang-test.page.ts
import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-lang-test',
templateUrl: './lang-test.page.html',
styleUrls: ['./lang-test.page.scss'],
})
export class LangTestPage implements OnInit {
langs: string[];
selectedLang: string;
constructor(private readonly translateService: TranslateService) {}
ngOnInit() {
this.langs = this.translateService.getLangs();
this.selectedLang =
this.translateService.currentLang || this.translateService.defaultLang;
}
onLanguageChange() {
this.translateService.use(this.selectedLang);
}
}
lang-test.page.html
(using ionic framework)
<ion-radio-group [(ngModel)]="selectedLang" (ionChange)="onLanguageChange()">
<ng-container *ngFor="let lang of langs">
<ion-item mode="md">
<ion-radio [value]="lang"></ion-radio>
<span>{{ 'SETTINGS.LANGUAGE.' + lang.toUpperCase() | translate }}</span>
</ion-item>
</ng-container>
</ion-radio-group>
When this code is rendered, every ion-radio
value has the lang code I defined in app.component.ts
. Something like this:
...
<ion-radio value="en"></ion-radio>
...
<ion-radio value="fr"></ion-radio>
...
<ion-radio value="es-ES"></ion-radio>
...
<ion-radio value="es-419"></ion-radio>
...
So, after all, the use
from translateService
is receiving the lang code. For example: this.translateService.use('en')
Thanks @joseph-navant, your solution worked for me.
This workaround works for me (angular 11 et ionic 5) :
I force to load all possible language in app.components :
this.translate.addLangs(['fr', 'en', 'es', 'de'])
this.translate.use('en') this.translate.use('es') this.translate.use('de') this.translate.use('fr')
then in other component, i can call again this.translate.use('xxx')
This issue was not present in previous version for angular 8
This solution worked for me, thanks @sguilly , although I think that this solution is very dirty
If you use TranslateModule.forChild()
, you get the default FakeTranslateLoader
per here: https://github.com/ngx-translate/core/blob/ce3c70c76577550718417912516136da51922c42/projects/ngx-translate/core/src/public_api.ts#L72)
So for me, I changed my non-root modules to just be TranslateModule
and the languages started to load as expected (same behavior as before).
@NgModule({
imports: [
...
TranslateModule,
...
]
}
I just came across this issue myself.
In my case, my language is set elsewhere by some other javascript so doing translateService.use
inside the app module constructor is not an option because the language is not set yet.
Instead I want to do it inside the AppInitializer where my code loads the language from the backend.
Doing translate.use
correctly downloads the language (I can see it in network) but all translations appear blank.
Not sure what to do, it feels very much like a bug.
Ah, it works on some reloads. So I think perhaps the bug is that you cannot set a new use
language before it has loaded the default language?
I am not sure about where, but it is definately a race condition problem somehow.
Ok I found the issue.
For some unknown reason, if you try to load angular locale data (or do any import maybe?) and at the same time try to do a .use
then the use
will only work (properly show the translations instead of blanks) IF the use
completes before the loading of the import is complete.
To fix it, I had to write this stupid code in order to force the angular locale loading to happen only after use was complete.
injector
.get(TranslateService)
.use(abp.localization.currentLanguage.name)
.subscribe(
() =>
loadAngularLocale(angularLocale, resolve, result, reject),
(err) => {
loadAngularLocale(angularLocale, resolve, result, reject);
console.log(err);
}
);
@ocombe Would love to hear your input on this if you have a minute