Inter­na­tio­na­li­ser une appli­ca­tion Mojo­li­cious

Faire une appli­ca­tion Mojo­li­cious, c’est bien, faire une appli­ca­tion Mojo­li­cious qui soit traduite dans plusieurs langages, c’est mieux !

Pour commen­cer, il faut instal­ler le plugin Mojo­li­cious::Plugin::I18N, qui va faire le gros du boulot.

On l’ac­tive simple­ment avec

$self->plugin('I18N');

dans le fichier prin­ci­pal de l’ap­pli­ca­tion (il y a des options possibles, listées sur la page CPAN du plugin).

Pour utili­ser les traduc­tions, 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 traduc­tion. J’ai long­temps fait comme indiqué sur la page du plugin, à savoir, par exemple pour le français, un fichier fr.pm qui contient la variable %Lexi­con qui elle-même contient les traduc­tions, dans un dossier I18N de l’ar­bo­res­cence de l’ap­pli­ca­tion (voir la page du plugin pour les détails). Ça marche, mais ce n’est pas vrai­ment très agréable à utili­ser. Il faut passer sur chaque fichier de traduc­tion pour rajou­ter une phrase, c’est un peu fasti­dieux.

Gettext est un système de traduc­tion bien connu qui a l’avan­tage d’avoir plein d’ou­tils pour l’uti­li­ser. On va donc plutôt utili­ser cela.

Pour pouvoir extraire auto­ma­tique­ment toutes les chaînes de traduc­tion, nous allons avoir besoin du module Perl Locale::Make­text::Extract qui four­nit le binaire xgettext.pl qui va servir à l’ex­trac­tion.

Pour que xgettext.pl réus­sisse à tout extraire correc­te­ment, une petite modi­fi­ca­tion de la syntaxe utili­sée précé­dem­ment dans les templates est néces­saire.

Au lieu de

<%=l 'truc' %>

on écrira désor­mais

<%= 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 perti­nents dans un fichier locales_files.txt.

Pour extraire mes chaînes :

xgettext.pl -f locales_files.txt

Cela donne un fichier messages.po. L’op­tion -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 utili­ser faci­le­ment ce fichier de traduc­tion, nous allons le placer dans le réper­toire de traduc­tion du plugin Mojo­li­cious. Et le renom­mer 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 Mojo­li­cious d’uti­li­ser direc­te­ment 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’ap­pli­ca­tion (un petit restart de l’ap­pli­ca­tion est néces­saire), le langage sera proposé lorsqu’un visi­teur utili­sant ce langage dans les préfé­rences de son navi­ga­teur passera par là :-).

On peut utili­ser poedit pour modi­fier les fichiers .po, cela offre des faci­li­tés que ne propose pas vim. Et l’uti­li­sa­tion du format .po permet d’uti­li­ser – par exemple — la plate­forme Tran­si­fex pour coor­don­ner les efforts de traduc­tion. 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 traduc­tion de Lstu sur Tran­si­fex, si le cœur vous en dit đź™‚

J’ai trouvé cette nouvelle façon de traduire mes appli­ca­tions Mojo­li­cious via ce billet et celui-ci.

Lut.im, un service d’hé­ber­ge­ment d’images gratuit, libre et anonyme

Que celui qui n’a jamais voulu parta­ger simple­ment une capture d’écran lève le doigt. Personne ?

Logo de LUTIm

Le partage d’images nous confronte souvent à divers problèmes :

  • un email prend du temps (retrou­ver l’adresse du desti­na­taire, l’en­voi, etc.) ;
  • un email prend de la place. Ce n’est pas grand chose, mais pour une image jetable, c’est de l’es­pace disque perdu, que ce soit dans le dossier « Envoyé » de l’ex­pé­di­teur ou celui du desti­na­taire. Oui, on peut suppri­mer le mail, mais c’est encore une action à effec­tuer.
  • une solu­tion commme imgur nous ramène au sempi­ter­nel problème des Condi­tions Géné­rales d’Uti­li­sa­tion imbi­tables, pas traduites et qu’on ne lit de toute façon jamais en entier. Pour ce genre de service, on risque de four­nir certains droits à l’hé­ber­geur… et ça c’est pas cool !
  • un owncloud (ou équi­valent) fera bien le travail, au prix d’une certaine complexité de partage et de liens à la longueur ahuris­sante.

Pour répondre à cette problè­ma­tique, j’ai codé LUTIm (pronon­cez comme lutin). Écrit en Perl avec le frame­work Mojo­li­cious, utili­sant le Twit­ter Boots­trap, un sous ensemble de Font Awesome et un plugin jQuery légè­re­ment modi­fié pour la gestion du glis­ser/dépo­ser, LUTIm est un logi­ciel libre (licence AGPL) de partage d’image anonyme et gratuit.

Capture d'écran de l'interface de LUTIm

Le prin­cipe est simple : on glisse/dépose des images (ou via le sélec­teur de fichier clas­sique) et on récu­père 3 liens :

  • un lien vers l’image (utili­sable dans une balise img par exemple) ;
  • un lien de télé­char­ge­ment de l’image (pour éviter le Clic droit > Enre­gis­trer sous) ;
  • un lien vers une page qui affiche l’image et qui est utili­sable sur Twit­ter (l’image appa­raî­tra dans le tweet).

Des options du formu­laire d’en­voi permettent de suppri­mer auto­ma­tique­ment les images après la première consul­ta­tion ou après 24h.

Bien évidem­ment, pour des ques­tions légales, il n’est pas possible d’avoir un service tota­le­ment anonyme : les IPs des envoyeurs d’image et celles des consul­teurs sont enre­gis­trées dans les logs, mais c’est quelque chose de tout à fait habi­tuel sur tout site web. Les IPs des envoyeurs ainsi que celle du dernier consul­teur sont enre­gis­trées dans la base SQLite pour accé­le­rer la recherche d’in­for­ma­tions en cas de requète judi­ciaire (je sais comme il peut être fasti­dieux et long de cher­cher dans des logs).

Lors de la suppres­sion auto­ma­tique d’une image, le fichier est bel et bien supprimé, mais son entrée en base de données persiste et contient l’em­preinte SHA512 du fichier.

De par sa nature libre, vous pouvez bien évidem­ment instal­ler et utili­ser très faci­le­ment LUTIm sur votre propre serveur, mais vous pouvez aussi vous conten­ter d’uti­li­ser l’ins­tance offi­cielle : http://lut.im

LUTIm est dispo­nible en français et en anglais, la langue étant choi­sie selon les préfé­rences du navi­ga­teur. Toutes les bonnes volon­tés sont les bien­ve­nues pour propo­ser d’autres langues !

Enfin, LUTIm propose un plugin pour Shut­ter, logi­ciel de capture d’écran, pour permettre à celui-ci d’en­voyer les capture sur http://lut.im direc­te­ment (plugin à instal­ler soi-même, le site du projet ayant l’air cassé, je n’ai pu leur remon­ter le plugin).