我正在创建一个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
答案 0 :(得分:2)
并非所有后端都符合相同的界面(在我看来非常糟糕),但是你可以通过猴子修补或创建自己的后端来完成你所需要的内容,该后端基于其中一个内置I18n后端。
例如,我希望有一个redis后端可以回退到默认的I18n后端,我需要它来处理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\"}}}"