【问题标题】:How to get all translations from all I18n backends如何从所有 I18n 后端获取所有翻译
【发布时间】:2014-03-13 16:43:07
【问题描述】:

我正在创建一个 rake 任务,它将收集 rails 应用程序中存在的所有翻译并将它们以某种格式(可能是 csv 的 yaml)输出到文件。

有没有办法使用内置(或某些 gem)方法获取所有翻译?

目前,我能想到的最好的方法是遍历 I18n.backend.backends 检查他们的类并在此基础上执行不同的操作,最后将所有内容合并到一个哈希中。

类似

all_translations = {}
I18n.backend.backends.each do |backend|
  if backend.class == Simple
    translations = backend.send(:translations)
    # etc
  elsif backend.class == KeyValue
    # something else
  else
    # ...
  end
end

【问题讨论】:

    标签: ruby-on-rails redis rails-i18n


    【解决方案1】:

    并非所有后端都符合相同的接口(在我看来这非常可怕),但是您可以通过猴子补丁或创建自己的基于内置的后端之一来完成您需要做的事情I18n 后端。

    例如,我想拥有一个回退到默认 rails I18n 后端的 redis 后端,并且我需要它与 i18n-js gem 一起工作。由于 KeyValue 后端允许您查找整个子树的翻译,因此只要您将所有内容存储在顶级键下,就可以模拟“翻译”方法。就这么简单:backend.translate(:en, 'top-level-key')"

    # config/initializers/custom_i18n.js
    module CustomI18n
      def self.backend
        Backend::Chain.new
      end
    
      module Backend
        class Chain < I18n::Backend::Chain
          def initialize
            super(RedisStore.new, I18n::Backend::Simple.new)
          end
    
          def initialized?
            backends.all? do |backend|
              !backend.respond_to?(:initialized?) || backend.initialized?
            end
          end
    
          protected
    
          def translations
            backends.each_with_object({}) do |backend, hash|
              backend.instance_eval do
                if respond_to?(:translations, true)
                  hash.deep_merge! translations
                else
                  available_locales.each do |locale|
                    translations = translate(locale, RedisStore::SCOPE, :scope => nil) rescue ArgumentError
                    hash.deep_merge!({ locale => translations }) if translations
                  end
                end
              end
            end
          end
        end
    
        class RedisStore < I18n::Backend::KeyValue
          SCOPE = 'redis'
    
          def initialize(*args)
            super(Redis.new)
          end
    
          def translate(*args)
            args << {} unless args.last.is_a?(Hash)
            args.last[:scope] = SCOPE unless args.last.has_key?(:scope)
            super
          end
    
          def store_translations(locale, data, options = {})
            super(locale, { SCOPE => data }, options)
          end
        end
      end
    end
    
    I18n.backend = CustomI18n.backend
    

    因此,使用这种方法,您可以执行以下操作:

    redis_backend = I18n.backend.backends.find { |backend| backend.is_a?(CustomI18n::Backend::RedisStore) }
    redis_backend.store_translations(:en, {:foo => { :bar => { :baz => 'qux' } } })
    

    并且它会自动存储在“redis”的顶级键下,但您可以通过各种不同的方式正常访问它:

    > I18n.backend.send(:translations)[:en][:foo]
    => {:bar=>{:baz=>"qux"}}
    
    > I18n.t('foo')
    I18N keys: [:en, :foo]
     => {:bar=>{:baz=>"qux"}}
    

    但是如果你真的看一下redis,你会发现它存储在顶级键下:

    > Redis.new.get('en.redis')
     => "{\"foo\":{\"bar\":{\"baz\":\"qux\"}}}"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-01
      • 1970-01-01
      • 2011-04-18
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多