1
votes

I am using ngx-translate for a multi-language app.

app.module.ts

import {TranslateLoader, TranslateModule, TranslateService} from '@ngx-translate/core';

export function HttpLoaderFactory(httpClient: HttpClient) {
   return new TranslateHttpLoader(httpClient, './assets/i18n');
}

@NgModule({
[
 TranslateModule.forRoot({
   loader: {
     provide: TranslateLoader,
     useFactory: HttpLoaderFactory,
     deps: [HttpClient]
   }
...
]
export class AppModule {
    constructor(translate: TranslateService) {

      translate.setDefaultLang('en');

      translate.use( 'en'); 
}

Followed Angular Universal: server-side rendering instructions, and run app in SSR mode:

  • the page is loaded with the lang strings ('Home.Title')
  • there is an HTTP call for en.json
  • the strings are replaced with the translation ('My site')

What do I need to change in order that the translations will be rendered in server?

4

4 Answers

1
votes

https://github.com/Angular-RU/angular-universal-starter with translate. Different module loader for server and browser part

translates-server-loader.service.ts

 public getTranslation(lang: string): Observable<any> {
    return Observable.create((observer) => {
      const jsonData: any = JSON.parse(
        fs.readFileSync(`${this.prefix}/${lang}${this.suffix}`, 'utf8'),
      );
      const key: StateKey<number> = makeStateKey<number>(`transfer-translate-${lang}`);
      this.transferState.set(key, jsonData);
      observer.next(jsonData);
      observer.complete();
    });
  }

translates-browser-loader.service.ts - important use transferState

public getTranslation(lang: string): Observable<any> {
    const key: StateKey<number> = makeStateKey<number>(`transfer-translate-${lang}`);
    const data: any = this.transferState.get(key, null);
    if (data) {
      return Observable.create((observer) => {
        observer.next(data);
        observer.complete();
      });
    } else {
      return new TranslateHttpLoader(this.http, this.prefix, this.suffix).getTranslation(lang);
    }
  }
1
votes

The best tutorial that I found for this purpose is the one here :

implementing-multi-language-angular-applications-rendered-on-server

I use Angular 10, with angular Universal (SSR) and ngx-translate, and it worked for me.

This tutorial helps avoiding the usage of localstorage not supported by the server, it separates the translateLoaderFactory for server and browser case, it uses TransferState to avoid unnecessary http calls to the language json file (as the server already loaded them they are embedded in the page the server returns) and finally it has a complete git-hub repository for step by step implementation. Thanks Dmitry Efimenko for the good work.

Once implemented as he recomends the page is then correctly rendered with the traductions embedded in the html and therefore no additional http request is performed for getting the language json file. This avoids the issues of flickering page and having to see the language keys displayed in the page even for a split second.

The only pending issue is that if the language is changed once the page is loaded, as the page is not reloaded by ngx-translate, it stays with the language originaly loaded within the html, so then an http request is then done to load the new language, but I don't see how to avoid this. At least a user that already has its language selected in the cookie, or is happy with the detected language will not have any http request done for the languge json. If I find a solution for language change rendering on the server I will update this answer with this information.

0
votes

I'm not sure that it is the best way to do it but as I understand we need to load translations somehow on server side. I used express for that:

app.get('/path/to/your/translations/*.json',(req, res) => {
 res.download( `/path/to/your/translations/${lang}`)

});

and HttpInterceptor in AppServerModule you can see here

0
votes

You need to add an http interceptor on the server, which will change translation files path to be able to load them on the server. It was my issue personally, and I fixed it by following the explanation of this article: https://itnext.io/angular-universal-how-to-add-multi-language-support-68d83f6dfc4d

It worth a look !