PostMultilingual Website with CakePHP

We all know that developing a website in CakePHP is very easy and also fast. Here’s how to create a multilingual website fast.

First open app/config/bootstrap.php and set the languages you want available for your website:


Configure::write('Config.languages', array(
'ro' => array(
'language' => 'Romanian',
'locale' => 'rum',
'localeFallback' => 'rum',
'charset' => 'utf-8'
),
'en' => array(
'language' => 'English',
'locale' => 'eng',
'localeFallback' => 'eng',
'charset' => 'utf-8'
),
)
);

I chose english and romanian for this example.

Now open your app controller (app/app_controller.php – create one if you don’t have it) and put this function in it:


function setLanguage() {
if(!isset($this->params['lang'])) $this->params['lang'] = 'ro';
$lang = $this->params['lang'];
App::import('Core', 'i18n');
$I18n =& I18n::getInstance();
$I18n->l10n->get($lang);
foreach (Configure::read('Config.languages') as $lang => $locale) {
if($lang == $this->params['lang'])
$this->params['locale'] = $locale['locale'];
}
}

All you have to modify in this function is the first line (that sets the default language). Change the default language to your chosen one.

It’s now time to create a route depending on the language. Open app/config/routes.php and add this route to it:


Router::connect('/:lang/:controller/:action/*', array('lang' => 'ro'), array('lang' => 'ro|en'));

Of course that this can change depending on the languages you are using and their number. You’re a smart boy so you’ll figure it out.

Now all you have left is to create the language files. Go to app/locale and create 2 folders: rum and en. In each of these folders create another folder called LC_MESSAGES. In the LC_MESSAGES folders you will now store the language files. Language files can be divided so it’s easier for you to store the translations ( .po files ).

For example, you can create a login.po, register.po, account.po and default.po.

In the language files you have to set the message id and message string.

English

msgid "hello"
msgstr "Hello"

Romanian

msgid "hello"
msgstr "Buna ziua"

And now to echo these strings on your website you have to remember the string id and the name of the language file (.po) it is stored in. Example:


__d('default', 'hello', true);
?>

This will take the string with the id “hello” from the default.po file and echo it. And true means that it will echo the string.
Good luck

Stay Connected

Subscribe to RSS Feed

Subscribe to RSS Feed

Follow me on Twitter

Follow me on Twitter

Subscribe via e-mail

Subscribe via e-mail

Comments 13 Responses to “Multilingual Website with CakePHP”

  1. Simple and direct. Nice article.

    The function __d() of Cake is for work with domains of translations (more complex than this article). To simplify, Cake created __() function. This assumes domain as ‘default’.

    __(‘hello’, true) === __d(‘default’, ‘hello’, true).

  2. Thank you for your comment Juan. I posted it like this so people who read this article understand how to use the __d() function and be more organized by using different .po files.

  3. Hi i tried this example,i created an po file in the three diffrent folders lets say english,french,german and the three po files related to them as well and i tried to use the function:__d(‘default’, ‘kaps’, true);

    it is only returning the string “kapil” only,even i write in the po file defualt:

    msgid “kaps”
    msgstr “kaps234”

    Please help me out where i am missing out.

  4. I don’t really get it kapil. How can it return the string kapil if you don’t have this string in your .po file.

    Search through your files for the string it returns (in your case “kapil”) and see what the problem is there.

  5. @Sava:
    This is for a predefined mannual translation. Say if i have small site, but lets say i have “browse, upload elements”, it automatically take the default browser language.

    Q. How to make browser based translation? (telling browser via cakephp, to render as romanian language or dutch or english etc, what ever, browser is supporting.)

    Thank you

    1. @Shamun,
      All you have to do is to take the browser’s language like this:

      $language = $_SERVER['HTTP_ACCEPT_LANGUAGE'];

      and $language will be en-us,en;q=0.5 in my case.
      You can also get an easier to use string with substr.


      $language = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);

      And $language will be en.

      And now just tell cakephp to use the language files for $language.

  6. Thanks for writing a nice article, i have followed your way and by manually using Configure::write(‘Config.language’, ‘ro’); i can do anything.
    I have one question everything works fine but when i use hebrew or arabic language to display i saved them in utf8 .po file. But inside view i see garbage characters instead of correct characters? can you elaborate little bit how we can manage this??

    1. Hello Farhan,
      You can read about using arabic characters here: http://bakery.cakephp.org/articles/view/unaneem-com-a-community-website-built-on-cakephp-with-extensive-use-of-ajax

      Scroll down and find “Challenges we had to face and overcome using CakePHP. There's a nice custom substring UTF-8 method (needs mb_string to be loaded) you should use.

  7. Hello,

    I am new in cake php. I want to create site which support multiple language support. I follow step given by you also create two table name (1) i18n (2) posts
    here is the table structure

    CREATE TABLE `i18n` (
    `id` int(10) NOT NULL auto_increment,
    `locale` varchar(6) NOT NULL,
    `model` varchar(255) NOT NULL,
    `foreign_key` int(10) NOT NULL,
    `field` varchar(255) NOT NULL,
    `content` mediumtext,
    PRIMARY KEY (`id`),
    KEY `locale` (`locale`),
    KEY `model` (`model`),
    KEY `row_id` (`foreign_key`),
    KEY `field` (`field`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

    but when try to implement in my view its not working properly. Can you please guide me.

    1. You need to edit the model as well for multiple languages :


      var $actsAs = array(
      'Translate' => array(
      'field1' => 'Field 1',
      'field2' => 'Field 2',
      'field3' => 'Field 3'
      )
      );

      And in your views you need to add this code for every field you want translated:


      < ? $title = Set::combine($this->data['title'], '{n}.locale', '{n}.content');
      foreach(Configure::read('Config.languages') as $codeLang => $locale):
      e($form->input(
      'Contest.title.'.$locale['locale'],
      array(
      'label' => '('.$codeLang.')',
      'value' => isset($title[$locale['locale']]) ? $title[$locale['locale']] : '',
      'class' => 'textField'
      )
      ));
      endforeach;
      ?>

      … this code will create a form input for each of the languages you configured CakePHP to use

  8. How do i make a link for home page that will change the language in home page?

    1. let’s say you have 2 languages: romanian and english.
      The links would look something like this:

      < ?php if($this->params['lang'] == 'ro'){ echo 'Romana';} else { echo $html->link('Romana', am($this->params['pass'], array('lang' => 'ro')));}?>
      < ?php if($this->params['lang'] == 'en') {echo 'English';} else {echo $html->link('English', am($this->params['pass'], array('lang' => 'en')));}?>

  9. Please help, i don’t seem to understand something here… these .po files contain small site-wide strings, like filed-names etc… but what about the actual pages’ content? i need to give the site owner a chance to add croatian and english version of each page (i.e. page’s main content, e.i. long texts). I already made the cms and have the separate fileds for page text in either language (db fields are text_cro and text_en).
    How do i grab and show the correct text?

    Thanx!