不用意に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}") %>
↓日本語での表示ができました↓
translateメソッド
t("activerecord.attributes.task.statuses.#{@task.status}")
の先頭t
はtranslate
メソッドの別名メソッド(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
の引数に渡すことで、日本語での表示を実装しました。
まとめ
enumのi18n対応が複雑みたいな記事を読んだことがあったので、とっつきづらいのかなあと思っていましたが、仕組みを理解した上で書いてみると思いの外手軽だったので、むやみにgemを追加することなく実装できて良いのではないかと感じました。
参考記事
・https://railsguides.jp/i18n.html ・https://pikawaka.com/rails/enum