CakePHP 3.1: Validation for translate behaviour fields (i18n) -
i'm trying add item including multiple translations in 1 form cakephp translate behaviour.
how can validate translation fields? e.g. make specific languages required?
let's assume have simple items
table separate translations table items_i18n
, set described in book. simple example items
table has 1 field title
translate , want save title
in 5 languages. make form (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();
and saving in controller (add
action/function) 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 $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);
this working without validation or if have validation rules "native" title
field (well should, simplified code stackoverflow , renamed parts example, maybe there typos, should idea...).
now let's further assume languages english (default) , spanish required, other language fields optional. how can achieve that?
in itemstable
tried 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; } }
but allways brings validation error "this field required" because patchentity($item, $this->request->data);
results in translations being thrown away. know open issue on github saving workflow (btw +1 request :).
so i'm not sure if there way define validation rules translation fields when using cakephp translation behaviour... required language fields example, same problem occurs if want validate e.g. min/max lenght of input field foreign language...
ok, think found solution. @ least temporarily, because discovered issue nestedvalidator , formhelper.
currently validation still applied all additional languages. not wanted , not final answer. if have idea how can apply validation single languages please leave comment or answer.
so current intermediate solution cakephp 3.1.1
:
in table class add nested validator i18n translation fields.
these nested validation rules apply additional language fields, because grouped 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 i18n fields (translate behaviour) // these rules apply 'title' fields in additional languages $translationvalidator = new validator(); $translationvalidator ->requirepresence('title', 'false') // want translation optional ->allowempty('title') // want translation optional ->add('title', [ 'minlength'=>['rule'=>['minlength', 5], 'message' => __('minlength 5')], 'maxlength'=>['rule'=>['maxlength', 255], 'message' => __('maxlength 255')], ]) ; // apply nested validator "main" validation // ('_translations' containing translated input data) $validator ->addnestedmany('_translations', $translationvalidator) // prevent "field required" "_translations" data ->requirepresence('_translations', 'false') ->allowempty('_translations') ; return $validator; } }
in test setup want translation fields optional , have other minlength default language. can see in code above, added allowempty
, set requirepresence
false
translation fields. translatebehaviour
still forcing translation title
fields required. added additionally 'required' => false
translation input fields in add/edit form:
echo $this->form->input('_translations.es.title', ['required' => false]);
the separate validation rules applied translation fields, shown in debug result (added temporarily in controller while testing):
$item = $this->items->patchentity($item, $this->request->data); debug($item);
when enter 1 character in input fields, minlength
error messages available in debug error array.
but formhelper
not support nested error messages. reported issue on github. temporarily solution show error in form checking error
array manually. so, add in controller:
$item = $this->items->patchentity($item, $this->request->data); if ( !$item->errors() ) { foreach ($this->request->data['_translations'] $lang => $data) { $item->translation($lang)->set($data, ['guard' => false]); } } // temp workaround issue#7532: else { $this->set('formerrors', $language->errors()); }
and in add/edit view can check , use additional $formerrors
array:
if ( isset($formerrors['_translations']['es']['title']) ) { ... }
another interesting approach shown in answer question.
Comments
Post a Comment