Internacionalization: Building Multi-Language Applications With Cakephp
Internacionalization: Building Multi-Language Applications With Cakephp
Tomorrow is my birthday
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
This could get you killed
● The switch lover
switch ($language) {
case 'en': echo 'My message'; break;
case 'es': echo 'Mi mensaje'; break;
}
// ...
echo $term['my_message'];
The CakePHP way
● Methods
● Translate behavior
● i18n extractor
The CakePHP way
● Multibyte
● 1 letter != 1 byte
● 8 bits -> 256
● wchar_t (L'w')
● mb_strlen(), mb_strpos(), mb_substr(), ...
● Multibyte::checkMultibyte() -> ord($char)
> 128
● Multibyte::utf8($string) -> array (values
higher than 128 allowed)
● Multibyte::ascii($array) -> string
The CakePHP way
locale/eng/LC_MESSAGES
locale/ default.po
default.pot POEDIT
default.mo
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
Translate Behavior
● Internationalization for our database
records
array(
[Pre-registration opened] => Body for Pre-registration opened
[Site Updates] => Body for Site Updates
)
Translate Behavior
$this->Post->create();
$this->Post->save(array('Post' => array(
'user_id' => 1,
'title' => array('eng' => 'ENG 1', 'spa' => 'spa1'),
'body' => array('eng' => 'Body for ENG 1', 'spa' => 'Cuerpo para spa1')
)));
$this->Post->create();
$this->Post->save(array('Post' => array(
'user_id' => 1,
'title' => array('eng' => 'ENG 1'),
'body' => array('eng' => 'Body for ENG 1')
)));
$this->Post->save(array('Post' => array(
'id' => $this->Post->id,
'title' => array('spa' => 'spa1'),
'body' => array('spa' => 'Cuerpo para spa1')
)));
Changing the language
class AppController extends Controller {
public $components = array('Cookie');
public function beforeFilter() {
$lang = null;
if (!empty($this->params['url']['lang'])) {
$lang = $this->params['url']['lang'];
$this->Cookie->write('CakeFestLanguage', $lang, false, '+365 days');
} else {
$lang = $this->Cookie->read('CakeFestLanguage');
}
if (empty($lang)) {
$lang = Configure::read('CakeFest.defaultLanguage');
}
Configure::write('Config.language', $lang);
}
function beforeRender() {
$this->set('currentLanguage', Configure::read('Config.language'));
}
}
Changing the language
class AppHelper extends Helper {
Public function url($url = null, $full = false) {
if (!empty($url) && !is_array($url) && $url[0] == '/') {
$urlRoute = Router::parse($url);
if (!empty($urlRoute['controller'])) {
$url = array_merge(array_intersect_key($urlRoute,
array_flip(array('admin', 'controller', 'action', 'plugin'))), $urlRoute['pass'],
$urlRoute['named']);
}
}
if (is_array($url)) {
if (!isset($url['lang']) && Configure::read('Config.language') !=
Configure::read('CakeFest.defaultLanguage')) {
$url['lang'] = Configure::read('Config.language');
}
}
return parent::url($url, $full);
}
}
Caching i18n elements
tmp/cache/views
element_eng_news
element_spa_news
And we are done
Questions?