如何在咖啡脚本中实现价值观的国际化

时间:2012-08-24 18:57:32

标签: ruby-on-rails-3 internationalization coffeescript

下面的代码是我在rails应用程序中的一个coffeescript文件中所拥有的。我正在努力为“Select Account First”和“Select One”等字符串值添加i18n支持。在常规的javascript文件中,我一直使用类似I18n.t(“shared.select_account_first”)的东西来获取使用i18n-js gem的字符串的国际化值。

jQuery ->
  networks = $('#account_offering_network_id').html()
  select_network_options = new Option("Select Account First", "", true, false)

  filter_networks_by_account = (account) ->
    if account is 'Select One'
      $('#account_offering_network_id').html(select_network_options)
    else
      escaped_account = account.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/@])/g, '\\$1')
      options = $(networks).filter("optgroup[label='#{escaped_account}']")
      $('#account_offering_network_id').html(options.html())

  # Show proper network dropdown first time
  filter_networks_by_account($('#account_offering_account_id :selected').text())

  # Show proper network dropdown on account change
  $('#account_offering_account_id').change -> filter_networks_by_account($('#account_offering_account_id :selected').text())

所有这一切的目标是根据所选帐户过滤网络下拉列表。如果未选择任何帐户(帐户下拉列表的值显示“选择一个”或相应的i18n值),网络下拉列表应在所选区域设置中显示“选择帐户优先”。

我正在使用i18s-js gem(https://github.com/fnando/i18n-js)在javascript中启用翻译。以下是我在应用程序中为支持gem所做的更改。

在application.js中:

//= require i18n
//= require i18n/translations

在production.rb和development.rb中添加的属性:

# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true
config.i18n.available_locales = [:en, :ru]

在application.html.erb中:

<%# For localization/i18n in javascript %>
<script type="text/javascript">
  I18n.defaultLocale = "<%= I18n.default_locale %>";
  I18n.locale = "<%= I18n.locale %>";
  I18n.fallbacks = true;
</script>

最后我运行了“rake i18n:js:export”,这将创建一个加载了名称 - 值对的翻译文件(app / javascripts / i18n / translations.js)。现在,从任何javascript我可以使用I18n.t(名称)访问翻译。

3 个答案:

答案 0 :(得分:0)

我试图做同样的事情,但我认为你不能,因为显然制作coffeescript的人做出了设计决定,禁止将红宝石变量注入coffeescript文件,以避免重新编译coffeescript每个请求 - 如果你问我,有点不好意思!一个可怕的方法是通过你需要内联的翻译,但这听起来很糟糕!

看看这个:How to access instance variables in CoffeeScript engine inside a Slim template

希望这有帮助!

答案 1 :(得分:0)

只想在这里讨好,因为这是我必须在一些项目上定期做的事情。它并不漂亮,但它是迄今为止我能够提出的最佳解决方案。

使用上面的示例代码:

networks = $('#account_offering_network_id').html()
select_network_options = new Option("Select Account First", "", true, false)

我假设你的HTML代码看起来像这样:

<select id="account_offering_network_id">
    ...you generate a list of stuff here...
</select>

但您真正的问题是您希望翻译“Select Account First”文本。所以这就是我的工作:

<select id="account_offering_network_id" data-default-option-text="Select Account First">
  ...you generate a list of stuff here...
</select>

然后在你的咖啡脚本中,你已经拥有了这个:

networks = $('#account_offering_network_id').html()

要访问已翻译的值(您在HTML / ERB文件中定义的而不是咖啡脚本文件),您可以访问它:

networks = $('#account_offering_network_id').html()
default_text = $('#account_offering_network_id').attr('data-default-option-text');

当然,在您的ERB文件中,您不会传递硬编码的英文翻译,因为您需要当前的区域设置翻译,因此您的实际选择框定义将如下所示:

<select id="account_offering_network_id" data-default-option-text="<%=I18n.t("views.default_select_text")%>">
  ...you generate a list of stuff here...
</select>

这将为您提供您希望通过您正在使用的任何元素的数据属性访问的coffeescript代码中可访问的任何内容的翻译版本。

就像我说的那样 - 它不是很棒,但效果非常好,我定期使用它。

答案 2 :(得分:0)

@mulus的建议很有意义,因为你想缩小你的js并缓存它;做.js.erb不是最佳方式。

无论如何,这是一种快速简便的方法:

我正在使用Ruby on Rails,所以在我的应用程序布局(app/views/layouts/application.html.erb)中我有以下内容:

<head>
  ...
  <meta name='locale' content="<%= params[:locale] %>"><meta>
  ...
</head>

这将允许我在“运行时”将Ruby on Rails中的语言环境传递给Javascript。

然后我创建了一个Translator.coffee文件

class Translator
  @en = {
    internet_connection_lost: "You internet connection has been lost"
    bid_received: "Bid received. New balance $$bid_balance$$"
  }

  @ar = {
    internet_connection_lost: "ra7et el connection"
    bid_received: "Bid received. New balance $$bid_balance$$"
  }

  # you can place the variables above in here too
  # or you can have them in different files. Organize stuff as needed
  @get_translations: (locale) ->
    switch (locale)
      when 'en'
        @en
      when 'ar'
        @ar

  @translate: (val, interpolation) ->
    # get locale from meta
    locale = $("meta[name='locale']").attr("content") || "en"

    # get the translation for the val
    translation = Translator.get_translations(locale)[val]

    # substitute values
    for k,v of interpolation
      translation = translation.replace(k, v)

    return translation

window.Translator = Translator

像这样打电话给Translator

message = Translator.translate("bid_received", { "$$bid_balance$$": "$10.00" })
console.log(message)