Search code examples
angularlocalizationinternationalizationtransloco

Transloco is not loading translations in Angular 17


Here is a minimal reproduction: link

I am using Angular (17) with Transloco. After following the instructions in the documentation I have attempted to translate a simple text using the structural directive inside a template

<ng-container *transloco="let t"> <h2>{{ t('greeting') }}</h2> </ng-container>

The issue is that as you can see, no text is rendered at all.

I have tried to use both relative and absolute path for the translation files, and also noticed that there is no Http call in the network tab, indicating that the translations aren't being fetched.

Full code

main.ts

import { Component, inject, isDevMode } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import { provideHttpClient } from '@angular/common/http';
import { TranslocoHttpLoader } from './transloco-loader';
import { TranslocoService, provideTransloco } from '@jsverse/transloco';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <ng-container *transloco="let t">
      <h2>{{ t('greeting') }}</h2>
    </ng-container>
    <button (click)="onChangeToSpanish()">Change to Spanish</button>
  `,
})
export class App {
  private translocoService = inject(TranslocoService);

  onChangeToSpanish() {
    this.translocoService.setActiveLang('es');
  }
}

bootstrapApplication(App, {
  providers: [
    provideHttpClient(),
    provideTransloco({
      config: {
        availableLangs: ['en', 'es'],
        defaultLang: 'en',
        // Remove this option if your application doesn't support changing language in runtime.
        reRenderOnLangChange: true,
        prodMode: !isDevMode(),
      },
      loader: TranslocoHttpLoader,
    }),
  ],
});

transloco-loader.ts

import { inject, Injectable } from '@angular/core';
import { Translation, TranslocoLoader } from '@jsverse/transloco';
import { HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class TranslocoHttpLoader implements TranslocoLoader {
  private http = inject(HttpClient);

  getTranslation(lang: string) {
    return this.http.get<Translation>(`/assets/i18n/${lang}.json`);
  }
}

Since this should be straight through, I feel like I am missing something.


Solution

  • The problems with the code are follows.

    1. Since we are using *transloco structural directive, it's required to add the import TranslocoDirective to the imports array of the standalone component.

    2. In the angular.json file we need to reference the assets folder, so that the translations files are resolved when we look them up.

    angular.json

    ...
    "options": {
        "assets": ["src/assets"],
        ...
    

    Full code

    import { Component, inject, isDevMode } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import 'zone.js';
    import { provideHttpClient } from '@angular/common/http';
    import { TranslocoHttpLoader } from './transloco-loader';
    import {
      TranslocoService,
      provideTransloco,
      TranslocoDirective,
    } from '@jsverse/transloco';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [TranslocoDirective],
      template: `
        <ng-container *transloco="let t">
          <h2>{{ t('greeting') }}</h2>
        </ng-container>
        <button (click)="onChangeToSpanish()">Change to Spanish</button>
      `,
    })
    export class App {
      private translocoService = inject(TranslocoService);
    
      onChangeToSpanish() {
        this.translocoService.setActiveLang('es');
      }
    }
    
    bootstrapApplication(App, {
      providers: [
        provideHttpClient(),
        provideTransloco({
          config: {
            availableLangs: ['en', 'es'],
            defaultLang: 'en',
            // Remove this option if your application doesn't support changing language in runtime.
            reRenderOnLangChange: true,
            prodMode: !isDevMode(),
          },
          loader: TranslocoHttpLoader,
        }),
      ],
    });
    

    Stackblitz Demo