Bug(バグ) #4000
完了MemberConfigFormのIsUnique制約に対するエラーメッセージが適切に出力されていない
100%
説明
現象¶
「PC メールアドレス設定」(/member/config?category=pcAddress) で、変更後のメールアドレスが他のメンバーとメードアドレスが重複する場合に「Invalid pc_address.」というエラーメッセージが表示される。
原因¶
当初 #3736 ではこの不具合を英日の翻訳漏れとして扱っていたが、実際には #1069 で追加したエラーメッセージが「Invalid %name%.」であったのに対して翻訳は「Invalid %name%.」ではなく「Invalid mobile_address.」に対して行われていたことに起因する問題であった。
source:lib/form/doctrine/MemberConfigForm.class.php@43190aa1#L232:
throw new sfValidatorError($validator, 'Invalid %name%.', array('name' => $name));
source:i18n/messages.ja.xml@43190aa1#L85
<trans-unit id="">
<source>Invalid mobile_address.</source>
<target>メールアドレスが無効です。</target>
</trans-unit>
このことで mobile_address 以外の IsUnique 制約を使用する全ての設定項目に対しては未翻訳のエラーメッセージが出力される状態となっていた。
また、この問題は「Invalid %name%.」に対する翻訳を追加するだけでは解決しない(「Invalid pc_address.」と表示されるまま変わらない)。
そもそも sfValidatorError::__construct($validator, $code, $arguments)
の第 2 引数はエラーメッセージそのものを渡すのではなくバリデーター内部で識別するエラーコードを渡すものであり、今まで Invalid pc_address.
のようなエラーメッセージが表示されていたのはエラーコードに対応するメッセージが存在しなかったためである。「%name%」のようなトークンを含むテキストに対して opI18n クラスによるローカライゼーションが正しく機能するためには、例えば以下のように適切な用法に書き換える必要がある。
public function setMemberConfigWidget($name)
{
....
if (!empty($config['IsUnique']))
{
$uniqueValidator = new sfValidatorCallback(array(
'callback' => array($this, 'isUnique'),
'arguments' => array('name' => $name),
'empty_value' => $this->validatorSchema[$name]->getOption('empty_value'),
));
$uniqueValidator->addMessage('duplicate', 'Invalid %name%.');
....
}
public function isUnique($validator, $value, $arguments = array())
{
....
throw new sfValidatorError($validator, 'duplicate', array('name' => $name));
}
ここまで修正してようやく「Invalid %name%」に対して翻訳文が出力される状態になる。
これらの経緯をまとめると、下記の問題点が積み重なった結果として冒頭の「現象」が現れたといえる。
- 独自のエラーメッセージを追加するために
sfValidatorBase::addMessage()
を使用せずsfValidatorErorr::__construct()
の引数$code
に直接エラーメッセージを指定していた - 上記が原因でローカライゼーションが正しく機能せず「Invalid %name%.」に対する翻訳が行えなかったため、やむなく「Invalid mobile_address.」に対して訳文を追加していた(と思われる)
- mobile_address 以外の IsUnique 制約を使用する member_config の設定項目については、訳文が存在しないため原文のままエラーメッセージが出力される状態となった
修正内容¶
MemberConfigForm 内でエラーメッセージを記述している箇所を上記の sfValidatorBase::addMessage()
を使用した用法に書き換えた上で、下記の翻訳文を追加する。
<trans-unit id="">
<source>Invalid %name%.</source>
<target>不正な %name% です。</target>
</trans-unit>
また、この翻訳文の改善について #3999 にて扱っており、修正の際にはコンフリクトする可能性がある点を留意する必要がある。
Youichi Kimura さんが約8年前に更新
- ステータス を New(新規) から Pending Review(レビュー待ち) に変更
- 担当者 を Youichi Kimura にセット
- 進捗率 を 0 から 50 に変更
isao sano さんがほぼ8年前に更新
- 関連している Backport(バックポート) #4043: MemberConfigFormのIsUnique制約に対するエラーメッセージが適切に出力されていない を追加
isao sano さんがほぼ8年前に更新
- 関連している Backport(バックポート) #4044: MemberConfigFormのIsUnique制約に対するエラーメッセージが適切に出力されていない を追加
Rimpei Ogawa さんが6年以上前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更