Introduction
Le jeu de caractères est un point très important à connaître avant même d’écrire le premier bout de code d’un site web. Si vous négligez cette partie intégrante du développement, alors vous courrez à des risques d’incompatibilité qui se traduirons par l’apparition de caractères ressemblant à cela : é, �.
Nous allons voir dans cet article les points les plus importants à connaître pour partir du bon pied dans le développement de votre projet.
Les jeux de caractères : courte explication
Pour un ordinateur, les caractères ne signifient strictement rien. Il ne comprend que les nombres. Afin de gérer les caractères, une table de correspondance appelée ASCII a été mise au point. Grâce à l’ASCII, l’ordinateur peut gérer jusqu’à 128 caractères, permettant d’écrire en anglais (par exemple, le caractère « A » correspond au nombre 65).
Toutefois, les 128 caractères ne permettaient pas la gestion de la totalité des langues existantes. Différents jeux de caractères ont alors été créés par la suite. Aujourd’hui, nous utilisons principalement l’ISO 8859-15 et l’UTF-8 (Unicode).
L’ISO 8859-15 permet d’écrire dans l’alphabet latin, c’est-à-dire en français, anglais, allemand, etc. L’UTF-8 permet la gestion de bien plus de langues (ex : caractères asiatiques).
Il faut savoir que l’ISO 8859-15 et l’UTF-8 ne sont pas compatibles, leur structure étant différente. Lorsque vous voyez des caractères étranges ou encore des signes s’apparentant à des points d’interrogation, c’est que vous mélangez probablement plusieurs jeux de caractères (ex : ISO et UTF-8).
Personnellement, j’utilise systématiquement l’UTF-8 dans mes projets et ce même si seul le français est utilisé. Ainsi, les projets pourront, à long terme, être traduits vers d’autres langues si nécessaire et sans souci.
Procéder à suivre
Il faut que tout l’environnement de votre projet soit dans le même jeu de caractères. Ceci comprend :
- les fichiers
- l’HTML
- le PHP
- et enfin MySQL (ou autre SGBD)
J’utiliserai l’UTF-8 comme jeu de caractères, mais le principe est le même pour les autres jeux. Quand j’indiquerai « ISO », je ferai référence à l’ISO 8859-15 (c’est juste un point de comparaison).
Les fichiers
La première étape est d’écrire les fichiers en UTF-8. Pourquoi ? Imaginons que vous souhaitez par exemple écrire un caractère asiatique dans le fichier. Si vous enregistrez le fichier en ISO, vous aurez alors des erreurs. Par exemple, dans Geany, une erreur s’affiche quand j’enregistre un fichier ISO contenant un caractère non pris en charge :
En rouge, j’ai souligné l’indicateur du jeu de caractères utilisé. Il est très souvent indiqué dans la barre de statut.
Il est possible de le changer en allant dans le menu. Dans cet éditeur de texte, c’est « Document > Définir l’encodage > Liste d’encodages ».
Je place donc le jeu de caractères sur UTF-8, et le contenu du fichier sera donc écrit en UTF-8.
Mise en garde : il faut bien vérifier que vous utilisez UTF-8 sans BOM. Le BOM est un marqueur d’ordre d’octets, permettant de détecter l’encodage Unicode du fichier. PHP ne gérant pas le BOM, ce dernier est interprété comme un caractère, donc un contenu hors des balises PHP en début de fichier. Vous aurez donc droit à des erreurs de type « header already sent by » lors de l’utilisation de fonction comme « session_start » ou encore « header« .
L’HTML
C’est la partie la plus simple. Elle consiste à indiquer au navigateur dans quel jeu de caractères la page est écrite. Une simple balise « meta » suffit :
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Le PHP
PHP n’a pas été développé avec le support natif d’Unicode, mais en ISO. Ce qui signifie que certaines fonctions peuvent poser problème avec l’encodage UTF-8. Si vous choisissez l’ISO, vous n’aurez pas ce souci.
Pour illustrer ce fameux problème, voici un exemple :
echo strlen('testé');
En théorie, le résultat de cette fonction devrait être 5, et pourtant, si vous testez ce code vous remarquerez que le résultat retourné est 6. PHP traitant la chaîne de caractères en ISO, il compte deux octets pour le caractère « é » ce qui porte la longueur de la chaîne à 6. Pratiquement toutes les fonctions sont concernées (strtoupper, strtolower, strstr, etc.). C’est une vrai problématique.
Heureusement, une extension appelée « mbstring » ajoute de nouvelles fonctions pour le traitement de chaîne de caractères dans différents jeux de caractères. Pour trouver les correspondances avec les anciennes fonctions, il suffit en général d’ajouter le préfixe « mb_ » et de préciser le jeu de caractères que vous souhaitez utiliser.
Voici un exemple d’utilisation :
// fonction natif, renvoi 6
echo strlen('testé');
// fonction mbstring, renvoi 5 en précisant l'encodage utilisé
echo mb_strlen('testé', 'UTF-8');
La fonction « mb_internal_encoding » permet de définir le jeu de caractères à utiliser par défaut, comme ceci :
// défini l'UTF-8 comme encodage par défaut (à placer dans le fichier de configuration par exemple)
mb_internal_encoding('UTF-8');
// inutile de préciser l'encodage
echo mb_strlen('testé');
Il devient donc inutile de préciser le jeu de caractères en second paramètre.
Parfois, il vous sera nécessaire de traiter une chaîne de caractères dans un jeu différent de celui utilisé dans votre projet. C’est le cas lorsque vous récupérez des informations à distance, sur un autre site par exemple. Dans ce cas, il vous faudra convertir la chaîne de caractères récupérée dans le bon jeu.
Deux fonctions existent et peuvent être utiles : utf8_encode et utf8_decode.
Elles permettent de convertir des chaînes de l’ISO vers UTF-8 et inversement. utf8_encode convertit une chaîne ISO-8859-1 en UTF-8, et utf8_decode effectue l’inverse. Référencez-vous à la documentation de ces deux fonctions pour en savoir plus.
Comme seul l’ISO-8859-1 est pris en charge, le caractère euro ne pourra être converti, car il n’est présent que dans l’ISO-8859-15. Quelques autres caractères sont concernés.
Une autre solution existe : iconv. C’est une extension permettant la conversion de chaîne de caractères dans différent jeu de caractères. Voici un exemple de conversion :
setlocale(LC_CTYPE, 'fr_FR.UTF-8');
echo iconv('UTF-8', 'ISO-8859-15', '@ € ä ç'); // retourne : '@ € ä ç' converti en ISO-8859-15
On précise le jeu de caractères de la chaîne à convertir (UTF-8), ensuite le jeu dans lequel nous souhaitons convertir la chaîne (ISO-8859-15) et enfin la chaîne à convertir.
Cette fonction est particulièrement utile car elle permet de gérer les caractères exotiques. Lorsque nous avons utilisé utf8_decode, le caractère euro (€) s’est transformé en un point d’interrogation, car celui-ci n’est pas supporté par l’ISO-8859-1.
Si nous tentons de convertir la chaîne de caractères précédente en ISO-8859-1 avec iconv, voici ce qui en ressort :
setlocale(LC_CTYPE, 'fr_FR.UTF-8');
echo iconv('UTF-8', 'ISO-8859-1', '@ € ä ç'); // retourne : @ ¤ ä ç
On voit donc que la conversion a échouée sur le signe euro. Mais en ajoutant « //TRANSLIT » :
setlocale(LC_CTYPE, 'fr_FR.UTF-8');
echo iconv('UTF-8', 'ISO-8859-1//TRANSLIT', '@ € ä ç'); // retourne : @ EUR ä ç
iconv a donc converti « € » en « EURO ». Dans le même principe, iconv est particulièrement utile pour supprimer les caractères accentués des chaînes de caractères.
MySQL
Comme à chaque fois où il est question de chaîne de caractères, il est aussi question de jeu de caractères, et MySQL n’échappe pas à la règle.
Que ce soit la création de la base de données, la création de table, des champs ou même la connexion au serveur, il est possible dans chacun de ces points de spécifier le jeu de caractères à utiliser.
Tout d’abord, il faut indiquer lors de la connexion au SGBD le jeu de caractères que nous souhaitons utiliser. Pour ce faire, une simple requête SQL suffit :
SET NAMES 'utf8';
Cette requête est la première à effectuer avant toute autre requête. Elle indique que les chaînes de caractères à traiter dans les prochaines requêtes seront en UTF-8.
Ensuite, nous créons une base de données avec le jeu de caractères UTF-8 :
CREATE DATABASE NomDeLaBase CHARACTER SET utf8 COLLATE utf8_bin;
« COLLATE » défini la collation à utiliser. J’utilise personnellement les deux suivantes :
- utf8_bin : la chaîne de caractères sera sensible à la casse. Donc le caractère « e » sera considéré comme différent de « E ».
- utf8_general_ci : la chaîne sera insensible à la casse. Donc « e » sera considéré équivalent à « E », mais en plus de cela « e » sera équivalent à « é ». Pratique pour la recherche.
Lors de la création de table, les jeux de caractères peuvent aussi intervenir. Par exemple :
CREATE TABLE Users ( id MEDIUMINT UNSIGNED AUTO_INCREMENT, username VARCHAR(30) NOT NULL, mail VARCHAR(60) NOT NULL UNIQUE COLLATE utf8_general_ci, password VARCHAR(40) NOT NULL, PRIMARY KEY(id) ) ENGINE=INNODB CHARACTER SET utf8 COLLATE utf8_bin;
Ici nous spécifions le jeu à utiliser globalement à la table (ligne 7). Mais, pour le champ « mail », nous définissons une collation différente pour que le champ soit insensible à la casse.
C’est à peu près tout pour MySQL.
Conclusion
Les jeux de caractères sont loin d’être aussi compliqués à comprendre et à utiliser. Tout est question d’attention. La seule complexité est, selon moi, l’utilisation avec PHP du fait de ses fonctions natives ne supportant pas UTF-8. Mais ce problème franchi avec les bon outils (iconv et mbstring), c’est presque un jeu d’enfant de programmer correctement sans souci de jeu de caractères.
NOTE : si vous rencontrez des erreurs dans cet article, n’hésitez pas à me les signaler, merci.

Pingback: Tout savoir pour bien gérer les accents dans un site web | KubX
Pingback: Tweets that mention PHP / MySQL : comment résoudre les problèmes d’accents ? | Programmation web -- Topsy.com
header('Content-type: text/html; charset=UTF-8');Je n’utilise plus du tout la fonction « header » pour définir le type d’encodage.
Normalement, avec les explications de cet article, il est inutile de l’utiliser.