Aller au menu - Aller au contenu

Un site multilingue avec GetText


Informations sur le tutoriel

Avatar
Auteur : Captain Awesome
Difficulté : Amateur (2 / 5)
Visualisations : 9 669


Plus d'informations Plus d'informations
Avez-vous déjà essayé de créer un site multilingue ? Si oui, comment ?
La façon la plus prisée des développeurs est de créer un fichier contenant uniquement des variables (ou constantes comme c'est le cas sur phpBB) dont les valeurs correspondent à des expressions prédéfinies.

Un exemple basique :

Code : PHP
1
2
3
4
<?php
$message_bienvenue = "Bienvenue sur mon site !";
$message_connexion = "Vous êtes désormais connecté...";
?>

Le fichier est ensuite enregistré dans un dossier /lang/fr/. Puis le programmeur code quelques autres fichiers avec des noms de variables identiques mais contenant des valeurs traduites ("Welcome to my site !", "Now you're logged in...") et les enregistre dans d'autres dossiers : /lang/en, /lang/de/, etc. Il ne lui reste plus qu'à implémenter un script permettant de récupérer le langage préféré de l'utilisateur et en fonction du résultat, inclure le fichier de langue correspondant.

Cette méthode a l'avantage d'être relativement simple à mettre en place ; cependant, vous constaterez rapidement que plus votre site grandira, plus vos fichiers de langue deviendront conséquents, et qui dit fichier plus conséquent dit fichier plus lourd, entraînant un ralentissement du temps d'exécution. Elle est donc réservée aux "petits" sites.

Mais si vraiment vous sentez que votre projet comportera beaucoup, beaucoup de texte à traduire, l'utilisation de la bibliothèque Gettext (GNU) sera préférable. C'est cette bibliothèque très utile mais peu connue des développeurs en herbe que je compte vous apprendre à manier dans ce tutoriel. :)

Ready ? Let's go ! :pirate:

Avant-propos

GetText ? Quésaco ?



Comme je l'ai mentionné en introduction, GetText est une bibliothèque GNU. Considérée comme une "bibliothèque d'internationalisation", elle a été créée dans le but de faciliter la traduction de programmes et ainsi, d'en améliorer "l'exportation". J'entends par là une meilleure compréhension des utilisateurs. En effet, l'anglais est une langue très, très utilisée en informatique (et pas qu'en informatique d'ailleurs), car étant mondialement reconnue, elle facilite les échanges entre développeurs de différents horizons. Mais qu'en est-il des petits utilisateurs comme nous qui comprenons un mot sur cinq ? :o C'est la question que se sont posé des programmeurs de GNU et pour y remédier, ils ont créé GetText, un "outil" permettant de traduire plus facilement des programmes en fonction de la langue de l'utilisateur.

Par chance, GetText est utilisable avec PHP ! Vous voyez où je veux en venir ? :D
GetText utilise des fichiers compilés .mo qui contiennent des couples clé - valeur, la clé représentant l'expression initiale (celle que vous écrirez dans votre code) et la valeur, la traduction correspondante (celle qui sera affichée à l'utilisateur). Pour obtenir ces fichiers .mo il nous faudra compiler des fichiers .po que nous aurons préalablement codés.

GetText étant initialement destinée aux systèmes Unix, je demande aux utilisateurs de Windows de télécharger la dernière version de la librairie sur ce site. Ne possédant pas moi-même cet OS, je n'ai aucune idée de la manière de l'installer. N'hésitez pas à me contacter par MP ou via les commentaires si vous avez la solution. Je me ferai une joie d'éditer mon tutoriel. ;)

Pour les utilisateurs de Debian, je viens de dénicher un petit tutoriel abordant l'installation de GetText ici.

Activation de GetText en local



Avant toute chose, il faut s'assurer que GetText est bien activée en local (car c'est bien évidemment en local que nous ferons nos tests). Pour cela, lancez votre serveur et créez un nouveau fichier PHP :

Code : PHP
1
2
3
<?php
phpinfo();
?>


Enregistrez le fichier à l'endroit où vous mettez tous vos scripts et exécutez-le dans votre navigateur.

Cherchez ensuite la ligne suivante :
Image utilisateur

Dans la plupart des cas, GetText sera activée (enabled) mais si ce n'est pas le cas (disabled), ouvrez le fichier de configuration php.ini et supprimez le ";" devant la ligne :
extension=gettext.so

