4

我试图以某种方式动态地将 i18next 翻译与 Knockout.js 一起使用,但我不知道如何。

自定义 Knockout 绑定或 i18next jQuery 插件似乎都不适用于可观察值。

可以在这里找到我想要实现的演示:http: //jsfiddle.net/rdfx2/1/

解决方法是这样的,但如果可能的话,我宁愿避免这种情况:

<div data-bind="text: translate('key', observable)"></div>

self.translate = function (key, value) {
   return i18next.t(key, {
      "var": value
   });
};

谢谢,

4

4 回答 4

7

我对 i18next 不是很熟悉,所以我可能错误地使用了 i18next,但是您可以通过创建 bindingHandler 轻松实现这一点。这种支持传递可选选项的 bindingHandler 的一个非常简单的版本可能如下所示:

ko.bindingHandlers['translatedText'] = {
    update: function(element, valueAccessor, allBindings){
        var key = ko.unwrap(valueAccessor());
        var options = ko.toJS(allBindings.get('translationOptions') || {});
        var translation = i18n.t(key, options);
        element.innerText = translation;
    }
};

给定以下 i18next 初始化代码:

i18n.init({
    lng: "en",
    debug: true,
    resStore: {
        en: {
            translation: {
                'myTextKey': 'My translated value is "__value__"',
                'otherTextKey': 'This is just a text which does not use options'
            }
        }
    }
});

您可以将其与以下 HTML 一起使用:

<input type="text" data-bind="value: input, valueUpdate: 'afterkeydown'"/>
<div data-bind="translatedText: 'myTextKey', translationOptions: { value: input }"></div>
<div data-bind="translatedText: 'otherTextKey'"></div>

以及以下视图模型:

function ViewModel(){
    this.input = ko.observable();
}

ko.applyBindings(new ViewModel);

我已将上面的代码保存到一个 jsfiddle 中,您可以在http://jsfiddle.net/md2Hr/找到它

于 2014-03-31T16:59:35.963 回答
4

我更新了代码以支持翻译 HTML 属性。

这是一个工作演示:http: //jsfiddle.net/remisture/GxEGe/

HTML

<label>HTML/text</label>
<textarea data-bind="i18n: 'key', i18n-options: {var: input}"></textarea>
<label>Attribute</label>
<input type="text" data-bind="i18n: '[placeholder]key', i18n-options: {var: input}" />

JS

define(['knockout', 'i18next'], function (ko, i18n) {
    ko.bindingHandlers.i18n = {
        update: function (element, valueAccessor, allBindings) {
            var key = ko.unwrap(valueAccessor()),
                options = ko.toJS(allBindings.get('i18n-options') || {}),
                translation,
                parts,
                attr;

            // Check whether we are dealing with attributes
            if (key.indexOf('[') === 0) {
                parts = key.split(']');
                key = parts[1];
                attr = parts[0].substr(1, parts[0].length - 1);
            }

            translation = i18n.t(key, options);

            if (attr === undefined) {
                // Check whether the translation contains markup
                if (translation.match(/<(\w+)((?:\s+\w+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/)) {
                    //noinspection InnerHTMLJS
                    element.innerHTML = translation;
                } else {
                    // Check whether the translation contains HTML entities
                    if (translation.match(/&(?:[a-z]+|#x?\d+);/gi)) {
                        //noinspection InnerHTMLJS
                        element.innerHTML = translation;
                    } else {
                        // Treat translation as plain text
                        element.innerText = translation;
                    }
                }
            } else {
                // Add translation to given attribute
                element.setAttribute(attr, translation);
            }
        }
    };
});
于 2014-04-08T12:31:06.940 回答
2

KO配置:

var language = ko.observable('');

ko.i18n = function(key) {
  return ko.computed(function() {
    if (language() != null) {
      return i18n.t(key, {
        lng : language()
      });
    } else {
      return "";
    }
  }, key);
};

视图模型:

var labels = {      
aboutUs: ko.i18n('app:labels.aboutUs'), 
contactUsBtn: ko.i18n('app:labels.contactUsBtn') }

看法:

<span data-bind="text: labels.aboutUs">
于 2014-03-31T20:22:36.127 回答
1

感谢您提供了一个很好的例子,@robert.westerlund!

我稍微修改了您的示例以更好地满足我的需求:

ko.bindingHandlers['i18n'] = {
        update: function (element, valueAccessor, allBindings) {
            var key = ko.unwrap(valueAccessor()),
                options = ko.toJS(allBindings.get('i18n-options') || {}),
                translation = i18next.t(key, options);

            // Check whether the translation contains markup
            if (translation.match(/<(\w+)((?:\s+\w+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/)) {
                element.innerHTML = translation;
            } else {
                // Check whether the translation contains HTML entities
                if (translation.match(/&(?:[a-z]+|#x?\d+);/gi)) {
                    element.innerHTML = translation;
                } else {
                    // Treat translation as plain text
                    element.innerText = translation;
                }
            }
        }
    };
于 2014-04-01T09:12:18.517 回答