Hi all,
I have been experimenting with the cakephp Translate Behaviour. Reading the docs, I liked the concept, but trying out I felt some discomforts. So I would like to share so that it can be improved.
The current view is assuming all languages contents are translating at the same time.
- Call inside the template
<!-- File: templates/Articles/add.php -->
<h1>Add Article : ('title').</h1>
<?php
echo $this->Form->create($article);
// Hard code the user for now.
echo $this->Form->control('user_id', ['type' => 'hidden', 'value' => 1]);
echo $this->Form->control('title');
echo $this->Form->control('body', ['rows' => '3']);
/*
<fieldset>
<legend>English</legend>
<?= $this->Form->control('_translations.en_GB.title'); ?>
<?= $this->Form->control('_translations.en_GB.body', ['rows' => '3']); ?>
</fieldset>
*/
?>
<fieldset>
<legend>Spanish</legend>
<?= $this->Form->control('_translations.es_AR.title'); ?>
<?= $this->Form->control('_translations.es_AR.body'); ?>
</fieldset>
<?php
echo $this->Form->control('tag_string', ['type' => 'text']);
echo $this->Form->button(__('Save Article'));
echo $this->Form->end();
?>
If you have closely looked at the above template, you can see the default locale field is using $this->Form->control('title')
for rendering and not as $this->Form->control('_translations.en_GB.title')
.
If we go with $this->Form->control('_translations.en_GB.title')
path, the title field inside the articles table will be empty. The default locale en_GB
goes to the articles_translations
table.
- Validation
According to the docs we can add validation as
$this->addBehavior('Translate', [
'strategyClass' => ShadowTableStrategy::class,
'fields' => ['title', 'body'],
'validator' => 'translated'
]);
so a validator as
public function validationTranslated(Validator $validator): Validator
{
$validator
->notEmptyString('title')
->minLength('title', 10)
->maxLength('title', 255)
->notEmptyString('body')
->minLength('body', 10);
return $validator;
}
But as we are using the $this->Form->control('title')
for the defaultLocale. So to validate the default fields we need to add another default validator.
public function validationDefault(Validator $validator): Validator
{
$validator
->notEmptyString('title')
->minLength('title', 10)
->maxLength('title', 255)
->notEmptyString('body')
->minLength('body', 10);
return $validator;
}
I think that is an extra overhead.
- Accessing the value
$lang = I18n::setLocale('es_AR');
// Update retrieving tags with contain()
$article = $this->Articles
->find('translations')
->where(['slug' => $slug])
->contain('Tags')
->firstOrFail();
Suppose you have the article object now you can access the value as
$article->title
: Which will provide the value from the current locale.$article->translation('es_AR')->title);
get the value of the locale.
The above two works. But lets assume your default locale is en_GB
and your current locale set is different. Now in-order to get the default locale, calling $article->translation('en_GB')->title);
is not giving you value.
Not sure if this is a bug or this is the default behavior.
All the source code for the experiment is located at GitHub - harikt/cakephp-experiments if anyone want to test this.