What you are doing there is creating a rule for the name
field on the main model, this won't affect translations. There is no built-in functionality for that, the behavior only assists with validation rules by making use of the validationTranslated()
method in case it exists on your model class, it won't help with application rules.
You'd have to create a custom application rule that checks the translation table, by matching against the field
, locale
, model
and content
fields, something along the lines of this:
$rules->add(
function (EntityInterface $entity) {
$behavior = $this->behaviors()->get('Translate');
$association = $this->association($behavior->getConfig('translationTable'));
$result = true;
foreach ($entity->get('_translations') as $locale => $translation) {
$conditions = [
$association->aliasField('field') => 'name',
$association->aliasField('locale') => $locale,
$association->aliasField('content') => $translation->get('name')
];
if ($association->exists($conditions)) {
$translation->setErrors([
'name' => [
'uniqueTranslation' => __d('cake', 'This value is already in use')
]
]);
$result = false;
}
}
return $result;
}
);
Note that this uses the association object rather then the target table, this will ensure that further conditions like the model name are being applied automatically.
Also this requires to set the errors on the entity manually, as they are nested, which isn't supported by the rules checker, currently it can only set errors on the first level entity (see the errorField
option).
It should also be noted that it would be possible to modify the rules checker for the translation table association (via the Model.buildRules
event), however this would result in the errors being set on new entities that will be put in a separate property (_i18n
by default) on the main entity, where the form helper won't find the error, so one would then have to read the error manually, which is a little annoying.
See also