Pipe Translater in Html Element

2020-05-07 08:26发布

问题:

So, dont know if anyone can help me. I have the below line of code in html :

<ion-item class="item-style">
  <ion-label>{{ 'SettingsPage.ChangeLanguage' | translate }}</ion-label>
  <ion-select [(ngModel)]="language" (ionChange)="onLanguageChange();" cancelText={{cancelText}} okText={{okText}}>
    <ion-select-option value="en">{{ 'SettingsPage.English' | translate }}</ion-select-option>
    <ion-select-option value="mt">{{ 'SettingsPage.Maltese' | translate }}</ion-select-option>
  </ion-select>
</ion-item>

and the following methods in the .ts :

 onLanguageChange() {
this.translate.use(this.language);
console.log(this.language);
this.globalVariableService.languageChanged = true;
this.globalVariableService.setCurrentLanguage(this.language);
this.storage.set('Language', this.language).then(() => {
  this.sectorDataServiceProvider.populateSectorData().then(data => {
    console.log('this.sectorInfo ', this.sectorDataServiceProvider.sectorInfo);
  });
});
this.setOkAndCancelText();

}

setOkAndCancelText() {
    if (this.language === 'en') {
      this.cancelText = 'Cancel';
      this.okText = 'OK';
    } else if (this.language === 'mt') {
      this.cancelText = 'Le';
      this.okText = 'Iva';
    }
  }

I wish to remove the s setOkAndCancelText() which is being used to fill the cancelText={{cancelText}} parameter when the language changes within the app, and have something similar to:

<p [innerHTML]="'TermsOfUsePage.Header' | translate"></p>

Any ideas how i can make this possible please?

回答1:

We have done it in following ways:

  • Installed the following packages:

"@ngx-translate/core": "11.0.1"

"@ngx-translate/http-loader": "4.0.0",

  • In app.module.js, add the following in imports:
 TranslateModule.forRoot({
          loader: {
            provide: TranslateLoader,
            useFactory: AppHttpLoaderFactory,
            deps: [HttpClient]
          }
        }),

export function AppHttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http, Environment.frontend('/assets/i18n/'), '.json');
}

Here we have kept our en.json file under i18n folder where all key values of text are there.

After this you can use it in html template:

<ion-select [(ngModel)]="language" (ionChange)="onLanguageChange();" cancelText={{'cancel.text' | translate }} okText={{okText}/>

Here cancel.text is a key in en.json file.



回答2:

Instead of reliaing on libraries, you can create your custom service and add your local strings i.e key and value as following:

@Injectable({
    providedIn: 'root'
})
export class LocalizationService {
    localizedStrings: any;

    constructor() {
        this.localizedStrings = {
            en: {
                SettingsPage: {
                    cancelText: 'Cancel'
                }
            },
            mt: {
                SettingsPage: {
                    cancelText: 'Le'
                }
            }
        }
    }

    getResource(keyString: string, workingLanguage: string): Promise<string> {
        return new Promise((resolve, reject) => {
            let resourceValue = null;
            if(this.localizedStrings[workingLanguage].hasOwnProperty(keyString)) {
                resourceValue = this.localizedStrings[workingLanguage][keyString];
            } else {
                resourceValue = this.getPropertyByKeyPath(this.localizedStrings[workingLanguage], keyString);
                // if(!resourceValue) {
                //     debugger;
                // }
            }

            if(resourceValue) {
                resolve(resourceValue);
            } else {
                resolve(keyString);
            }
        });        
    }

    private getPropertyByKeyPath(targetObj, keyPath) { 
        var keys = keyPath.split('.');
        if(keys.length == 0) return undefined; 

        keys = keys.reverse();
        var subObject = targetObj;
        while(keys.length) {
            var k = keys.pop();
            if(!subObject.hasOwnProperty(k)) {
                return undefined;
            } else {
                subObject = subObject[k];
            }
        }
        return subObject;
    }  
}

Note that it is flexible, you can go deeper in objects. Now simply create a pipe for this service:

import { Pipe } from '@angular/core';

import { LocalizationService } from '../shared/localization.service';

    @Pipe({
      name:"translate"
    })
    export class LocalizedResourcePipe {
        constructor(private localizationService: LocalizationService) {

        }

        transform(resourceKey: string, workingLanguage: string) {
            return new Promise((resolve, reject) => {
                if(!resourceKey) {
                    resolve();
                } else {
                    this.localizationService.getResource(resourceKey, workingLanguage)
                    .then((value) => {
                        resolve(value); 
                    });
                }
            });
        }
    }

Now simply call it in your HTML:

<ion-select [(ngModel)]="language" (ionChange)="onLanguageChange();" cancelText={{'SettingsPage.cancelText' | translate: 'en' | async}} okText={{'SettingsPage.cancelText' | translate: 'en' | async}}>

You can could make the the language parameter dynamic as well and in pipe, give it a default value. anyway here is the way to call it for your other language:

<ion-select [(ngModel)]="language" (ionChange)="onLanguageChange();" cancelText={{'SettingsPage.cancelText' | translate: 'mt' | async}} okText={{'SettingsPage.cancelText' | translate: 'mt' | async}}>


回答3:

Try this stackblitz example

Translate Service

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class TranslateService {
  data: any = {};

  constructor(private http: HttpClient) { }

  use(lang: string): Promise<{}> {
    return new Promise<{}>((resolve, reject) => {
      const langPath = `assets/languageFiles/${lang || 'en'}.json`;
      this.http.get<{}>(langPath).subscribe(
        translation => {
          this.data = Object.assign({}, translation || {});
          resolve(this.data);
        },
        error => {
          this.data = {};
          resolve(this.data);
        }
      );
    });
  }
}

Translate Pipe

import { Pipe, PipeTransform } from '@angular/core';
import { TranslateService } from './translate.service';

@Pipe({
  name: 'translate',
  pure:false
})
export class TranslatePipe implements PipeTransform {

  constructor(private translate: TranslateService) {}
  transform(key: any): any {
    return this.translate.data[key] || key;
  }

}