Saturday, December 29, 2012

CodeIgniter internationalization


CodeIgniter is an open-source PHP framework that follows the MVC architecture (Model–View–Controller). Its main advantage is being simpler and lighter (4Mb all wet) than Zend or Symfony, with a fast learning curve. We will detail in this post the internalization by language files in the version 2.1.3 of this framework.

Internationalization handling


The default language is defined in the application/config/config.php configuration file.
$config['language'] = 'en';
Language files are stored in the application/language/ directory.

We choose here a two-letter language code (en, ISO 639-1 code), but we could just as well use a three-letter code (eng, ISO 639-2 or 639-3 code), a localized two-letter language code (en-ca for Canadian English, ISO 639-1 language code and ISO 3166-1 country code), the name of the language in full (english), or any other formalism.

The recommended way is to prefix the language file name (_lang.php) by a semantic unit (here, the controller name, hence test).

Likewise, to avoid any collision between the keys of the different files, it is common practice to prefix each key by this same semantic unit.

system/language/en/test_lang.php
$lang['test_test'] = "Let's test";
$lang['test_my_view'] = "My view";
system/language/fr/test_lang.php
$lang['test_test'] = "Essayons";
$lang['test_my_view'] = "Ma vue";
The call of the localized variable is made in the controller by loading the language file using the method load to which we give two parameters: the prefix of the language file (here, the controller's name in lower case) and the language code used as sub-directory name of the language directory (if the second parameter is omitted, this is the default language of the configuration file that will be used).

We then assign the variables containing the strings of the language file with the method line (parameterized by the key of the associative array $lang), as many keys of the associative array $data.

The controller is then:
public function view() {
    $this->lang->load('test', 'fr');

    $data['lets_test'] = $this->lang->line('test_test');
    $data['my_view'] = $this->lang->line('test_my_view');

    $this->load->view('test', $data);
}
On the view side, the variables are directly displayable: $lets_test and $my_view.

Using parameters in a language file


The direct approach consists of inserting as many placeholders as needed in the localized string following the PHP function sprintf formalism (which is %s for a standard string).

application/language/en/test_lang.php
$lang['test_lets'] = "Let's %s now";
$lang['test_program'] = "program";
application/language/fr/test_lang.php
$lang['test_lets'] = "Allons %s maintenant";
$lang['test_program'] = "programmer";
The controller inserts the missing substring when called.
$data['lets_dance'] = sprintf($this->lang->line('test_lets'), $this->lang->line('test_program'));
The display in the view will then return either Let's program now, or Allons programmer maintenant.

The problem becomes complicated when multiple substrings are passed as arguments, as their order can be different depending on the language used.

The trick then is to use numbered parameters with the function sprintf. These variables can also be reused.

application/language/en/test_lang.php
$lang['test_there'] = "There are %1\$s in the %2\$s. I like %1\$s.";
$lang['test_monkeys'] = "monkeys";
$lang['test_banana_tree'] = "banana tree";
application/language/fr/test_lang.php
$lang['test_there'] = "Le %2\$s est plein de %1\$s. J'aime les %1\$s.";
$lang['test_monkeys'] = "singes";
$lang['test_banana_tree'] = "bananier";
The controller inserts the missing substrings in the same order when called, whatever the language.
$data['there'] = sprintf($this->lang->line('test_there'), $this->lang->line('test_monkeys'), $this->lang->line('test_banana_tree'));
The view display will then be either There are monkeys in the banana tree. I like monkeys, or Le bananier est plein de singes. J'aime les singes.

Let's sum it up


We have seen in this short tutorial how to internationalize an application produced with the CodeIgniter framework: how to set up language files, how to load them in controllers, then how to display their variables in views, while managing their parameterization and the question of variables order.

In a future post, we will see how to make CodeIgniter URLs SEO-friendly and internationalized.

Some reading

Professional CodeIgniter

If you want to go a bit further, I recommend you this book: Professional CodeIgniter, by Thomas Myer (2008, 336 pages).


Internationalisation de CodeIgniter (in French)
Internacionalización de CodeIgniter (in Spanish)
Internacionalização de CodeIgniter (in Portuguese)

1 comment:

  1. Hi! I saw you can internationalize CodeIgniter projects with https://poeditor.com/ by using this library https://github.com/joelvandal/codeigniter-gettext-poeditor

    ReplyDelete