Si tout va bien, continuons. :)

Arborescence des dossiers

Pour commencer, je vais vous demander de créer quelques dossiers qui contiendront les fichiers de langue. Créons d'abord un dossier locale à la racine de notre projet. Dans ce répertoire, créez ensuite quelques dossiers correspondant chacun à une langue et veillez à ce que les noms de ces dossiers respectent le format fr_FR. Dans le cadre de ce tutoriel, je vais en créer trois : fr_FR, en_US et de_DE. Pour finir, créez, dans chacun de ces dossiers, un dossier LC_MESSAGES. Le dossier LC_MESSAGES contiendra le fichier final. Si vous avez bien suivi, vous devriez vous retrouver avec cette arborescence :

dossier racine
--- locale
------ fr_FR
--------- LC_MESSAGES
------ en_US
--------- LC_MESSAGES
------ de-DE
--------- LC_MESSAGES


Le dossier en_US contiendra les expressions françaises et les traductions anglaises qui leur sont associées, le dossier de_DE contiendra les traductions allemandes et le dossier fr_FR contiendra les expressions françaises. Quel intérêt d'avoir des traductions françaises ? me direz-vous. C'est tout simplement pour pouvoir revenir à la version française si le site utilise un fichier de langue étranger. ;)

Avoir des dossiers c'est bien. Encore faut-il les remplir. :p Pas de panique, le chapitre suivant s'en occupe...

Création et compilation du fichier de langue

Création



Comme je l'ai dit dans la première partie, GetText utilise des fichiers .mo qui contiennent des couples clé - valeur. Les fichiers .mo sont des fichiers .po compilés. ;) Dans ce tutoriel, je vais considérer que la langue initiale de mon site est le français. Les clés correspondront donc aux expressions françaises et les valeurs seront leurs traductions. Étant donné que nous possédons trois dossiers de langue (fr_FR, en_US, de_DE), nous devons créer trois fichiers .po différents. Attaquons tout de suite notre premier fichier : en_US. :)

Code : Autre
1
2
3
4
5
msgid "Bienvenue !"
msgstr "Welcome !"

msgid "Au revoir !"
msgstr "Goodbye !"


Analysons ce petit code : tout d'abord, nous voyons le mot msgid . msgid permet de définir une clé. Celle-ci est écrite entre guillemets. Dans la seconde ligne, nous pouvons voir un autre mot : msgstr . msgstr permet de définir une valeur. Celle-ci est également donnée entre guillemets. Notez qu'il n'y a pas de ";" à la fin des lignes. ;) Ce code permet donc d'associer la valeur "Welcome !" à la clé "Bienvenue !". Ainsi, il suffira d'écrire "Bienvenue !" dans notre script et "Welcome !" sera automatiquement affiché. Ce n'est peut-être pas très parlant pour le moment mais ne vous inquiétez pas, vous comprendrez très vite.

Enregistrez ce fichier dans votre dossier en_US/LC_MESSAGES/ et nommez-le traductions.po. ;)

En pratique, les expressions à traduire seront beaucoup plus longues (parfois de très longs textes). Pour faciliter la lecture et l'écriture de ces fichiers il est possible "d'étaler" les msgid et msgstr sur plusieurs lignes. En voici un exemple :

Code : Autre
1
2
3
4
5
6
msgid ""
"Ceci est un très long message"
" qui tient sur plusieurs lignes"
msgstr ""
"This is a long text written"
" on several lines"


Comme vous pouvez le voir, on met deux guillemets vides après msgid et msgstr pour annoncer des sauts de lignes.

Répétons maintenant cette manipulation pour les dossier fr_FR et de_DE :

de_DE/LC_MESSAGES/traductions.po
Code : Autre
1
2
3
4
5
msgid "Bienvenue !"
msgstr "Wilkommen !"

msgid "Au revoir !"
msgstr "Auf Wiedersehen !"


fr_FR/LC_MESSAGES/traductions.po
Code : Autre
1
2
3
4
5
msgid "Bienvenue !"
msgstr "Bienvenue !"

msgid "Au revoir !"
msgstr "Au revoir !"


Donnez bien le même nom à vos fichiers de langues ! Ici, tous nos fichiers s'appellent traductions.po. ;)


Compilation



Maintenant que nous avons écrit nos fichiers de langue (.po), nous allons devoir les compiler (.mo). Pour cela, nous allons utiliser la commande msgfmt dans la console.
Elle s'utilise de cette façon :

