Ngx-translate and Ionic 3?

Yes, this. When I experimented with lazy page loading, every custom component that I imported got duplicated. See app-scripts #867. I fear that this might also befall you and others going down this path with ngx-translate. Perhaps it isn’t so large that it has a measurable effect, but it definitely did for me.

@rapropos First I took the same decision as you did, I experimented lazy loading but didn’t followed that pass yet. About your question, I just had a look at my experimental branch and I’ve to say that it seems that ngx-translate isn’t duplicated respectively only included once in the main bundle. But, don’t know if it’s a side effect of my design because I lazy load every pages except the first one (the login page).

I did the following:

First I generated all source map:

source-map-explorer main.js main.js.map 

to

 source-map-explorer 29.main.js 29.main.js.map 

and then checked the html files like following

grep -rnw *.html -e "ngx"

which only gave me one file as result

1 Like

Thank you for your investigation.

1 Like

ngx translation with ionic 3 app not working for me. below is my code:
app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { HttpModule,Http } from '@angular/http';
import { IonicStorageModule } from '@ionic/storage';

import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

import { MyApp } from './app.component';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';



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

@NgModule({
  declarations: [
    MyApp
  ],
  imports: [
    BrowserModule,
    HttpModule,
    IonicStorageModule.forRoot(),
    TranslateModule.forRoot({
                    loader: {
                      provide: TranslateLoader,
                      useFactory: (createTranslateLoader),
                      deps: [Http]
                    }
                  }),
    IonicModule.forRoot(MyApp),
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
  ]
})
export class AppModule {}

app.component.ts

import { Component, ViewChild } from '@angular/core';
import { Nav, Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { Storage } from '@ionic/storage';
import { TranslateService } from '@ngx-translate/core';


@Component({
  templateUrl: 'app.html'
})

export class MyApp {
  @ViewChild(Nav) nav: Nav;
  public rootPage: any;

  constructor(public platform: Platform, 
    public statusBar: StatusBar, 
    public splashScreen: SplashScreen,
    public storage: Storage,
    public translate: TranslateService) {

    this.storage.get('AppLangcode')
          .then((AppLangcode) => {
            if(AppLangcode==null){
              translate.setDefaultLang('en');
            }else{
              translate.setDefaultLang(AppLangcode);
            }
          })
  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      this.menu.swipeEnable(false);

    });
  }
}

In above file i am checking storage preference in local db and then set it to default language on load application.

My RootPage home.module.ts

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { HomePage } from './home';
import { TranslateModule } from '@ngx-translate/core';

@NgModule({
  declarations: [
    HomePage,
  ],
  imports: [
    IonicPageModule.forChild(HomePage),
    TranslateModule.forChild()
  ],
  exports: [
    HomePage
  ]
})
export class HomePageModule {}

home.ts

import { Component} from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Storage } from '@ionic/storage';
import { TranslateService } from '@ngx-translate/core';

@IonicPage()
@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController, 
    public navParams: NavParams,
    public storage: Storage,
    public translate: TranslateService,) {

  }

  ionViewDidLoad() {
    //console.log('ionViewDidLoad HomePagePage');
  }

}

home.html

<ion-header>
  <ion-navbar color='navbarColor'>
    <button ion-button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title><img src="assets/icon/logo.png" alt="Ionic logo"></ion-title>
  </ion-navbar>
</ion-header>

<ion-content  class="grid-basic-page">
    <ion-grid>
        <ion-row>
          <ion-col (click)="openPage('QuickBookPage');">
            <div><img src="assets/icon/icon-book-cylinder.png">{{"quick_book_pay" | translate}}</div>
          </ion-col>
          <ion-col (click)="openPage('RefilHistoryPage');">
            <div><img src="assets/icon/icon-quickpay.png">{{"refil_history" | translate}}</div>
          </ion-col>
        </ion-row>

        <ion-row>
          <ion-col (click)="openPage('ServicesPage');">
            <div><img src="assets/icon/icon-mechanic.png">{{"service_request" | translate}}</div>
          </ion-col>
          <ion-col>
          <button [disabled]="!clickhandle" (click)="emergencyCall();"><img src="assets/icon/icon-emergency.png">{{"emergency_helpline" | translate}}</button>
          </ion-col>
        </ion-row>  
  </ion-grid>

