Skip to content

Instantly share code, notes, and snippets.

@ocombe
Last active May 11, 2023 07:01
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ocombe/593d21598d988bf6a8609ba5fc00b67e to your computer and use it in GitHub Desktop.
Save ocombe/593d21598d988bf6a8609ba5fc00b67e to your computer and use it in GitHub Desktop.
ng2-translate file loader for Angular Universal (server side)
import {TranslateLoader} from "ng2-translate/ng2-translate";
import {Observable} from "rxjs/Observable";
import fs = require('fs');
export class TranslateUniversalLoader implements TranslateLoader {
constructor(private prefix: string = 'i18n', private suffix: string = '.json') {}
/**
* Gets the translations from the server
* @param lang
* @returns {any}
*/
public getTranslation(lang: string): Observable<any> {
return Observable.create(observer => {
observer.next(JSON.parse(fs.readFileSync(`${this.prefix}/${lang}${this.suffix}`, 'utf8')));
observer.complete();
});
}
}
@SamVerschueren
Copy link

To import CJS modules in TypeScript, use import fs = require('fs');. That's the recommended way.

@ocombe
Copy link
Author

ocombe commented Jan 1, 2017

Thanks, updated

@elliotwesoff
Copy link

elliotwesoff commented Mar 2, 2017

It would be really great if there were something in the core docs mentioning this file. However, how is FS supposed to work from the browser? I've been using BrowserFS to get file access, but it only works for the browser's local storage. Is there something I'm missing for this?

P.S. import {TranslateLoader} from "ng2-translate/ng2-translate" should be changed to import {TranslateLoader} from "@ngx-translate/core" to match the new package name.

@ilDon
Copy link

ilDon commented Mar 6, 2017

@elliotwesoff, I was successfully using this code with ng2-translate, but after upgrading to ngx-translate I get an error in the terminal, I've posted the issue on StackOverflow.
Should it be sufficient to update only the import statement? In my case it's not working unfortunately.

@hantsy
Copy link

hantsy commented Apr 16, 2017

@elliotwesoff If you are using webpack, add json loader to load JSON directly.

import en from './i18n/en.json';

@fulls1z3
Copy link

fulls1z3 commented May 1, 2017

Hi everyone, I was trying to handle the universal loader in a more programmatic way, and ended up releasing the universal-loader package on github (https://github.com/fulls1z3/ngx-translate/tree/master/packages/%40ngx-universal/translate-loader) as well as on npm (https://www.npmjs.com/package/@ngx-universal/translate-loader).

It basically accepts the loader for the browser platform as a parameter, and provides the translations to the server platform using fs.

You can visit the ng-seed/universal for demo usage/instructions.

@ocombe, as a non-contributor, I didn't have chance to create a repo under ngx-translate. But if you think it would be useful for others, you can fork/copy and amend this package to distribute under ngx-translate.

@ysus
Copy link

ysus commented May 30, 2017

how i can use ngx-universal/translate-loader with an angular cli project with universal support

@vukasin-nikodijevic
Copy link

vukasin-nikodijevic commented Jun 15, 2017

Keep it simple - I'm using @angular/cli

file: src/shared/lang-switcher/custom-translate-loader.ts

import { en } from "assets/i18n/en";
import { srb } from "assets/i18n/srb";
import { TranslateLoader } from '@ngx-translate/core';
import { Observable } from 'rxjs/Observable';

export class CustomTranslateLoader implements TranslateLoader {
    public getTranslation(lang: string): Observable<any> {
        return Observable.create(observer => {
            if (lang === 'srb') {
                observer.next(srb);
            } else {
                observer.next(en);
            }
            observer.complete();
        });
    }
}

file: src/app/app.module.ts

TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useClass: CustomTranslateLoader
            }
        }),

Translation files

file: src/assets/i18n/en.ts

export const en = {
    menu: 'Menu',
    search: 'Search',
};

file: src/assets/i18n/srb.ts

export const srb = {
    menu: 'Meni',
    search: 'Pretraži',
};

Hope this will help someone ;-)

@chriseugenerodriguez
Copy link

any1 had issues with integration and resolved it? can use your help. ngx-translate/core#581

