Internationaliser une application Mojolicious

Faire une application Mojolicious, c’est bien, faire une application Mojolicious qui soit traduite dans plusieurs langages, c’est mieux !

Pour commencer, il faut installer le plugin Mojolicious::Plugin::I18N, qui va faire le gros du boulot.

On l’active simplement avec

$self->plugin('I18N');

dans le fichier principal de l’application (il y a des options possibles, listées sur la page CPAN du plugin).

Pour utiliser les traductions, on utilise le helper l :

# dans un fichier de template
<%=l 'truc' %>
# dans un controller
$c->l('truc');

Ensuite, on crée des fichiers de traduction. J’ai longtemps fait comme indiqué sur la page du plugin, à savoir, par exemple pour le français, un fichier fr.pm qui contient la variable %Lexicon qui elle-même contient les traductions, dans un dossier I18N de l’arborescence de l’application (voir la page du plugin pour les détails). Ça marche, mais ce n’est pas vraiment très agréable à utiliser. Il faut passer sur chaque fichier de traduction pour rajouter une phrase, c’est un peu fastidieux.

Gettext est un système de traduction bien connu qui a l’avantage d’avoir plein d’outils pour l’utiliser. On va donc plutôt utiliser cela.

Pour pouvoir extraire automatiquement toutes les chaînes de traduction, nous allons avoir besoin du module Perl Locale::Maketext::Extract qui fournit le binaire xgettext.pl qui va servir à l’extraction.

Pour que xgettext.pl réussisse à tout extraire correctement, une petite modification de la syntaxe utilisée précédemment dans les templates est nécessaire.

Au lieu de

<%=l 'truc' %>

on écrira désormais

<%= l('truc') %>

Comme je n’ai pas envie de parser tous mes fichiers, qui ne contiennent pas tous des chaînes à traduire, j’ai listé les fichiers pertinents dans un fichier locales_files.txt.

Pour extraire mes chaînes :

xgettext.pl -f locales_files.txt

Cela donne un fichier messages.po. L’option -o FILE permet de dire dans quel fichier mettre les chaînes à traduire. Si le fichier cible existe déjà, xgettext.pl le mettra à jour si besoin est.

Pour utiliser facilement ce fichier de traduction, nous allons le placer dans le répertoire de traduction du plugin Mojolicious. Et le renommer pour lui donner le nom d’un langage. Pour mon projet Lstu, cela donne lib/Lstu/I18N/fr.po, en lieu et place du fichier lib/Lstu/I18N/fr.pm évoqué plus haut.

Pour dire au plugin Mojolicious d’utiliser directement les fichiers .po, on va créer le fichier lib/Lstu/I18N.pm :

package Lstu::I18N;

use base 'Locale::Maketext';
use File::Basename qw/dirname/;
use Locale::Maketext::Lexicon {
    _auto => 1,
    _decode => 1,
    '*' => [Gettext => dirname(__FILE__) . '/I18N/*.po']
};

1;

Et c’est fini ! Il ne reste plus qu’à copier le fichier fr.po dans les langages voulus et à les traduire.

cp fr.po en.po
vi en.po

Dès qu’un nouveau fichier de langue est détecté par l’application (un petit restart de l’application est nécessaire), le langage sera proposé lorsqu’un visiteur utilisant ce langage dans les préférences de son navigateur passera par là :-).

On peut utiliser poedit pour modifier les fichiers .po, cela offre des facilités que ne propose pas vim. Et l’utilisation du format .po permet d’utiliser – par exemple — la plateforme Transifex pour coordonner les efforts de traduction. Je sais, ça pue, c’est pas libre, mais il faut dire ce qui est, c’est pratique. D’ailleurs, j’ai déposé les fichiers de traduction de Lstu sur Transifex, si le cœur vous en dit 🙂

J’ai trouvé cette nouvelle façon de traduire mes applications Mojolicious via ce billet et celui-ci.