30
26

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 5 years have passed since last update.

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

Posted at

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で記述すればいいことがわかります。

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

30
26
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
30
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?