Search code examples
angularngx-translateangular-standalone-components

Use @ngx-translate in standalone components in Angular 17


I use standalone components in Angular 17. When I used module architecture, I didn't have this problem. I added it to import in AppModule and it works good.

imports: [
 TranslateModule.forRoot(loader)
],

But if I add TranslateModule.forRoot(loader) in standalone components

@Component({
 selector: 'app-main-work-space',
 standalone: true,
 imports: [
  // @ts-ignore
  TranslateModule.forRoot(loader)
 ],
 templateUrl: './main-work-space.component.html',
 styleUrl: './main-work-space.component.scss'
})

In result I have this mistake.

✘ [ERROR] TS-992012: 'imports' contains a ModuleWithProviders value, likely the result of a 'Module.forRoot()'-style call. These calls are not used to configure components and are not valid in standalone component imports - consider importing them in the application bootstrap instead.

I try add @ts-ignore but it doesn't help.

How can I fix it?


Solution

  • I think you missed the importProvidersFrom wrapper for translation module, please find below working example along with extra sample code, to help you resolve your problem!

    import { Component, importProvidersFrom } from '@angular/core';
    import { TranslateService } from '@ngx-translate/core';
    import { CommonModule } from '@angular/common';
    import { provideHttpClient } from '@angular/common/http';
    import { bootstrapApplication } from '@angular/platform-browser';
    import { AppModule } from './app/app.module';
    import { BrowserModule } from '@angular/platform-browser';
    import { HttpClient, HttpClientModule } from '@angular/common/http';
    import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
    import { TranslateHttpLoader } from '@ngx-translate/http-loader';
    import 'zone.js';
    
    // AoT requires an exported function for factories
    export function HttpLoaderFactory(httpClient: HttpClient) {
      return new TranslateHttpLoader(httpClient);
    }
    
    @Component({
      selector: 'app-root',
      imports: [CommonModule, TranslateModule],
      standalone: true,
      template: `
        <div>
          <h2>{{ 'HOME.TITLE' | translate }}</h2>
          <label>
            {{ 'HOME.SELECT' | translate }}
            <select #langSelect (change)="translate.use(langSelect.value)">
              <option *ngFor="let lang of translate.getLangs()" [value]="lang" [selected]="lang === translate.currentLang">{{ lang }}</option>
            </select>
          </label>
        </div>
      `,
    })
    export class AppComponent {
      constructor(public translate: TranslateService) {
        translate.addLangs(['en', 'fr']);
        translate.setDefaultLang('en');
    
        const browserLang = translate.getBrowserLang();
        translate.use(browserLang.match(/en|fr/) ? browserLang : 'en');
      }
    }
    
    bootstrapApplication(AppComponent, {
      providers: [
        provideHttpClient(),
        importProvidersFrom(
          TranslateModule.forRoot({
            loader: {
              provide: TranslateLoader,
              useFactory: HttpLoaderFactory,
              deps: [HttpClient],
            },
          })
        ),
      ],
    });
    

    stackblitz

    Stackblitz for reference not by me