8.Internationalisation (i18n) et encodage en PHP

8.1.Introduction

Si vous souhaitez créer un site web (ou un script) capable d'afficher des caractères autres que les caractères latin vous devrez faire attention au choix de l'encodage[c'est quoi?] des chaînes de caractères.
La solution la plus courante étant d'opter pour un encodage unicode tel que l'UTF-8. Cela est pour ainsi dire indispensable si vous souhaitez proposer un site en différentes langues, où vous serez alors peut-être amenés à afficher des caractères du genre: Ñ, ø, 異) mais même si vous n'êtes pas dans ce cas, nous vous invitons à adopter d'emblé l'encodage UTF-8 (ceci afin de ne pas avoir à le regretter par la suite).
Nous allons donc voir comment faire en PHP et quels impacts cela a sur la programmation.

8.2.Déclarer l'encodage choisi

Pour commencer, il convient de préciser comment sont encodées les pages HTML que nous générons via PHP, ceci afin que le navigateur puisse les afficher correctement.
Le serveur transmet cette information au navigateur via un entente HTTP baptisé 'Content-Type' qui contient une valeur précisant à la fois la nature du document (ex: 'text/html' pour un document HTML, 'text/plain' pour un document texte, 'img/gif' pour une image gif, etc) et l'encodage via charset=<nom de l'encodage>.
Ainsi, pour un document HTML encodé en UTF-8, il faudra ajouter à nos scripts PHP, l'instruction suivante:
<?php
header('Content-Type: text/html; charset=UTF-8');
?>
Cette instruction doit être placée avant l'affichage du premier caractère du document (i.e. avant la balise <html> ou plutôt avant <!DOCTYPE pour les documents HTML valides)
rem
  • S'il y a confusion dans la déclaration de l'encodage alors le navigateur risque d'interpréter des caractères UTF-8 comme étant des caractères latin et cela se traduira par l'affichage de é (à la place de é), ç (à la place de ç), etc.
  • Pour que votre page HTML soit correctement affichée, y compris lorsqu'elle est lue non plus via le net (où le content-type est passé dans l'entête HTTP) mais via un fichier (dans l'hypothèse où la page web a été sauvegardée sur le disque) alors il faut ajouter en tout début du bloc <head> du document (avant la balise <title>) la ligne suivante
    <meta http-equiv="Content-Type" value="text/html; charset=UTF-8" />

8.3.Se tenir à l'encodage choisi

8.3.1.Au niveau du texte saisi dans l'éditeur

Si vos scripts contiennent des messages destinés a être affichés, il faut s'assurer qu'ils sont bien en UTF-8. En d'autres termes, vous devez vous assurer que l'éditeur que vous utilisez pour écrire vos scripts PHP est bien configuré pour utiliser l'UTF-8. Pour cela, je vous laisse jeter un oeil dans les options de configuration de votre éditeur.

8.3.2.Au niveau du texte échangé avec une base de données

Généralement, par défaut, les échanges avec les bases de données ainsi que le stockage des données se font avec un encodage latin. Pour être sur de ne pas perdre d'information vous devrez préciser, lors de la connexion à la base de données (ou juste après) que vous souhaitez travailler en UTF-8.
Evidemment, la façon de faire dépend de la nature de la base de données et de la bibliothèque choisie.
  • Avec MySQL: faire appel à mysql_set_charset('UTF8'); juste après mysql_connect();
  • Avec MySQLi (procédural): faire appel à mysqli_set_charset($lien, 'UTF8'); juste après mysql_connect();
  • Avec MySQLi (objet): faire appel à la méthode set_charset('UTF8'); juste après avoir instancié[c'est quoi?] l'object MySQLi
Encore faut-il que les bases, ou les tables ou les champs concernés soit eux-même déclarés comme stockant de l'UTF-8[comment?]

8.3.3.Au niveau du texte récupéré d'une source externe

Si vos scripts récupèrent des informations auprès de sources externes (fichiers, annuaire LDAP, MySQL, etc) vous devrez vérifier l'encodage utilisé par ces diverses sources de données et si nécessaire convertir l'encodage.
Par exemple, si les informations lues sont encodées en ISO-8859-1 ou cp1252 (les encodages classiques non unicode) vous pourrez les convertir en UTF-8 via la fonction utf8_encode().
<?php
$chaineUTF8 = utf8_encode($chaineLatin);
?>
rem
  • Un caractère accentué encodé en latin apparaîtra généralement sous la forme d'un point d'interrogation lorsqu'il est affiché en UTF-8

8.3.4.Au niveau des fonctions utilisées

PHP n'ayant pas été écrit dès le début pour gérer l'unicode, malgré un gros effort (et une tentative pour le moment avortée de sortie une version 6 de PHP), il existe de nombreuse fonction qui ne gèrent pas (bien) l'UTF-8.
A chaque fois que vous utilisez une fonction de manipulation de chaîne de caractères vous devez vérifier que cette fonction est dite 'binary-safe' ou autrement dit qu'elle gère les chaînes binaires.
En effet la plupart des autres fonctions considèrent qu'un caractère est codé sur un seul octet, ce qui n'est pas le cas avec l'unicode.
Certaines fonctions vous demandent de préciser l'encodage: comme htmlEntities() qui en version UTF-8 devra être appelée de la façon suivante:
<?php
echo htmlEntities($chaine, ENT_COMPAT, 'UTF-8');
?>