-
Internationalisation d'un site web
par Skreo, le 9 Juillet 2008 à 02:03Je me suis demandé il y a quelques temps quelle serait la meilleure solution pour traduire facilement un site web en plusieurs langues, tout en gardant une facilité de mise à jour, une accessibilité optimale, et des urls correctes pour le référencement. Le sujet a certes beaucoup été traité, mais j'ai trouvé très peu de solutions pratiques, jolies et performantes sur le web.
Certains webmasters recopient simplement l'intégralité de leur site dans un autre dossier ou sur un autre domaine, puis le traduisent. Oublions tout de suite cette solution... Il faut donc opter pour une solution dynamique, que je traiterai ici en php.
URL et détection de la langue
Avant de traduire le site, il faut être capable de détecter la langue du visiteur, de lui proposer de changer de langue, et de mémoriser son choix :
<?php
session_start(); // Démarrage de la session pour la sauvegarde du choix de la langue
$langs = array('en', 'fr', 'it'); // Liste des langues
// Si la langue a été changée par get ou cookie, on enregistre la modif
if(isset($_GET['lang']) && in_array($_GET['lang'], $langs) && (!isset($_SESSION['lang']) || $_SESSION['lang']!=$_GET['lang']))
$_SESSION['lang'] = $_GET['lang'];
else if(isset($_COOKIE['lang']) && in_array($_COOKIE['lang'], $langs) && (!isset($_SESSION['lang']) || $_SESSION['lang']!=$_COOKIE['lang']))
$_SESSION['lang'] = $_COOKIE['lang'];
// Si aucune langue n'est définie, on prend celle du navigateur du visiteur
if(!isset($_SESSION['lang'])){
$lang = strtolower(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2));
$_SESSION['lang'] = in_array($lang, $langs) ? $lang : $langs[0];
}
// Si le cookie de la langue n'est pas défini ou est différent de la var de session, on le définit
if(!isset($_COOKIE['lang']) || $_SESSION['lang']!=$_COOKIE['lang'])
setcookie('lang', $_SESSION['lang'], time()+60*24*3600, '/');
// Variable $lang locale que nous utiliserons plus loin
$lang = $_SESSION['lang'];
?>Ce code devra être appelé au tout début de chaque page du site. Nous avons maintenant notre moyen de détection et de mémorisation de la langue.
Ensuite, nous allons prendre l'exemple d'URLs du type http://www.monsite.com/lang/page.html, ce qui a l'avantage de bien référencer toutes les pages dans toutes les langues traduites. Mais nous pourrions tout aussi bien garder des URLs classiques dans le cas d'un service accessible uniquement aux utilisateurs connectés : par exemple Twitter. La langue serait alors enregistrée dans les paramètres de l'utilisateur.
Pour cela, mettons en place un .htaccess avec de l'URL Rewriting à la racine :
RewriteEngine On
RewriteRule ^(en|fr|it)/([^\?]+)?(\?(.*))?$ /$2?$4&lang=$1 [QSA,L]
Et voilà, désomais, un accès à la page http://www.monsite.com/fr/page.php appellera la page page.php à la racine du site en lui passant la variable GET lang=fr, ce qui aura pour effet avec le script précédent d'enregistrer "fr" comme langue dans le cookie et la variable de session du visiteur.Proposons maintenant au visiteur de choisir sa langue tout en restant sur la même page, au cas où elle aurait été mal détecté (navigateur en anglais pour un français par exemple) :
<?php
$URI = $_SERVER['REQUEST_URI'];
if($URI=='/') $URI = '/'.$lang.'/';
?>
<a href="<?php echo preg_replace('#^/[a-z]{2}#', '/en', $URI); ?>"><img src="/images/en.png" alt="English" /></a>
<a href="<?php echo preg_replace('#^/[a-z]{2}#', '/fr', $URI); ?>"><img src="/images/fr.png" alt="Français" /></a>
<a href="<?php echo preg_replace('#^/[a-z]{2}#', '/it', $URI); ?>"><img src="/images/it.png" alt="Italiano" /></a>
Vous trouverez plein de super icônes de drapeaux ici.Stockage des traductions
On peut imaginer deux solutions de stockage pour les textes traduits. J'ai retenu la deuxième :
1- Première solution : Une fonction getText choisissant entre plusieurs textes proposés. Par exemple
<?php
function getText($en, $fr){
global $lang;
if($lang=='fr') return $fr;
else return $en;
}
// Affichage d'un texte traduit :
echo getText('Text in english', 'Texte en français');
?>
Ce n'est pas très pratique, et pas très lisible dès que les textes deviennent un peu gros et le nombre de langues grand.2- Deuxième solution : Le stockage des textes dans divers fichiers : un fichier par langue. L'avantage ici est qu'on peut traduire (ou faire traduire) le site en ajoutant simplement un seul fichier. Nous stockerons les fichiers en.php, fr.php, et it.php dans un dossiers langs. Il suffira d'ajouter cette ligne après la détection de la langue :
require_once 'langs/'.$lang.'.php';Ensuite, nous avons encore le choix entre plusieurs méthodes de stockage. Les deux principalement utilisées consistent soit à créer une constante par texte, soit un grand tableau avec une entrée par texte. La méthode des constantes a l'avantage d'être performante mais n'est vraiment pas propre. Celle du tableau n'est pas non plus des plus performantes. Je parle bien sûr ici pour une grande échelle : prévoyons 15 000 entrées pour voir réellement les différences entre les méthodes.
Je vais vous proposer une autre méthode, une sorte de compromis, mais performante, pratique, et plus lisible. Elle consiste à utiliser une classe pour stocker les textes sous forme de constantes. Ces constantes restent dans la classe, c'est donc propre, l'accès y est très facile, et les performances sont très bonnes (j'avais fait un benchmark il y a quelques mois, mais je ne l'ai plus sous la main...). Nous allons donner un nom très court à cette classe, par exemple "_". Voici un exemple pour le fichier fr.php, il suffit ensuite de copier le fichier et de le traduire pour les autres langues :
<?php
// Classe de stockage :
final class _ {
const TEXT1 = 'Mon premier texte en français';
const EXEMPLE = 'Ceci est un exemple';
const NUM = 'un, deux, trois';
}
?>Puis pour afficher le texte :
<?php
// Affichage du texte :
echo _::TEXT1 . '<strong>'. _::EXEMPLE . '</strong><br />'. _::NUM;
?>Et voilà, j'espère que ce tuto pourra servir à quelqu'un. Qu'en pensez-vous ? Quelles solutions utilisez-vous ?
Partager cet article :