@mchambaud
Copy link

That loader will not work with Angular-cli until Angular teams resolve node modules.

@mchambaud
Copy link

@Vukasin0 this solution will bundle all translations into your app. This will be problematic for larger applications...

@philip-firstorder
Copy link

philip-firstorder commented Jul 1, 2018

This file loader created a lot of problems for me, from AOT compilation errors to lint errors to big translation bundles.

For Angular Universal I successfully used the prerender from https://github.com/angular/universal-starter with a default language.

@mohamedmelsayed
Copy link

@vukasin-nikodijevic your simple solution worked for me thank you.

@shoomkloom
Copy link

shoomkloom commented Apr 29, 2020

Thanks @vukasin-nikodijevic, your solution worked perfectly!
Also wanted to add my 2 cents:
Since the different language files are actually objects, I added some more attributes for example "direction":"rtl" and "textside": "text-right" (for Bootstrap) to the Hebrew string file, and so I could use the language object throughout the application to control all the behavior related to the selected language.
Also:
Each language file has a code field e.g.: "code": "en" and I changed the browser's document title like this:
In app.component.ts:
constructor(
public translate: TranslateService,
private titleService:Title
) {
translate.addLangs([en.code, he.code]);
translate.setDefaultLang(en.code);
const browserLang = translate.getBrowserLang();
translate.use(browserLang.match(/en.code|he.code/) ? browserLang : en.code);
this.translate.get("HOME.TITLE").subscribe(title => {
this.titleService.setTitle(title);
});
}

@OmarioHassan
Copy link

OmarioHassan commented May 19, 2020

Keep it simple - I'm using @angular/cli

file: src/shared/lang-switcher/custom-translate-loader.ts

import { en } from "assets/i18n/en";
import { srb } from "assets/i18n/srb";
import { TranslateLoader } from '@ngx-translate/core';
import { Observable } from 'rxjs/Observable';

export class CustomTranslateLoader implements TranslateLoader {
    public getTranslation(lang: string): Observable<any> {
        return Observable.create(observer => {
            if (lang === 'srb') {
                observer.next(srb);
            } else {
                observer.next(en);
            }
            observer.complete();
        });
    }
}

file: src/app/app.module.ts

TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useClass: CustomTranslateLoader
            }
        }),

Translation files

file: src/assets/i18n/en.ts

export const en = {
    menu: 'Menu',
    search: 'Search',
};

file: src/assets/i18n/srb.ts

export const srb = {
    menu: 'Meni',
    search: 'Pretraži',
};

Hope this will help someone ;-)

Amazing & Simple
Thnx

@Arian94
Copy link

Arian94 commented Nov 10, 2020

Keep it simple - I'm using @angular/cli

file: src/shared/lang-switcher/custom-translate-loader.ts

import { en } from "assets/i18n/en";
import { srb } from "assets/i18n/srb";
import { TranslateLoader } from '@ngx-translate/core';
import { Observable } from 'rxjs/Observable';

export class CustomTranslateLoader implements TranslateLoader {
    public getTranslation(lang: string): Observable<any> {
        return Observable.create(observer => {
            if (lang === 'srb') {
                observer.next(srb);
            } else {
                observer.next(en);
            }
            observer.complete();
        });
    }
}

file: src/app/app.module.ts

TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useClass: CustomTranslateLoader
            }
        }),

Translation files

file: src/assets/i18n/en.ts

export const en = {
    menu: 'Menu',
    search: 'Search',
};

file: src/assets/i18n/srb.ts

export const srb = {
    menu: 'Meni',
    search: 'Pretraži',
};

Hope this will help someone ;-)

Worked well! 👍

@all2pie
Copy link

all2pie commented Sep 21, 2021

custom-translate-loader.ts for latest rxjs:

import { of } from 'rxjs';
import { en } from '../../../assets/i18n/en';
import { ar } from '../../../assets/i18n/ar';
import { TranslateLoader } from '@ngx-translate/core';

export class CustomTranslateLoader implements TranslateLoader {
  public getTranslation(lang: string) {
    if (lang === 'ar') {
      return of(ar);
    }
    return of(en);
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment