CakePHP 3.1:验证翻译行为字段(i18n) [英] CakePHP 3.1: Validation for translate behaviour fields (i18n)

查看:99
本文介绍了CakePHP 3.1:验证翻译行为字段(i18n)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用CakePHP

I'm trying to add an item including multiple translations in one form with the CakePHP translate behaviour.

如何验证翻译字段?要求使用特定语言?

假设您有一个简单的items表,其中的单独的翻译表 items_i18n,如本书中所述进行设置.举一个简单的例子,items表只有一个要转换的字段title,我想用五种语言保存title.因此,我制作了一个这样的表单(在add视图模板中):

Let's assume you have a simple items table with a separate translations table items_i18n, set up as described in the book. As simple example the items table has only one field title to translate and I want to save the title in five languages. So I make a form like this (in add view template):

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动作/功能):

And saving in the controller (add action/function) like this:

$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的代码并重命名了该示例的某些部分,所以也许有一些错别字,但你应该明白这个主意...).

This is working without validation or if I only have validation rules for the "native" title field (well it should, I simplified the code for stackoverflow and renamed some parts for the example, so maybe there are some typos, but you should get the idea...).

现在,让我们进一步假设英语(默认)和西班牙文必填,其他语言字段是可选的.我该如何实现?

Now let's further assume the languages English (default) and Spanish are required, other language fields are optional. How can I achieve that?

ItemsTable中,我尝试了以下类似方式进行验证:

In the ItemsTable I tried something like this for validation:

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);会导致翻译被丢弃.我通过在GitHub上打开问题了解有关保存工作流程的信息(对此,顺便说一句+1)请求:).

But this allways brings a validation error "This field is required" because patchEntity($item, $this->request->data); results in the translations being thrown away. I know this by an open issue on GitHub about the saving workflow (btw +1 for this request :).

因此,当前我不确定使用CakePHP翻译行为时是否可以为翻译字段定义验证规则... 必填语言字段仅是一个示例,也会发生相同的问题如果您想验证例如外语输入字段的最小/最大长度...

So currently I'm not sure if there is a way to define validation rules for translation fields when using the CakePHP translation behaviour... Required language fields is only an example, the same problem occurs if you want to validate e.g. the min/max lenght of a input field for a foreign language...

推荐答案

好的,我想我找到了解决方案.至少是暂时的,因为我还用 NestedValidator 发现了问题 >和 FormHelper .

Ok, I think I found a solution. At least temporarily, because I also discovered an issue with NestedValidator and FormHelper.

当前,验证仍然适用于所有种其他语言.所以这不是我想要的,也不是最终答案.如果您有想法如何将验证应用于单一语言,请发表评论或答案.

Currently the validation is still applied to all additional languages. So this is not exactly what I wanted and not the final answer. If you have an idea how I can apply the validation to single languages please leave a comment or answer.

这是我目前使用CakePHP 3.1.1的中间解决方案:

So this is my current intermediate solution with CakePHP 3.1.1:

在表类中添加用于i18n翻译字段的嵌套验证器.

In the table class add a nested validator for the i18n translation fields.

这些嵌套的验证规则将应用于所有其他语言字段,因为它们在$this->request->data['_translations']中分组在一起:

These nested validation rules will apply to all additional language fields, because they are grouped together in $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:

In my test setup I want the translation fields to be optional and have other minLength as the default language. As you can see in the code above, I added allowEmpty and set requirePresence to false for the translation fields. Currently the TranslateBehaviour is still forcing the translation title fields to be required. So I added additionally 'required' => false to the translation input fields in add/edit form:

echo $this->Form->input('_translations.es.title', ['required' => false]);

现在,将单独的验证规则应用于转换字段,如调试结果所示(在测试时临时添加到控制器中):

The separate validation rules are now applied to the translation fields, as shown in the debug result (added temporarily in the controller while testing):

$item = $this->Items->patchEntity($item, $this->request->data);
debug($item);

在输入字段中仅输入一个字符时,minLength错误消息在调试错误数组中可用.

When you enter only one character in the input fields, the minLength error messages are available in the debug error array.

但目前FormHelper不支持嵌套错误消息.我报告了此

But currently the FormHelper does not support nested error messages. I reported this issue on GitHub. A temporarily solution to show an error in the form is by checking the error array manually. To do so, add in the 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数组:

And in the add/edit view you can check and use the additional $formerrors array:

if ( isset($formerrors['_translations']['es']['title']) ) { ... }

中显示了另一种有趣的方法这个问题的答案.

这篇关于CakePHP 3.1:验证翻译行为字段(i18n)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