The document discusses internationalization in CakePHP, including:
- Using methods like __() and __n() to translate text strings, and Configure::write() to set the application language.
- The Translate behavior, which allows translating database records into multiple languages and automatically filtering by the current language.
- Generating translation files using the i18n extractor, editing them with POEDIT, and caching translated elements.
4. Why do we need i18n?
● Expand your audience
● CakePHP makes it simple
● Translators don't have to know our
application
● Works with files (views, models,
controllers), and database records
● Think about your future needs
5. This could get you killed
● The switch lover
switch ($language) {
case 'en': echo 'My message'; break;
case 'es': echo 'Mi mensaje'; break;
}
● The table lover
$terms = $this->Term->find('all');
$terms = Set::combine($terms, '/Term/code', '/Term/text');
$this->set(compact('terms'));
// ...
echo $term['my_message'];
8. The CakePHP way
<p><?php __('Welcome to my page'); ?></p>
<?php echo $html->link(__('Home', true), '/'); ?>
<p><?php echo sprintf(__('Your name is %s', true),
$name); ?></p>
$ cake i18n extract -output app/locale
locale/eng/LC_MESSAGES
locale/ default.po
default.pot POEDIT
default.mo
9. Let's go to work
● Our own example
● Modify the view
● Run the extractor
● Look at the generated template file
● Run POEDIT → nplurals=2; plural=(n != 1);
● Look at the translated files
● Some tips when using POEDIT
10. Translate Behavior
● Internationalization for our database
records
● All translations in the same table
● Automatically filters the records to
fetch them in the current language
11. Translate Behavior
class Post extends AppModel {
public $actsAs = array('Translate' => array(
'title', 'body'
));
public $belongsTo = array('User');
}
CREATE TABLE `posts`( CREATE TABLE `posts`(
`id` INT NOT NULL AUTO_INCREMENT, `id` INT NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL, `user_id` INT NOT NULL,
`title` VARCHAR(255) NOT NULL, `title` VARCHAR(255) NOT NULL,
`body` TEXT, `body` TEXT,
`created` DATETIME, `created` DATETIME,
`modified` DATETIME, `modified` DATETIME,
PRIMARY KEY(`id`) PRIMARY KEY(`id`)
); );
12. Translate Behavior
mysql> desc i18n;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| locale | varchar(6) | NO | MUL | NULL | |
| model | varchar(255) | NO | MUL | NULL | |
| foreign_key | int(10) | NO | MUL | NULL | |
| field | varchar(255) | NO | MUL | NULL | |
| content | text | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
mysql> select * from i18n;
+----+--------+-------+-------------+-------+------------------------------------------+
| id | locale | model | foreign_key | field | content |
+----+--------+-------+-------------+-------+------------------------------------------+
| 1 | eng | Post | 1 | title | Pre-registration opened |
| 2 | spa | Post | 1 | title | Pre-inscripciones abiertas |
| 3 | eng | Post | 1 | body | Body for Pre-registration opened |
| 4 | spa | Post | 1 | body | Cuerpo para Pre-inscripciones abiertas |
+----+--------+-------+-------------+-------+------------------------------------------+
4 rows in set (0.00 sec)
13. Translate Behavior
$posts = $this->Post->find('all', array(
'recursive' => -1, 'fields' => array('title', 'body')
));
$posts = Set::combine($posts, '/Post/title', '/Post/body');
SELECT `I18n__title`.`content`, `I18n__body`.`content`
FROM `posts` AS `Post`
LEFT JOIN `i18n` AS `I18n__title` ON (`Post`.`id` = `I18n__title`.`foreign_key` AND
`I18n__title`.`model` = 'Post' AND `I18n__title`.`field` = 'title')
LEFT JOIN `i18n` AS `I18n__body` ON (`Post`.`id` = `I18n__body`.`foreign_key` AND
`I18n__body`.`model` = 'Post' AND `I18n__body`.`field` = 'body')
WHERE `I18n__title`.`locale` = 'eng' AND `I18n__body`.`locale` = 'eng'
array(
[Pre-registration opened] => Body for Pre-registration opened
[Site Updates] => Body for Site Updates
)