Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ng2-translate not working in lazy-loaded module

I'm using ng2-translate for language handling in an Angular 2 RC5 app I'm creating. The app has two feature modules, one lazy loaded and one eager loaded. TranslateModule is made available through a shared module. The problem is that the translate pipe works fine in the eager-loaded module but not the lazy-loaded one. To verify it has to do with the loading method I converted both to eager-loading and everything worked fine.

A plunk that demonstrates the issue can be found here: Plunker The significant code is below as well.

The initial page is the eager-loaded one, hence why the strings look fine. Click Login and it will go to the lazy-loaded one where all strings are upper-case, i.e. not translated.

Any help would be appreciated.

app.module:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { TranslateModule } from 'ng2-translate/ng2-translate';
import { AppComponent }  from './app.component';
import { WelcomeModule } from './welcome/welcome.module';
import { routing }       from './app.routing';

@NgModule({
  imports: [ BrowserModule, WelcomeModule, TranslateModule.forRoot(), routing ],
  declarations: [ AppComponent ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

app.routing:

import { Routes, RouterModule } from '@angular/router';

export const routes: Routes = [
  { path: '', redirectTo: 'welcome', pathMatch: 'full'},
  { path: 'backend', loadChildren: 'app/backend/backend.module' }
];

export const routing = RouterModule.forRoot(routes);

app.component:

import { Component } from '@angular/core';
import { TranslateService } from 'ng2-translate/ng2-translate';

@Component({
    selector: 'my-app',
    template: `
        <router-outlet></router-outlet>
    `
})
export class AppComponent { 
    constructor(translate: TranslateService) {
        // this language will be used as a fallback when a translation isn't found in the current language
        translate.setDefaultLang('en');

        // the lang to use, if the lang isn't available, it will use the current loader to get them
        translate.use('en');
    }
}

shared.module:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpModule } from '@angular/http';
import { TranslateModule } from 'ng2-translate/ng2-translate';

@NgModule({
    imports: [
        CommonModule,
        HttpModule,
        TranslateModule.forRoot()
    ],
    exports: [
        CommonModule,
        TranslateModule
    ],

})
export class SharedModule {}

welcome.module (eager loaded)

import { NgModule }      from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { WelcomeComponent }  from './welcome.component';
import { routing } from './welcome.routing';

@NgModule({
  imports: [ SharedModule, routing ],
  declarations: [ WelcomeComponent ]
})
export class WelcomeModule { }

welcome.component:

import { Component } from '@angular/core';

@Component({
    template: `
        <h2>{{ 'PLEASELOGIN' | translate }}</h2>
        <nav><a routerLink="/backend">{{ 'LOGIN' | translate }}</a></nav>
    `
})
export class WelcomeComponent { }

welcome.routing

import { RouterModule }  from '@angular/router';

import { WelcomeComponent } from './welcome.component';

export const routing = RouterModule.forChild([
    { path: 'welcome', component: WelcomeComponent}
]);

backend.module (lazy loaded)

import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { BackendComponent } from './backend.component';
import { routing } from './backend.routing';

@NgModule({
    imports: [ SharedModule, routing ],
    declarations: [ BackendComponent ]
})
export default class BackendModule { }

backend.component:

import { Component } from '@angular/core';

@Component({
    template: `
        <h2>{{ 'WELCOME' | translate }}</h2>
        <nav><a routerLink="/welcome">{{ 'LOGOUT' | translate }}</a></nav>
    `
})
export class BackendComponent { }

backend.routing

import { Routes, RouterModule }  from '@angular/router';
import { BackendComponent }    from './backend.component';

const routes: Routes = [
    { path: '', component: BackendComponent }
];

export const routing = RouterModule.forChild(routes);

en.json

{
    "LOGIN": "Login",
    "LOGOUT": "Logout",
    "WELCOME": "Welcome!",
    "PLEASELOGIN": "Please Login"
}
like image 285
Jason Avatar asked Aug 17 '16 02:08

Jason


People also ask

How do you split your i18n file per lazy loaded module with NGX-translate?

In your AppModule call forRoot() In all your lazy loaded modules call forChild() with isolated: 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.

How do you Lazyload a component?

To lazy load the component, we will use the import() method inside an async/await function. The above function first clears the container; otherwise, on every click of the button, the new instance of GreetComponent would be added in the container.

What is lazy loading of modules?

Lazy loading is the process of loading components, modules, or other assets of a website as they're required. Since Angular creates a SPA (Single Page Application), all of its components are loaded at once. This means that a lot of unnecessary libraries or modules might be loaded as well.


2 Answers

I had the same problem. Adding TranslateLoader and TranslateService to the forRoot method solved the problem.

    import {TranslateModule, TranslateService, TranslateLoader, TranslateStaticLoader} from 'ng2-translate/ng2-translate';
    @NgModule({
        imports: [..,TranslateModule],
        declarations: [..],
        exports: [ .., TranslateModule]
    })
    export class SharedModule {

    static forRoot(): ModuleWithProviders {

       function translateLoader(http: Http) {
            return new TranslateStaticLoader(http, 'i18n', '.json');
        }
        return {
            ngModule: SharedModule,
            providers: [UserService, ItemService, {
                provide: TranslateLoader,
                useFactory: translateLoader,
                deps: [Http]
            },
                TranslateService],
        };
    }
    }
like image 57
Marcel Hoekstra Avatar answered Sep 25 '22 23:09

Marcel Hoekstra


Though the accepted answer pointed me in the right direction, the translator was not working in the lazy loaded module. In other modules it was working.

I had to inject the TranslatorService again in the lazy loaded module's main component and init the language settings like I've done in app.component.ts

export class MainComponentOfLazyLoadedModule implements OnInit {

    constructor(private translate: TranslateService) {
        Language.currentLang = "en";
        translate.addLangs(["en", "sp"]);
        translate.setDefaultLang(Language.currentLang);
        translate.use(Language.currentLang);
    }

    ngOnInit() {

    }

}
like image 32
Drunken Daddy Avatar answered Sep 21 '22 23:09

Drunken Daddy