Comment traduire un site internet ?

Par Jean-François GAZET le 15 septembre 2015

Traduire un site, ou un logiciel, dans le monde des bisounours ce serait ça :

  • Dans votre code source, vous écrivez tout ce que vous voulez sans vous soucier des traductions.
  • Vous lancez un programme (mais pas trop loin) qui parcourt votre code source à la recherche de textes et génère un fichier à traduire.

Oui mais mon code évolue ce qui implique des nouveaux textes à traduire, et des textes obsolètes dans les fichiers de traduction ?
Ben, vous relancez le programme, il met à jour les fichiers de traduction en ajoutant les nouveaux textes à traduire et en supprimant ceux qui ne sont plus utilisés.

Ce programme existe, il s’appelle gettext. Il n’est pas nouveau, c’est même un dinosaure. Mais comprendre son fonctionnement et le mettre en place peut être un peu déroutant au début.

Voyons pas à pas comment traduire un site en PHP.

Adaptation du projet

Cas concret : vous avez la page internet index.php suivante dans votre site :

<!DOCTYPE html>
<html>  
  <head>
    <meta charset="utf-8">
    <title>Titre de page</title>
  </head>
<body>
  <p>
    <strong>Premier paragraphe</strong>
  </p>
  <p>
    Cool, demain j'ai piscine.
  </p>
</body>
</html>

Modifiez-la comme ceci :

<!DOCTYPE html>
<html>  
  <head>
    <meta charset="utf-8">
    <title><?php echo _("Titre de page"); ?></title>
  </head>
<body>
  <p>
    <strong><?php echo _("Premier paragraphe"); ?></strong>
  </p>
  <p>
    <?php echo _("Cool, demain j'ai piscine."); ?>
  </p>
</body>
</html>

Dans le navigateur vous ne verrez aucune différence. On a juste isolé le texte traductible. Pour info “_” est un alias de la fonction gettext.

Comme vous l’avez remarqué, en l’absence de traduction, le texte par défaut est affiché (“Titre de page”, etc.). Il servira d’index donc je conseille d’écrire en anglais dans le code source.

Dans l’arborescence du site, créez un dossier locale et un sous-dossier pour chaque langue que vous souhaitez. Vous devez respecter obligatoirement la structure suivante :

monsite/locale
    /en_US
        /LC_MESSAGES
    /es_ES
        /LC_MESSAGES
    ...

Pour avoir un aperçu des pays existants, saisissez la commande :

cat /usr/share/i18n/SUPPORTED

Création d’un modèle de base

On va parcourir le code source, en extraire les textes, et générer un fichier qui servira de base pour toutes les traductions. Celui-ci pourra être écrasé au besoin, pour suivre les mises à jour de votre code.

En ligne de commande, tapez (mais pas trop fort) :

cd monsite
find . -iname "*.php" | xargs xgettext -o locale/traductions.pot

C’est quoi ce charabia ?

  • cd monsite : on se place à la racine du dossier contenant le code source.
  • find . -iname "*.php" : on recherche de façon récursive dans le dossier courant (et sous-dossiers), les fichiers se terminant par php, quelque soit la casse.
  • xgettext : la commande magique qui extrait les textes à traduire depuis chaque fichier PHP.
  • -o locale/traductions.pot : on crée le fichier modèle traductions.pot dans le dossier locale.

Pour l’anecdote .pot signifie Portable Object Template.

Première traduction dans une langue

On va traduire en anglais. Copiez le fichier modèle pot dans le dossier LC_MESSAGES de la langue. Changez l’extension en po :

cd monsite/locale
cp traductions.pot en_US/LC_MESSAGES/traductions.po

Alternativement, on peut utiliser la commande msginit qui tiendra compte de vos variables d’environnement pour y ajouter vos informations :

msginit --locale=en -i locale/traductions.pot -o locale/en_US/LC_MESSAGES/traductions.po

Ouvrez ce fichier en_US/LC_MESSAGES/traductions.po dans votre éditeur de texte préféré :

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: MonSite\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-14 23:23+0200\n"
"PO-Revision-Date: 2015-09-14 23:24+0100\n"
"Last-Translator: Jean-François GAZET <theboss@jeffprod.com>\n"
"Language-Team: JeffProd <thedreamteam@jeffprod.com>\n"
"Language: English\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: index.php:5
msgid "Titre de page"
msgstr ""

#: index.php:9
msgid "Premier paragraphe"
msgstr ""

#: index.php:12
msgid "Cool, demain j'ai piscine."
msgstr ""
  • Les lignes commençant par # sont des commentaires pour information.
  • Vous pouvez modifier les entêtes (date de création, traducteur, équipe…).
  • Les chaines de texte à traduire ont un identifiant : msgid.
  • Leur emplacement dans chaque fichier est précisé, ex. : index.php:9 pour ligne 9

