Ngx-translate - TranslateHttpLoader with external URL

I’m loading the translation files from the server using TranslateHttpLoader in my app.module.ts like this:

export function createTranslateLoader(http: Http) {
   return new TranslateHttpLoader(http, AppConfig.API_URL+'/static/i18n/', '.json');
}

@NgModule({
  ...
  
  imports: [

    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: (createTranslateLoader),
        deps: [Http]
      }
    }), 
    
  ],
  ...
})

Everything works fine, but i’m wondering if there is a way to catch event when the loader fails to retrieve the language file for whatever reason (server issues, net con etc.) and possibly load a local json file with some default translation strings?

I want to catch this event if the app on the first load fails to grab the language file , and fallback to minimal local json file to just display translated mainetnance page/error page or something.

1 Like

I would think this would require writing a custom loader.

Before exporting createTranslateLoader(), make a request to the link (i.e. AppConfig.API_URL+’/static/i18n/).
If there is no response then Ionic will throw 404 Error. Trap this error using Custom Error Handling and point the value of AppConfig.API_URL to the local directory.

@rapropos , @devX - thanks for pointing me the right direction guys, i wrote a custom loader that resolves the requirement:

import { Injectable } from '@angular/core';
import { Headers, Http, Response } from "@angular/http";
import { TranslateLoader } from '@ngx-translate/core';
import { AppConfig } from "./config"
import {Observable} from 'rxjs/Observable'; 
 

@Injectable()
export class CustomTranslateLoader implements TranslateLoader  {
    contentHeader = new Headers({"Content-Type": "application/json","Access-Control-Allow-Origin":"*"});

    constructor(private http: Http) {}
    getTranslation(lang: string): Observable<any>{
        var apiAddress = AppConfig.API_URL+"/static/i18n/"+ lang+".json";
        return Observable.create(observer => {
          this.http.get(apiAddress, { headers: this.contentHeader }).subscribe((res: Response) => {
                    observer.next(res.json());
                    observer.complete();               
                },
            error => {
                //  failed to retrieve from api, switch to local
                this.http.get("/assets/i18n/en.json").subscribe((res: Response) => {
                    observer.next(res.json());
                    observer.complete();               
                })
            }
            );
        }); 
    }
}
4 Likes

Hi,

I felt on your solution and i really need to understand how you are doing that. Can you explain me with precision where to put that class and how/when to call it after for retrieving that translation from web URL ?

I don’t understand where to place it then where I should call it ?

  • place the code above in your services folder as trans.loader.ts

  • in your app.module.ts:

import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { CustomTranslateLoader } from '../services/trans.loader'

@NgModule({
  imports: [
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useClass: CustomTranslateLoader,
        deps: [Http]
      }
    }),
  ]
})
  • then you can use TranslateService as usual, but your custom loader will be used instead of the default one
1 Like

import { AppConfig } from “./config”

how create and import above class please help

Hi thank you @rapropos, @devX and @mthomka for sharing your custom Class, It helped developing mine me while working on my angular website project, I just needed to modify it like this :

  • Removing .json function from beacause it applies automatically and returns Observable<HttpResponse<string>> . We no longer need to call this function anymore.

  • Modifing the apiAdress

Here is my code :

import { Injectable } from ‘@angular/core’;
import { Headers, Http, Response } from ‘@angular/http’;
import { TranslateLoader } from ‘@ngx-translate/core’;
import { Observable } from ‘rxjs’;

@Injectable()
export class CustomTranslateLoader implements TranslateLoader {
contentHeader = new Headers({ ‘Content-Type’: ‘application/json’, ‘Access-Control-Allow-Origin’: ‘*’ });

constructor(private http: Http) { }
getTranslation(lang: string): Observable<any> {
    const apiAddress = '/assets/i18n/' + lang + '.json';
    return Observable.create(observer => {
        this.http.get(apiAddress, { headers: this.contentHeader }).subscribe((res: Response) => {
            observer.next(res);
            observer.complete();
        },
            error => {
                //  failed to retrieve from api, switch to local
                this.http.get('/assets/i18n/en.json').subscribe((res: Response) => {
                    observer.next(res);
                    observer.complete();
                });
            }
        );
    });
}

}

Dear @mthomka , you should make provider for it and call the ngxtranslate by using custom method and try to use catch block over there, for your more clarification i will make a code for you.