rhanda | 元銀行員Web系エンジニアの日記

実務未経験からWeb系受託開発企業に転職したひよっこエンジニアが覚えたことや日々の感情を残すブログ

【Rails】gemを使わないで手軽にenumをi18nに対応させて日本語化する

不用意にgemを追加すべきでない場面もあるかと思い、学習を兼ねて取り組んでみました。 また同じようなやり方をしている記事も見当たらなかったので、記録として残すものです。



前提

今回は簡単なタスク管理アプリケーションを想定し、Taskモデルに["waiting", "doing", "done"]の3つを持つステータスカラムを列挙型で実装し、それをi18nでlocalizeして、[未着手, 着手中, 完了]で日本語表示しようとしています。

enum status: { waiting: 0, doing: 1, done: 2 }

結論

以下のようなコードになりました。

ja.yml
ja:
  activerecord:
    models:
      task: タスク
    attributes:
      task:
        id: ID
        name: タスク名
        created_at: 登録日時
        updated_at: 更新日時
        status: ステータス
        statuses:
          waiting: 未着手
          doing: 着手中
          done: 完了
セレクトボックスの選択肢を日本語表示
<%= f.select :status, options_for_select(Task.statuses.map { |k, _v| [t("activerecord.attributes.task.statuses.#{k}"), k] }) %>
タスク詳細画面での表示
 <%= t("activerecord.attributes.task.statuses.#{@task.status}") %>

↓日本語での表示ができました↓

スクリーンショット 2021-06-16 21.06.06.png

スクリーンショット 2021-06-16 21.24.13.png

translateメソッド

t("activerecord.attributes.task.statuses.#{@task.status}")の先頭ttranslateメソッドの別名メソッド(Railsガイドを参照)で訳文を参照します。

config/application.rbなどでconfig.i18n.default_locale = :jaと使用するロケール(言語)を設定しておくと、ロケールに合致する辞書ファイル(今回はja.yml)が選択され、activerecord→attributes→tasks→tatusesと順番に参照されて、今回は#{@task.status}waitingを登録しておいたので、この書き方で未着手が表示されています。

定数リスト取得メソッド

モデルファイルのenumに記載している複数個の定数リストを取得するメソッドのことで、モデルクラス.enumカラム名の複数形という形で使用します。(こちらを参照)

irb(main):001:0> Task.statuses
=> {"waiting"=>0, "doing"=>1, "done"=>2}


セレクトボックスの日本語表示を実装している箇所では、Task.statusesで取得したハッシュに対してmapメソッドを使用し、その後の#tメソッドで翻訳されたステータスと、そのままのステータスが入った配列の配列を作成しています。

irb(main):007:0> Task.statuses.map{ |k, _v| [I18n.t("activerecord.attributes.task.statuses.#{k}"), k] }
=> [["未着手", "waiting"], ["着手中", "doing"], ["完了", "done"]]

それをoptions_for_selectの引数に渡すことで、日本語での表示を実装しました。



まとめ

enumi18n対応が複雑みたいな記事を読んだことがあったので、とっつきづらいのかなあと思っていましたが、仕組みを理解した上で書いてみると思いの外手軽だったので、むやみにgemを追加することなく実装できて良いのではないかと感じました。

参考記事

https://railsguides.jp/i18n.htmlhttps://pikawaka.com/rails/enum