Internationaliser son site Web avec PHP et gettext

Le 29 juin 2012 — par

Lorsque l’on parle internationalisation avec PHP, plusieurs options peuvent venir à l’esprit : Utilisation de tableaux PHP, fichiers INI/XML, stockage (no)SQL(ite)… Le plus standard et le plus rapide reste néanmoins l’extension gettext. Voyons comment peut-on combiner le développement Web efficace avec gettext, ce vieux dinosaure conçu pour le monde logiciel.

Ce benchmark montre en effet que nous aurions tort de nous priver du module gettext de PHP pour nos applications Web.

Benchmark par Pablo Hoch

En soi, l’utilisation de gettext est assez aisée. Exemple simple :

La fonction bindtextdomain fait référence à un fichier messages.po dans le répertoire locale/fr_FR/LC_MESSAGES. Un fichier .po peut très bien se créer à la main car sa syntaxe est simple. Mais tout l’intérêt de gettext réside dans l’utilisation des outils annexes comme msgmerge ou xgettext.

En effet, grâce à un script bash, on pourra facilement récupérer les données à traduire dans les scripts de notre site :

Attention, le paramètre --keyword=__ a été mis ici pour anticiper le texte qui va suivre.

Votre fichier est maintenant prêt à être traduit, le logiciel le plus utilisé pour cela s’appelle Poedit et a l’avantage d’être multiplateforme et gratuit. Lorsque vous sauverez le fichier, vous aurez un fichier .mo qui est la forme binaire de votre .po. Si vous ne voulez pas utiliser Poedit, il y a aussi msgfmt qui s’occupe de la compilation.

Une fois le fichier traduit et compilé, il ne reste plus a priori qu’à l’utiliser avec la fonction standard _($message). Seulement l’extension gettext n’est rapide qu’à une seule condition : Redémarrer le serveur Web à chaque fois que l’on met à jour le fichier .po, pour vider le cache.

Pour contourner cette limitation pendant la phase de développement, j’ai développé une fonction alternative nommée __($message), qui utilise le fichier .po en direct avec une émulation simple du parsing de gettext via PHP :

De cette manière, lors du développement local, le fichier sera parsé à chaque affichage de la page et les traductions pourront apparaître en direct (n’oubliez pas de vider le cache à la fin du traitement de la page), ce qui enlève le problème majeur qui en fait aussi sa rapidité : le besoin de redémarrer les serveurs Web à la mise à jour des fichiers.

Nous en revenons, comme vous vous en doutez, au paramètre keyword utilisé dans le fichier précédent. Grâce à ce paramètre, le script va chercher toutes les utilisations de la fonction __() dans votre code et remplir pour vous les traductions qui n’auraient pas été inscrites dans le fichier .po. Plus besoin de remplir votre fichier à la main.

Mise à jour : J’ai commencé cet article en octobre 2011 (oui je sais). Avec le recul, le problème que je craignais s’est avéré vrai : Les fichiers de langue ne sont pas assez stables sur un site Web pour ne demander qu’un seul redémarrage de temps en temps. C’est d’autant plus vrai lorsqu’on a 10 serveurs Web à redémarrer à chaque fois. Mais gettext reste pratique pour tout ce que j’ai évoqué au dessus, ainsi le compromis que j’ai trouvé est d’utiliser gettext avec Memcache.

La perte de performances reste minime, la preuve avec 1 million d’appels à la fonction __() ci-dessous.

Comparatif d'internationalisation avec PHP

Sources : GNU gettext sur Wikipedia & Playing with gettext.

S'abonner au flux RSS du blog
Recevoir les nouveaux articles par e-mail :