【初心者向け】i18nを利用して、enumのf.selectオプションを日本語化する[Rails]

こんにちは、エンジニアとして就職を目指しています、タヌキです。
前回の記事では、haml, form_withを利用して、f.selectの入力フォームを作るために色々と試行錯誤した話、
さらに、enumを利用してデータを利用しやすくした話を書きました。

▼前回の記事はこちら
[【初心者向け】form_with, haml, enumを使ってselectによるプルダウンリストを作った話[Rails]][1]
[1]:https://qiita.com/tanutanu/items/1bb5f12ac8ae90e71352



その中で、f.selectの入力フォームは実装できたのですが、
最後に選択肢が英語になってしまうという課題が残りました。

そのため、今回はenum利用時に、f.selectの選択肢を日本語にするための方法をご紹介したいと思います。
合わせて、日本語化したデータをビューなど他の場所でも使うための方法もご紹介いたします。
どうぞよろしくお願いいたします。


## 今回参考にした記事

まず、今回参考にさせていただいた記事はこちらです。
参考というよりも、こちらの記事がとても良すぎて、ほとんどこのままの内容で実装できましたので、
本記事の内容も下記の記事とほぼ同じです。

ページ下方の、selectオプション以外への使用方法の項だけ、内容が異なります。
自分自身のまとめのために、やったことを記しているので、
selectオプションへの使用方法だけが知りたい！という方は下記の記事を参照された方が良いと思います。

▼参考にした記事はこちら
https://qiita.com/tomoharutsutsumi/items/272a10f4fefb555944f2

## 必要なファイル
enumを日本語化する上で必要だったファイルは下記の通りです。


* (gem) enum_help, rails-i18n
*  model  ←今回は restaurant.rb
*  ja.yml
*  application.rb


その他、enumを日本語化して記載したいビューファイルです。

## gem ファイルのインストール

まずは、enumをI18n(国際化)対応させるgem
enum_help をインストールします。

```ruby:Gemfile
gem 'enum_help'
```

※追記：当初は`rails-i18n`というgemも必要と書いていたのですが、`rails-i18n`はRails 2.2以降からRailsに同梱されているそうです。

bundle lnstall します。

## model に enumを記載する

次に、modelにenumを記載します。
今回は、レストラン情報を載せるrestaurantsテーブルの、昼の予算のカラム budget_d に対して、下記のようにenumを記載しました。


```ruby:models/restaurant.rb
enum budget_d: {
    default: 0,
    till_1000: 1,
    till_2000: 2,
    till_3000: 3,
    till_4000: 4,
    till_5000: 5,
    over_5000: 6
  },  _prefix: true
```

最後の _prefix: true は、同じ値をもつ複数のenumが存在するときにつけるものです。
今回は、夜の予算を定義する budget_n も同じアプリ内に存在していたので、 _prefix:true をつけました。

＊追記： statusが２個あるとか、そんな場合にもつけるべきらしいので、上記のようにものすごく似た２つのテーブルがある場合以外にもつけたほうが良さそうです。

▼詳しくは、こちらをご覧ください。
[Rails5 から enum 使う時は_prefix（接頭辞）_suffix（接尾辞）を使おう][3]
[3]:https://qiita.com/emacs_hhkb/items/fce19f443e5770ad2e13


##  ja.ymlに翻訳情報を記載する

翻訳情報を記したファイル、ja.ymlを
config/locales/ 内に作成し、下記のように記します。

```ruby:config/locales/ja.yml

ja:
  enum:
    restaurant:
      budget_d:
        default: "--"
        till_1000: "~¥999"
        till_2000: "¥1,000~¥1,999"
        till_3000: "¥2,000~¥2,999"
        till_4000: "¥3,000~¥3,999"
        till_5000: "¥4,000~¥4,999"
        over_5000: "¥5,000~"
     
```

上記は、enumのデータを翻訳したい時の記載方法ですので、その他の場所を翻訳したいときには、別の記載方法となります。

▼詳しくは、こちらの記事をご覧ください。
https://qiita.com/shi-ma-da/items/7e5c3d75c9a9f51abdd5


## デフォルトの言語を日本語化する

application.rb の設定を変更して、デフォルトの言語を日本語にします。

```ruby:config/application.rb

　#  前略

module SomeApp
  class Application < Rails::Application
    
    #　中略

    config.i18n.default_locale = :ja # デフォルトのlocaleを日本語(:ja)にする

　end
end
```

## パスを通して、i18nのロケールファイルが読み込まれるようにする。

以下の記述も　application.rb　に追記して、locales フォルダ内のファイルが全て読み込まれるようにします。

```ruby:config/application.rb

#  前略

module SomeApp
  class Application < Rails::Application
    
    #　中略

    config.i18n.default_locale = :ja
    config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # 追記

  end
end
```

これで、enumを日本語化するための設定は完了です！
設定だけでかなり長かったです・・・。


## 最終的なコード

そして、今回　f.select に使用したコードは下記のようになりました。

```haml:viewfile

= f.select :budget_d, Restaurant.budget_ds_i18n.keys.map{|k| [I18n.t("enum.restaurant.budget_d.#{k}"), k]}

```

まず、budget_d の中身を含む配列、budget_ds　に対し、
keys メソッドを実施し、[["default": "--"], ["till_1000": "~¥999"], ...] などのキーだけ（["default", "till_1000"]）を配列の形で取り出します。

そして、その値一つ一つに対して、mapを使い処理をしています。

処理の内容は、
I18n.t ... enumの内容を翻訳するメソッド
を使って、["翻訳した内容":"value"]の配列を作る処理です。

enum.restaurant.budget_d のように、
ja.ymlに書いたenumの翻訳情報の位置をきちんと記します。

## 結果

その結果、できたドロップダウンリストがこちら。

[![Image from Gyazo](https://i.gyazo.com/bc749ff5853247ae31ed27886c98fb2c.png)](https://gyazo.com/bc749ff5853247ae31ed27886c98fb2c)

生成されたコードがこちらです。

[![Image from Gyazo](https://i.gyazo.com/133f8a6a00666c2b08962e8a46c8b6f0.png)](https://gyazo.com/133f8a6a00666c2b08962e8a46c8b6f0)

valueがdefaultやtill_1000などになっていますが＾＾；これで正しくvalueはデータベースに保存されます。

## その他の場所で、翻訳したデータを使う。

最後に、ビューのその他の場所で翻訳したファイルを使う方法をご紹介します。
基本的には、「カラム名_i18n」をつけた表記にすればokです。

```haml:view

%p= restaurant.budget_d_i18n #これで、昼の予算が日本語で表示される

```

enumの日本語化といい、f.selectの表記といい、なかなか時間のかかった実装でした。
それでは、ここまで読んでくださり、ありがとうございました。