【问题标题】:How to make client side I18n with mustache.js如何使用 mustache.js 制作客户端 I18n
【发布时间】:2011-03-22 10:17:26
【问题描述】:

我有一些静态 html 文件,想通过 mustache.js 客户端修改来更改里面的静态文本。

这似乎是 Twitter 在 github 上的小胡子扩展:https://github.com/bcherry/mustache.js

但最近特定的 I18n 扩展已被删除或更改。

我设想一个解决方案,其中http:/server/static.html?lang=en 加载mustache.js 和基于语言参数data_en.json 的语言JSON 文件。

然后 mustache 将 {{tags}} 替换为发送的数据。

谁能给我一个例子如何做到这一点?

【问题讨论】:

    标签: internationalization mustache


    【解决方案1】:

    您可以将 lambdas 与 i18next 之类的库或其他库一起使用。

    {{#i18n}}greeting{{/i18n}} {{name}}
    

    以及传递的数据:

    {
        name: 'Mike',
        i18n: function() {
            return function(text, render) {
                return render(i18n.t(text));
            };
        }
    }
    

    这解决了我的问题

    【讨论】:

    • 最佳评论恕我直言,非常简单而有效。
    • "runction" →"function" 我无法编辑,因为编辑将是
    【解决方案2】:

    我认为 Silent 的回答并不能真正解决/解释问题。

    真正的问题是你需要运行 Mustache 两次(或者使用其他东西然后 Mustache)。

    这是大多数 i18n 的两步过程,如下所示:

    1. 使用给定变量渲染 i18n 文本。
    2. 使用后期渲染的 i18n 文本渲染 HTML。

    选项 1:使用 Mustache 部分

    <p>{{> i18n.title}}</p>
    {{#somelist}}{{> i18n.item}}{{/somelist}}
    

    给这个胡子模板的数据可能是:

    { 
      "amount" : 10, 
      "somelist" : [ "description" : "poop" ]
    }
    

    然后,您会将所有 i18n 模板/消息作为 mustache 模板的大量 JSON 对象存储在服务器上:

    以下是“en”的翻译:

    { 
       "title" : "You have {{amount}} fart(s) left", 
       "item" : "Smells like {{description}}"
    }
    

    现在这种方法存在一个相当大的问题,因为 Mustache 没有逻辑,因此处理诸如多元化之类的事情会变得混乱。 另一个问题是执行这么多部分负载时性能可能会很差(也许不会)。

    选项 2:让服务器的 i18n 完成工作。

    另一种选择是让服务器进行第一次扩展(步骤 1)。 Java 确实有很多用于 i18n 扩展的选项,我认为其他语言也有。

    这个解决方案比较烦人的是你必须加载你的模型两次。一次使用常规模型,第二次使用扩展 i18n 模板。这很烦人,因为您必须确切知道要扩展哪些 i18n 扩展/模板并将其放入模型中(否则您将不得不扩展所有 i18n 模板)。换句话说,你会得到一些很好的 DRY 违规行为。

    解决上一个问题的一种方法是预处理小胡子模板。

    【讨论】:

    • 这是对国际化和小胡子问题的很好总结!
    【解决方案3】:

    我的回答是基于开发者的。他的回答非常好,我将在消息键码中添加使用小胡子标签的可能性。如果您希望能够根据当前的胡须状态或循环获取消息,则确实需要它

    它基于简单的双重渲染

     info.i18n = function(){
            return function(text, render){
                var code = render(text); //Render first to get all variable name codes set
                var value = i18n.t(code)
                return render(value); //then render the messages
            }
        }
    

    因此,表演不会因为小胡子操作非常小的字符串而受到影响。

    这里有一个小例子:

    Json 数据:

     array : 
        [
            { name : "banana"},
            { name : "cucomber" }
        ]
    

    小胡子模板:

    {{#array}}
        {{#i18n}}description_{{name}}{{/i18n}}
    {{/array}}
    

    消息

    description_banana = "{{name}} is yellow"
    description_cucomber = "{{name}} is green"
    

    结果是:

    banana is yellow
    cucomber is green
    

    复数

    [编辑]:正如评论中所问的,下面是一个示例,其中包含英语和法语复数处理的伪代码。这是一个非常简单且未经测试的示例,但它给了你一个提示。

    description_banana = "{{#plurable}}a {{name}} is{{/plurable}} green" (Adjectives not getting "s" in plurals)
    
    description_banana = "{{#plurable}}Une {{name}} est verte{{/plurable}}" (Adjectives getting an "s" in plural, so englobing the adjective as well)
    
    info.plurable = function() 
    {
      //Check if needs plural
      //Parse each word with a space separation
      //Add an s at the end of each word except ones from a map of common exceptions such as "a"=>"/*nothing*/", "is"=>"are" and for french "est"=>"sont", "une" => "des"
      //This map/function is specific to each language and should be expanded at need.
    }
    

    【讨论】:

    • 你会如何处理复数?
    • 很难回答,复数因语言、法语、德语、英语、日语等而有很大不同...有时您必须仅将单词调整为复数,有时则必须删除/也可以为周围的单词添加元素,甚至更改单词本身。根据我的经验,复数必须使用子函数处理,具体到语言和本地语法。
    【解决方案4】:

    这很简单,也很直接。

    首先,您需要添加代码来确定查询字符串lang。为此,我使用 sn-p taken from answer here

    function getParameterByName(name) {
    
        var match = RegExp('[?&]' + name + '=([^&]*)')
                        .exec(window.location.search);
    
        return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
    
    }
    

    然后,我使用jQuery来处理ajaxonReady状态处理:

    $(document).ready(function(){
        var possibleLang = ['en', 'id'];
        var currentLang = getParameterByName("lang");
        console.log("parameter lang: " + currentLang);
        console.log("possible lang: " + (jQuery.inArray(currentLang, possibleLang)));
        if(jQuery.inArray(currentLang, possibleLang) > -1){
            console.log("fetching AJAX");
            var request = jQuery.ajax({
                processData: false,
                cache: false,
                url: "data_" + currentLang + ".json"
            });
            console.log("done AJAX");
    
            request.done(function(data){
                console.log("got data: " + data);
                var output = Mustache.render("<h1>{{title}}</h1><div id='content'>{{content}}</div>", data);
                console.log("output: " + output);
                $("#output").append(output);
            });
    
            request.fail(function(xhr, textStatus){
                console.log("error: " + textStatus);
            });
        }
    });
    

    对于这个答案,我尝试使用简单的 JSON 数据:

    {"title": "this is title", "content": "this is english content"}
    

    获取this GIST 以获得完整的 HTML 答案。

    【讨论】:

    • 你会如何处理复数?
    【解决方案5】:

    请务必记住,其他语言与 EN 有很大不同。

    在 FR 和 ES 中,形容词在名词之后。 “green beans”在 FR 中变成了“haricots verts”(beans green),所以如果你插入变量,你翻译的模板必须以相反的顺序包含变量。因此,例如, printf 将不起作用,因为参数不能更改顺序。这就是为什么您使用上面选项 1 中的命名变量,并在整个句子和段落中使用翻译模板,而不是连接短语。

    您的数据也需要翻译,因此来自数据的“便便”一词 - 必须以某种方式进行翻译。不同的语言有不同的复数形式,英语也是如此,如牙齿/牙齿,脚/脚等。EN也有眼镜和裤子总是复数。其他语言也有类似的例外和奇怪的惯用语。在英国,IBM 参加了贸易展,而在美国,IBM 参加了贸易展。俄语有几种不同的复数规则,具体取决于它们是人、动物、狭长物体等。在其他国家/地区,千位分隔符是空格、点或撇号,在某些情况下不能使用 3 位数字:4 in日本,印度不一致。

    满足于平庸的语言支持;工作量太大了。

    不要将语言变化与国家变化混为一谈 - 瑞士、比利时和加拿大也有法语使用者,更不用说大溪地、海地和乍得了。奥地利讲德语,阿鲁巴讲荷兰语,澳门讲PT。

    【讨论】:

      猜你喜欢
      • 2011-12-24
      • 1970-01-01
      • 1970-01-01
      • 2012-07-25
      • 2017-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多