【Rails】エラーメッセージを日本語化する

本記事では、入力フォームが空のまま送信された場合に表示されるエラーメッセージを、
英語から日本語に変換する方法をアウトプットしていきます。

# 前提条件
・Rubyバージョン2.6.5
・Railsバージョン6.0.0
・エラーメッセージを表示したいページは作成済みとします。

# この記事の構成
①エラーメッセージのビュー作成
②部分テンプレートの呼び出し設定
③日本語の言語設定とGemの導入
④`devise.ja.yml`の作成
⑤`ja.yml`の作成
⑥バリデーションでさらに詳細なエラーメッセージを設定

#①エラーメッセージのビュー作成
まずはエラーメッセージを生成するビューを作ります。
どのモデルのバリデーションにも対応できるように、if文に`model.errors.any?`を記述しています。

```app/views/layouts/_error_messages.html.erb
<% if model.errors.any? %>
  <div class="error-alert">
    <ul>
      <% model.errors.full_messages.each do |message| %>
        <li class='error-message'><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>
```

#②部分テンプレートの呼び出し設定

エラーメッセージを表示させたい部分に、`<%= render 'layouts/error_messages', model: form.object %>`を記述します。

```app/views/tweets/_form.html.erb
<%= form_with(model: tweet, local: true) do |form| %> 
  <%= render 'layouts/error_messages', model: form.object %>　#この一行を追加
  <%= form.text_field :image, placeholder: "Image Url" %>
  <%= form.text_area :text, placeholder: "text", rows: "10" %>
  <%= form.submit "SEND" %>
<% end %>
```

先程の`_error_messages.html.erb`は「layoutsディレクトリ」、
上記の`_form.html.erb`は「tweetsディレクトリ」となっており**異なるディレクトリの部分テンプレートを呼び出す**ため、`layouts/error_messages`のようにディレクトリ名から指定しています。

`form.object`には入力されたフォームの値が入っており、`modelキー`で管理しています。
そして部分テンプレートを呼び出す際にこの`modelキー`を渡すことで、
`if model.errors.any?`で「エラーがあるかどうか？」＝「バリデーションに引っかかる値はあるかどうか？」を判断してくれます。
<br>
なおログイン画面で、EmailとPasswordに何も入力せず投稿した場合にエラーメッセージを表示するには以下のように記述します。

```
<div class="contents row">
  <div class="container">
    <h2>Log in</h2>
    // 追加ここから
    <div class='login-flash-message'>
      <%= flash[:notice] %>
      <%= flash[:alert] %>
    </div>
    <%= form_with model: @user, url: user_session_path, id: 'new_user', class: 'new_user', local: true do |f| %>
    // 追加ここまで
      <div class="field">
        <%= f.label :email %><br />
        <%= f.email_field :email, autofocus: true %>
      </div>
```
※新規登録には、deviseの機能で初めからエラーメッセージが表示される機能が備わっています。


# ③日本語の言語設定とGemの導入
英語から日本語に変える設定を行っていきます。
`:ja`は日本語設定にするという意味です。

```config/application.rb
# 中略
module Pictweet
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0

    # 日本語の言語設定。この一行を追加。
    config.i18n.default_locale = :ja
      # 省略
    end
end
```

日本語に対応する"rails-i18n"というGemを導入します。

```
#中略
gem 'rails-i18n'
```

記述後は`bundle install`を実行します。

#④devise.ja.ymlの作成
エラーメッセージを全て日本語にするためには、**localeファイル**が必要になります。
localeファイルとは、様々な言語に対応できる言語ファイルです。

**step1**
`config/localesディレクトリ`に、`devise.ja.yml`というファイルを手動で作成します。

**step2**
下記サイトの記述内容を丸ごとコピーして、作成したdevise.ja.ymlの中に貼り付けます。
[devise.ja.yml](https://github.com/tigrish/devise-i18n/blob/master/rails/locales/ja.yml)

この段階で、ログイン画面は、全て日本語のエラーメッセージが表示されるようになりましたが、自分で追加したカラムは英語表記のままとなっています。
したがって、それらを翻訳するファイルを手動で作成していきます。


#⑤ja.ymlの作成
`config/localesディレクトリ`に、`ja.yml`というファイルを作成します。

```config/locales/ja.yml
ja:
  activerecord:
    attributes:
      user:
        nickname: ニックネーム
      tweet:
        text: テキスト
        image: 画像
  activemodel:   # Formオブジェクトを用いた場合
     attributes:
       order_object:
         post_code: 郵便番号
```

これで「nickname = ニックネーム」と表示されるようになります。
なおFormオブジェクトで設定しているカラム名を日本語設定する場合は、`activemodel`の下に記述します。
これはFormオブジェクトを作成する際、`include ActiveModel::Model`のようにしているためです。

#⑥バリデーションでさらに詳細なエラーメッセージを設定
もし「郵便番号はハイフンを含めた半角文字列で入力してください」のように詳細なエラーメッセージを設定したい場合は、バリデーションで`message`を指定します。
以下いろいろなパターンをまとめてみたので、ご参考ください。

```
  with_options presence: true do
    validates :post_code, format: { with: /\A[0-9]{3}-[0-9]{4}\z/, message: 'はハイフンを含めた半角文字列で入力してください (例：123-4567)' }
    validates :prefecture_id, numericality: { other_than: 1, message: "を入力してください" }
    validates :phone_number, format: { with: /\A[0-9]{10,11}+\z/, message: 'は10桁以上11桁以内の半角数値で入力してください' }
    validates :image, presence: { message: 'を選択してください' }
  end
```
<br>
以上でエラーメッセージの日本語化は完了です！お疲れ様でした。
ご指摘などあれば、ご教授いただけると幸いです。