部分HTML本地化

时间:2015-03-11 18:26:12

标签: asp.net-mvc razor knockout.js typescript requirejs-text

问题

我需要本地化我的Web应用程序。我使用两种语言 - 英语和挪威语(这无关紧要)。

我使用资源文件来本地化标准视图。他们坐在一个名为Myproject.Localisation的单独项目中:

  • Localised.resx
  • Localised.no.resx

在剃须刀视图中看起来像这样:

<li>@Localised.WhatEverINeedToLocalise</li>

然后我有两个标准的部分html文件,其中包含一些html和一些knockout.js,这些文件作为amd依赖项加载,并在稍后用于我的typescript类:

///<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及其敲除绑定,编写一个T4模板,它将从resx文件生成翻译jsons,然后使用knockout转换部分htmls。 然而,它似乎过于复杂

1 个答案:

答案 0 :(得分:1)

我在项目中所做的是使用基本viewmodel类来处理从服务器检索文本数据。 每个viewmodel都有自己的Id,它与服务器上使用的资源ID相匹配。 提取的文本保存在基本viewmodel类中,结构如下:

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);
}

..从viewmodel中获取的特定文本,如下所示:

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绑定处理程序从viewmodel中获取正确的文本。通常,每个视图模型都会导出到名为 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>

这是一个庞大的设置,但是一旦到位,文本处理由基本viewmodel类处理,你需要为每个viewmodel做的唯一事情就是在服务器端设置资源文件,数据绑定您的标签和值与简单的敲除绑定。