</ion-content>

Side Menu Page language.ts

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams,Events } from 'ionic-angular';
import { NgForm,FormBuilder, FormGroup, Validators  } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
import { Storage } from '@ionic/storage';


@IonicPage()
@Component({
  selector: 'page-language',
  templateUrl: 'language.html',
})
export class LanguagePage {
  public langform:FormGroup;
  public langcod:string;

  constructor(public navCtrl: NavController, 
    public navParams: NavParams,
    public formBuilder: FormBuilder,
    public translate: TranslateService,
    public storage: Storage) {

    this.storage.get('AppLangcode')
          .then((AppLangcode) => {
            
            if(AppLangcode==null){
              this.langcod = 'en';
              this.langform.get('langcode').setValue(this.langcod);
            }else{
              this.langcod = AppLangcode;
              this.langform.get('langcode').setValue(this.langcod);
            }
          })

    this.langform = formBuilder.group({
      langcode: [this.langcod, Validators.required]
    });
  }

  langselect(form: NgForm){
    let langselcode = this.langform.value.langcode;
    this.storage.set('AppLangcode', langselcode);
    this.translate.setDefaultLang(langselcode);
    this.translate.use(langselcode);
  }

}

language.module.ts

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { LanguagePage } from './language';
import { TranslateModule } from '@ngx-translate/core';

@NgModule({
  declarations: [
    LanguagePage,
  ],
  imports: [
    IonicPageModule.forChild(LanguagePage),
    TranslateModule.forChild()
  ],
  exports: [
    LanguagePage
  ]
})
export class LanguagePageModule {}

language.html

<ion-header>
 <ion-navbar color='navbarColor'>
    <button ion-button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title><img src="assets/icon/logo.png" alt="Ionic logo"></ion-title>
  </ion-navbar>
</ion-header>


<ion-content padding>
<form [formGroup]="langform" (submit)="langselect($event)">

    <ion-list radio-group  formControlName="langcode">
      <ion-row responsive-sm>
      <ion-col col-6>
            <ion-item>
              <ion-label>{{"english" | translate}}</ion-label>
              <ion-radio value="en" checked></ion-radio>
            </ion-item>
            <ion-item>
              <ion-label>{{"hindi" | translate}}</ion-label>
              <ion-radio value="hi"></ion-radio>
            </ion-item>
      </ion-col>
    </ion-row>

  </ion-list>

    <ion-row responsive-sm>
      <ion-col>
        <button ion-button block type="submit" [disabled]="!langform.valid">
            Submit
        </button>
      </ion-col>
    </ion-row>
  </form>

</ion-content>

en.json

{
    "english"   : "English",
    "hindi"     : "हिंदी",

    "quick_book_pay":"Quick Book & Pay",
    "refil_history":"Refill History",
    "service_request":"Service Request",
    "emergency_helpline":"Emergency Helpline"
}

hi.json

{
    "english"   : "English",
    "hindi"     : "हिंदी",
    
    "quick_book_pay":"त्वरित बुक और भुगतान करें",
    "refil_history":"रीफिल इतिहास",
    "service_request":"सेवा अनुरोध",
    "emergency_helpline":"आपातकालीन हेल्पलाइन"
}

On change language it show keys instead translation. Please let me know what wrong i am doing ? I am looking for the issue for a long.

