Bonjour à tous,

Attention, c'est un peu long. Voici quelques interrogations et les tests que j'ai pu faire. Si vous pouviez éclairer ma lanterne, ou confirmer ou infirmer mes suppositions, ça serait pas mal. Smiley smile


Sans être totalement ignorant des questions relatives aux encodages de caractères, j'avoue que leur gestion par divers programmes et langages me dépasse un peu.

J'ai un site construit avec Movable Type 4, dont les données sont en UTF-8. Mais lorsque je les visualise avec phpMyAdmin, ces données apparaissent sous la forme suivante: «Téléchargement» pour «Téléchargement». Pourtant, la page servie par phpMyAdmin est bien en UTF-8. J'ai vérifié. Si je demande à Firefox de m'afficher la même page en ISO-8859-1, j'obtiens «Téléchargement». Smiley smile

Pourtant, sur mon site Movable Type, tout est bien affiché, je suis en UTF-8 sur toute la ligne (j'utilise d'ailleurs régulièrement des caractères typographiques inexistants en ISO-8859-1), etc.

Le problème me semble donc être du côté de phpMyAdmin. Le coup des données corrompues à l'affichage (c'est à dire avec un affichage type «données utf-8 affichées en latin1» alors qu'on est déjà en utf8) me semble révélateur.

À tout hasard, je me suis écrit un micro-script PHP pour interroger directement ma base. La page produite est servie en UTF-8, et les données s'affichent bien. J'en conclus donc que mes données sont bien en UTF-8 dans la base, malgré ce qu'affiche phpMyAdmin.

Maintenant, une petite subtilité. Si je rajoute à mon script PHP:
mysql_query("SET character_set_results = 'UTF8'");
(ou bien le plus générique "SET NAMES 'UTF8'"), j'obtiens des résultats corrompus! Tandis que si je fais la même chose mais en demandant du "latin1", j'obtiens des résultats intacts (données en UTF-8).

Série de suppositions:

1. Ma base de données a été créée avec l'encodage utf8 (me dit phpMyAdmin).

2. Lors de l'installation du blog, Movable Type a créé les tables en indiquant pour chaque table un "CHARSET=latin1".

