ionic2 ng2-translate not working in modal

968 views Asked by At

I have problems using ng2-translate in combination with modals in ionic2. Translations in normal pages are working.

This is my app.module.ts file:

import ...
@NgModule({
    declarations: [
    MyApp,
    //...
  ],
  imports: [
    TranslateModule.forRoot({
      provide: TranslateLoader,
      useFactory: (createTranslateLoader),
      deps: [Http]
    }),
    IonicModule.forRoot(MyApp),
  ],
  exports: [
    TranslateModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    //...
  ],
  providers: [Storage, {provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}
export function createTranslateLoader(http: Http) {
  return new TranslateStaticLoader(http, 'assets/i18n', '.json');
}

For example in my dashboard I can use following HTML-Code and get the correct translation:

<h2>{{'general.tasks' | translate}}</h2>

But when I now open a new modal with the ModalController from ionic-angular by following code:

let taskModal = this.modalCtrl.create(TaskCancelPage, {'task': task});
taskModal.onDidDismiss(data => {
    console.log(data);
});
taskModal.present();

Having the same HTML Code in that new TaskCancelPage

<h2>{{'general.tasks' | translate}}</h2>

But here I only get general.tasks instead of the translated value.

2

There are 2 answers

0
nyluje On BEST ANSWER

It works for me here is what I've done:

In [project]/src//app.module.ts:

import { TranslateModule, TranslateStaticLoader, TranslateLoader } from 'ng2-translate/ng2-translate';
export function createTranslateLoader(http: Http) {
    return new TranslateStaticLoader(http, './assets/i18n', '.json');
}

import { TranslationService } from '../services/translation/translation';
//custom pipe
import { CapitalizePipe } from '../custom-pipes/capitalize/capitalize';    

@NgModule({
  declarations: [
     ...,
     CapitalizePipe,
     ....
  ],
  imports: [
    IonicModule.forRoot(MyApp),
    TranslateModule.forRoot({provide: TranslateLoader,
      useFactory: (createTranslateLoader),
      deps: [Http]})
  ],
  bootstrap: [IonicApp],
  entryComponents: [
     ...
  ],
  providers: [
    TranslationService,
    .... 
  ]
})

In [project]/src/app/app.component.ts

        ...
        import { TranslationService } from '../services/translation/translation';
        import { CapitalizePipe } from '../custom-pipes/capitalize/capitalize';

        @Component({
          templateUrl: 'app.html',
        })
        export class MyApp {
          ....

          constructor(
            ...,
            public translationService: TranslationService, ...
          ) {}
          ....
        ngOnInit() {
            return this.defineLang().then(
             (event) => {
                 console.log(MyApp.CLASS_TAG + " this.defineLang() fired: ",event , " getLangs is " , this.translationService.getLangs());
               this.[yourFunctionToDefineRootPage]();
             }
           );
         }
    ...
      private defineLang(): Promise<any> {
        let appDfltLang = 'fr';
          this.translationService.getBestLanguageAccordingToBrowserAvailability(appDfltLang);
        let promise = this.translationService.langSettingOnInit();
        return promise;
      }
....
}

in [project]/src/custom-pipe/capitalize/capitalize.ts:

import { PipeTransform, Pipe } from '@angular/core';
@Pipe({name:'capitalize'})

export class CapitalizePipe implements PipeTransform {
       transform(value?: any,args?: any): any{
                return (!!value)?value.charAt(0).toUpperCase()+value.substr(1):value;
       }

        }

in [project]/src/services/translation/translation.ts

import { Injectable } from '@angular/core';
import { LangChangeEvent, TranslateService } from 'ng2-translate/ng2-translate';
import { Observable } from 'rxjs/Observable';
import { CapitalizePipe } from '../../custom-pipes/capitalize/capitalize';

@Injectable()
export class TranslationService {

    private static readonly CLASS_TAG = "TranslationService";

    private availableLang: Array<string> = ["fr","en","nl"];
    private defaultLanguage:string = "en";

    constructor(
        private translateService: TranslateService
    ) { }

    setDefaultLang(lang: string) {
        return this.translateService.setDefaultLang(lang);
    }


    use(lang: string): Observable<any> {
        let brLgSubStr:string = this.getBrowserLang().substr(0,2);
        let findLg:number = this.availableLang.indexOf(brLgSubStr);
        if(findLg==-1){
            lang = this.defaultLanguage;
        }

        return this.translateService.use(lang);
    }

    getCurrentLang(): string {
        return this.translateService.currentLang;
    }

    getDefaultLang(): string {
        return this.translateService.getDefaultLang();
    }

    getBestLanguageAccordingToBrowserAvailability(appDfltLang:string) {
    console.log(TranslationService.CLASS_TAG + "getBestLanguageAccordingToBrowserAvailability() starts ");

        let brLang = this.getBrowserLang().substr(0,2);
        let brLangAmongPossibilities:boolean = false;

        for(let i in this.availableLang){
            if(this.availableLang[i]==brLang){
                brLangAmongPossibilities=true;
            }
        }
        if(brLangAmongPossibilities){
            this.translateService.use(brLang);
        } else {
            this.translateService.use(appDfltLang);

        }

        this.translateService.setDefaultLang(appDfltLang);

    }

    getBrowserLang():string {
        return this.translateService.getBrowserLang();
    }

    getLangs():Array<string> {
        return this.translateService.getLangs();
    }

    getAvailableLangs():Array<string>{
        return this.availableLang;
    }

    langSettingOnInit(): Promise<LangChangeEvent> {
        return new Promise((resolve, reject) => {
            this.translateService.onLangChange.subscribe(
                (event) => {
                    resolve(event);
                },
                (error) => {
                    console.log(TranslationService.CLASS_TAG + "onLangChangeInit() error: " ,error);
                    reject(error);
                }
            );
        });
    }

    instant(key: string | Array<string>, interpolateParams?: Object): string | any {
        let result =  key && this.translateService.instant(key, interpolateParams);
        result = (result !== key) ? result : '';

        if (key && !result) {
            console.error(`[not translated key]::${key}`);
        }

        return result;
    }

     instantCapitalize(key: string | Array<string>, interpolateParams?: Object): string | any {

        return new CapitalizePipe().transform(this.instant(key));
    }
}

Then in your pages (modal or not) where you want to use it import the service:

import { TranslationService } from '[root folder]/services/translation/translation';

And declare the service in the constructor of the page:

@Component({
    selector:'custom',
    templateUrl: 'custom.html'

})
export class CustomPage {

    constructor(...,public translationService:TranslationService,...){
    }
    ....
}

In your html template call it:

<[some text tag]>{{ "[some id word from your trad file]" | translate | capitalize }}</some text tag]>

or if you don't want to capitalize the first letter :

<[some text tag]>{{ "[some id word from your trad file]" | translate  }}</some text tag]>

And in a page if you call an AlertController for example you can do -:

this.translationService.instantCapitalize("[some id word from your trad file]");

or if you don't want to capitalize the first letter :

this.translationService.instant("[some id word from your trad file]");

FOR SOME REASON IT ONLY READS THE TRAD FILES UNDER [project]/wwww/assets/i18n/[2 chars language code].json

1
Joyal On

For ionic 5 Declare the modal component or page in the Current Module ex: declarations: [HomePage,FilterComponent]