【问题标题】:How to use Knockout observables in i18next?如何在 i18next 中使用 Knockout observables?
【发布时间】:2014-05-10 17:25:39
【问题描述】:

我正在尝试以某种方式动态地将 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
   });
};

谢谢,

【问题讨论】:

    标签: javascript jquery html knockout.js i18next


    【解决方案1】:

    我对 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/ 找到它

    【讨论】:

    • 小心,resStore 必须是 resourses...感谢您的解决方案 :)
    【解决方案2】:

    我更新了代码以支持翻译 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);
                }
            }
        };
    });
    

    【讨论】:

      【解决方案3】:

      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">
      

      【讨论】:

        【解决方案4】:

        感谢@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;
                        }
                    }
                }
            };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-09-04
          • 2014-07-09
          • 2013-04-20
          • 1970-01-01
          • 1970-01-01
          • 2014-08-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多