riula
riula

Reputation: 181

Saving multiple translations at once with CakePHP

I have a tabbed form and in each tab, a set of identical fields that differ in language only. For example, I have a name and description field in each tab, and I would create each input using CakePHP's form helper in the following fashion:

English Tab

$this->Form->input("Service.en.name");
$this->Form->input("Service.en.description");

French Tab

$this->Form->input("Service.fr.name");
$this->Form->input("Service.fr.description");

After which (this may be wrong but it worked) I would set the value of a particular field to be an array containing the values keyed by the various locales.

I'm using the TranslateBehavior and all has been well until I upgraded to the most recent of CakePHP (2.4.3 from 2.3). Now whenever I try to save I get an error saying: Unknown column "Array"

I can't find anything on saving multiple languages at once. Any ideas would be greatly appreciated!!

Update 1

I have also tried moving the locale to the end like so:

$this->Form->input("Service.name.en")

With same results

Update 2

According to xdebug, this is the SQL:

UPDATE `cc_dev`.`services` SET `name` = Array, `description` = Array, `duration` = 60, `category_id` = 1, `backend_only` = "0", `id` = 1, `vendor_id` = 116, `updated` = "2013-11-26 18:46:11"  WHERE `cc_dev`.`services`.`id` = "1"

And it occurs during save. I simply check to ensure that the request data isn't empty first, and nothing more.

if (!empty($this->request->data)) {
    $this->Service->save($this->request->data);
}

Update 3

Content of the submitted request data, currently in the format specified in Update 1

<pre>Array (
[Service] => Array
    (
        [name] => Array
            (
                [en] => One-to-One Session
                [fr] => Séance individuelle
            )

        [description] => Array
            (
                [en] => Choose a personalized training session of 45 minutes.
                [fr] => Choisissez une séance de formation individuelle de 45 minutes.
            )

        [duration] => 60
        [category_id] => 1
    )
)
</pre>

Upvotes: 1

Views: 1762

Answers (2)

Gestudio Cloud
Gestudio Cloud

Reputation: 290

The locale is not required to be in ISO 639-2, by default, Cake2 uses it, but in my case, Configure:write('Config.language') = 'en' and so my forms were:

$this->Form->input("Service.name.en");
$this->Form->input("Service.description.en");

It is working great, the only problem i encountered was gathering data from db in the correct format to fit this form automatically. Before the find function, i used bindTranslation() as stated in CakePhp docs:

$this->Service->bindTranslation(array('name'=>'nameTranslation'));  

Removing or adjusting the contain or adding recursive = 1, it gets the translations, but finally, the nameTranslations must be moved to the Service Index in the array to be in the correct format so the CakeMagic Forms works.

'Service' => array(
        'id' => '108',
        'name' => 'Hugs',
        'created' => '1391082480',
        'locale' => 'en'
    ),
    'nameTranslation' => array(
        (int) 0 => array(
            'content' => 'Hugs',
            'locale' => 'en',
            'foreign_key' => '108'
        ),
        (int) 1 => array(
            'content' => 'Abrazos',
            'locale' => 'es',
            'foreign_key' => '108'
        )
    )
)

As you see, that array format is clear but definitely it is not valid, so i had to add the following foreach to move values and clean it up.

$this->request->data['Service']['name'] = array();
foreach($this->request->data['nameTranslation'] as $translation)
     $this->request->data['Service']['name'][$translation['locale']] = $translation['content'];

unset($this->request->data['nameTranslation'],$this->request->data['Service']['locale']);

The result was exactly what I was looking for:

'Service' => array(
        'id' => '108',
        'name' => array(
            'en' => 'Hugs',
            'es' => 'Abrazos'
        ),
        'created' => '1391082480'
    )

It is done and online, but there must be a better way to do it.

Upvotes: 0

riula
riula

Reputation: 181

Ok, I finally got it working.

The new preferred locale format for CakePHP is based on ISO 639-2, so I updated all current locale records to match. This is especially important when using gettext in Cake as the folder for your *.po files changes (not entirely relevant, but good to know).

After that I changed the structure of my forms to be:

$this->Form->input("Service.name.eng");
$this->Form->input("Service.description.eng");

Finally, I had to now call saveMany, as opposed to simply calling save being mindful that saveMany expects an array of records.

if (!empty($this->request->data)) {
    $this->Service->saveMany(array($this->request->data));
}

So now I can save numerous translations at once again.

Upvotes: 2

Related Questions