0

CakePHP のtranslate behaviorを使用して、1 つのフォームに複数の翻訳を含むアイテムを追加しようとしています。

翻訳フィールドを検証するにはどうすればよいですか? たとえば、特定の言語を必須にしますか?

本で説明されているように設定された、別の変換テーブルitemsを持つ単純なテーブルがあると仮定しましょう。簡単な例として、テーブルには翻訳するフィールドが 1 つしかなく、5 つの言語で保存したいとします。だから私はこのようなフォームを作成します(ビューテンプレートで): items_i18nitemstitletitleadd

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機能します (スタックオーバーフローのコードを単純化し、例の一部の名前を変更したため、タイプミスがある可能性がありますが、アイデアを得る必要があります) ...)。

さらに、英語(デフォルト) とスペイン語必須で、他の言語フィールドはオプションであるとします。どうすればそれを達成できますか?

で、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);ただし、翻訳が破棄されるため、常に「このフィールドは必須です」という検証エラーが発生します。これは、ワークフローの保存に関する GitHub の未解決の問題でわかっています (ところで、このリクエストには +1 :)。

そのため、現在、CakePHP の翻訳動作を使用するときに翻訳フィールドの検証ルールを定義する方法があるかどうかはわかりません...必要な言語フィールドは単なる例です。最小/最大などを検証する場合、同じ問題が発生します。外国語の入力フィールドの長さ...

4

1 に答える 1

1

わかりました、解決策を見つけたと思います。NestedValidatorFormHelperの問題も発見したため、少なくとも一時的には。

現在、検証は引き続きすべての追加言語に適用されます。したがって、これはまさに私が望んでいたものではなく、最終的な答えでもありません。検証を単一の言語に適用する方法がわからない場合は、コメントまたは回答を残してください。

したがって、これは私の現在の中間ソリューションCakePHP 3.1.1です:

テーブル クラスで、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);

入力フィールドに 1 文字だけを入力するminLengthと、デバッグ エラー配列でエラー メッセージを使用できます。

ただし、現在、FormHelperネストされたエラー メッセージはサポートされていません。この問題は 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']) ) { ... }

この質問への回答には、別の興味深いアプローチが示されています。

于 2015-10-11T21:09:54.070 に答える