Informatique > Faire un site multilingue > PHP et l'UTF8
derniére édition le: 7/09/2006
PHP ne gére pas correctement l'UTF8. Ce qui ne signifie pas qu'il soit impossible d'utiliser cet encodage. L'important est de connaitre le comportement de PHP et de contourner les problémes.
Pour comprendre cet article, mieux vaut savoir programmer en PHP. La lecture de cet article sur l'encodage UTF8 est également conseillée.
J'ai cherché longtemps une information claire sur les problémes liés à l'UTF8 avec PHP mais presque toutes les pages se bornent a parler de la fonction utf_encode().
php.net déclare sur son site que les encodages multi-octets
compatibles avec la norme ASCII pour les caractères de l'intervalle 0à 127 sont supportés. UTF8 est mentionné comme
un encodage supporté. Cela veut dire que l'on peut continuer a écrire nos scripts normalement: il ne faut pas utiliser
de caractéres accentués sauf dans une chaine de caractéres. Cette chaine devra tout de même être manipulée à l'aide
de fonctions adaptées aux encodages multi octets. Super!
Seulement il semble y avoir quelques problémes qui rendent l'utilisation d'UTF8 trés difficile.
Nous allons créer une page web encodée en UTF8 qui inclus un script PHP. La page sera composée de deux DIVS l'un en dessous de l'autre. Voici le code de la page test.php:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head>
<body>
<div style="background-color:blue;">eee</div>
<?
include('test2.php');
?>
</body>
</html>
Voici le code de test2.php:
<?echo '<div style="background-color:green;">eee</div>';?>
Testez donc cette page sous internet explorer6, histoire de rigoler.
Les deux blocs ne sont pas collés. Et vous pourrez
bidouiller tant que vous voudrez votre CSS, le blanc ne disparaitra pas! J'en ai fait la douloureuse expérience.
Maintenant affichez la source de cette page: comme vous pouvez le voir, un caractére parasite s'est inséré entre les
deux DIVS!
Si vous essayez sous Firefox, l'affichage sera correct, mais ne vous y trompez pas, les caractéres parasites
sont tout de même présents et peuvent avoir des effets imprévisibles. Essayez d'inclure la page test toute entiére dans
une autre page test3. Si vous mettez la page en ligne et que votre débit n'est pas trop puissant, vous devez voir apparaitre
le phénomène suivant: une page blanche s'affiche et le texte  s'affiche à l'écran. Tout de suite aprés, la page s'affiche,
avec les deux DIVS.
C'est que des caractéres imprévus ont été insérés avant le doctype! Ce qui a pour conséquence facheuse de faire passer
internet explorer et firefox en mode brouillon! De quoi passer des heures inutiles à batailler avec votre CSS. Et puis
c'est quelque chose que les validateurs ne doivent pas aimer, les moteurs de recherche non plus. Le pire,
c'est que vous ne pouvez rien contre ce bug.
Il faut donc abandonner l'idée d'encoder ses scripts php en UTF8.
PHP ne sait pas lire les scripts encodés en UTF8, trés bien.
Mais nous avons tout de même a disposition deux fonctions indispensables: utf8_encode(), et utf8_decode(). On
peut donc continuer a encoder nos fichiers PHP en ANSI. Par contre, dés que l'on veut afficher une chaine de
caractéres il faut l'encoder en UTF8 au préalable.
Hélas, cette solution a un coût: elle complique la relecture en ajoutant des fonctions suplémentaires, et surtout elle allonge le temps d'éxécution du script! J'ai fait un petit essai pour voir:
<?
function microtime_float() {
return array_sum(explode(' ', microtime()));
}
$temps_debut = microtime_float();
for($i=0;$i<1000;++$i)
echo 'é';
$temps_fin = microtime_float();
echo 'Temps d\'execution du script : '.round($temps_fin - $temps_debut, 4);
?>
Résultat: 0.0007 secondes.
<?
function microtime_float() {
return array_sum(explode(' ', microtime()));
}
$temps_debut = microtime_float();
for($i=0;$i<1000;++$i)
echo utf8_encode('é');
$temps_fin = microtime_float();
echo 'Temps d\'execution du script : '.round($temps_fin - $temps_debut, 4);
?>
Résultat: 0.0539 secondes!
Bon, ce chiffre est tout de même à nuancer,
jamais vous utiliserez 1000 utf8_encode dans un script. Ou alors c'est déja du bon script!
L'astuce repose sur l'utilisation de Notepad++. C'est un bloc notes amélioré trés adapté aux programmeurs. On peut éditer plusieurs documents grâce à un systéme d'onglets. Les numéros de lignes sont affichés et une coloration syntaxique est disponible pour 25 languages de programmation. Mais ce qui nous intéresse pour le moment c'est son menu format avec la possibilité de voir un fichier ANSI comme s'il était encodé en UTF8.

Le menu format de Notepad++
Grâce à cette option, vous pouvez continuer à encoder vos scripts php en ASCII, tout en étant capable d'écrire du texte
sans se soucier des caractéres spéciaux. Votre fichier sera vu comme de l'UTF8, vous pouvez écrire le texte, mais si vous
désactivez cette option votre texte deviendra du charabia.Cependant, aucun souci au niveau des navigateur si vous avec spécifié
que votre page HTML est encodée en UTF8. Testé sous internet explorer6 et Gecko.
Encore une petite précision, hélas il y a un bug dans notepad++, parfois il arrive que le texte devienne incompréhensible
pour les navigateurs. Quand on édite la source de la page, on voit que des caractéres ont été insérés un peu partout. Je ne
sais pas exactement comment ça arrive, je me suis arraché les cheveux avant d'écrire cet article mais j'ai trouvé
un parade. En cas de probléme étditez votre fichier, rajoutez un caractére puis supprimé le. Enregistrez votre fichier
et ça remarche!
Reste un dernier probléme à aborder. La manipulation de chaines de caractéres encodées en UTF8 ne doit pas se faire à l'aide des fonctions standard. Prenons ce code pour exemple:
<?
$a=utf8_encode('é');
$b=strlen($a);
$a=utf8_decode($a);
echo 'longueur de "'.$a.'" : '.$b.' caractéres';
?>
Le résultat obtenu sera: "longueur de "é" : 2 caractéres".
Heureusement des modules ont été rédigés pour permettre malgré tout de manipuler des chaines.
Personnellement j'ai utilisé la fonction mb_convert_encoding
, qui permet de convertir une chaine de caractéres UTF8 en chaine ASCII. Il existe de nombreuses fonctions
permettant de manipuler des chaines dans divers encodages, vous trouverez surement votre bonheur. Pensez aussi a voir le module
iconv.
Voilà l'inventaire des problémes que j'ai eu avec l'UTF8. Je crois que cet article peut vous faire économiser un grand nombre d'heures de travail. A présent j'utilise Notepad++ avec mb_conv et je n'ai plus du tout de probléme, pourvu que ça dure!
Par bigguiz
Informatique > Faire un site multilingue > PHP et l'UTF8