Help us understand the problem. What is going on with this article?

Railsのvalidate周りのi18n対応でハマったこと

More than 3 years have passed since last update.

Model.errorsを view で表示する際にハマったので同じ気持の人が減ることを祈って
調べたことをまとめます。

今回やろうとしたこと。

Itemモデルの登録formでのvalid結果をviewに表示。
表示の際にエラーメッセージはi18nを用いて日本語化する。

ItemモデルはDraftという名前空間に定義している。

ハマったこと

変換されない。(結論から言うと勘違いです。)

結論

<% @item.errors.full_messages.each do |msg| %>
  <ul class="list">
    <li><%= msg %></i>
  </ul>
<% end %>
ja.yml
ja:
  activerecord:
    attributes:
      draft/item:
        item_name: 商品名

上記のように設定し、Model.errors.full_messageを使用すると、
i18nで変換されたカラム名(attribute)が取得できる。

名前空間を指定する場合は
draft/item:のように、スラッシュ区切りで指定する。

調べられた事。

途中色々とつまずいた為、
足りない箇所については指摘していただけると幸いです。

勘違い

まず、Model.errors.full_messages ではなく、
Model.errors.messagesを使用していました。

messages には以下のようにハッシュが入っています。

@messages={:item_name=>["を入力してください"]}

このハッシュのkeyである、item_name が変換されないと困っていました。(アホ)

どのように変換されるのか。

変換される箇所、メソッドは以下です。

activemodeのtranslation.rb

def human_attribute_name(attribute, options = {})
 略
end

上記メソッドが、full_messagesメソッドから辿ると呼ばれています。

activemodelのerrors.rb

def full_messages
      map { |attribute, message| full_message(attribute, message) }
end

def full_message(attribute, message)
      return message if attribute == :base
      attr_name = attribute.to_s.tr('.', '_').humanize
      attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
      I18n.t(:"errors.format", {
        default:  "%{attribute} %{message}",
        attribute: attr_name,
        message:   message
      })
end

これにより、full_messagesメソッドによって返却されるエラーメッセージは、
i18nで変換した結果が取得されます。

うまく思い通りに変換されない場合の対処法

yamlの記述の仕方がわからない等(今回でいうと名前空間に定義したモデルだとyamlの書き方が変わる)
場合に、どのように記述すればよいか調べる。

今回の場合では、human_attribute_nameメソッドで、
i18nで取得しようとしているパスと優先順位がわかるため、デバッグすることで確認します。

:"#{attributes_scope}.#{klass.model_name.i18n_key}/#{namespace}.#{attribute}"

上記のように文字列連結で、i18nで取得するパスを作成しているので、
作成された結果をデバッグで見れば確認することが出来ます。

今回は以下のようになっていました。

[:"activerecord.attributes.draft/item.item_name", :"attributes.item_name", "Item name"]

優先順位が高い順番で格納されています。
このようにyamlで記述すればいいことがわかります。

他に変換がうまく行かないものも、
このように、パスを設定している箇所を特定しデバッグすることで確認できます。
その設定している箇所を特定するいい方法はわかりません・・・。
ご存知の方がいましたらアドバイスをお願い致します・・。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした