Internationalization 如何使用mustache.js制作客户端I18n

Internationalization 如何使用mustache.js制作客户端I18n,internationalization,mustache,Internationalization,Mustache,我有一些静态html文件,希望通过mustache.js修改客户端的静态文本 这似乎是Twitter在github上的胡须扩展: 但最近,特定的I18n扩展被删除或更改 我设想了一个解决方案,其中http:/server/static.html?lang=en加载mustache.js和一个基于lang参数数据的语言JSON文件 然后,Mustach用发送的数据替换{{tags}} 有人能给我举个例子吗?这很简单,也很简单 首先,您需要添加代码来确定查询字符串lang。为此,我使用snippet

我有一些静态html文件,希望通过mustache.js修改客户端的静态文本

这似乎是Twitter在github上的胡须扩展:

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

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

然后,Mustach用发送的数据替换
{{tags}}


有人能给我举个例子吗?

这很简单,也很简单

首先,您需要添加代码来确定查询字符串
lang
。为此,我使用snippet

然后,我使用jQuery处理
ajax
onReady
状态处理:

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

获取完整的HTML答案。

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

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

也就是说,大多数i18n的工作过程分为两步,如下所示:
  • 使用给定的变量呈现i18n文本
  • 使用后期呈现的i18n文本呈现HTML
  • 选项1:使用胡须部分 然后,将所有i18n模板/消息存储为服务器上Mustach模板的一个大型JSON对象:

    以下是“英语”翻译:

    { 
       "title" : "You have {{amount}} fart(s) left", 
       "item" : "Smells like {{description}}"
    }
    
    现在,这种方法有一个相当大的问题,因为胡子没有逻辑,所以处理多元化的事情会变得混乱。 另一个问题是,执行如此多的部分加载可能会导致性能下降(可能不会)

    选项2:让服务器的i18n完成这项工作。 另一种选择是让服务器进行第一次扩展(步骤1)。 Java确实有很多i18n扩展选项,我想其他语言也有

    这个解决方案最让人恼火的是,您将不得不加载两次您的模型。一次使用常规模型,第二次使用扩展的i18n模板。这相当烦人,因为您必须准确地知道要扩展哪些i18n扩展/模板并将其放入模型中(否则您必须扩展所有i18n模板)。换句话说,你会得到一些不错的干货


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

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

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

    你的数据也需要翻译,所以“poop”这个词来自数据——不知何故,它必须被翻译。不同语言的复数形式不同,英语也是如此,比如牙/牙、脚/脚等等。英语还有眼镜和裤子,它们总是复数形式。其他语言也有类似的例外和奇怪的IDOM。在英国,IBM“正在”参展,而在美国,IBM“正在”参展。俄语对复数有几种不同的规则,这取决于它们是人、动物、狭长物体等。在其他国家,数千个分隔符是空格、点或撇号,在某些情况下不适用于3位数:在日本为4,在印度则不一致

    满足于平庸的语言支持;工作太多了


    不要把不断变化的语言和不断变化的国家混为一谈——瑞士、比利时和加拿大也有法语国家,更不用说塔希提岛、海地和乍得了。奥地利说DE,阿鲁巴说NL,澳门说PT。

    你可以使用lambdas和一些像i18next或其他的图书馆

    {{#i18n}}greeting{{/i18n}} {{name}}
    
    以及传递的数据:

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

    这解决了我的问题

    我的答案是基于开发的。他回答得很好,我只想添加在消息键代码中使用小胡子标签的可能性。如果您希望能够根据当前的mustache状态或在循环中获取消息,那么确实需要它

    它基于简单的双重渲染

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

    最好的评论,非常简单但有效→“函数”我无法编辑,因为编辑将<6个字符!这是对国际化和胡子问题的一个很好的概括描述!你会如何称呼复数?你会如何称呼复数?很难回答,复数根据语言、法语、德语、英语、日语等有很大的不同。。。有时你不得不把这个词改成复数,有时你还得把周围的词去掉/加上元素,甚至改变这个词本身。根据我的经验,复数必须使用子函数来处理,具体到语言和本地语法。
    {{#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.
    }