2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

i18n の hash をフラットにする

Last updated at Posted at 2021-10-22

やりたいこと

https://github.com/svenfuchs/rails-i18n/blob/v6.0.0/rails/locale/ja.yml の翻訳ファイルを i18n を使って読み込むと、以下のような hash を取得できます。

require 'i18n'

I18n.load_path << 'rails/locale/ja.yml'
I18n.locale = :ja
I18n.t('.')
#=>
# {:activerecord=>{:errors=>{:messages=>{:record_invalid=>"バリデーションに失敗しました: %{errors}", :restrict_dependent_destroy=>{:has_one=>"%{record}が存在しているので削除できません", :has_many=>"%{record}が存在しているので削除できません"}}}},
#  :date=>
#   {:abbr_day_names=>["日", "月", "火", "水", "木", "金", "土"],
#    :abbr_month_names=>[nil, "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
#    (省略)
#  :datetime=>
#   {:distance_in_words=>
#     {:about_x_hours=>{:one=>"約1時間", :other=>"約%{count}時間"},
#      :about_x_months=>{:one=>"約1ヶ月", :other=>"約%{count}ヶ月"},
#      (省略)
#    :prompts=>{:second=>"秒", :minute=>"分", :hour=>"時", :day=>"日", :month=>"月", :year=>"年"}},
#  :errors=>
#   {:format=>"%{attribute}%{message}",
#    :messages=>
#     {:accepted=>"を受諾してください",
#      :blank=>"を入力してください",
#      (省略)

これを以下のようなフラットな hash に変換したいです。

{
  "activerecord.errors.messages.record_invalid" => "バリデーションに失敗しました: %{errors}",
  "activerecord.errors.messages.restrict_dependent_destroy.has_one" => "%{record}が存在しているので削除できません",
  "activerecord.errors.messages.restrict_dependent_destroy.has_many" => "%{record}が存在しているので削除できません",
  "date.abbr_day_names"=>["日", "月", "火", "水", "木", "金", "土"],
  "date.abbr_month_names"=>[nil, "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
  # 省略
  "datetime.distance_in_words.about_x_hours.one" => "約1時間",
  "datetime.distance_in_words.about_x_hours.other" => "約%{count}時間",
  "datetime.distance_in_words.about_x_months.one" => "約1ヶ月",
  "datetime.distance_in_words.about_x_months.other" => "約%{count}ヶ月",
  # 省略
  "datetime.prompts.second" => "秒",
  "datetime.prompts.minute" => "分",
  "datetime.prompts.hour" => "時",
  "datetime.prompts.day" => "日",
  "datetime.prompts.month" => "月",
  "datetime.prompts.year" => "年",
  "errors.format" => "%{attribute}%{message}",
  "errors.messages.accepted" => "を受諾してください",
  "errors.messages.blank" => "を入力してください",
  # 省略
}

例えば言語ファイル (YAML) を複数に分割している場合に、すべての翻訳データを列挙するためにこのようなフラットな hash を取得したいです。

方法

ネストした hash を再帰的に処理してフラットな hash に変換するためのメソッドを用意します。

def flatten_nested_hash(hash, previous_key: nil, flat_hash: {})
  hash.each do |key, value|
    current_key = [previous_key, key.to_s].compact.join('.')
    
    if value.is_a?(Hash)
      flatten_nested_hash(value, previous_key: current_key, flat_hash: flat_hash)
      next
    end
    
    flat_hash[current_key] = value
  end
  
  flat_hash
end

flat_hash = flatten_nested_hash(I18n.t('.'))
flat_hash['datetime.distance_in_words.about_x_hours.other']
#=> "約%{count}時間"
I18n.t('datetime.distance_in_words.about_x_hours.other')
#=> "約%{count}時間"
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?