【问题标题】:Rails: Internationalization of Javascript Strings?Rails:Javascript 字符串的国际化?
【发布时间】:2011-02-11 16:55:28
【问题描述】:

所以,我们现有的 Rails 2.3.5 应用程序根本不支持国际化。现在,我非常熟悉 Rails I18n 的东西,但我们在 /javascripts/ 中有很多输出字符串。我不是这种方法的忠实拥护者,但不幸的是,现在修复它为时已晚。

我们如何将存储在 Rails 应用程序中的 JS 文件中的字符串国际化? Rails 甚至不提供 JS 文件...

我想我总是可以让 Rails 应用程序提供 JS 文件,但这似乎很糟糕。有没有插件可以做到这一点?

【问题讨论】:

    标签: javascript ruby-on-rails internationalization


    【解决方案1】:

    为什么不做一些简单的事情:

    <script type="text/javascript">
      window.I18n = <%= I18n.backend.send(:translations).to_json.html_safe %>
    </script>
    

    然后在 JS 中你可以这样做:

    I18n["en-US"]["alpha"]["bravo"];
    

    我已经将我的包裹在一个应用程序助手中。

    def current_translations
      @translations ||= I18n.backend.send(:translations)
      @translations[I18n.locale].with_indifferent_access
    end
    

    然后我在 application.html.erb 中的调用如下所示:

    <script type="text/javascript">
      window.I18n = <%= current_translations.to_json.html_safe %>
    </script>
    

    这使您不必知道 JavaScript 中的当前语言环境。

    I18n["alpha"]["bravo"];
    

    或者

    I18n.alpha.bravo;
    

    【讨论】:

    • 完美运行,谢谢。我还实现了这个t 方法以使其更加有轨范。 gist.github.com/6a3f1b3a4cf8de889e34t("products.price");
    • 我只是花了一点时间试图让 i18n-js 工作......你的解决方案更简单并且立即生效!
    • “加载”翻译时不需要包含整个文件。 I18n.backend.send(:translations) 返回一个哈希值,因此您可以使用 I18n.backend.send(:translations)["alpha"] 之类的内容限定翻译范围,这只会加载您需要的部分。
    • 我不知道为什么 i18n-js 这么复杂。这非常有效(甚至是预编译!),并且在我最终需要时很容易拆分和扩展。谢谢!
    • 如何将其用于像这样的翻译 show_text: "Showing %{entry_name} Choices"
    【解决方案2】:

    Balibu 被遗弃了。使用 i18n-js:https://github.com/fnando/i18n-js

    【讨论】:

      【解决方案3】:

      Ryan 上面的解决方案是完美的,只是后端如果还没有初始化,就需要初始化。

      I18n.backend.send(:init_translations) unless I18n.backend.initialized?
      # now you can safely dump the translations to json
      

      【讨论】:

      • 当翻译返回空哈希时,我被卡住了,直到我读到你的答案!谢谢
      【解决方案4】:

      为什么不在你的 Javascript 文件中简单地写这个:

      var a_message = "<%= I18n.t 'my_key' %>"
      

      为此,您必须将 .erb 添加到 Javascript 文件的扩展名中。

      如果您不使用 ruby​​ >= 2.0,您可能还需要在 Javascript 文件的顶部添加以下行。

      <%# encoding: utf-8 %>
      

      有关更多信息,请参阅此线程中已接受答案的最后一条评论:Encoding issues in javascript files using rails asset pipeline

      【讨论】:

      • 这会很困难的一个重要原因是资产预编译。当资产被预编译时,javascript 将与您的默认目录翻译一起放入公共目录中。您必须按需编译该资产。不是说这是错的,但肯定有一些问题。
      【解决方案5】:

      对于 rails 3 应用程序,您可以这样做:

      创建一个 i18n.js.erb 文件并将其添加到您的 application.js。并添加这段代码 到文件中。

      <%
      @translator = I18n.backend
      @translator.load_translations
      @translations ||= @translator.send(:translations)[I18n.locale][:javascript]
      %>
      
      window.I18n = <%= @translations.to_json.html_safe %>
      

      我还将我的翻译范围限定为没有巨大的 javascript 文件。我的范围是:javascript。

      希望它对某人有所帮助!

      【讨论】:

      • 这个解决方案有两个问题: 1. 在生产环境中总是相同的,因为资产编译 2. 每次在 yml 中更改翻译时都需要清除 tmp/cache
      【解决方案6】:

      另一个可能有用的选项:

      假设您有一个包含所有可用语言的模型语言(slug)。 它处理缺少翻译的情况(它被默认的语言环境版本取代)

      assets/javascript/i18n.js.erb

      <%
      @translator = I18n.backend
      @translator.load_translations
      
      translations = {}
      Language.all.each do |l|
          translations[l.slug] = @translator.send(:translations)[l.slug.to_sym]
      end
      
      @translations = translations
      
      %>
      window.I18n = <%= @translations.to_json.html_safe %>
      
      window.I18n.t = function(key){
          if(window.I18n[current_locale]){
              el = eval("I18n['"+current_locale+"']." + key);
          }
          if(window.I18n[default_locale] && typeof(el) == 'undefined'){
              el = eval("I18n['"+default_locale+"']." + key);
          }
          if(typeof(el) == 'undefined'){
              el = key;
          }
          return el;
      };
      

      views/layout/application.html.erb

      ...
      <%= javascript_tag "var current_locale = '#{I18n.locale.to_s}';" %>
      <%= javascript_tag "var default_locale = '#{I18n.default_locale}';" %>
      ...
      

      在你的javascript代码中,你可以这样翻译:

      // current_locale:fr , default_locale:en
      
      // existing translation (in french) 
      I18n.t('message.hello_world'); // => Bonjour le monde
      
      // non-existing translation (in french) but existing in english 
      I18n.t('message.hello_this_world'); // => Hello this world
      
      // non-existing translation (french & english) 
      I18n.t('message.hello_this_new_world'); // => message.hello_this_new_world
      

      希望对你有帮助!

      【讨论】:

        【解决方案7】:

        Babilu 是一个 Rails 插件,可以为您完成这项工作。

        【讨论】:

          【解决方案8】:

          Ryan 解决方案非常出色。 但不包括您应该使用的整个文件:@translations[I18n.locale].with_indifferent_access["alpha"] 而不是I18n.backend.send(:translations)["alpha"]

          【讨论】:

            【解决方案9】:

            I18n-js 非常适合我,我会推荐它。如果您使用他的rewrite branch,那么该插件将包含一个/assets/i18n/filtered.js 文件,该文件会准确输出@ryan-montgomery 回答的内容,而无需自己手动执行任何操作。

            这样,您可以在后端使用相同的翻译 使用 Rails 助手 t(:key) 并在前端的 Javascript 中使用 I18n.t('key')

            【讨论】:

              【解决方案10】:

              对于像你描述的“根本不支持国际化”和“现在修复它为时已晚”的应用程序,我写了一个非常快速的方法:jQuery 插件 Quick-i18n:https://github.com/katio/Quick-i18n 演示(以及如何使用它):http://johannpaul.net/Quick-i18n/

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-02-16
                • 2022-06-22
                • 1970-01-01
                • 2012-10-10
                • 1970-01-01
                • 2014-01-19
                相关资源
                最近更新 更多