如何使用mustache.js建立客户端I18n

时间:2011-03-22 10:17:27

标签: internationalization mustache

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

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

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

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

然后小胡子用发送的数据替换{{tags}}

有人能举例说明如何做到这一点吗?

5 个答案:

答案 0 :(得分:6)

您可以将lambdas与某些库一起使用,例如i18next或其他。

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

数据通过:

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

这解决了我的问题

答案 1 :(得分:3)

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

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

大多数情况下i18n的工作步骤如下:

  1. 使用给定变量渲染i18n文本。
  2. 使用帖子渲染的i18n文本渲染HTML。
  3. 选项1:使用Mustache partials

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

    此胡子模板的数据可能是:

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

    然后,您将所有i18n模板/消息存储为服务器上的胡子模板的大型JSON对象:

    以下是“en”翻译:

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

    现在这种方法存在一个相当大的问题,即Mustache没有逻辑,因此处理多元化等问题会变得混乱。 另一个问题是执行如此多的部分负载(可能不是)可能会导致性能下降。

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

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

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

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

答案 2 :(得分:2)

我的回答是基于developo's。他的回答非常好我只是添加了在消息密钥中使用小胡子标签的可能性。如果您希望能够根据当前的胡须状态或循环

获取消息,那么确实需要它

它基于简单的双重渲染

 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.
}

答案 3 :(得分:0)

这很简单,非常简单。

首先,您需要添加代码以确定查询字符串lang。为此,我使用了代码段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回复。

答案 4 :(得分:0)

请务必记住其他语言与EN明显不同。

在FR和ES中,形容词出现在名词之后。 FR中的“绿豆”变为“haricots verts”(豆绿色),因此如果您插入变量,则翻译后的模板必须具有相反顺序的变量。因此,例如,printf将无法工作,因为参数不能改变顺序。这就是为什么你使用上面的选项1中的命名变量,并在整个句子和段落中翻译模板,而不是连接短语。

您的数据也需要翻译,所以“poop”这个词来自数据 - 不知何故必须翻译。不同语言的复数形式不同,英语也是如此,如牙齿/牙齿,脚/脚等.EN还具有总是复数的眼镜和裤子。其他语言同样有异常和奇怪的idoms。在英国,IBM'正在参加贸易展,而在美国,IBM'正在参加贸易展。俄语对复数有几种不同的规则,取决于它们是人,动物,狭长的物体等。在其他国家,千位分隔符是空格,点或撇号,在某些情况下不能使用3位数:4 in日本,印度不一致。

满足于平庸的语言支持;这太过分了。

不要混淆不断变化的语言与不断变化的国家 - 瑞士,比利时和加拿大也有FR发言人,更不用说塔希提岛,海地和乍得。奥地利说DE,Aruba说NL,澳门说PT。