May, 2010 archive

Sat08May

GNU gettext with PHP

Written in Development

When we started the development of trackingo a question came to our minds “what would be the best way to localize the entire application?”. The best choice must be one that was able to separate the text outside the source code, making easier to bring more languages to the application.

The easiest setup is probably to have tens or hundreds of PHP constants or an array with all the phrases and choose which array or which source code with constants apply depending on the language of the user. That system is very easy to understand, but is evident that for more than two languages is unsustainable: the source code gets bigger and bigger and there is no way back. The scalability of the system is simply zero.

In terms of performance is also very very poor: all phrases will be stored in the local memory, are they used or not.

Once we had discarded that option, we chose the official GNU translation system, GNU-gettext.

POEdit gettext editor

Translation system:

  • The files with translations are the .PO file, editable with Notepad or with the specialized POEdit and the .MO file, is the compiled version of the .PO source file. The programming language you are going to use with that only will read the .MO file, so you need to compile it after any change made in the original .PO.
  • Each folder have a .PO and a .MO file and each folder corresponds to a language. The main language of the application not have to have a folder for it.

The advantages we find with that system are:

  • Complete separation between PHP code and translations. If we want, we can pass the .PO file to a professional translator and get back with perfect translations; Otherwise we would have needed a person with almost basic programming knowledge.
  • Performance, gettext is more optimized than any trick we could manage to do with PHP. The access to translation won’t be a bottleneck.
  • Standard. GNU gettext is the standard for translations using open programming languages such as PHP.
  • Clean code. Calling a translation is as simple as call a function called __(), pass it a string and if is in the .PO, the phrase will be translated.

Using gettext for PHP:

To use gettext with PHP you must download the free library php-gettext and call it from your source code:

require_once(GETTEXT_FOLDER."php-gettext-1.0.9/gettext.inc");
$locale = $this->language;
$encoding = ‘UTF-8′;

T_setlocale(LC_MESSAGES, $locale);
$domain = ‘trackingo’;
T_bindtextdomain($domain, LOCALE_DIR);
T_bind_textdomain_codesett($domain, $encoding);
if ($locale!="en") {
        textdomainin($domain);
}
 

You set a default encoding (UTF-8), the language and call the functions T_setlocale, T_bindtextdomain, T_bin_textdomain_codesset and textdomainnin. Be carefull that $domain is no your website domain, but the .MO filename. The main language for your application don’t have to be called.

To call a translation, simple call the function __(“string”) with the phrase to translate. You can use sprintf() or printf() if you need a custom message, for example:

printf(__("Things %s are tracking"),ucfirst($username));
 

Possible modification of the source code:

An interesting thing that I think this system lacks is a function that direct output the value of the translation, so I edited the source code of gettext.inc to include a function for do that:

/*echo gettext*/
function _e($msgid) {
        echo _gettext($msgid);
}
 

Simply echo the translation but is lighter and in some cases can be very useful.

In summary:

I see gettext as the best choice to localize your web. If you are thinking about translating your web, use gettext.