1

Let's make example for ng2-translate plugin.

I have root AppModule, and children TopPanelModule and PagesModule.


I configure ng2-translate for AppModule.

@NgModule({
  imports: [TranslateModule.forRoot({
    provide: TranslateLoader,
    useFactory: (http: Http) => new TranslateStaticLoader(http, '/assets/i18n', '.json'),
    deps: [Http]
  })],
  exports: []
})
export class AppModule {
  constructor(translateService: TranslateService) {    
  }
}

In AppComponent I set languages and basic configuration for TranslateModule.

@Component(...)
export class AppComponent {
  constructor(translateService: TranslateService) {
    translateService.addLangs(["en", "fr"]);
    translateService.setDefaultLang('fr');

    const browserLang = 'fr';
    translateService.use(browserLang.match(/en|fr/) ? browserLang : 'en');    
  }
}

And then I'm trying to use TranslateModule in children modules components - TopPanelComponent, PagesComponent. It does'n work. Pipe not exists error, no translate etc..


For resolving this problem, I create a separate module MyTranslateModule, configure TranslateModule on it, and use this module in my PagesModule and TopPanelModule.

@NgModule({
  imports: [TranslateModule.forRoot({
    provide: TranslateLoader,
    useFactory: (http: Http) => new TranslateStaticLoader(http, '/assets/i18n', '.json'),
    deps: [Http]
  })],
  exports: [TranslateModule]
})
export class MyTranslateModule {
  constructor(translateService: TranslateService) {
    translateService.addLangs(["en", "fr"]);
    translateService.setDefaultLang('fr');

    const browserLang = 'fr';
    translateService.use(browserLang.match(/en|fr/) ? browserLang : 'en');

    console.log('AdminTrModule: calling');
  }
}

and

@NgModule({
  imports: [MyTranslateModule]
})
export class PagesModule{

}

@NgModule({
  imports: [MyTranslateModule]
})
export class TopPanelModule{

}

This is important part. It works! But I think it creates a two instances of TranslateModule, so, when I change transalte langauge by calling in TopComponent translateService.use('en'), it change language in TopPanelModule, but not in PagesModule.

Mistalis
  • 17,793
  • 13
  • 73
  • 97
Grigor Aleksanyan
  • 540
  • 1
  • 6
  • 19
  • Are you using lazy loading? – Günter Zöchbauer Dec 20 '16 at 13:55
  • @GünterZöchbauer, if i know right, angular2 use lazy loading by default. – Grigor Aleksanyan Dec 20 '16 at 14:19
  • No, lazy loading is used when you use `loadChildren` in routes. – Günter Zöchbauer Dec 20 '16 at 14:21
  • @GünterZöchbauer, Yes, I'm using lazy loading – Grigor Aleksanyan Dec 20 '16 at 15:04
  • 2
    That's what causes multiple instance to be generated. By default all providers from all imported modules are registered in the applications root scope, but lazy loaded modules get their own root scope (which is a child scope of the application root scope). When a component or service from a lazy loaded module injects some service and the lazy loaded module has it register an instance from there is injected, only if the lazy loaded module doesn't have a provider DI checks with the application root scope. All non-lazy loaded modules that request the same dependency get one from the app root – Günter Zöchbauer Dec 20 '16 at 15:08
  • 1
    Check https://angular.io/docs/ts/latest/guide/ngmodule.html. I never dived into that topic about how to ensure services of lazy loaded modules get registered at the application root scope but I guess it is possible. Also check the link at the bottom (https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html) – Günter Zöchbauer Dec 20 '16 at 15:09
  • https://github.com/ngx-translate/core/issues/209 – Radu Dumbrăveanu Jul 13 '17 at 06:50

1 Answers1

1

You need to define a forRoot function in module 'MyTranslateModule'

export class MyTranslateModule {

static forRoot(): ModuleWithProviders {
    return {
      ngModule: MyTranslateModule ,
      providers: [TranslateService,TRANSLATION_PROVIDERS]
    };
  }

}

then import MyTranslateModule in appModule as following

@NgModule({
  bootstrap: [App],
  declarations: [
    App
  ],
  imports: [ // import Angular's modules
    BrowserModule,
    MyTranslateModule.forRoot(),
    PagesModule,
    TopPanelModule
  ],
  providers: [ // expose our Services and Providers into Angular's dependency ]
})

in this case translate service will be created as singleton "one instance along the application"

user3170856
  • 83
  • 1
  • 7