Ngx translate with shared/lazy loading modules

12,391

I solved this by doing the following:

  1. Create a SharedModule, with below code

SharedModule

export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    TranslateModule.forChild({
      loader: {
      provide: TranslateLoader,
      useFactory: HttpLoaderFactory,
      deps: [HttpClient]
    },
    isolate: false
}),
  ],
  exports: [TranslateModule],
})
export class SharedModule {

  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [ShoppingCartService, AccountService]
    }
  }
}

So this makes sure that for every module that imports SharedModule, TranslateModule will use the same configuration. Make sure to export it. The forRoot() also solved making sure that ShoppingCartService and AccountService are only one instance and not every lazy-module creating a separate service.

  1. Change AppModule:

AppModule

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    HttpClientModule,
    BrowserModule,
    AppRoutingModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      },
      isolate : false
    }),
    SharedModule.forRoot(),
    ContrySelectorModule,
    
  ],
  providers: [    ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Since AppModule is your main entry point, do the forRoot() call here to TranslateModule and the SharedModule.

  1. Any lazy loaded module just has to import SharedModule without any method calls. Also CountrySelectorModule in my example has to just import SharedModule and nothing else.
Share:
12,391

Related videos on Youtube

CularBytes
Author by

CularBytes

Nothing to see here...

Updated on June 04, 2022

Comments

  • CularBytes
    CularBytes almost 2 years

    Probably one of the most common questions, while the documentation and some other questions I found try to clear up things for me, yet I am still not sure how to fix this.

    So this is my structure:

    enter image description here

    • App module is of course the main module that is bootstrapped
    • Countryselector module: takes care of loading the default country(based on IP) and takes care of deciding what language to use based on the browser. It basically is the core functionality of deciding what country/language is used + it contains a dropdown for a user to change the country/language.
    • Checkout module, selection module, payment module are all lazy-loaded with routing.

    AppModule

    export function HttpLoaderFactory(http: HttpClient) {
      return new TranslateHttpLoader(http);
    }
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        HttpClientModule,
        BrowserModule,
        AppRoutingModule,
        ContrySelectorModule,
        TranslateModule.forRoot({
          loader: {
            provide: TranslateLoader,
            useFactory: HttpLoaderFactory,
            deps: [HttpClient]
          }
        })
      ],
      export class AppModule { }
    

    CountrySelectorModule

    @NgModule({
      declarations: [CountryselectorComponent],
      imports: [
        CommonModule,
        TranslateModule.forRoot({
          loader: {
            provide: TranslateLoader,
            useFactory: HttpLoaderFactory,
            deps: [HttpClient]
          }
        })
      ],
      exports: [
        CountryselectorComponent
      ]
    })
    export class ContrySelectorModule { }
    

    Selection module:

    @NgModule({
      declarations: [SelectionComponent],
      imports: [
        CommonModule,
        SelectionRoutingModule,
        UspblockModule,
        TranslateModule.forChild({//or forRoot, no idea how to configure this
          loader: {
            provide: TranslateLoader,
            useFactory: HttpLoaderFactory,
            deps: [HttpClient]
          }})
      ],
    })
    export class SelectionModule { }
    

    Now the problem is that I don't want to do the language configuration again within the lazy-loaded modules, because the country selector module already takes care of this. I am not sure now how to correctly configure the lazy-loaded modules (and actually not sure if countrySelectorModule is done correctly). Using the standard github documentation I was not able to pull this off. I've tried messing around with .forChild() but no luck so far.

    Do I need a share module? Do I need to import countrySelectorModule everywhere (not preferred)? Custom loader? t.b.h. I have no idea and the documentation is a bit short for more advanced scenarios.

  • Develobba
    Develobba about 4 years
    Your "ContrySelectorModule" is not lazy loaded. You import your module in app.module, so there is no lazy loading feature possible. The solution for the TranslateModule is not working, if you have REAL lazy loading modules.
  • CularBytes
    CularBytes about 4 years
    CountrySelectorModule is part of the main page and therefor imported in the AppModule. I'm quite sure that this setup works for lazy-loaded modules, true that the examples is perhaps a bit off.
  • Develobba
    Develobba about 4 years
    Got a other solution. TranslateModule.forRoot in app.module, the shared module is only imported in the lazy loaded modules and shared.module need TranslateModule.forChild({extend:true})
  • CularBytes
    CularBytes about 4 years
    Not sure what extended does but the rest is similar to my code.
  • M. Al Jumaily
    M. Al Jumaily almost 2 years
    Using Angular 13+: Instead of doing static forRoot(): ModuleWithProviders { ... }, use the following: static forRoot(): ModuleWithProviders<AppModule> { ... }
  • Mr. Learner
    Mr. Learner almost 2 years
    @CularBytes could you pls create your implementation in stackblitz? am also working on same task, it would help me if provide your stackblitz implementation . Thanks :)