To develop any multilingual website (Translated database content only) using cakephp framework all basic steps are discussed below. If you want fully multilingual website with translated button text or label text then go forward with Internationalizing your application
To manage multiple language translated content for any specific models specific field cakephp has a core behavior named TranslateBehavior.
Suppose we want a website with multiple number of language support and site administrator can add/edit/delete any language and front-end user can choose any language to visit the website.
Here are the list of steps given below.
Step 1: Create a db language table
CREATE TABLE `languages` ( `id` int(11) NOT NULL auto_increment, `title` varchar(120) NOT NULL, `flag` varchar(100) default NULL, `code_2_digit` varchar(2) NOT NULL, `code_4_digit` varchar(6) NOT NULL, `created` datetime NOT NULL, `modified` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
now do a management for languages db table for site administrator
Step 2: Add a language as default on cakephp core
Configure::write('Config.language', 'en_us');
Step 3: Create a db table i18n
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`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Suppose you want to add this multilingual features for db pages table and the translateable field will be title and description here
Step 4: Create a db pages table
CREATE TABLE `pages` ( `id` int(11) unsigned NOT NULL auto_increment, `title` varchar(255) default NULL, `identifier` varchar(255) default NULL, `description` text, `meta_key` text, `meta_desc` text, PRIMARY KEY (`id`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and then on page.php model you need to add The translate behavior as below
var $actsAs = array( 'Translate' => array( 'title'=>'titleTranslate', 'description'=>'descriptionTranslate' ) );
Basically that’s all, now if you add or save this Page model with data on i18n table there will be added 2 new row or update existing row as:
i18n table data samle:
id: auto id locale: Configure::read('Config.language'); //'en_us' model: Page foreign_key: page_id from Page model field: title content: new or updated content for title field and id: auto id locale: Configure::read('Config.language'); //'en_us' model: Page foreign_key: page_id from Page model field: description content: new or updated content for description field
now if you change the configuration value with es_mx like
Configure::write('Config.language', 'es_mx');
then when saving Page model all fields value will be same but locale filed value will be es_mx.
So if you want to save Page models data with another language like Spanish (Mexico)
you can use below code on controller before same the Page model
$this->Page->locale = 'es_mx'; $this->Page->save($this->data);
Additional Steps: Saving all languages content at a time.
if you go for edit Page model and load specific row by id and debug it’s value like
$this->data=$this->Page->read(); pr($this->data);
the pr() output will be look like
Array ( [Page] => Array ( [id] => 14 [title] => Terms & Condition [identifier] => terms-condition [description] => Terms & Condition Description will goes here [meta_key] => [meta_desc] => [locale] => en_us ) [titleTranslate] => Array ( [0] => Array ( [id] => 15 [locale] => en_us [model] => Page [foreign_key] => 14 [field] => title [content] => Terms & Condition ) [1] => Array ( [id] => 132 [locale] => es_mx [model] => Page [foreign_key] => 14 [field] => title [content] => Terms & Condition ) ) [descriptionTranslate] => Array ( [0] => Array ( [id] => 16 [locale] => en_us [model] => Page [foreign_key] => 14 [field] => description [content] => Terms & Condition Description will goes here ) [1] => Array ( [id] => 133 [locale] => es-mx [model] => Page [foreign_key] => 14 [field] => description [content] => Terms & Condition Description will goes here ) ) )
So that means you can save all languages i18n entry at a time with cakephp saveAll method!
Our target is to save all languages(which all is already available on languages db table) translated content at a time for Page model.
To do it, create a translate method on pages_controller.php like
function admin_translate($id=null) { if($id==null){ $this->redirect($this->referer()); exit; } if(!empty($this->data)){ if($this->Page->saveAll($this->data)) { $this->Session->write('Success',true); $this->Session->setFlash('Page has been seved successfully!'); $this->redirect(array('controller' => 'pages', 'action' => 'index')); exit; } } elseif($id) { $this->Page->id=$id; $this->data=$this->Page->read(); $this->set('id',$id); } $this->paginate = array('Language' => array('limit' => $this->admin_page_factor)); $languages = $this->paginate('Language'); $this->set(compact('languages')); }
now create a admin_translate.ctp for Page model and create a form to save Page model and it’s sub entry like numtiple titleTranslate and descriptionTranslate with all fields and submit that form on admin_translate method!
Final step: Management for front-end visitor
For front-end landing page show the list of languages from languages db table.
When visitor click on any language to choose it then redirect him/her on a page and save visitor chosen language code on SESSION and redirect him/her on site home page like
function choose($identifier){ $this->Session->write('language',$identifier); $this->redirect(array('controller' => 'pages', 'action' => 'display', 'home')); exit; }
and on site home page load the page content like
$this->Page->locale = $this->_get_language(); $identifier=='home'; $details=$this->Page->findByIdentifier($identifier);
where _get_language(); is a method from app_controller.php to get current SESSION 4 digit language code like
/** * If it is defined the language in session using landing page then it will return language * other wise it will return en_us as default * * @return String * @access public */ public function _get_language(){ $language = $this->Session->read('language'); if(empty($language)){ $language = 'en_us'; } return $language; }
Hi,
A good starting point however for people just getting involved in full-app localization, you seemed to leave out your most crucial part.
“now create a admin_translate.ctp for Page model and create a form to save Page model and it’s sub entry like numtiple titleTranslate and descriptionTranslate with all fields and submit that form on admin_translate method!”
Could you please elaborate on this with an example?
Thank you.
LikeLike
Hey,
finally I found a really good article on that subject. But right now I’m stuck at creating the admin_translate.ctp. To be specifig, how the input fields for the translations should be created.
Could you post the code of the ctp here?
Thanks in advance!
LikeLike
Hi,
either I’m too stupid or the comment view here is broken. I can only see the speech bubble and “2 comments” but I don’t see the actual comments.
LikeLike
Yes you are right, The comment section is acting something headless, I don’t know what’s happening there 😦
LikeLike
Hi,
I couldn’t understand the mean of ‘now do a management for languages db table for site administrator’. Do i need to insert the languages in db by phpMyAdmin?
Thanks
LikeLike
Hi,
What you mean by ‘now do a management for languages db table for site administrator’ and how can i get the data for all languages?
Thanks
LikeLike
Please see my attachment on this post, where I have added 2 screenshot for language management, 1 controller, 1 model and the view folder from one of my live projects, You are advised to just follow the steps and idea. Thanks
LikeLike
Hello.
I’m building a multilingual app with CakePHP and I “took advantage” of your tutorial.
In the app I want administrator to add and edit subpage in all available languages within one form.
The add function works fine, the problem is when I want to edit
subpage and all translations at one time with the use of one form – one of the fields does not want to update in i18n table with translations.
My Subpage model:
http://pastebin.com/Mas1aciu
admin_add function in subpages_controller.php (works fine, adds record to “subpages” table and records to “i18n” table containing title, link and content in every language):
http://pastebin.com/N61WLwNQ
admin_add view:
http://pastebin.com/Y6a1WquA
admin_edit function:
http://pastebin.com/1ZdumqUe
admin_edit view:
http://pastebin.com/BWcXvGKY
The “link” field is created on the basis of entered title. Saving changes after editing the title and content in every language affects only the translations of fields “link” and “content” in i18n table. The “title” field just doesn’t want to change.
I have a Polish – pol – and German – ger – languages in my app.
The var_dump($this->request->data) after submiting edit form, called before Subpage->saveAll, returns:
array(1) {
[“Subpage”]=>
array(8) {
[“id”]=>
string(1) “1”
[“title”]=>
array(2) {
[“pol”]=>
string(15) “Title in Polish”
[“ger”]=>
string(15) “Title in German”
}
[“content”]=>
array(2) {
[“pol”]=>
string(34) ”
Test content in Polish
”
[“ger”]=>
string(34) ”
Test content in German
”
}
[“only_footer”]=>
string(1) “0”
[“only_logged”]=>
string(1) “0”
[“link”]=>
array(2) {
[“pol”]=>
string(15) “title-in-polish”
[“ger”]=>
string(15) “title-in-german”
}
}
}
Even that in var_dump both [title] versions values are updated (AND the “link” fields are correctly transformed on the basis on the titles) – “title”s don’t update in ‘i18n’ table.
I’ve also build another model – Category. Same issue here, although I
translate only two fields (name and link, based on the name). The same
situation with saving changes after edit – only “link” translation is being updated, and “name” isn’t.
Do you have a clue what could be the problem?
Regards,
Anna
LikeLike