如何在 Rails 中列出所有可用的语言环境键?

How to list all available locale keys in Rails?

我的语言环境文件因一堆嵌套键而变得笨拙。有没有办法从单个语言环境文件中获取所有可用语言环境键的列表或所有语言环境键?

例如

en:
  car:
     honda:
          civic:
               name: 'Civic'
               description: 'Entry Level Sedan'
     ferrari:
          la_ferrari:
               name: 'La Ferrari'
               description: 'Supercar'

此语言环境应 return 键列表,在本例中为

['en.car.honda.civic.name', 'en.car.honda.civic.description',
'en.ferrari.la_ferrari.name', 'en.car.ferrari.la_ferrari.name.description']

是否有 Rails (I18n) 助手来执行此操作? 另一种方法是遍历解析后的 YAML。

我不假装这是唯一正确的解决方案,但这段代码对我有用。

# config/initializers/i18n.rb
module I18n
  class << self
    def get_keys(hsh = nil, parent = nil, ary = [])
      hsh = YAML.load_file("config/locales/en.yml") unless hsh
      keys = hsh.keys
      keys.each do |key|
        if hsh.fetch(key).is_a?(Hash)
          get_keys(hsh.fetch(key), "#{parent}.#{key}", ary)
        else
          keys.each do |another|
            ary << "#{parent}.#{another}"[1..-1]
          end
        end
      end
      ary.uniq
    end
  end
end

结果

[14] pry(main)> I18n.get_keys
=> ["en.car.honda.civic.name", "en.car.honda.civic.description", "en.car.ferrari.la_ferrari.name", "en.car.ferrari.la_ferrari.description", "en.car.suzuki.escudo.name", "en.car.suzuki.escudo.description"]

我的en.yml

en:
  car:
    honda:
      civic:
        name: 'Civic'
        description: 'Entry Level Sedan'
    ferrari:
      la_ferrari:
        name: 'La Ferrari'
        description: 'Supercar'
    suzuki:
      escudo:
        name: 'Escudo'
        description: 'SUV'

这是我不得不处理这个问题时编写的脚本。对我来说很棒。

#! /usr/bin/env ruby

require 'yaml'

filename = if ARGV.length == 1
  ARGV[0]
elsif ARGV.length == 0
  "/path/to/project/config/locales/new.yml"
end

unless filename
  puts "Usage: flat_print.rb filename"
  exit(1)
end

hash = YAML.load_file(filename)
hash = hash[hash.keys.first]

def recurse(obj, current_path = [], &block)
  if obj.is_a?(String)
    path = current_path.join('.')
    yield [path, obj]
  elsif obj.is_a?(Hash)
    obj.each do |k, v|
      recurse(v, current_path + [k], &block)
    end
  end
end

recurse(hash) do |path, value|
  puts path
end

获取一系列可用语言环境:

I18n.available_locales

我建议避免将多个区域设置放在一个 YAML 文件中。如果您出于某些与处理相关的原因需要这样做,您可以随时将文件与您的 *NIX shell:

...到文件

cat my_app/config/locales/*.yml >> locales.yml

...或到另一个进程

cat my_app/config/locales/*.yml | command_that_takes_stdin -