Suivre le flux RSS des commentaires de cet article
Revenir à la liste des articles
-
Commentaires
1divarvel
9 Juillet 2008 à 10:29C'est clair que c'était galère la solution de la fonction getText... Par contre pour les constantes, va falloir trouver une bonne charte de nommage, car du texte, il y en a plein.... Une fois que le premier fichier est fait, ça va, mais pour le faire...
Il est clair que ce genre de problème est souvent casse-tête ! J'approuve ta méthode qui est relativement propre, mais ça peut devenir complexe quand tu abordes des langues en dehors de la norme ISO-8859-1 (arabe, mandarin, japonais...).
Le mieux, c'est d'aussi aborder la problématique de l'encodage avant même de commencer à traduire, je pense. C'est un point trop souvent oublié :)
5Loïc9 Décembre 2008 à 12:39Bonjour,
Sans m'étendre, gettext ne se résume pas vraiment à ça et ça ne ressemble pas tout à fait à ça non plus. C'est nettement plus adapté à de "gros" sites. C'est la solution employé par bon nombre de projet open source notamment (sites ou logiciels). Le fait de mettre des phrase en paramètre de la fonction rend le code plus compréhensible. Mais dans tous les cas ceci n'est pas obligatoire. Il s'agit seulement d'un ID. Donc _("toto") pour traduire "Bienvenue sur monsite" ça marche aussi.
quelques info
quelques info#2
+ wikipedia, etc.
Ajouter un commentaire
Haut de page