Code : Console
msgfmt -o le_fichier_de_sortie.mo le_fichier_dentree.po


Pour compiler notre fichier d'anglais, nous ferons donc :

Code : Console
msgfmt -o /dossier_racine/locale/en_US/LC_MESSAGES/traductions.mo /dossier_racine/locale/en_US/LC_MESSAGES/traductions.po


Appuyez sur ENTREE pour valider la commande. Si tout se passe bien, un fichier .mo apparaît dans votre dossier en_US/LC_MESSAGES/ à côté du .po. C'est ce fichier dont nous nous servirons avec GetText. ;)

Je vous laisse le soin de compiler les deux autres fichiers (fr_FR, de_DE). Pensez bien à donner leur chemin complet !

Comme je l'ai dit plus tôt, GetText est avant tout prévue pour les systèmes Unix. Pour ceux qui ne posséderaient pas Unix (mais Windows, entre autres), la commande msgfmt ne fonctionnera sûrement pas. Je vous invite donc à télécharger la dernière version de GetText ici. ;)


Voilà qui est fait pour nos fichiers de traduction. Ils sont fin prêts à l'utilisation ! Dernière partie mais pas des moindres : le code PHP. :D

Code et affichage

Maintenant que nous avons fini de préparer le terrain, nous allons pouvoir commencer à coder. :)

Pour afficher une traduction, il suffit de faire echo gettext("La clé") ou echo _("La clé") (c'est un alias). En faisant ceci, PHP ira chercher le fichier de traduction que nous aurons spécifié plus tôt dans le code et affichera la valeur (msgstr ) correspondant à la clé entre guillemets (msgid ).

Notre code sera très simple.
Nous créerons une page contenant 3 petits liens : français, anglais et allemand. En fonction du bouton sur lequel l'utilisateur aura cliqué, nous afficherons un message de bienvenue et nous lui dirons au revoir dans la langue souhaitée.

PHP fournit des fonctions permettant d'utiliser GetText. Voici celles que nous utiliserons :

Nous nous servirons également des fonctions putenv() et setlocale() qui permettent respectivement de modifier la valeur d'une variable d'environnement et de changer les informations de localisation.

Je ne vais pas vous faire languir plus longtemps, voici le code entièrement commenté :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
if (!empty($_GET['lang'])) { // Si l'utilisateur a choisi une langue
	switch ($_GET['lang']) { // En fonction de la langue, on crée une variable $langage qui contient le code
		case 'fr':
			$langage = 'fr_FR';
			break;
		case 'en':
			$langage = 'en_US';
			break;
		case 'de':
			$langage = 'de_DE';
			break;
		default:
			$langage = 'fr_FR';
			break;
	}
	
	putenv("LANG=$langage"); // On modifie la variable d'environnement
	setlocale(LC_ALL, $langage); // On modifie les informations de localisation en fonction de la langue
	
	$nomDesFichiersDeLangue = 'traductions'; // Le nom de nos fichiers .mo
	
	bindtextdomain($nomDesFichiersDeLangue, "./locale"); // On indique le chemin vers les fichiers .mo
	textdomain($nomDesFichiersDeLangue); // Le nom du domaine par défaut
	
	/* On affiche les phrases traduites */
	echo gettext('Bienvenue !');
	echo '<br >';
	echo _('Aurevoir !');
	echo '<br /><br />';
}

/* On affiche les liens des différents langages */
echo '<a href="index.php?lang=fr">français</a><br />';
echo '<a href="index.php?lang=en">english</a><br />';
echo '<a href="index.php?lang=de">deutsch</a><br />';
?>


Ce code illustre bien l'utilisation de la fonction gettext() : soit on l'écrit sous la forme echo gettext("La clé"); soit sous la forme echo _("La clé"); . ;)


