PHP Video Tutorial: Internationalizing with gettext
In this video we will discover the gettext PHP extension which allows to manage the localization of character strings.
How gettext works
gettext is a set of tools designed in the GNU system to manage the internationalization of user interfaces. These tools will rely on 2 types of important files:
- The files
.po
(for Portable Object) can be read and edited by humans and associates a translation with a given character string. - The files
.mo
(for Machine Object) are binary files that are designed to be read by a machine.
To edit and work on these files, we can for example use poedit which offers a visual interface to manage the creation and modification of these files. It will also scan source code for new strings to update translations.
Integration in PHP
The first step is to check that your project supports gettext, you can check this via phpinfo()
activating the gettext extension or more simply checking the presence of the gettext method. You can modify your configuration file php.ini
to activate the extension if needed.
if (!function_exists('gettext')) {
throw new \Exception("L'extension gettext n'est pas active")
}
Then, in your code you can use the function gettext()
(which has an alias _()
) to translate a string.
<h1><?= _('Welcome on my website') ?></h1>
By default, in the absence of translation, this function will simply return the character string directly. You can also use the function ngettext()
to handle the plural.
<p><?= sprintf(ngettext("%d user", "%d users", $count), $count) ?></p>
Once these functions have been used you can use poedit to scan your source code and generate the translations in .po and .mo files that will have to be placed in a certain way in a folder of your project. The structure should be as follows.
<dossier>/<lang_code>_<COUNTRY_CODE>/<CATEGORY>/<domain>.po
For example, to translate a string into French in our application, we will place the files in this way.
locale/fr_FR/LC_MESSAGES/grafikart.po
locale/fr_FR/LC_MESSAGES/grafikart.mo
Then we will be able to tell gettext how to load the files linked to our domain.
$domain = 'grafikart';
$locale="fr_FR";
bindtextdomain($domain, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'locale');
textdomain($domain);
if (!setlocale(LC_ALL, $locale, "{$locale}.UTF-8")) {
throw new \Exception("Locale non supporée $locale")
};
It is also possible to use the environment variables to define the language to use, in this case it will be necessary to use setlocale
passing it an empty string.