L’UTF-8 est un encodage permettant de gérer bien plus de caractères que l’ISO, limité à seulement 256. Il est universel et couvre aussi bien les caractères latins que cyrilliques, arabes, japonais… à titre personnel, il m’est nécessaire pour afficher mon prénom ;).

Si l’UTF-8 est très utile, il n’en reste pas moins que, si l’on est peu habitué aux problématiques d’encodage des caractères, son utilisation peut être déroutante. En effet, même si l’utilisation de l’UTF-8 est devenu la norme, il n’est pas forcément l’encodage par défaut des outils que nous utilisons.
Je vais dans cet article tenter de transmettre ce que je sais sur cet encodage. Vous verrez qu’une fois que l’on sait un minimum comment tout cela fonctionne, l’utilisation d’UTF-8 n’aura plus que des avantages.

Avant de commencer, je tiens à souligner que la majeure partie de ce que j’ai pu apprendre sur cet encodage provient d’une seule source, un article brillant d’un certain Thierry. Celui-ci n’est depuis quelques temps plus en ligne ce qui m’a motivé à rédiger cet article. Dans l’éventualité qu’il soit à nouveau en ligne, voici le lien qui y menait : http://electron-libre.fassnet.net/utf8.php L’article est de nouveau en ligne : http://www.electron-libre.org/utf8.php

Les sources de vos données

L’encodage et MySQL

Sous MySQL, il vous est possible de définir l’encodage utilisé sur quatre niveaux :

  • la connexion
  • la base de donnée
  • la table
  • le champs

Sauf cas particuliers, veillez à ce que l’encodage soit “utf8" (sans tiret) sur chacun de ces niveaux. Pour préciser au serveur que vous allez communiquer avec lui en UTF-8, exécutez cette requête directement après chaque connexion :

SET NAMES 'utf8'

La collation (COLLATE) n’impactera pas vos données mais, lors de vos recherches elle définie comment les caractères sont regroupés.

  • utf8_bin effectue un regroupement binaire “a != à != A != À”.
  • utf8_general_cs effectue un regroupement par “généralité” sensible à la casse “a = à != A = À”.
  • utf8_general_ci effectue un regroupement par “généralité” insensible à la casse “a = à = A = À”.

Si vous ne savez pas lequel choisir, utilisez utf8_general_ci.

Vos fichiers aussi doivent être encodés

Sachez que si vous stocker des données dans des fichiers, ceux-ci devront eux aussi être encodé en UTF-8. D’une manière générale, encodez toujours vos fichiers en UTF-8.

Aussi, vos fichiers ne doivent pas contenir de BOM. Ce caractère “invisible” spécifique à l’unicode est parfois ajouté en début de fichier par votre éditeur et peut être source de perturbations. En effet, bien qu’il s’agisse d’un caractère invisible il aura pour effet, par exemple dans un script php, d’envoyer et clore l’entête HTTP et débuter l’envois du corps de celle-ci.

L’encodage de vos fichiers se gère dans votre éditeur, qui a sa propre méthode. Une liste de procédures à suivre en fonctions de différents éditeurs est à votre disposition, n’hésitez pas à proposer le votre s’il n’y figure pas.

Éditeurs Windows

Komodo Edit

Configuration par défaut
Edit › Current file settings › Onglets “Properties” › Encoding (UTF-8). Décochez “Use signature (BOM)”

UltraEdit

Configuration par défaut
Advanced › Configuration › File Handling › Save. Décochez “Write UTF-8 BOM header to all UTF-8 files when saved” et “Write UTF-8 BOM on new files created within this program (if above is not set)”

phpDesigner 8 (merci à LeFauve)

Configuration par défaut
Tools › Preferences › General (UTF-8). Cochez “Encoding Types” et “Load as UTF-8”, activez “UTF-8” et décochez “Save with BOM”

Définition par fichier
File › File Encoding

Éditeurs OS X

Panic coda

Configuration par défaut
Coda › Preferences › Editor › Default File Encoding › Unicode (UTF-8)

Définition par fichier
Text › Encoding › Unicode (UTF-8)

TextEdit

Configuration par défaut
TextEdit › Préférences › Ouverture et enregistrement › Encodage › Unicode (UTF-8)

Ubuntu

Bluefish

Définition par fichier
Document › encodage des caractères › UTF-8

Multi OS

Aptana Studio 3

Configuration par défaut
Aptana Studio 3 › Preferences › General › Workspace › Text file encoding › Other › UTF-8

Données externes

Il peut arriver que vous récupériez vos données depuis d’autres services et/ou de vos utilisateurs (formulaires). Il vous faudra vous assurer qu’elles soient bien en UTF-8.

function toUtf8($string) {
    if ('UTF-8' != $encoding = mb_detect_encoding($string, mb_detect_order(), true)) {
        if($encoding) {
            $string = mb_convert_encoding($string, 'UTF-8', $encoding);
        } else {
            $string = mb_convert_encoding($string, 'UTF-8');
        }
    }
    return $string;
}

