Javascript 如何使用handlebar.js(胡须模板)制作i18n?

Javascript 如何使用handlebar.js(胡须模板)制作i18n?,javascript,jquery,internationalization,handlebars.js,mustache,Javascript,Jquery,Internationalization,Handlebars.js,Mustache,我目前正在使用handlebar.js(与主干网和jQuery相关)制作一个几乎完全由客户端呈现的web应用程序,我对这个应用程序的国际化有问题 我怎样才能做到这一点 有插件吗?是一个ruby gem,它将从您的config/locales文件夹创建一个国际化文件。但是,如果您不使用rails,您可以找到自己使用的javascript 然后,只需将翻译存储在嵌套对象中 I18n.translations = {"en":{"date":{"formats":{"default":"%Y-%m-%

我目前正在使用handlebar.js(与主干网和jQuery相关)制作一个几乎完全由客户端呈现的web应用程序,我对这个应用程序的国际化有问题

我怎样才能做到这一点

有插件吗?

是一个ruby gem,它将从您的config/locales文件夹创建一个国际化文件。但是,如果您不使用rails,您可以找到自己使用的javascript

然后,只需将翻译存储在嵌套对象中

I18n.translations = {"en":{"date":{"formats":{"default":"%Y-%m-%d","short":"%b %d","long":"%B %d, %Y"}}}};
我在我的项目中使用的一个可能对您也有用的东西是“胡子补丁”,它可以自动转换格式为@@translation\u key的字符串@@

i18nize = function (result) {
    if (I18n) {
      var toBeTranslated = result.match(/@@([^@]*)@@/gm);
      if (!toBeTranslated) return result;
      for(var i = 0; i < toBeTranslated.length; i++) {
        result = result.replace(toBeTranslated[i], I18n.t(toBeTranslated[i].replace(/@/g, "")));
      }
    }
    return result;
};
i18nize=函数(结果){
if(I18n){
var toBeTranslated=result.match(/@([^@]*)@@/gm);
如果(!toBeTranslated)返回结果;
for(var i=0;i
然后在渲染后调用i18nize,以允许将翻译放入模板中,而不是将其传递

小心修补小胡子,因为您将无法将模板移植到标准小胡子实现。但是在我的情况下,提供的好处超过了这个问题


希望这能有所帮助。

我知道这已经得到了回答,但我想与大家分享我的简单解决方案。为了基于Gazler使用I18n.js的解决方案(我们在工作中的项目中使用了I18n.js),我只使用了一个非常简单的Handlebars助手来简化动态本地化过程:

处理程序

Handlebars.registerHelper('I18n',
  function(str){
    return (I18n != undefined ? I18n.t(str) : str);
  }
);
模板

<script id="my_template" type="x-handlebars-template">
    <div>{{I18n myVar}}</div>
</script>

{{I18n myVar}}
这样做的主要优点是,在整个json对象上没有昂贵的前/后处理。更不用说传入的json是否有嵌套的对象/数组,如果对象很大,查找和解析它们所花费的时间可能会很昂贵


干杯

根据@poweratom的回答:

仅适用于ember.js,与传递给I18n.js的选项相同

如果使用计算属性,它将神奇地重新加载

Ember.Handlebars.helper "t", (str, options) ->
  if I18n? then I18n.t(str, options.hash) else str
模板:

{{t 'sharings.index.title' count=length}}
Yml:


对于那些不使用任何JS框架的人来说,看起来也很有希望


只需使用NodeJs/Express创建Handlebar helper来调用如下翻译

  • (检测接受语言标头)

  • 示例翻译文件

    {   
     "hello": "hello",   
     "home-page": {
       "home": "Home",
        "signup": "Sign Up"  
     } 
    }
    
  • 快速控制器

    ...
    data.tr = req.__('home-page');
    var template = Handlebars.compile(source);
    var result = template(data);
    
  • 车把模板

        <li class="active"><a href="/">{{tr.home}}</a></li>
    

问题已经得到了回答,但在这种情况下,您可能不想依赖任何i8n库而完全使用自己的库。我正在使用我自己的灵感来源于

,正如已经建立的那样,使用手柄进行国际化意味着您必须注册一个自定义帮助程序来链接到您选择的i18n库。大多数i18n库都没有现成的“胶水”,但添加起来非常容易

基于@poweratom的答案(这反过来又建立在@Glazer的答案之上),可以注册一个助手,该助手允许通过handlebar参数

Handlebars.registerHelper('i18n',
  function(str){
    return new Handlebars.SafeString((typeof(i18n) !== "undefined" ? i18n.apply(null, arguments) : str));
  }
);
现有答案使用其他库,但我更喜欢(npm/roddeh-i18n),因为它更好地支持客户端国际化的更重要方面,如语法规则(并且它不依赖于YML和/或Ember,也不需要使用nodejs进行服务器端呈现)

使用上面注册的帮助程序,我们只需使用客户端JSON/JavaScript即可添加翻译:

i18n.translator.add({
  "values":{
    "Yes": "はい",
    "No": "いいえ",
    "It is %n": [[0,null,"%nです"]],
    "Do you want to continue?": "続けたいですか?",
    "Don't worry %{name}": "%{name}を心配しないでください",
    "%{name} uploaded %n photos to their %{album} album": "%{name}は彼の%{album}アルバムに写真%n枚をアップロードしました"
  },
  "contexts":[
    {
      "matches": { "gender": "male" },
      "values": { "%{name} uploaded %n photos to their %{album} album": [[0,null,"%{name}は彼の%{album}アルバムに写真%n枚をアップロードしました"]] }
    },
    {
      "matches": { "gender": "female" },
      "values": { "%{name} uploaded %n photos to their %{album} album": [[0,null,"%{name}は彼女の%{album}アルバムに写真%n枚をアップロードしました"]] }
    }
  ]
});
现在,我们创建的任何把手模板都可以通过向库传递参数进行国际化。例如,格式化一个数字(即“%n”)要求第一个参数是该数字的路径。因此,要从对象{“count”:3}获取计数,我们可以引用路径“/count”或只是“count”。条件匹配要求最后一个参数是找到匹配项的对象的路径;通常只有根对象“.”

下面是一个更完整的示例:

//使用http://i18njs.com (npm/roddeh-i18n)
//包括:
//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js
//rawgit.com/components/handlebar.js/master/handlebar.js
//cdn.jsdeliver.net/npm/roddeh-i18n@1.2.0/dist/i18n.min.js
//注册I18N帮助程序{{I18N'要翻译的文本'}}
车把.注册表帮助器('i18n',
功能(str){
返回新的把手.SafeString((typeof(i18n)!=“undefined”?i18n.apply(null,参数):str));
}
);
//注册模板
var templateSource=$(“#atemplate”).html();
var template=handlebar.compile(templateSource);
函数更新消息(数据){
$('#目标消息').html(模板(数据));
}
//添加翻译
函数集语言(lang){
//西班牙文
如果(lang='es'){
i18n.translator.reset();
i18n.translator.add({
“价值观”:{
“是”:“是”,
“否”:“否”,
“要继续吗?”:“继续吗?”,
“不必担心%{name}”:“不必担心%{name}”,
“它是%n”:[[0,null,“Es%n”]],
“%$name}已将%n张照片上载到其%{album}相册:”[
[0,0,“%{name}ha subido%n fotos a su album%{album}”],
[1,1,“%{name}ha subido%n foto a su album%{album}”],
[2,null,“%{name}ha subido%n fotos a su album%{album}”]
]
}
});
}
//日文
else if(lang='jp'){
i18n.translator.reset();
i18n.translator.add({
“价值观”:{
“是”:はい",
“否”:いいえ",
“它是%n”:[[0,null,”%nです"]],
“要继续吗?”:“続けたいですか?",
“别担心%{name}”:“%%{name}”を心配しないでください",
“%$name}已将%n张照片上载到其%{album}相册”
Handlebars.registerHelper('i18n',
  function(str){
    return new Handlebars.SafeString((typeof(i18n) !== "undefined" ? i18n.apply(null, arguments) : str));
  }
);
i18n.translator.add({
  "values":{
    "Yes": "はい",
    "No": "いいえ",
    "It is %n": [[0,null,"%nです"]],
    "Do you want to continue?": "続けたいですか?",
    "Don't worry %{name}": "%{name}を心配しないでください",
    "%{name} uploaded %n photos to their %{album} album": "%{name}は彼の%{album}アルバムに写真%n枚をアップロードしました"
  },
  "contexts":[
    {
      "matches": { "gender": "male" },
      "values": { "%{name} uploaded %n photos to their %{album} album": [[0,null,"%{name}は彼の%{album}アルバムに写真%n枚をアップロードしました"]] }
    },
    {
      "matches": { "gender": "female" },
      "values": { "%{name} uploaded %n photos to their %{album} album": [[0,null,"%{name}は彼女の%{album}アルバムに写真%n枚をアップロードしました"]] }
    }
  ]
});
<script id="messagestemplate" type="text/x-handlebars-template">
  <p>
    {{i18n 'Do you want to continue?'}} {{i18n 'Yes'}}<br>
    {{i18n 'Don\'t worry %{name}' . }}<br>
    {{i18n 'It is %n' count}}<br>
    {{i18n '%{name} uploaded %n photos to their %{album} album' count . .}}
  </p>
</script>
var userData = {
  gender: "male",
  name: "Scott",
  album: "Precious Memories",
  count: 1
};

var templateSource = $("#messagestemplate").html();
var messagesTemplate = Handlebars.compile(templateSource);
var renderedMessages = messagesTemplate(userData);

$('#target-message').html(renderedMessages);