similar issue posted here https://stackoverflow.com/questions/44371233/ionic-3-with-ngx-translate-lazy-loaded

  1. Your code looks good. May only guess is maybe trying to move your initialization part from app.component constructor to app.component ngAfterViewInit for example ? A wild guess is that maybe this.storage isn’t yet initialized when you try to access it in your app.component contructor and therefore the default language couldn’t be set?

  2. If I doesn’t miss it I’ve to feeling you are not telling ngx-translate which language should be use. You set a default language but doesn’t set the one to use. I would add this.translateService.use(…);

  3. Also it’s possible to guess the language without the storage, so I would do something like

     ngAfterViewInit() {
        let userLang = navigator.language.split('-')[0];
       userLang = /(hi)/gi.test(userLang) ? userLang : 'en';
    
     this.translateService.setDefaultLang('en');
     this.translateService.use(userLang);
    
     this.storage.get('AppLangcode')
       .then((AppLangcode) => {
         if(AppLangcode==null){
            this.translateService.use(userLang);
         }else{
            this.translateService.use(AppLangcode);
         }
       });
     }
    

Not sure it will work but maybe i will give you some ideas?

  1. Thanks for your response. storage preference working good and it also set default language when app initlize. like if hi language it set in storage then my home page data also shows in hi langauge.
    this code working fine (you can see app.component.ts ):
this.storage.get('AppLangcode')
  .then((AppLangcode) => {
    if(AppLangcode==null){
      translate.setDefaultLang('en');
    }else{
      translate.setDefaultLang(AppLangcode);
    }
  })

2.On change language i am doing 3 tasks, adding preference to storage for future app uses. setting langauge to default and using also for current session.

see Side Menu Page language.ts

langselect(form: NgForm){
    let langselcode = this.langform.value.langcode;
    this.storage.set('AppLangcode', langselcode);
    this.translate.setDefaultLang(langselcode);
    this.translate.use(langselcode);
  }

3.i didn’t get purpose of below code, do app remember my default preference without save it for future session ?

 let userLang = navigator.language.split('-')[0];
  userLang = /(hi)/gi.test(userLang) ? userLang : 'en';
1 Like

the issue is after set language it shows keys instead translation. and with next app session it shows translation as well… it seems working if app is reload. i am using lazy loading FYI.

still think you should use this.translate.use at loading time

otherwise no idea sorry

other people seems having the issue https://github.com/ngx-translate/core/issues/574

1 Like

i have updated my language module and this worked for me, not sure if this is right way but it’s worked.

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { LanguagePage } from './language';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { HttpModule,Http } from '@angular/http';

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

@NgModule({
  declarations: [
    LanguagePage,
  ],
  imports: [
    IonicPageModule.forChild(LanguagePage),
    TranslateModule.forChild({
            loader: {
                      provide: TranslateLoader,
                      useFactory: (createTranslateLoader),
                      deps: [Http]
                    }
            
        })
  ],
  exports: [
    LanguagePage
  ]
})
export class LanguagePageModule {}

i have added loader for child and export TranslateHttpLoader in language.module.ts

language.ts

langselect(form: NgForm){
  	let langselcode = this.langform.value.langcode;
  	this.storage.set('AppLangcode', langselcode);
  	this.translate.use(langselcode);
  }
2 Likes

I have been dealing with the same issue for last 2 days.
Above solution worked for me.

Thanks sonuyadav

1 Like

Did you add

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

In the app.module.ts

Yes i did add this in app.module.ts and language.module.ts both, it need to add for forRoot in app.module.ts and for forChild in language.module.ts

More Updates are Ngx-translate and lazy loading - some languages not found

Thanks, that solution helped.

This is not working with ionic 3.9.2 and angular 5.0.1. ngx translate is broken when using lazy loading. Tons of issues pending on the github repo and it seems that the main developer isn’t focusing on his repo anymore because he is with the angular core them now.
I hope Ionic will help us use the native i18n instead of ngx translate.
Please!!!

@lolaswift1 not agree sorry, it still works like a charm (ionic-angular 3.9.2, angular 5.0.0, ngx-translate 8.0.0, lazy loading on, app live with these in stores)

if you’ve got problem with your app, have you created a post about it?

Could you please share which version of ngx-translate/core and ngx-translate/http-loader you’re using?

I was able to successfully get translations working by following this post: Ngx translate is broken when used with ionic lazy loading

I tried the code wherein I am using lazy loading to load pages and also translating the stuffs as required: https://github.com/dmkdfc/IonicMultiLanguage.git