0

Я пытаюсь добавить элемент, включая несколько переводов в одной форме с CakePHP translate behaviour.CakePHP 3.1: Validation for translate fields (i18n)

Как я могу проверить поля перевода?. указать конкретные языки?

Предположим, у вас есть простой стол items с separate translations tableitems_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); 

Это работает без проверки или если у меня есть только правила валидации для «родного» поля 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 о сберегающем рабочем потоке (битва +1 для этого запроса :).

В настоящее время я не уверен, есть ли способ определить правила валидации для полей перевода при использовании поведения перевода CakePHP ... Обязательный Языковые поля являются лишь примером, та же проблема возникает, если вы хотите утвердить, например минимальная/максимальная длина поля ввода для иностранного языка ...

+1

Мой подход к subjetcs здесь, если он может вам помочь: http://stackoverflow.com/questions/33426427/cakephp-3-1-my-validation-for-translate-behaviour-fields-need-some- помощь-в-ре – Angyo

ответ

1

Хорошо, я нашел решение. По крайней мере временно, потому что я также обнаружил issue с NestedValidator и FormHelper.

В настоящее время валидация по-прежнему применяется к всем дополнительным языкам. Так что это не совсем то, что я хотел, а не окончательный ответ. Если у вас есть идея, как я могу применить проверку на одном языке, оставьте комментарий или ответ.

Так что это мое текущее промежуточное решение с CakePHP 3.1.1:

В классе таблицы добавить nested validator для полого i18n перевода.

Эти вложенные правила проверки будут применяться ко всем дополнительным полям языка, потому что они сгруппированы в $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 вручную. Для этого добавьте в контроллере:

$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.