部分 html 本地化
Partial html localisation
问题
我需要本地化我的网络应用程序。我使用两种语言 - 英语和挪威语(应该无关紧要)。
我使用资源文件来本地化标准视图。他们坐在一个名为 Myproject.Localisation:
的单独项目中
- Localised.resx
- Localised.no.resx
在剃须刀视图中看起来像这样:
<li>@Localised.WhatEverINeedToLocalise</li>
然后我有两个标准的部分 html 文件,其中一些 html 和一些 knockout.js 像这样作为 amd 依赖项加载并在我的打字稿中使用 class 后来在:
///<amd-dependency path="text!./productTemplate.html" />
///<amd-dependency path="text!./anotherTemplate .html" />
var contentTemplate = require("text!./productTemplate.html");
var anotherTemplate = require("text!./anotherTemplate .html");
问题
显然,我也必须在其中进行翻译。有没有一种方法可以使用 razor 并使用我拥有的资源文件生成这些部分 html 文件?
如果没有,是否有任何其他选项,可能比我的解决方案(阅读下文)更简单?
我的解决方案
我想到的唯一方法是安装 i18next 及其 knockout 绑定,编写一个 T4 模板,该模板将从 resx 文件生成翻译 json,然后使用 knockout 翻译部分 htmls。 然而,它似乎过于复杂。
我在项目中所做的是使用基本视图模型 class 来处理从服务器检索的文本数据。
每个视图模型都有自己的 ID,与服务器上使用的资源 ID 相匹配。
获取的文本以如下结构保存在基本视图模型 class 中:
public texts: KnockoutObservableArray<ITextItem> = ko.observableArray<ITextItem>();
.. 其中 ITextItem 是这样的结构:
interface ITextItem {
id: string;
value: KnockoutObservable<string>;
}
.. 使用这样的函数获取:
public updateTexts(cultId: string): Q.Promise<any> {
if (this.textsName === '')
this.textsName = this.modelId;
if (this.lastCultureIdFetched != cultId) {
this.lastCultureIdFetched = cultId;
return mm_cspData.cspCtx.getTexts(this.textsName, this.texts);
}
else
return Q.resolve(true);
}
.. 从视图模型中获取的特定文本,如下所示:
public tx(id: string): string {
var match: ITextItem = ko.utils.arrayFirst(this.texts(), item=> item.id === id);
if (!match)
return '';
else
return match.value();
}
因此,每次激活视图模型或更改应用程序语言时,都会触发 updateText 方法。
为了在我的 html 视图中显示文本,我使用 knockout 绑定处理程序从视图模型中获取正确的文本。通常,每个视图模型都会导出到一个名为 vm 的变量中,所以我可以这样操作:
ko.getVmTx = (label: any, bindingContext: any) : string => {
if (label === null)
return '';
var vm: any;
var labelId;
if (typeof label === 'object' && typeof label.vm === 'object' && typeof label.vm.tx !== 'function') {
vm = label.vm;
labelId = label.tx;
} else {
vm = bindingContext.$root.vm;
labelId = ko.unwrap(label);
}
if (vm === null || typeof vm === 'undefined' || typeof vm.tx !== 'function') {
console.log('tx binding: unable to find vm for ' + label);
return '';
}
else
return vm.tx(labelId);
}
ko.bindingHandlers.tx = {
update: (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) => {
$(element).text(ko.getVmTx(valueAccessor(),bindingContext));
}
};
ko.bindingHandlers.txVal = {
update: (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) => {
$(element).val(ko.getVmTx(valueAccessor(), bindingContext));
}
};
最后,在我看来,我使用这样的绑定处理程序:
<span class="app-badge-label-bg" data-bind="tx: 'FinInvAmount'"></span>
这是一个庞大的设置,但是一旦到位,文本处理将由基本视图模型处理 class,您唯一需要为每个视图模型做的就是设置资源服务器端的文件,并使用简单的敲除绑定对标签和值进行数据绑定。
问题
我需要本地化我的网络应用程序。我使用两种语言 - 英语和挪威语(应该无关紧要)。
我使用资源文件来本地化标准视图。他们坐在一个名为 Myproject.Localisation:
的单独项目中- Localised.resx
- Localised.no.resx
在剃须刀视图中看起来像这样:
<li>@Localised.WhatEverINeedToLocalise</li>
然后我有两个标准的部分 html 文件,其中一些 html 和一些 knockout.js 像这样作为 amd 依赖项加载并在我的打字稿中使用 class 后来在:
///<amd-dependency path="text!./productTemplate.html" />
///<amd-dependency path="text!./anotherTemplate .html" />
var contentTemplate = require("text!./productTemplate.html");
var anotherTemplate = require("text!./anotherTemplate .html");
问题
显然,我也必须在其中进行翻译。有没有一种方法可以使用 razor 并使用我拥有的资源文件生成这些部分 html 文件?
如果没有,是否有任何其他选项,可能比我的解决方案(阅读下文)更简单?
我的解决方案
我想到的唯一方法是安装 i18next 及其 knockout 绑定,编写一个 T4 模板,该模板将从 resx 文件生成翻译 json,然后使用 knockout 翻译部分 htmls。 然而,它似乎过于复杂。
我在项目中所做的是使用基本视图模型 class 来处理从服务器检索的文本数据。 每个视图模型都有自己的 ID,与服务器上使用的资源 ID 相匹配。 获取的文本以如下结构保存在基本视图模型 class 中:
public texts: KnockoutObservableArray<ITextItem> = ko.observableArray<ITextItem>();
.. 其中 ITextItem 是这样的结构:
interface ITextItem {
id: string;
value: KnockoutObservable<string>;
}
.. 使用这样的函数获取:
public updateTexts(cultId: string): Q.Promise<any> {
if (this.textsName === '')
this.textsName = this.modelId;
if (this.lastCultureIdFetched != cultId) {
this.lastCultureIdFetched = cultId;
return mm_cspData.cspCtx.getTexts(this.textsName, this.texts);
}
else
return Q.resolve(true);
}
.. 从视图模型中获取的特定文本,如下所示:
public tx(id: string): string {
var match: ITextItem = ko.utils.arrayFirst(this.texts(), item=> item.id === id);
if (!match)
return '';
else
return match.value();
}
因此,每次激活视图模型或更改应用程序语言时,都会触发 updateText 方法。
为了在我的 html 视图中显示文本,我使用 knockout 绑定处理程序从视图模型中获取正确的文本。通常,每个视图模型都会导出到一个名为 vm 的变量中,所以我可以这样操作:
ko.getVmTx = (label: any, bindingContext: any) : string => {
if (label === null)
return '';
var vm: any;
var labelId;
if (typeof label === 'object' && typeof label.vm === 'object' && typeof label.vm.tx !== 'function') {
vm = label.vm;
labelId = label.tx;
} else {
vm = bindingContext.$root.vm;
labelId = ko.unwrap(label);
}
if (vm === null || typeof vm === 'undefined' || typeof vm.tx !== 'function') {
console.log('tx binding: unable to find vm for ' + label);
return '';
}
else
return vm.tx(labelId);
}
ko.bindingHandlers.tx = {
update: (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) => {
$(element).text(ko.getVmTx(valueAccessor(),bindingContext));
}
};
ko.bindingHandlers.txVal = {
update: (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) => {
$(element).val(ko.getVmTx(valueAccessor(), bindingContext));
}
};
最后,在我看来,我使用这样的绑定处理程序:
<span class="app-badge-label-bg" data-bind="tx: 'FinInvAmount'"></span>
这是一个庞大的设置,但是一旦到位,文本处理将由基本视图模型处理 class,您唯一需要为每个视图模型做的就是设置资源服务器端的文件,并使用简单的敲除绑定对标签和值进行数据绑定。