我正在尝试使用CakePHP translate behaviour添加包含多个翻译以一种形式的项目。
如何验证翻译字段?例如需要特定的语言吗?
我们假设您有一个简单的items
表格,其中separate translations table items_i18n
的设置如书中所述。举个简单的例子,items
表只有一个要翻译的字段title
,我想用五种语言保存title
。所以我创建了一个这样的表单(在add
视图模板中):
echo $this->Form->create($item, ['controller' => 'Items', 'action' => 'add']);
echo $this->Form->input('title', ['label' => __('English')]);
echo $this->Form->input('_translations.es.title', ['label' => __('Spanish')]);
echo $this->Form->input('_translations.fr.title', ['label' => __('French')]);
echo $this->Form->input('_translations.de.title', ['label' => __('German')]);
echo $this->Form->input('_translations.it.title', ['label' => __('Italian')]);
echo $this->Form->button(__('Save'), ['type' => 'submit']);
echo $this->Form->end();
并保存在控制器(add
动作/功能)中,如下所示:
$item = $this->Items->newEntity();
if ($this->request->is('post')) {
$translations = [
'es' => ['title' => $this->request->data['_translations']['es']['title']],
'fr' => ['title' => $this->request->data['_translations']['fr']['title']],
'de' => ['title' => $this->request->data['_translations']['de']['title']],
'it' => ['title' => $this->request->data['_translations']['it']['title']],
];
foreach ($translations as $lang => $data) {
$item->translation($lang)->set($data, ['guard' => false]);
}
$item = $this->Items->patchEntity($item, $this->request->data, ['validate' => 'default'] );
if ( $this->Items->save($item) ) { $this->Flash->success(__('Saved.')); }
else { $this->Flash->error(__('Not saved.')); }
}
$this->set('item', $item);
这是在没有验证的情况下工作,或者我只有“native”title
字段的验证规则(它应该是,我简化了stackoverflow的代码并为示例重命名了一些部分,所以也许有一些错别字,但你应该明白......)。
现在让我们进一步假设语言英语(默认)和西班牙语 必需,其他语言字段是可选的。我怎样才能做到这一点?
在ItemsTable
我尝试了类似这样的验证:
class ItemsTable extends Table {
public function validationDefault(Validator $validator) {
$validator
// Title English (default field)
->requirePresence('title')
->notEmpty('title', __('Required field'))
// Title Spanish (translate behaviour field)
->requirePresence('_translations.es.title')
->notEmpty('_translations.es.title', __('Required field'))
;
return $validator;
}
}
但是这总是带来验证错误“此字段是必需的”,因为patchEntity($item, $this->request->data);
导致翻译被丢弃。我通过开放issue on GitHub了解保存工作流程(此请求的btw +1)。
所以目前我不确定在使用CakePHP翻译行为时是否有办法为翻译字段定义验证规则... 必需的语言字段只是一个例子,同样的问题发生如果你想验证,例如外语输入字段的最小/最大长度......
答案 0 :(得分:1)
好的,我想我找到了解决方案。至少是暂时的,因为我还发现issue带有 NestedValidator 和 FormHelper 。
目前,验证仍适用于所有其他语言。所以这不是我想要的,而不是最终答案。如果您知道如何将验证应用于单一语言,请发表评论或回答。
所以这是我目前使用CakePHP 3.1.1
的中间解决方案:
在表格类中为i18n翻译字段添加nested validator。
这些嵌套验证规则将适用于所有其他语言字段,因为它们在$this->request->data['_translations']
中组合在一起:
class ItemsTable extends Table {
public function validationDefault(Validator $validator) {
$validator
// Title English (default language)
->requirePresence('title')
->notEmpty('title')
->add('title', [
'minLength'=>['rule'=>['minLength', 2], 'message' => __('MinLength 2')],
'maxLength'=>['rule'=>['maxLength', 255], 'message' => __('MaxLength 255')],
])
;
// Nested Validation for i18n fields (Translate Behaviour)
// These rules will apply to all 'title' fields in all additional languages
$translationValidator = new Validator();
$translationValidator
->requirePresence('title', 'false') // I want translation to be optional
->allowEmpty('title') // I want translation to be optional
->add('title', [
'minLength'=>['rule'=>['minLength', 5], 'message' => __('MinLength 5')],
'maxLength'=>['rule'=>['maxLength', 255], 'message' => __('MaxLength 255')],
])
;
// Now apply the nested validator to the "main" validation
// ('_translations' is containing the translated input data)
$validator
->addNestedMany('_translations', $translationValidator)
// To prevent "field is required" for the "_translations" data
->requirePresence('_translations', 'false')
->allowEmpty('_translations')
;
return $validator;
}
}
在我的测试设置中,我希望翻译字段是可选的,并将其他minLength作为默认语言。正如您在上面的代码中看到的,我添加了allowEmpty
并将requirePresence
设置为false
以获取翻译字段。目前,TranslateBehaviour
仍然强制要求翻译title
字段。所以我在添加/编辑表单中添加了'required' => false
到翻译输入字段:
echo $this->Form->input('_translations.es.title', ['required' => false]);
单独的验证规则现在应用于转换字段,如调试结果中所示(在测试时临时添加到控制器中):
$item = $this->Items->patchEntity($item, $this->request->data);
debug($item);
如果在输入字段中只输入一个字符,则调试错误数组中会出现minLength
错误消息。
但目前FormHelper
不支持嵌套错误消息。我报告此issue on GitHub。在表单中显示错误的临时解决方案是手动检查error
数组。为此,请添加Controller:
$item = $this->Items->patchEntity($item, $this->request->data);
if ( !$item->errors() ) {
foreach ($this->request->data['_translations'] as $lang => $data) {
$item->translation($lang)->set($data, ['guard' => false]);
}
}
// Temp workaround for issue#7532:
else {
$this->set('formerrors', $language->errors());
}
在添加/编辑视图中,您可以检查并使用其他$formerrors
数组:
if ( isset($formerrors['_translations']['es']['title']) ) { ... }
另一个有趣的方法显示在answer to this question。