BeanValidationで日本語メッセージを出力する

BeanValidation1.0の参照実装であるHibernate Validatorのデフォルトメッセージは英語です。

例えば@NotNullでは「may not be null」、@AssertTrueでは「must be true」といったメッセージが出力されます。通常、JSF2.0を組み合わせて使うときには『"名前"が入力されていません』のように、日本語でかつ入力箇所をメッセージとして出力したいかと思います。

具体例を紹介すると、以下のようなコードを書いた場合のメッセージ表示についてです。

こんな入力フォーム(facelets/XHTML)を作って

<h:inputText id="isbn" label="ISBNコード" value="#{controller.book.isbn}" />
<br/>
<h:message for="isbn" errorStyle="color:red"/>

こんな風にBean Validationを使うと

@Named
public class Book {
    @Id @NotBlank private String isbn;

デフォルトではメッセージも英語で、入力コンポーネント名も出力されません。
f:id:n_agetsuma:20121017215133p:plain


ここでは、日本語メッセージと入力コンポーネントの表示方法についてまとめます。

1. Bean Validationのメッセージファイルを作る

Bean Validationの日本語メッセージは参照実装であるHibernate Validator4.3.1にはバンドルされていないため、ユーザにて作成します。

ValidationMessesages_jp_JP.properties

javax.faces.validator.BeanValidator.MESSAGE={1} {0}
org.hibernate.validator.constraints.NotBlank.message=は必須入力です。

まずファイル名ですが、この名前はHibernate Validatorで決められているデフォルト名*1です。
また、格納フォルダのデフォルトではクラスパスのルートと決められています。そのため、自分は以下のようにsrc/main/resourcesに置いてみました。

f:id:n_agetsuma:20121017221744p:plain

次に内容についてです。
1行目の「javax.faces.validator.BeanValidator.MESSAGE={1} {0}」ですが、JSF2.0がライフサイクルの中でBeanValidationを実行した時、このキーのメッセージをFacesContextに登録しているようです(mojjaraのコード確認してないので、少し自信なし)。{0}にはBeanValidationのメッセージが代入されます。{1}には入力コンポーネントのlabel属性の設定値が代入されます。

この設定については、JSFの仕様書*2においても紹介されています。

このキーのメッセージはデフォルトでは「javax.faces.validator.BeanValidator.MESSAGE={0}」と定義されています。このため、最初に紹介したエラーメッセージ画像では、入力コンポーネントのlabel属性が表示されていません。

2行目は実際に画面に出力したい日本語のメッセージです。上記のようにキー値をBeanValidationのデフォルトと合わせておくと、アノテーション側でキーを明示的に指定せずに済みます。

例えば、以下のメッセージプロパティとした場合

notblank=は必須入力です。

@NotBlankのmessage属性を定義する必要があります。

@Id @NotBlank(message="{notblank}") private String isbn;

HibernateValidator4.3.1の場合、キー値の命名規則はアノテーションFQDN+.messageとなっています。


2. faces-config.xmlに登録する

作成したファイルをJSFの設定として登録します。

BeanValidationの設定としては、classpathのルートにValidationMessages_XX.xmlを置くと自動的に読み込んでくれますが、JSFとしての設定をしないと入力コンポーネントが表示されずに「は必須です」としか出力されません。

faces-config.xmlの追記を忘れた場合
f:id:n_agetsuma:20121017225839p:plain

faces-config.xmlには以下の設定を追記します。

<application>
  <message-bundle>ValidationMessages</message-bundle>
</application>

これで設定は終わりです。
設定がうまくいっていれば、以下のように入力コンポーネント名と日本語メッセージが出力されるようになると思います。

f:id:n_agetsuma:20121017230120p:plain

(余談:日本語がなくても、実は他の組み込み言語はたくさん入っている)
Hibernate Validator4.3.1のjarに含まれるValidationMessages_xx.propertiesを確認すると、チェコ語(cs)、ドイツ語(de)、スペイン語(es)、アジア圏では中国語(zh_CN)など、計10種類のプロパティファイルが含まれていましたが、日本語(ja_JP)はありませんでした。やはり提案やパッチ提供などの貢献が少ないと、対応が後回しにされてしまうのかな。

*1:参考1 Hibernate Validator Reference Guide 2.2.4. Message interpolation http://docs.jboss.org/hibernate/validator/4.3/reference/en-US/html_single/

*2:参考2 JavaServer Faces Specification Version2.1 2 3.5.6.3 Localization of Bean Validation Messages