Cette fonction vérifie qu’une chaine de caractères est bien encodée en UTF-8 et, si tel n’est pas le cas, la convertie. Elle retournera donc toujours une chaîne encodée en UTF-8.

Pour les formulaires html il existe l’attribut “accept-charset”, cependant, comme tout ce qui provient du client est modifiable, je vous déconseille son utilisation. Préférez plutôt le passage des valeurs saisies à la fonction ci-dessus, cela demandera plus de ressource server mais vous serez sûr que les données reçues soient bien en UTF-8.

Manipuler vos données UTF-8

Les fonctions classiques de manipulation de string, tel que strlen, ne sont pas faites pour fonctionner avec de l’UTF-8. En remplacement, nous utiliseront mbstring. Un petit exemple rapide :

echo strlen('Ç');               // Affiche 2
echo mb_strlen('Ç', 'UTF-8');   // Affiche 1

Comme vous pouvez le constater, strlen est dans les choux et ce parcequ’elle n’est pas faite pour manipuler des caractères encodés sur plusieurs octets. mb_strlen elle, peut manipuler des chaines sous différents encodages, spécifié à l’aide du second paramètre. Il en est de même de toutes les fonctions mbstring.

Pour plus de confort et, parceque nous avons décider de n’utiliser que de l’UTF-8, nous allons en faire notre encodage par défaut. Vous pouvez le faire dans votre php.ini, httpd.conf, .htaccess ou script php. Ici nous allons le définir dans notre fichier .htaccess :

<IfModule mod_php5.c>
    php_value mbstring.detect_order         "auto"
    php_value mbstring.http_output          "UTF-8"
    php_value mbstring.internal_encoding    "UTF-8"
    php_value mbstring.language             "uni"
</IfModule>

Notez que nous prenons soin de vérifier la présence du module php. Plus exactement, ici nous testons la présence du module php5 mais vous pourriez tout à fait remplacer mod_php5.c par mod_php4.c ou encore mettre deux blocs ifModule, un pour chaque version de php dans le but d’avoir un fichier .htaccess paré à toutes situations.

Nous ajoutons ensuite une définition alternative dans notre script php au cas où php ne serait pas exécuté en tant que module apache :

if(mb_internal_encoding() !== 'UTF-8') {
    mb_detect_order('auto');
    mb_http_output('UTF-8');
    mb_internal_encoding('UTF-8');
    mb_language('uni');
}

Maintenant, il n’est plus nécessaire de spécifier l’encodage lors de l’utilisation de fonctions mbstring.

Si vous utilisez les fonctions preg_replace, preg_match,… veillez à utiliser le pattern modifier “u” (attention à la casse) pour que le pattern comme le sujet soient traités en UTF-8. mbstring n’offrant que les fonctions ereg.

L’affichage de vos données

Maintenant que vos données sont stockées dans le bon format il vous faut les afficher correctement. Pour se faire il va falloir spécifier le charset utilisé.

Trois méthodes vont vous êtres expliquées. Voici l’ordre de priorité d’application du charset de celles-ci, de la plus prioritaire à la moins prioritaire :

  1. PHP
  2. Apache
  3. HTML

Apache

Si vous faites le choix d’utilisez exclusivement UTF-8, privilégiez autant que possible de définir le charset au niveau d’apache. Cela vous assurera un charset défini pour tous vos scripts.

Dans votre fichier httpd.conf ou dans un fichier .htaccess ajoutez/modifier l’instruction suivante :

AddDefaultCharset UTF-8

PHP

Si vous ne pouvez pas modifier la configuration d’apache d’une façon ou d’une autre vous pouvez spécifier l’encodage de cette façon :

header('Content-type: text/html; charset=UTF-8');

Notez qu’ici l’on spécifie un type text/html mais vous pouvez le modifier si vous désirer envoyer tout autre type de contenu.

HTML

Vous pouvez enfin utiliser une balise meta :

<meta http-equiv="Content-type" content="text/html; charset=UTF-8"/>

Attention, en html5 la syntaxe change :

<meta charset="utf-8" />

Détecter et corriger les erreurs d’encodage

Si vous rencontrez des caractères de ce type :

ÀÁÂÃÄÅà áâãäåÒÓÔÕÖØòóôõöøÈÉÊËéèêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ

C’est que vos données sont bien encodées en UTF-8 mais qu’elles ne sont pas affichées comme tel. Vérifiez chaque point de la partie “L’affichage de vos données

Si vous rencontrez des “�” c’est que vos données ne sont pas encodées en UTF-8. Dans ce cas, demandez-vous d’où elles proviennent et veillez à ce que chaque point de la partie “Les sources de vos données" qui s’y rapportent soient bien respectés.

blog comments powered by Disqus
  1. klohfr a reblogué ce billet depuis cahnory
  2. goetter a reblogué ce billet depuis cahnory
  3. cahnory a publié ce billet