Ici, nous affichons trois liens correspondants à divers langages. Chacun d'eux envoie par l'URL une variable $_GET['lang'] qui contient soit fr soit en soit de . Le script vérifie si cette variable existe (donc si l'utilisateur a choisi une langue) et si c'est le cas, en fonction de son contenu, il crée une variable $langage ayant pour valeur le code langage correspondant (en -> en_US, fr -> fr_FR, de -> de_DE). Les fonctions putenv() et setlocale() sont ensuite appelées avec comme attribut le contenu de $variable . Cela permet en gros de dire à PHP que l'utilisateur utilise telle langue. Puis nous indiquons le nom et l'emplacement de nos fichiers de traduction au moyen des fonctions bindtextdomain() et textdomain() . Enfin, nous affichons les phrases traduites avec gettext() qui prend en argument la clé du fichier de langue (.mo) correspondant à la valeur traduite que l'on souhaite afficher. En fait, on dit à PHP le fichier qu'il doit aller chercher et la phrase qu'il doit trouver dans ce fichier.

Si vous testez ce code - et à condition que vous avez correctement suivi le tutoriel jusqu'ici - vous devriez voir que le texte est traduit en fonction du lien choisi.

C'est peut-être un peu flou pour le moment mais ne vous en faites pas, ça viendra avec la pratique. ;)

Améliorons ce code



Le script que je vous ai donné était un exemple pour vous expliquer le fonctionnement de GetText. Il reste donc très basique et inutilisable de cette façon sur un vrai site web. Je ne suis pas là pour vous apprendre à coder mais voici quelques suggestions pour perfectionner votre système de traduction.

  • Utilisez un cookie pour retenir la langue de l'utilisateur. Au prochain chargement, essayez de récupérer ce cookie pour afficher le site directement dans le langage préféré de l'utilisateur.
  • Utilisez la superglobale $_SERVER["HTTP_ACCEPT_LANGUAGE"] pour obtenir directement la langue favorite de l'utilisateur.

Pour le deuxième point, vous aurez besoin de traiter la valeur de $_SERVER["HTTP_ACCEPT_LANGUAGE"] . Voici une fonction trouvée sur le tutoriel original qui prend en argument la superglobale et qui renvoie un tableau contenant les langues préférées de l'utilisateur par ordre de préférence. Cette fonction retournant seulement les deux premières lettres (en , fr , de , es , it ...), pensez à récupérer le code par la suite (en_US, fr_FR...). ;) Je ne m'attarderai pas sur ce code car ce n'est pas le but de mon tutoriel.

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
function get_pref_language_array($str_http_languages)
{
  $langs = explode(',',$str_http_languages);
  $qcandidat = 0;
  $nblang = count($langs);

  for ($i=0; $i<$nblang; $i++)
  {
    for ($j=0; $j<count($langs); $j++) {
      $lang = trim($langs[$j]);
      
      if (!strstr($lang, ';') && $qcandidat != 1) {
        $candidat = $lang;
        $qcandidat = 1;
        $indicecandidat = $j;
      }
      else {
        $q = ereg_replace('.*;q=(.*)', '\\1', $lang);

        if ($q > $qcandidat) {
          $candidat = ereg_replace('(.*);.*', '\\1', $lang); ;
          $qcandidat = $q;
          $indicecandidat = $j;     
        }
      }
    }
    
    $resultat[$i] = $candidat;

    $qcandidat=0;
    unset($langs[$indicecandidat]);   
    $langs = array_values($langs);
  }
  return $resultat;
}
?>


N'oubliez pas de toujours laisser le choix de la langue à l'utilisateur : avec cette fonction, un Français résidant aux USA ne pourra pas afficher votre site en français. Pensez donc à placer un lien ou un bouton vers les différentes langues. ;)

Nous voilà arrivés à la fin de ce tutoriel. Comme vous l'avez sans doute constaté, GetText est une librairie puissante mais assez difficile à mettre en place. Cependant elle est préférable pour les sites affichant beaucoup de texte. Et personnellement, je trouve que cette façon de coder est "plus propre" que l'utilisation de centaines de variables ou de constantes qui viendront alourdir votre site.

Je tiens à préciser que je n'ai pas pu aborder TOUT ce qu'il y a à savoir sur GetText mais cela devrait être suffisant pour concocter un site multilingue correct. Si vous souhaitez approfondir vos connaissances sur le sujet, je vous invite à consulter les liens ci-dessous. ;)

Pour tout problème ou suggestion, n'hésitez pas à poster un commentaire ou à demander de l'aide sur le forum. ;)

Quelques liens utiles


Informations sur le tutoriel

Retour en haut Retour en haut

Créé : Le 07/11/2008 à 19:03:42
Modifié : Le 16/06/2009 à 12:20:43
Avancement : 100%
Licence : Copie non autorisée

L'orthographe, la grammaire et la présentation de ce tutoriel ont été vérifiées par les zCorrecteurs.
32 commentaires