今回成し遂げたいこと
- Validationエラーをカスタマイズしたい!
- ヘッダーの
Accept-Language
を見て、エラーを英語と日本語で表示できるようにしたい!
前提
今回は、下記のようなAddressモデルがあると仮定して話をしていきます。addressをcreateするときに、カスタマイズしたエラー、さらにAccept-Language
がja
(または未指定)なら日本語エラー、en
なら英語エラーを表示させることが目標です。
class Address < ApplicationRecord
validates :zip_code, format: { with: /\A[0-9]{3}-[0-9]{4}\z/ }
validates :residence_name, length: maximum: 250
end
コントローラーのcreateメソッドはこんな感じ
class AddressesController < ApiApplicationController
def create
address = Address.new(address_params)
address.save! #例外を発生させたいので!をつける
hash = { message: I18n.t("addresses.address_registration_success"), data: address }
render status: 200, json: { data: hash }
end
end
また、今回はAPIを作っていると仮定し、返り値は全てJSONとします。
現時点でcreateメソッドを動かすと、zip codeがXXX-XXXXの形でないよ
、residence nameは10文字以下でないといけないよ
、が英語で返ってきます。これを日本語化、さらにエラーメッセージをカスタマイズしていきます。
まずはモデルに直接書き込んでみる方法
日本語のエラー文だけで問題ないなら、validationにmessageというパラメターと表示したいメッセージを書いてあげるだけで大丈夫です。
class Address < ApplicationRecord
validates :user_id, uniqueness: true
validates :zip_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "はXXX-XXXXのように記入してください (記入例:123-4567)" }
validates :residence_name, length: { maximum: 10, message: "は10文字以内で入力してください" }
end
結果:カラム名だけ英語になっちゃう
でもカラム名が英語になっていますね。。。。ここも日本語にしてあげたい。その場合はI18n
対応が必要です!
I18nとは?
I18nってなんぞやという方のために、Railsガイドの説明文です。
なんかごちゃごちゃしてよくわからん・・・・(読む気にもならない)。
とりあえず、アプリを日本語にも英語にも、その他ドイツ語とかフランス語とか、多言語に対応できるようにしよう!という機能です。
I18nを入れてみる
I18n用のGemをGemfileに追記して、bundle install
します。
gem 'rails-i18n', '~> 5.1'
I18n
のデフォルト設定をapplication.rb
のApplication Class
内に追記します。
config.i18n.default_locale = :ja #デフォルト言語は日本語にするよ設定
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s] #言語変換表はここにあるよ設定
config.i18n.available_locales = %w(en ja) #変換表は日本語と英語があるよ
最後に、/config/locales
の直下に、ja.yml
という名前のファイルを作成します。
このファイル内で、変換してほしい言葉を書き書きしていきます。
変換例はこんな感じ。
ja:
activerecord:
models:
モデル名: "日本語モデル名"
attributes:
モデル名:
カラム名: "日本語カラム名"
なので今回は、address
のzip_code
とresidence_name
を日本語に変換したいので、下記のように入力していきます。
このymlファイル、インデントなどが間違っているとうまく動いてくれないので、気をつけてくださいね。
ja:
activerecord:
models:
address: "住所"
attributes:
address:
zip_code: "郵便番号"
residence_name: "建物名"
結果・・・日本語になった!!
でも英語でも日本語のエラーになっちゃう
今回は日本語のエラー文をmodelのvalidationの中に直接書き込んでいるので、Accept-Language
をen
にしても、日本語エラー文になっちゃう。
ということで、validationのエラーメッセージもI18n
で日本語と英語を変換してくれるように修正していきます。まずは日本語のエラーメッセージをja.ymlファイルの中で用意します。
下記のようにすることでaddresses.zip_code_validation
が呼ばれたら、"はXXX-XXXXのように記入してください (記入例:123-4567)"
と表示する、という風に表示したいメッセージをカスタマイズできます。
ja:
activerecord:
models:
モデル名: "日本語モデル名"
attributes:
モデル名:
カラム名: "日本語カラム名"
addresses:
zip_code_validation: "はXXX-XXXXのように記入してください (記入例:123-4567)"
residence_name_validation: "は10文字以内で入力してください"
英語用のエラーメッセージも用意していきましょう。/config/locales
の直下に、en.yml
ファイルがあると思うので(なければ作成してね)、下記のように追記します。インデントには注意してくださいね。
en:
activerecord:
models:
address: "address"
attributes:
address:
zip_code: "zip code "
residence_name: "residence name "
addresses:
zip_code_validation: "must be in XXX-XXXX format. (ex:123-4567)"
residence_name_validation: "must be less than 10 length"
最後に、モデルを下記のように修正します。
class Address < ApplicationRecord
validates :zip_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: I18n.t(:'addresses.zip_code_validation')}
validates :residence_name, length: { maximum: 10, message: I18n.t(:'addresses.residence_name_validation') }
end
これで、下記の設定ができました。Accept-Language
を見て英語日本語どちらかのカスタマイズされたメッセージを表示してくれます。
-
zip_code
のformat
のバリデーションが通らなかった場合は、ymlファイルのaddresses.zip_code_validation
のメッセージを表示 -
residence_name
のlength
のバリデーションが通らなかった場合は、ymlファイルのaddresses.residence_name_validation
のメッセージを表示
結果
Accept-Language
がja
の場合
全て日本語になった!!デフォルトはja
で設定しているのでAccept-Language
の指定がなければ日本語文が表示されます。
Accept-Language
がen
の場合
まとめ
ということで、Railsでの多言語化対応と、それに伴うI18nの基本的な使い方の説明でした。
最初は「I18n!?!?名前からして難しそう・・・」って感じですが、慣れてしまえば簡単。