Migrer un site de Latin-1 vers UTF-8

Ça y est, j’ai finalement pris la décision de migrer critiqueslibres.com de Latin-1 vers UTF-8. Il y a beaucoup de bonnes raisons, la dernière en date étant que je voudrais intégrer les notices bibliographiques de la Bnf dans notre base, et que certaines informations peuvent être dans des langues non-européenne (par exemple, le nom d’un auteur japonais, le titre original d’un livre de Dostoïevski),…

J’ai « googlé » pas mal, j’ai trouvé beaucoup de tutoriels et d’articles, mais mes premiers essais ont été des échecs. Finalement, j’ai pris l’approche de celui-ci, que j’ai adapté un peu : Getting out of MySQL Character Set Hell.

La procédure que j’ai suivie contient les étapes suivantes :

  • Prendre un backup !!!
  • migrer la base de données : c’est la partie difficile
  • adapter le code PHP : utilisation de la librairie mbstring et changer les fonctions qui sont sensibles au jeu de caractères (dans mon cas, il s’agit de htmlentities), indiquer à mysql qu’on est en utf-8 lors de la connection
  • changer le header dans les pages HTML et adapter le httpd.conf

La base de données

Pour la base de données, voici ma stratégie retenue. Il y en a d’autres, mais celle-ci a marché chez moi, tandis que les autres ont échouées.

1. J’ai créé trois scripts SQL. Le premier qui contient les définitions de tables, index et contraintes d’intégrité. Un deuxième qui contient les commandes de création des fonctions et un troisième qui contient les commandes de création des triggers. C’est de toute façon une bonne pratique de maintenir ces scripts et de les « versionner » dans l’outil de « source control ».
Note : il est facile de créer les scripts si on ne les a pas encore : il suffit de faire un export de la base de données avec sqldump et l’option –no-data, ensuite d’éditer le fichier généré (supprimer toute les commandes inutiles ajoutées par mysql, séparer les tables des triggers et des fonctions,…).

A chaque commande « create table » dans le script, j’ai ajouté l’option UTF8. Par exemple

CREATE TABLE mytable (
  id INT NOT NULL,
  ...
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;

2. J’ai créé un petit script shell qui exporte le contenu de chaque table dans un fichier. Par exemple,

mysqldump -umonuser -pmonpassword--skip-set-charset \
    --extended-insert=false --no-create-info \
    --triggers=FALSE mabase latable1 > latable1.sql

.. etc pour chaque table de la base de données.

Il faut vérifier que le fichier généré est bien en UTF-8, avec la commande linux « file ». Dans mon cas, vu que mon serveur est linux avec comme locale utf-8, mysql a bien créé un fichier en utf-8. Si ce n’était pas le cas, alors j’aurais probablement du faire la conversion moi-même (commande linux iconv).

3. Editer le fichier de config de MySQL.

Dans le fichier /etc/my.cnf, changer les lignes suivantes :

[client]
default-character-set=utf8
...
[mysqld]
default-character-set=utf8

Il faut ensuite redémarrer MySql.

Pour vérifier que tout est en ordre, se connecter en mysql, et exécuter le SQL suivant :

mysql>show variables like 'char%'. 

Problème : en production (plus vieille version de mySQL), le show variables like ‘char%’ montrait que certaines variables étaient toujours en latin1 si je n’étais pas connecté avec root (avec root, pas de problèmes). Je n’ai pas investiger plus en détail, j’ai juste éditer le fichier my.cnf et j’ai ajouté dans la section [mysqld]

init-connect='SET NAMES utf8' 

Ensuite, je droppe la base de données, et je la recrée (Avoir un backup !!!).

drop database mabase;
create database mabase 
default character set 'utf8' default collate 'utf8_general_ci';

Ensuite, je recrée les tables à partir du script dont il est question plus haut. Il faut créer les tables (et les index + contraintes) uniquement (pas encore les fonctions et les triggers, ce sera fait après l’import des données). Et il suffit maintenant d’importer les fichiers générés plus haut, au moyen d’un script shell.

mysql -umonuser -pmonmotdepasse mabase < matable1.sql 

pour chacune des tables de la DB.

Il faut ensuite recréer les fonctions et les triggers.

PHP

Il faut installer le paquet php-mbstring si nécessaire.

yum install php-mbstring.

Editer le php.ini, et ajouter ceci :

mbstring.func_overload = 7

Il faut changer les appels à la fonction htmlentities, pour fournir le paramètre "utf-8".

htmlentities($message)

devient

htmlentities($message,ENT_COMPAT,"UTF-8") 
 

Dans mon site, j'avais quelques appels à decode_utf8 et encode_utf8, ils doivent maintenant être supprimés.

Au moment de la connexion à la base de données, il faut ajouter ceci :

mysql_set_charset('utf8',lelink);
ou bien
mysql_query("SET NAMES 'utf8'");

Apache et le HTML

Pour apache, il suffit d'éditer le fichier httpd.conf, et dans la section "virtual host" correspondante à votre site, ajouter ceci :

AddDefaultCharset UTF-8

Dans la page html, il faut changer le tag meta http-equiv, dans l'attibut content indiquer le charset UTF-8.

Conclusion

Il y a pas mal de techniques décrites sur le WEB pour migrer un site de jeu de caractères. Il faut bien tester, et choisir celle qui convient. Il est évidemment indispensable de prendre un backup avant !

Une fois que le site est migré, il faut s'assurer que son environnement de développement est en UTF-8 aussi, ce qui est le cas avec eclipse et linux. En eclipse, s'assurer que le caractère de l'éditeur est utf-8.

2 réflexions au sujet de « Migrer un site de Latin-1 vers UTF-8 »

  1. Merci Garance. Je poste ces trucs techniques en me disant que ça pourra aider un autre webmaster, qui serait confronté au problème (tout comme j’ai moi-même trouvé de l’info sur d’autres blogs).