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

发布于 2024-10-26 06:19:30 字数 458 浏览 4 评论 0原文

我有一些静态 html 文件,想要通过 Mustache.js 进行客户端修改来更改其中的静态文本。

看来这可能是 Twitter 在 github 上的 Mustache 扩展: https://github.com/bcherry/mustache.js

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

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

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

有人可以给我一个例子如何做到这一点吗?

i have some static html files and want to change the static text inside with client side modification through mustache.js.

it seems that this was possible Twitter's mustache extension on github: https://github.com/bcherry/mustache.js

But lately the specific I18n extension has been removed or changed.

I imagine a solution where http:/server/static.html?lang=en loads mustache.js and a language JSON file based on the lang param data_en.json.

Then mustache replaces the {{tags}} with the data sent.

Can someone give me an example how to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

枉心 2024-11-02 06:19:30

您可以将 lambda 表达式与一些库(例如 i18next 或其他库)一起使用。

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

数据通过了:

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

这解决了我的问题

You can use lambdas along with some library like i18next or something else.

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

And the data passed:

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

This solved the problem for me

浮华 2024-11-02 06:19:30

我认为沉默的回答并没有真正解决/解释问题。

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

大多数 i18n 的工作过程分为两步,如下所示:

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

选项 1:使用 Mustache 部分

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

提供给此 Mustache 模板的数据可能是:

{ 
  "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 的情况。

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

I don't think Silent's answer really solves/explains the problem.

The real issue is you need to run Mustache twice (or use something else and then Mustache).

That is most i18n works as two step process like the following:

  1. Render the i18n text with the given variables.
  2. Render the HTML with the post rendered i18n text.

Option 1: Use Mustache partials

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

The data given to this mustache template might be:

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

Then you would store all your i18n templates/messages as a massive JSON object of mustache templates on the server:

Below is the "en" translations:

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

Now there is a rather big problem with this approach in that Mustache has no logic so handling things like pluralization gets messy.
The other issue is that performance might be bad doing so many partial loads (maybe not).

Option 2: Let the Server's i18n do the work.

Another option is to let the server do the first pass of expansion (step 1).
Java does have lots of options for i18n expansion I assume other languages do as well.

Whats rather annoying about this solution is that you will have to load your model twice. Once with the regular model and second time with the expanded i18n templates. This is rather annoying as you will have to know exactly which i18n expansions/templates to expand and put in the model (otherwise you would have to expand all the i18n templates). In other words your going to get some nice violations of DRY.

One way around the previous problem is pre-processing the mustache templates.

楠木可依 2024-11-02 06:19:30

我的答案是基于developmento的。他的回答非常好,我将添加在消息键码中使用胡子标签的可能性。如果您希望能够根据当前的 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
        }
    }

因此由于 Mustache 在非常小的字符串上运行,因此性能不会受到影响。

这里有一个小例子:

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

My answer is based on developingo's. He's answer is very great I'll just add the possibility to use mustache tags in the message keycode. It is really needed if you want to be able the get messages according to the current mustache state or in loops

It's base on a simple double rendering

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

Thus performances aren't hit because of mustache operating on a very small string.

Here a little example :

Json data :

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

Mustache template :

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

Messages

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

The result is :

banana is yellow
cucomber is green

Plurals

[Edit] : As asked in the comment follows an example with pseudo-code of plural handling for english and french language. Its a very simple and not tested example but it gives you a hint.

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.
}
执手闯天涯 2024-11-02 06:19:30

这非常简单,也非常直接。

首先,您需要添加代码来确定查询字符串 lang。为此,我使用摘自此处答案的片段摘自此处

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

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

This is quite simple and pretty straightforward.

First, you will need to add code to determine the Query String lang. For this, I use snippet taken from answer here.

function getParameterByName(name) {

    var match = RegExp('[?&]' + name + '=([^&]*)')
                    .exec(window.location.search);

    return match && decodeURIComponent(match[1].replace(/\+/g, ' '));

}

And then, I use jQuery to handle ajax and onReady state processing:

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

For this answer, I try to use simple JSON data:

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

Get this GIST for complete HTML answer.

吖咩 2024-11-02 06:19:30

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

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

你的数据也需要被翻译,所以来自数据的“便便”这个词——不知何故必须被翻译。不同的语言对复数的理解也不同,英语也是如此,如“tooth/teeth”、“foot/feet”等。EN 中的“glasses”和“pants”也始终是复数。其他语言也同样有例外和奇怪的习惯用法。在英国,IBM “正在”参加贸易展,而在美国,IBM “正在”参加贸易展。俄语对复数有几种不同的规则,具体取决于它们是人、动物、狭长物体等。在其他国家/地区,千位分隔符是空格、点或撇号,在某些情况下不能使用 3 位数字:4 in日本,印度则不一致。

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

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

Make sure to remember that other languages are significantly different from EN.

In FR and ES, adjectives come after the noun. "green beans" becomes "haricots verts" (beans green) in FR, so if you're plugging in variables, your translated templates must have the variables in reverse order. So for instance, printf won't work cuz the arguments can't change order. This is why you use named variables as in Option 1 above, and translated templates in whole sentences and paragraphs, rather than concatenating phrases.

Your data needs to also be translated, so the word 'poop', which came from data - somehow that has to be translated. Different languages do plurals differently, as does english, as in tooth/teeth, foot/feet, etc. EN also has glasses and pants that are always plural. Other languages similarly have exceptions and strange idoms. In the UK, IBM 'are' at the trade show whereas in in the US, IBM 'is' at the trade show. Russian has several different rules for plurals depending on if they are people, animals, long narrow objects, etc. In other countries, thousands separators are spaces, dots, or apostrophes, and in some cases don't work by 3 digits: 4 in Japan, inconsistently in India.

Be content with mediocre language support; it's just too much work.

And don't confuse changing language with changing country - Switzerland, Belgium and Canada also have FR speakers, not to mention Tahiti, Haiti and Chad. Austria speaks DE, Aruba speaks NL, and Macao speaks PT.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文