背景
Railsの多言語化にはi18nがよく利用されます。
通常下記のように設定をしますよね
config/locales/*.yml
ja:
activemodel:
# モデル名
models:
user: "ユーザー"
attributes:
# モデル毎の属性名
user:
name: "名前"
# 共通の属性名
attributes:
gender: "性別"
# バリデーションエラー
errors:
# テンプレート
format: "%{attribute}%{message}"
# エラー毎のメッセージ
messages:
blank: "を入力してください"
en:
# 同じ構造なので略
User.rb
class User < ApplicationRecord
validates :name, presence: true
end
この時、フォームでnameに空白のままsubmitを実行すると、名前を入力してくださいと表示されます。
ですが、例えばnameが空白の時に名前はフルネームで入力してくださいとか、名前は姓・名で分けてくださいと表示したかった場合どうしますか?
*.ymlのmodels.attributes.user.nameとerrors.messages.blankを書き換える力技もありますが、これでは保守性0です。
美しくありません。また、
User.rb
class User < ApplicationRecord
validates :name, presence: { message: '名前はフルネームで入力してください' }
end
上記も悪くないけど、多言語化に対応できていない。
そこで、i18nを用いた、メッセージのカスタマイズ方法を紹介いたします。
解決策
Procを組み合わせます。lambdaでも可能です。
config/locales/*.yml
ja:
activemodel:
# 同じ構造なので略
# バリデーションエラー
errors:
messages:
blank: "を入力してください"
models:
user:
fullname_blank: "名前はフルネームで入力してください"
en:
# 同じ構造なので略
User.rb
class User < ApplicationRecord
validates :name, presence: {
message: -> (rec, data) {
I18n.t('activemodel.errors.models.user.fullname_blank')
}
}
end
これを実行すると、うまく多言語化されると思います。
ちなみに、Procを使わないとうまく多言語化されないので気をつけてください。下記が悪い例です。
User.rb
class User < ApplicationRecord
validates :name, presence: {
message: I18n.t('activemodel.errors.models.user.fullname_blank')
}
end