Search code examples
formscakephpmultilingualtranslate

CakePHP 3.6 multi language form


As mentioned in CakePHP 3.6.10 Translate behaviour not showing 'defaultLocale' values the default language values should be saved in the source table so they can be used as a fallback for empty fields in other languages. However I have a problem building the forms for this. I have 5 languages (locales): en_US, nl_BE, fr_BE, de_BE and ru_RU. The defaultLocale is en_US. So to ADD a new record I did:

// for the defaultLocale
echo $this->Form->control('title');
// for all other languages I iterate over every language except of the defaultLocale
foreach ($supported_locales as $key => $val):
    if ($key !== $default_locale):
        echo $this->Form->control('_translations.' . $key . '.title');
    endif;
endforeach;

This works fine. Allthough I'm not sure if this is the proper Cake-way to do it?

But in the VIEW (using a disabled form) and EDIT the defaultLocale field

echo $this->Form->control('title');

shows the translated value of the selected locale at that moment instead of the defaultLocale which is saved in the source table. F.e. when you switched the language to Russian at that moment you'll get to see:

  • English: Русский титул
  • Dutch: Nederlandse titel
  • French: Titre français
  • Deutsch: Deutscher Titel
  • Russian: Русский титул

So you're missing the value for the default locale (English) because it's replaced by the value for the currently selected language (here Russian). And you're not able to edit the value for the default locale when you're using the page in another language.

Am I overlooking something and is there a easier way to make this work 'out of the box'?


Solution

  • You must make sure that you fetch the records in the default locale, irrespectively of the current environments locale. You can do so using the translate behaviors setLocale() method (locale() before CakePHP 3.6), to explicitly set the locale to use for a specific repository, for example:

    $locale = \Cake\Core\Configure::read('App.defaultLocale');
    $this->Articles->setLocale($locale);
    $query = $this->Articles->find('translations');
    

    This will retrieve the articles in the configured default locale, irrespectively of what might have been set via I18n::setLocale(). If you are including associations where you need the locale applied too, then you have to explicitly set the locale for them too, ie:

    $this->Articles->setLocale($locale);
    $this->Articles->Comments->setLocale($locale);
    $query = $this->Articles->find('translations')->contain('Comments');
    

    See also