Search code examples
angularinternationalizationngrxngx-translate

ngx-translate: Separate translation file for module does not load


I am currently trying to get a translation working for an Angular module in an NgRx project. For the translation I am using a ngx-translate and the whole project is based on a template called "Angular NgRx Material Starter".

However, currently I am facing the problem that I have created a new module called "setup" that shall use a separate translation from the /assets/i18n/setup directory. To create the new module and a component in this module, I have used the Angular CLI.

Unfortunately the translation file does not load when I access the "devices" component in the "setup" module, so the page only shows the key of the string in the translation file. To show the problem, I have created a very simple example to reproduce the behavior with the base template. Since I am totally stuck here, any help is highly appreciated.

This a ZIP file containing the full project: ngx-translate problem

Any ideas?

core.module.ts: (loaded once at the beginning), the main translation is loaded:

export {
  ...
};

export function httpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(
    http,
    `${environment.i18nPrefix}/assets/i18n/`,
    '.json'
  );
}

@NgModule({
  imports: [
    ...
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: httpLoaderFactory,
        deps: [HttpClient]
      }
    })
  ],
  declarations: [],
  providers: [
    ...
  ],
  exports: [
    ...
    TranslateModule
  ]
})
export class CoreModule {
  ...
}

shared.module.ts: The "shared" module just imports and exports the TranslationModule:

@NgModule({
  imports: [
    ...
    TranslateModule,
    ...
  ],
  declarations: [
    ...
  ],
  exports: [
    ...
    TranslateModule,
    ...
  ]
})
export class SharedModule {
  ...
}

setup.module.ts: The "setup" module looks like this:

export function setupHttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(
    http,
    `${environment.i18nPrefix}/assets/i18n/setup/`,
    '.json'
  );
}

@NgModule({
  imports: [
    LazyElementsModule,
    SharedModule,
    SetupRoutingModule,
    StoreModule.forFeature(FEATURE_NAME, reducers),
    TranslateModule.forChild({
      loader: {
        provide: TranslateLoader,
        useFactory: setupHttpLoaderFactory,
        deps: [HttpClient]
      },
      isolate: true
    }),
    EffectsModule.forFeature([
    ])
  ],
  declarations: [DevicesComponent]
})
export class SetupModule {
}

devices.component.ts/.html: This is the "devices" component:

@Component({
  selector: 'anms-devices',
  templateUrl: './devices.component.html',
  styleUrls: ['./devices.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class DevicesComponent implements OnInit {

  constructor(private translate: TranslateService) { }

  ngOnInit(): void {
  }

}
<p>devices works!</p>
<h1>{{ 'setup.translation.test' | translate }}</h1>

setup-routing.module.ts: The "setup" routing module:

const routes: Routes = [
  {
    path: '',
    redirectTo: 'devices',
    pathMatch: 'full'
  },
  {
    path: 'devices',
    component: DevicesComponent,
    data: { title: 'ecue.setup.devices.title' }
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class SetupRoutingModule { }


Solution

  • Okay, I found the answer to the problem and it was quite simple (and maybe too obvious). In the newly created module I have created an effect that will set the language in the translation service for the sub-module:

    setTranslateServiceLanguage = createEffect(
    () => () =>
      this.store.pipe(
        select(selectSettingsLanguage),
        distinctUntilChanged(),
        tap((language) => this.translateService.use(language))
      ),
     { dispatch: false }
    );