Search code examples
angularionic-frameworkionic2ng2-translate

ionic2 ng2-translate not working in modal


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.


Solution

  • 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