Il ne vous reste qu’à inscrire les traductions dans les msgstr comme ceci :

#: index.php:5
msgid "Titre de page"
msgstr "Page title"

#: index.php:9
msgid "Premier paragraphe"
msgstr "First paragraph"

#: index.php:12
msgid "Cool, demain j'ai piscine."
msgstr "Yes, swimming pool tomorrow."

Maintenant, on génère à partir de ce fichier texte, un catalogue binaire de messages (fichier mo). C’est ce dernier qui sera utilisé par le site :

cd locale/en_US/LC_MESSAGES
msgfmt traductions.po -o traductions.mo

Voilà. La traduction anglaise est prête.

Adaptation du projet (suite)

Revenons à notre page PHP. Le texte est toujours affiché en français. Ajoutons un peu de code en haut de page :

<?php
// Choix de la langue : de_DE, fr_(FR,BE,CA,CH,LU) en_(US,GB)...
$locale='en_US.utf8';

// Domaine : nom du fichier 'mo', car vous pouvez en gérer plusieurs.
// La traduction sera cherchée dans :
// ./locale/en_US/LC_MESSAGES/traductions.mo
$domaine = 'traductions'; 

putenv('LC_ALL='.$locale); // Fixe la valeur d'une variable d'environnement
setlocale(LC_ALL, $locale); // Modifie les informations de localisation
bindtextdomain($domaine, 'locale'); // Fixe le chemin (relatif ou absolu) d'un domaine
textdomain($domaine); // choix du domaine par défaut

?><!DOCTYPE html>
<html>  
  <head>
    <meta charset="utf-8">
    <title><?php echo _("Titre de page"); ?></title>
  </head>
<body>
  <p>
    <strong><?php echo _("Premier paragraphe"); ?></strong>
  </p>
  <p>
    <?php echo _("Cool, demain j'ai piscine."); ?>
  </p>
</body>
</html>

La page est affichée maintenant en anglais. Vous pouvez adapter ce code pour prendre en compte par exemple une variable de session ou un paramètre dans l’URL pour le choix de la langue. Vous pouvez également placer ce code dans un fichier séparé (et l’inclure avec include).

Le plus dur est fait. Pour la suite, c’est la même chose.

Mise à jour des traductions

Le code évolue. J’ajoute du texte, j’en modifie, et j’en supprime :

<?php
// Choix de la langue : de_DE, fr_(FR,BE,CA,CH,LU) en_(US,GB)...
$locale='en_US.utf8';

// Domaine : nom du fichier 'mo', car vous pouvez en gérer plusieurs.
// La traduction sera cherchée dans :
// ./locale/en_US/LC_MESSAGES/traductions.mo
$domaine = 'traductions'; 

putenv('LC_ALL='.$locale); // Fixe la valeur d'une variable d'environnement
setlocale(LC_ALL, $locale); // Modifie les informations de localisation
bindtextdomain($domaine, 'locale'); // Fixe le chemin (relatif ou absolu) d'un domaine
textdomain($domaine); // choix du domaine par défaut

?><!DOCTYPE html>
<html>  
  <head>
    <meta charset="utf-8">
    <title><?php echo _("Titre"); ?></title>
  </head>
<body>
  <p>
    <?php echo _("Cool, demain j'ai piscine."); ?><br>
    <?php echo _("ou course à pied."); ?><br>
  </p>
</body>
</html>

La méthode est la même. On regénère le fichier modèle pot en écrasant l’ancien (même commande que précédemment) :

cd monsite
find . -iname "*.php" | xargs xgettext -o locale/traductions.pot

Info : si vous obtenez l’erreur “Commentaire non-ASCII”, ajoutez --from-code=UTF-8 à la fin de la ligne de commande.

On fait un remix du nouveau modèle avec le fichier po de langue anglaise existant :

msgmerge locale/en_US/LC_MESSAGES/traductions.po locale/traductions.pot --output-file=locale/en_US/LC_MESSAGES/traductions.po

Ouvrez le fichier locale/en_US/LC_MESSAGES/traductions.po. Vous constatez que les traductions supprimées ont été placées en commentaire. Celles qui sont toujours d’actualité sont inchangées. Et il y a des nouvelles lignes à traduire. Yapluka.

On génère ensuite le fichier binaire mo (comme précédemment) :

cd locale/en_US/LC_MESSAGES
msgfmt traductions.po -o traductions.mo

Et la traduction est à jour.

Interfaces graphiques

Pour ceux qui redoutent les lignes de commande il existe des logiciels “user-friendly” :

Pour aller plus loin

On peut gérer les traductions au pluriel comme “j’ai %d bonbon” ou “j’ai %d bonbons” selon la valeur du nombre : pour cela voir ngettext.
gettext sur Wikipedia
Site officiel de gettext et manuel en ligne


Partagez cet article


A lire également Tous les articles