Angular 2 app

时间:2016-05-02 15:35:12

标签: angular localization

我需要将我的角度2应用程序本地化为浏览器本地化定义的语言(向数据库发送POST请求 - 为我提供在标题中指定的此语言的翻译)。

我现在实施的内容:

我有一些共享变量,例如在dictionary.ts文件中的Dictionary。请注意,我默认将其设置为英语。

export let Dictionary = {
  1 : "engishVar1",
  2 : "englishVar2"
}

在我的AppComponent中,这是我的应用程序的入口点(因为我正在做Bootstrap(AppComponent),我在构造函数中有这样的东西:

this._appService.translationRequest(aptxIdsToTranslatePost)
     .subscribe(
          data => this.handleResponse(data),
          err => console.log("[App component] Error " + JSON.stringify(err)),
          () => console.log("[App component] GET translations finished: " + JSON.stringify(this.responseOnTranslationRequest))
          );

aptxIdsToTranslatePost 是JSON正文,我告诉我的后端服务器,给我ID 1和2,语言取自http POST标题。现在,服务器再次使用语言返回ID。

在handleResponse方法中,我这样做:

this.responseOnTranslationRequest.forEach(element => {
      Dictionary[element.id] = element.text;
});

正如我在上面看到的,我的词典就像键值存储一样。问题是什么?如果POST被延迟,我的应用程序不会被本地化,因为视图是在设置字典之前呈现的。如果我重新加载页面,之后视图完全本地化,因为转换被缓存,我不能等待POST响应。现在在我的组件中,我在构造函数中创建本地化,例如:

constructor() {
        this.welcomeTitle = Dictionary[1];
        this.welcomeDescription = Dictionary[2];
        this.welcomeBuyText = Dictionary[3];
        this.welcomeBuyTicket = Dictionary[4];
    }

我在考虑其他三种解决方案,但我认为,它们都不是很好。

首先是,我将我的本地化从组件的构造函数转换为稍后的角度2生命周期,通常是ngAfterViewInit或类似的东西。在这里,不能保证POST的答案可以回答,也许是,也许不是。

接下来是,我将同步创建POST,而不是异步,但这是个坏主意,因为我的应用可能会冻结(从POST转换的一些问题)。

最后一个是(我今天实现了,但它不起作用),我将创建Dictionary类(现在是JSON变量),并且在每个组件上我将创建它的实例。然后在AppComponent上,我将订阅响应(handleResponse),就像我在上面的例子中一样,在handleResponse中,我将调用一些类型为EventEmitter()的方法。所以在我的其他组件上,我将订阅它(在组件的构造函数中),通常是:

//in AppComponent after handleResponse
this._sharedService.dictionaryTranslationEvent.emit(this.dictionary);

//subscription in my component on new instance of Dictionary
this._sharedService.dictionaryTranslationEvent.subscribe(
       (dictionary) => {
           this.dictionary = dictionary;
           this.welcomeTitle = this.dictionary.getDictionary[1];
           this.welcomeDescription = this.dictionary.getDictionary[2];
           this.welcomeBuyText = this.dictionary.getDictionary[3];
           this.welcomeBuyTicket = this.dictionary.getDictionary[4];
 });

可以肯定的是,我现在附上了dictionary.ts:

export class Dictionary {

    private dict: any;

    constructor() {
        this.dict = {
            1: "englishVar1",
            2: "englishVar2",
        }
    }

    /* GET */
    get getDictionary(): any {
        return this.dict;
    }

    /* SET */
    set setDictionary(dictionary: any) {
        this.dict = dictionary;
    }
}

那么创建angular 2 app的本地化最好的想法是什么?感谢。

2 个答案:

答案 0 :(得分:3)

面对类似的问题,我选择了以下策略。

1)创建一个实现Dictionary角色的DictionaryService类;这个类包含一个JSON对象,它为每个需要翻译的字符串存储一个条目,以及一个为给定stringId和LanguageId提供翻译字符串的方法,例如

        @Injectable()
    export class LabelDictionaryService { 
        public dictionary: {};

        constructor(private _session: Session) {
            this.dictionary = this.getDictionary();
        }

    getDictionary() {
       return {
        stringId1: {en: 'String1InEnglish', it: 'String1InItalian', sp: 'String1InSpanish', ....},
        stringId2: {en: 'String2InEnglish', it: 'String2InItalian', sp: 'String2InSpanish', ....}
        ....
        }
    }

     getTranslation(inStringId: string, inLanguageId?: string) {
            let langId;
            if (inLanguageId) {
               langId = inLanguageId; 
            } else {
                langId = getDefualtLanguageId();  //getDefualtLanguageId() needs to be implemented in the DictionaryService class and retrieves the default language from the environment
            }
            let translation;
            if (this.dictionary[inLabelId]) {
                translation = labelTexts[langId];
            }
            if (translation == null) {
               text = inLabelId;
               console.error(inStringId + ' has no defined text for language ' + langId); 
            }
            return translation;
        }

    }

2)使用依赖注入在应用程序周围移动字典,以便可能需要字典服务的组件可以访问它

此解决方案并未直接解决来自外部服务的Dictionary内容的负载,但我认为您可以适应此要求稍微更改上面的代码示例tp在ngOnInit()方法中实现Dictionary内容的加载您的AppComponent。如果您还需要实现一种机制,阻止用户在加载词典之前继续使用您的应用程序(这对我来说很有意义),您需要找出最优雅的方法来禁用UI,直到加载词典(可能与超时逃脱)。

我希望这会有所帮助

答案 1 :(得分:0)

// Best way to change language Globally is to use pipes and send the language parameter as an argument.
// This would automatically change the Language across the components where the language pipe is utilized.
// The following example can be used to supple multiple language at a time and can be used to change Language dynamically on a single click

// for example: **language.pipe.ts**

`import { Pipe, PipeTransform, OnInit, OnChanges } from '@angular/core';
import { LanguageService } from '../services/language.service';

@Pipe({
    name: 'language'
})
export class LanguagePipe implements PipeTransform {

    constructor(
        public lang: LanguageService
    ) { }

    transform(value: string, args?: any): any {
        return this.lang.getLang(value);
    }
}
`

// **language.service.ts**

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

@Injectable()
export class LanguageService {

    selectedLanguage = 'ch';
    segmentsNames: any = {};
    constantSegmentNames: any = {};
    language = {
        undefined: { 'en': '', 'ch': '' },
        null: { 'en': '', 'ch': '' },
        '': { 'en': '', 'ch': '' },
        'hello': { 'en': 'Hello', 'ch': '你好' },
        'world': { 'en': 'World', 'ch': '世界' }
    };

    constructor(private _http: HttpClient) { }

    getLang(value: string, args?: any): any {
        if (this.language[value]) {
            return this.language[value][this.selectedLanguage];
        }
        return value;
    }

    /**
     * @function that is used to toggle the selected language among 'en' and 'ch'
     */
    changeLanguage() {
        if (this.selectedLanguage === 'en') {
            this.selectedLanguage = 'ch';
        } else {
            this.selectedLanguage = 'en';
        }
    }
}
`

// **Use Language Pipe in HTML AS**

`<strong>{{'hello' | language:lang.selectedLanguage}}{{'world' | language:lang.selectedLanguage}}</strong>`

PS:不要忘记在要使用此功能的所有组件中导入管道和服务

**结论:**您可以编写自己的逻辑,以根据用户选择的语言从数据库中获取适当的数据,并将其用于上述服务中