CakePHP Translate Behavior - Lessons Learned

Posted on 12/15/2009 at 08:29 am by Kevin Wentworth
Viewed 34,429 times | 5 comments

I've been working on setting up a multi-lingual web site for one of my clients.  I was excited at the opportunity to finally use CakePHP's built-in internationalization and locale functions.  However, I ran into some issues that I'm sure other newbies to internationaliztion will run into as well.  Here's some take-backs of what I learned while using the Translate Behavior in Cake...

(Author's Note: This posting is still a work in progress. I'm still implementing the translate behavior and have found quite a few work-arounds that I needed to implement.  Over the next few days/weeks I'll be sharing more about Cakephp's translate behavior and how I wrangled it for my use.  It looks like CakePHP will fix/implement several issues I've had with the translate behavior to date)

Only Simple Find Methods Return Translated Fields

This is important!  At this moment (v 1.2.5),  the Translate Behavior will only translate simple $model->find() calls. If you have a model that relates to a translated model, the related model will not be translated!  After much research and reading, I've learned that it's due to the lack of support for beforeFind and afterFind calls in CakePHP related models/behaviors (see: ticket).

I did find a work-around, that I recommend for anyone needing to use related models with translated fields at this time.

Less Configuration is Better

With the translate behavior, the less you configure it the better.  I got really confused at first by attempting to return ALL the translations using the bindTranslation() method (actually, I set the behavior to return all translations).  I did this because I was building the back-end first, but wasted a lot of time thinking things weren't working right.  The other area that got me into trouble was setting the locales manually using $this->Model->locale instead of the Config.language setting.

To recap, if you have the i18n table populated with data in the current locale, when you do any type of DB find, the fields will be automagically re-mapped to have the right translation in the find results. With no intervention (or configuration) you'll end up with just what you wanted- translated fields in the "find" data array.

$this->Model->locale Value Changes Translate Behavior Results

You wouldn't think it would change things too much, but how you specify languages via $this->Model->locale changes the results and behavior of Translate.  I recommend not setting the locale this way, it's too confusing and abnormal.

Setting it to a string works as expected (i.e. normal).  However if you set locale to an array() then things change:

  • $this->Model->locale = 'en-us'
    • Returns false if translation doesn't exist
  • $this->Model->locale = array('en-us'); //or array('en-us', 'de-de', '3-rd');
    • DOESN'T RETURN FALSE if en-us doesn't exist (instead returns default Config.language)
    • returns what's in the model table... does no translation even if it exists
    • effectively shuts off translate behavior

Locale and Language are Different

This one got me good.  I kept trying to set the default language to German in my CakePHP app using Config::write('Config.language', 'de_de');  It wasn't working and the en_us locale kept getting returned.  Well, as it turns out, you actually need to set your languages using HYPHENS not UNDERSCORES!

Once I began using de-de (not de_de) everything worked like a charm.  I still don't know all the details of the locale vs. language.  I now at least have a reference point: l10n class (look at var $__l10nCatalog definition).

What Do You Use for Abbreviations/Codes for Locales?

For English (American) as the locale, I was using en_us.  (Not to be confused with the language identifier of en-us)  However, I see 'eng' all over the web. What locale do you use?  It looks like 'eng' is mapped to 'en' anyway, so I'm not sure why the localeFallback isn't just en?  RESEARCH AND FIGURE THIS OUT

Array Format for Saving Multiple Languages at Once

You can change the $this->Model->locale setting and then save your translation, however you can avoid changing the $model->locale (see above) by using the following array format:

Bookmark and Share

Tags for CakePHP Translate Behavior - Lessons Learned

Web Programming | Cakephp | Usage | Php | Mysql

Comments for this Posting

Posted by Nicolas

on 21/1/10

Thanks for this article and the link to the workaround! It worked perfectly for me :)

Posted by Axel

on 10/3/10

good article, thanks!

Posted by Rich

on 23/5/10

RE: Array Format for Saving Multiple Languages at Once

I can't see the code sample, has it been removed?

This is exactly the information I am afterr as I want to build a CMS with tabs for each locale containing the translated model fields - saving the data all at once instead of one locale at a time.

Posted by Lapinski

on 8/8/10

Locale and language are different, but not by - and _ : en-us or en_us both implies en as language and us as locale. Check out ISO 3166 for country codes and ISO 639-2 and 639-3 for language codes, and that's why the mapping between en and eng for English.

Posted by José

on 8/4/11

I'm very curious about the array format for saving many translations at once, it seems it didn't appear in your blog, can you email me with it please??

Sorry, comments are closed for this posting.

Please Email Kevin if you have any questions. Thanks!

Meet Site Avenger - Hosted Content Management System

Powered By: Site Avenger | Site Production: Saco Design