3. Par la suite, Movable Type insère ses données en UTF-8 (c'est à dire qu'il envoie des valeurs numériques correspondant à de l'UTF-8, qui sont enregistrées telles quelles par MySQL, et restituées telles quelles également, en ignorant le "CHARSET=latin1".

4. Si j'utilise SET NAMES ou SET character_set_results, MySQL essaie de transcrire les données quand ça lui semble nécessaire. Si je demande des données d'une table (ou à fortiori d'un champ) marqué comme étant en latin1, et que je demande de l'UTF-8, alors MySQL transcrit les données de latin1 vers UTF-8, et comme les données sont déjà en UTF-8 elles sont alors corrompues.

5. J'imagine que phpMyAdmin doit faire la même chose que moi: comme la base de données a été créée en UTF-8, il utilise un SET NAMES 'UTF8' ou équivalent, et paf corruption des données.

La grande question est: pourquoi diable Movable Type crée-t-il des tables en latin1 pour y insérer des données UTF-8 par la suite? Et là je parle de Movable Type, mais il me semble que CMS Made Simple fait exactement la même chose. (Du moins si je ne me fourvoie pas complètement pour l'un comme pour l'autre.)
Une idée comme ça: ce serait un mécanisme pour pouvoir utiliser l'enregistrement des données en UTF-8 avec de vieilles versions de MySQL, MySQL 3 ou peut-être même 4. Ces versions ne supporteraient pas UTF-8, et donc on ne pourrait pas leur demander de tout gérer en UTF-8. On se contenterait alors de leur passer des données brutes, sans faire appel à leurs facultés de conversion des données.

Ça vous semble plausible ou bien je délire à plein tube?


Enfin, la question corrolaire: quel type d'export faut-il faire avec mysql_dump?

Si j'utilise mysql_dump sans rien indiquer de spécial, il travaille par défaut en UTF-8 et dans le fichier d'export j'ai... des données corrompues. Si je lui demande de travailler en latin1 (--default-character-set=latin1), dans le fichier d'export j'obtiens... des données en UTF-8. Bref, même topo qu'avec mon script PHP de test.

Mais, à tout hasard, les données «corrompues» ne sont-elles pas nécessaires sous cette forme pour pouvoir faire un import qui marche (dans une nouvelle base de données sur un autre serveur, par exemple, ou sur le même en cas de restauration nécessaire)?

Demain matin je dois faire un transfert de base de données pour un site CMS Made Simple qui semble présenter exactement le même problème. Je vais tenter les deux type d'export avec mysql_dump, et je vous dirai ce qui marche bien. Smiley cligne
Modifié par Florent V. (13 Mar 2008 - 12:05)
Bonjour,

Quel est l'encoding de la base MySQL elle-même ?

MT ne précise pas d'encodings et stocke les strings encodées en UTF8, indépendamment de l'encoding réellement utilisé par MySQL.

Il est possible de votre base soit définie comme Latin1, ce qui doit perturber phpMyAdmin.

JY
Hello Florent,

J'ai remarqué le phénomène aussi.

Apparemment phpMyAdmin effectue un utf8_encode (ou équivalent) sur le contenu, alors que celui-ci est déjà encodé en tant que tel.

Il y a donc une possibilité que tu n'a pas mentionnée qui est un bug de phpMyAdmin.

Dans le cas contraire (bug MT), il s'agit peut-être simplement du fait que les énoncé create table ne spécifient pas l'encodage à utiliser (et celui par défaut est pris).


Pour les export je confirme que c'est un joyeux bordel, j'avais finit par tout tenter Smiley biggol
Modifié par Necromantik (05 Mar 2008 - 17:50)
Bonjour Jean-Yves et merci pour cette réponse,

MySQL est configuré en UTF-8, mais pour la base elle-même je n'ai pas l'information. Je n'ai pas d'accès shell (j'ai un accès ssh aux fichiers mais la base de données est sur un autre serveur), donc phpMyAdmin est ma principale source d'information sur la base.

Si je passe par phpMyAdmin et que je lui demande d'exécuter successivement:
SELECT CHARSET(DATABASE());
SELECT COLLATION(DATABASE());
il me retourne "utf8" et "utf8_general_ci".

Donc j'aurais tendance à dire que la base a "utf8" comme encodage paramétré. Les tables par contre sont en "latin1" et "latin1_german_ci", sans que je sois intervenu dessus pour ma part. C'est pour ça que j'ai pensé à une création de tables avec pour chaque table un charset par défaut sur "latin1". Mais n'ai-je pas utilisé le bon moyen pour obtenir l'information?

Du côté de Movable Type, les tables sont-elles créées explicitement avec l'encodage UTF-8 comme paramètre?

PS: simple curiosité et si ça n'est pas trop indiscret, c'est un mécanisme d'alerte automatisé qui vous a conduit à ce post, ou bien une recherche manuelle ou encore le signalement d'un lecteur?
Je n'ai pas encore testé, je ferai sans doute ça demain.

Il me semble que la deuxième solution proposée (export depuis phpMyAdmin avec option "charset of file = iso-8859-1") correspond à ce que je fais lorsque je fais un export avec mysqldump en précisant --default-character-set=latin1 (ça doit être la même commande). J'avais pensé à éditer le fichier pour pouvoir faire un import avec des tables taguées en "utf8" au lien de "latin1". Je testerai ça demain sur une base vide créée pour l'occasion.

Détail en passant: en faisant un export avec mysqldump, j'obtiens un fichier en utf-8 (y compris avec --default-character-set=latin1) qui contient quelques valeurs non régulières. Ces valeurs non régulières perturbent les éditeurs de code que j'ai pu tester (ça va de «j'ouvre le fichier mais j'arrive pas à reconnaitre l'encodage» à «rien à foutre, j'ouvre pas le fichier et en plus je rame»). J'ai trouvé un moyen «simple» de résoudre ça:
- ouvrir le fichier avec Firefox (si besoin, renommer le fichier en .txt pour qu'il soit ouvert et pas proposé en téléchargement);
- faire «Affichage > Encodage des caractères > UTF-8» si ça n'a pas été détecté automatiquement;
- faire un copier-coller dans un éditeur de code;
- enregistrer en UTF-8.

On n'a plus que des caractères valides. Avec un fichier d'export de 1,3 Mo, le fichier corrigé fait 35 octets de plus que l'original. Je ne sais pas si infos importantes ont été altérées, ou si cette correction est nécessaire. Je la note ici au cas où.
(Si je ne m'abuse, les données numériques brutes devraient être exportées en ASCII, sous la forme \FF pour un octet de valeur 255 -- FF en hexadécimal --, non?)
Florent V. a écrit :
Bonjour Jean-Yves et merci pour cette réponse,

MySQL est configuré en UTF-8, mais pour la base elle-même je n'ai pas l'information. Je n'ai pas d'accès shell (j'ai un accès ssh aux fichiers mais la base de données est sur un autre serveur), donc phpMyAdmin est ma principale source d'information sur la base.

Si je passe par phpMyAdmin et que je lui demande d'exécuter successivement:
SELECT CHARSET(DATABASE());
SELECT COLLATION(DATABASE());
il me retourne "utf8" et "utf8_general_ci".

Donc j'aurais tendance à dire que la base a "utf8" comme encodage paramétré. Les tables par contre sont en "latin1" et "latin1_german_ci", sans que je sois intervenu dessus pour ma part. C'est pour ça que j'ai pensé à une création de tables avec pour chaque table un charset par défaut sur "latin1". Mais n'ai-je pas utilisé le bon moyen pour obtenir l'information?

Du côté de Movable Type, les tables sont-elles créées explicitement avec l'encodage UTF-8 comme paramètre?

PS: simple curiosité et si ça n'est pas trop indiscret, c'est un mécanisme d'alerte automatisé qui vous a conduit à ce post, ou bien une recherche manuelle ou encore le signalement d'un lecteur?


Movable Type ne précise pas l'encoding, comme tu le supposes plus haut pour être compatible avec les anciennes versions de MySQL. il stocke les données en UTF8, et MySQL stocke les données binaires telles quelles sans vérification.

Les tables ont donc été créés en Latin1 par MySQL, je ne sais pas pourquoi, ça paraitrait logique qu'il utilise l'encoding par défaut de la base.

Cf ici :

http://alexking.org/blog/2008/03/06/mysql-latin1-utf8-conversion

Tu peux sans doute utiliser ton mysqldump qui te retourne les données en utf8 avec le create table en latin1, changer ce latin1 et mettre utf8 dans le create table, et réimporter le tout dans une nouvelle base.

PS : c'est quelqu'un d'autre de Six Apart qui m'a envoyé le lien, je ne sais pas s'il a une alerte dans une rechercher Google ou autre.
Modifié par jystervinou (13 Mar 2008 - 11:29)
Merci Jean-Yves pour ce complément d'information. Content de voir que mes suppositions étaient correctes. Smiley smile

La solution que tu suggère est celle que j'avais imaginée. Je la testerai dès que j'aurais un peu de temps, sans doute ce week-end.

J'ai depuis peu un petit serveur virtualisé (Gandi). Je tenterai peut-être une installation standard de Movable Type et peut-être de CMS Made Simple et Wordpress, juste pour voir avec quel charset les tables sont créées, et si quelque chose dans la configuration de MySQL joue là-dessus. Ça sera à priori un test plus fiable que sur un hébergement mutualisé pour lequel je n'ai pas de prise sur la configuration de MySQL.

J'apporterai donc peut-être quelques informations supplémentaires à ce sujet, mais comme il répond aux principales interrogations je le marque déjà comme résolu.
Florent V. a écrit :
Merci Jean-Yves pour ce complément d'information. Content de voir que mes suppositions étaient correctes. Smiley smile

La solution que tu suggère est celle que j'avais imaginée. Je la testerai dès que j'aurais un peu de temps, sans doute ce week-end.

J'ai depuis peu un petit serveur virtualisé (Gandi). Je tenterai peut-être une installation standard de Movable Type et peut-être de CMS Made Simple et Wordpress, juste pour voir avec quel charset les tables sont créées, et si quelque chose dans la configuration de MySQL joue là-dessus. Ça sera à priori un test plus fiable que sur un hébergement mutualisé pour lequel je n'ai pas de prise sur la configuration de MySQL.

J'apporterai donc peut-être quelques informations supplémentaires à ce sujet, mais comme il répond aux principales interrogations je le marque déjà comme résolu.


Une autre solution c'est d'utiliser la fonction export (notes, commentaires, dans un format reconnu par les logiciels de blogs principaux) , ou la fonction sauvegarde de Movable Type, qui va t'exporter tout le contenu du blog, ainsi que les fichiers uploadés, dans un fichier zip ou gz.