我需要将我的角度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的本地化最好的想法是什么?感谢。
答案 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:不要忘记在要使用此功能的所有组件中导入管道和服务
**结论:**您可以编写自己的逻辑,以根据用户选择的语言从数据库中获取适当的数据,并将其用于上述服务中