Bonjour à tous,

Je suis actuellement en stage en entreprise, en fin de DUT Info. Je suis en Allemagne, et mon projet est de refaire un site web. Ok easy, mais le seul bémol, c'est que l'affichage des caractères spéciaux en local est moisie Smiley ohwell (Je suis sous Windows Vista, et Xampp pour émuler le serveur)


Explications :

La base originale du site web ( http://isuv.de ) est une base MySQL en ISO-8895-1, que j'appelerais latin1, la collation est en latin1_german1_ci et celle-ci contient des caractères UTF-8.
La configuration de PHP, d'Apache, et du "Server encoding" est en Latin1, pourtant si vous allez sur le site, clique droit, informations sur la page, vous voyez que celui-ci s'affiche en UTF-8.

Ce qu'on m'a demandé, c'est de faire disparaitre le latin1 ! On a donc fait tout ceci :

Dump de la base mysql

ssh -p 1022 (siteweb) "mysqldump --compact --max_allowed_packet=1677619200 --default-character-set=latin1 isuvdb | gzip > /home/isuv/isuvdb_`date +%F`.gz"
scp -P 1022 (siteweb):/home/isuv/isuvdb_`date +%F`.gz .


Remplacement des chaines de caractères suivantes dans le dump.

zcat isuvdb_`date +%F`.gz | sed 's/CHARSET=latin1/CHARSET=utf8/' | sed 's/latin1_german1_ci/utf8_general_ci/' > isuvdb_latin1.sql


Création de la base en local.

DROP DATABASE isuvdb; CREATE DATABASE isuvdb DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;


Insertion des données dans la base.

mysql --force --max_allowed_packet=1677619200 --default-character-set=utf8 –-database=isuvdb --user=root < isuvdb_latin1.sql


Bon voilà tout est inséré, je regarde dans l'interface PHPMyAdmin, toutes les données sont LISIBLES, les ü et les ß s'affichent à travers PHPMyAdmin (notez que dans la base orignelle que m'a montré le boss, elles ne s'affichaient pas bien, puisque le texte était de l'utf8 et la base du latin1). Et quand je lance le site en local, j'obtiens tout plein de caractères : &#65533;

Boooon, je me suis donc renseigné sur Internet (ICI) à savoir qu'il fallait modifier le fichier httpd.conf d'Apache et lui rajouter la ligne
AddDefaultCharset	UTF-8

J'ai également ajouté au fichier php.ini les lignes suivantes :
mbstring.language=UTF-8
mbstring.internal_encoding= UTF-8
mbstring.http_input=UTF-8
mbstring.http_output=UTF-8
mbstring.detect_order= auto


Et voilà, cela n'a strictement rien changé...

Screenshot à l'appui : http://img247.imageshack.us/img247/1149/isuvxz6.th.jpg

Pouvez-vous m'aider ? Dites moi ce que j'ai oublié de faire ? (et si j'ai oublié de préciser certaines choses...) Mon boss m'a demandé de changer l'encodage du serveur, mais je suis sous windows, et je ne sais absolument pas comment faire... Il faut que je termine ça rapidement de préférence Smiley decu

Merci à vous,

Corentin
Modifié par eXtaZiuM (04 Apr 2008 - 12:06)
Je souhaiterai ajouter que lorsque, dans Firefox, je vais dans Affichage, Encodage des caractères et que je change UTF-8 pour ISO-8895-1, les caractères s'affichent normalement, alors que sur le site Internet http://isuv.de l'encodage des caractères est UTF-8 et cela fonctionne très bien.

Qu'en pensez-vous ?
Hello,

Parmi les possibilités:
- le script du site se connecte à la base MySQL avec un "SET NAMES latin1", ce qui fait que MySQL va traduire les données de UTF-8 (si tes tables sont bien marquées comme étant en utf-8) à ISO-8859-1;
- le script du site convertit les données reçues en ISO-8859-1, ou bien utilise des fonctions de PHP qui gèrent mal les encodages multi-octets.

Sinon, est-ce que tu as essayé de taper directement dans la base avec un script PHP simple, et testant ces trois cas de figure:
1. pas de SET NAMES;
2. SET NAMES utf8;
3. SET NAMES latin1.
Et qu'est-ce que ça donne dans les trois cas?
Florent V. a écrit :
Hello,

Parmi les possibilités:
- le script du site se connecte à la base MySQL avec un "SET NAMES latin1", ce qui fait que MySQL va traduire les données de UTF-8 (si tes tables sont bien marquées comme étant en utf-8) à ISO-8859-1;
- le script du site convertit les données reçues en ISO-8859-1, ou bien utilise des fonctions de PHP qui gèrent mal les encodages multi-octets.

Sinon, est-ce que tu as essayé de taper directement dans la base avec un script PHP simple, et testant ces trois cas de figure:
1. pas de SET NAMES;
2. SET NAMES utf8;
3. SET NAMES latin1.
Et qu'est-ce que ça donne dans les trois cas?


Ha j'ai oublié de préciser que le site avait été généré à l'aide d'un CMS : TikiWiki. Donc j'ai fait une recherche dans les ifchiers du site (ultra nombreux... un truc comme 9000 fichiers) Pour info le dump de la base du site fait 127mo, celui du forum en fait 377mo. C'est un sacré projet.

Je n'ai pas compris comment ça marche SET NAMES. Il faut le faire à chaque requête ? Ou une seule fois et c'est bon ?

Et qu'entends tu par "le script du site convertit les données reçues en ISO-8859-1" ? Comment peut on le voir ? Si c'est dans le header, la réponse est non, il m'affiche bien de l'UTF-8.

Merci de ta réponse Smiley smile
eXtaZiuM a écrit :
Je n'ai pas compris comment ça marche SET NAMES. Il faut le faire à chaque requête ? Ou une seule fois et c'est bon ?

À chaque ouverture de connexion MySQL, pas à chaque requête.

eXtaZiuM a écrit :
Et qu'entends tu par "le script du site convertit les données reçues en ISO-8859-1" ? Comment peut on le voir ?

En connaissant par coeur tout le code de l'application...
... ou en connaissant les fonctions potentiellement fautives dans le langage utilisé, et en cherchant dans les fichiers sources de l'application...
... mais le plus simple est sans doute de demander sur le forum ou la liste de l'application en question.

Mais procède déjà aux tests que je mentionne pour savoir où tu vas exactement.
Re,

Non je n'ai pas essayé, j'ai cherché un peu, mais je ne comprends pas comment cela fonctionne. (J'ai un peu de mal, on est vendredi -_-' ) Ca s'insère dans la requête d'affichage ou c'est une autre requête à part ? Peux tu me donner un exemple ? Je te remercie Smiley smile
eXtaZiuM a écrit :
Ca s'insère dans la requête d'affichage ou c'est une autre requête à part ?

C'est une autre requête à part, à envoyer tant qu'à faire en début de connexion.

eXtaZiuM a écrit :
Peux tu me donner un exemple ?

mysql_connect(...);
mysql_select_db(...);
mysql_query("SET NAMES 'utf8'"); 
Bonjour,

J'ai fait ce que tu m'as dit, c'est à dire que j'ai cherché "mysql_connect" et "mysql_select_db" dans tous les fichiers du site, j'ai rajouté la ligne "mysql_query("SET NAMES 'utf8'"); " à la suite de mysql_select_db ... Et cela n'a rien changé. Smiley decu

Quel peut être le problème à ton avis ? Cela vient du dump ? De la configuration de l'encodage du serveur (que je ne sais absolument pas où changer, car mon patron a fait une différence entre la configuration du serveur, et la configuration d'apache...) ? Bref je n'en sais rien et ça commence à me gonfler Smiley ohwell

Merci,

Corentin

PS : Ha j'ai aussi remarqué que quand je passais l'encodage de Firefox (dans Afficahge, Encodage des caractères, ISO), tout s'affichait correctement ! Je ne comprends pas, j'ai pourtant spécifié UTF-8 ! Smiley decu
Modifié par eXtaZiuM (07 Apr 2008 - 10:04)
Les données qui s'affichent sont alors en ISO-8859-1. Trois raisons possibles:
1. Le script (PHP ou autre) fait la conversion (c'est le cas par exemple en PHP de la fonction htmlentities et de la fonction htmlspecialchars, si on ne leur passe pas le bon encodage en paramètre).
2. MySQL fait la conversion car les données sont correctement identifiées dans la base comme UTF-8, mais la connexion est en ISO-8859-1.
3. Les données dans la base sont en ISO-8859-1.

Tu n'as toujours pas fait les tests que je préconisais... Je me cite:
a écrit :
Sinon, est-ce que tu as essayé de taper directement dans la base avec un script PHP simple, et testant ces trois cas de figure:
1. pas de SET NAMES;
2. SET NAMES utf8;
3. SET NAMES latin1.
Et qu'est-ce que ça donne dans les trois cas?

Je parle bien de passer par un script simple et indépendant de ton application.

Quant à la configuration serveur, il y a:
1. la configuration d'Apache pour déclarer l'encodage aux agents-utilisateur (typiquement via l'en-tête HTTP Content-Type);
2. la configuration de MySQL (sous linux: fichier /etc/my.conf, ou /var/lib/mysql/my.conf).
Les deux sont bien entendu documentés dans les documentations officielles de chacun de ces deux logiciels.
FlorentV a écrit :
Sinon, est-ce que tu as essayé de taper directement dans la base avec un script PHP simple, et testant ces trois cas de figure:
1. pas de SET NAMES;
2. SET NAMES utf8;
3. SET NAMES latin1.
Et qu'est-ce que ça donne dans les trois cas?


Alors j'ai fait les tests (enfin Smiley lol ) donc voilà :

Sans SET NAMES, on obtient ceci :

http://img266.imageshack.us/img266/2996/coderientm1.th.jpg
http://img402.imageshack.us/img402/3950/resriensp5.th.jpg

Avec le SET NAMES latin1, on obtient ceci :

http://img253.imageshack.us/img253/2999/codelatinsw6.th.jpg
http://img211.imageshack.us/img211/3960/reslatinrp5.th.jpg

Avec le SET NAMES utf8, on obtient ceci :

http://img266.imageshack.us/img266/1453/codeutfgh4.th.jpg
http://img402.imageshack.us/img402/9293/resutfwk6.th.jpg

Florent V. a écrit :
Les données qui s'affichent sont alors en ISO-8859-1. Trois raisons possibles:
1. Le script (PHP ou autre) fait la conversion (c'est le cas par exemple en PHP de la fonction htmlentities et de la fonction htmlspecialchars, si on ne leur passe pas le bon encodage en paramètre).


J'ai fait une recherche d'htmlentities dans tous les fichiers et j'ai trouvé ceci.
function htmlconverter($text) {
	global $phpversion;
	$charsets = array('ISO-8859-1', 'ISO-8859-15', 'UTF-8', 'CP1252', 'WINDOWS-1252', 'KOI8-R', 'BIG5', 'GB2312', 'BIG5-HKSCS', 'SHIFT_JIS', 'EUC-JP');
	
	if (version_compare($phpversion, '4.3.0') >= 0 && in_array(wbb_strtoupper(ENCODING), $charsets)) return @htmlentities($text, ENT_COMPAT, ENCODING);
	elseif (in_array(wbb_strtoupper(ENCODING), array('ISO-8859-1', 'WINDOWS-1252'))) return htmlentities($text);
	else return htmlspecialchars($text);
}

 function convertHTML($text) {
 	static $charset;
 	global $phpversion;

 	if(!isset($charset)) {
  		global $lang;
  		$charset=strtolower($lang->items['LANG_GLOBAL_ENCODING']);

 	}
 	if(version_compare($phpversion, "4.3.0")>=0 && ($charset=="iso-8859-1" || $charset=="iso-8859-15" ||
 	$charset=="utf-8" || $charset=="cp1252" || $charset=="windows-1252" || $charset=="koi8-r" || $charset=="big5" ||
 	$charset=="gb2312" || $charset=="big5-hkscs" || $charset=="shift_jis" || $charset=="euc-jp"))
 	return @htmlentities($text, ENT_COMPAT, $charset);
 	elseif($charset=="iso-8859-1" || $charset=="windows-1252") return htmlentities($text);
 	else return htmlspecialchars($text);
}


FlorentV a écrit :

2. MySQL fait la conversion car les données sont correctement identifiées dans la base comme UTF-8, mais la connexion est en ISO-8859-1.
3. Les données dans la base sont en ISO-8859-1.

Ca j'imagine qu'on le sait suivant les tests que je viens d'effectuer ?

FlorentV a écrit :

Quant à la configuration serveur, il y a:
1. la configuration d'Apache pour déclarer l'encodage aux agents-utilisateur (typiquement via l'en-tête HTTP Content-Type);
2. la configuration de MySQL (sous linux: fichier /etc/my.conf, ou /var/lib/mysql/my.conf).
Les deux sont bien entendu documentés dans les documentations officielles de chacun de ces deux logiciels.

Les indications données par cette article sont-elles juste ? http://blog.neovov.com/index.php?2007/03/06/143-convertir-un-site-en-utf-8

Merci bien !
Bonjour,

1. Les informations données dans l'article que tu cites ont l'air correctes, du moins pour la configuration Apache. On peut rajouter que suivant la configuration du serveur il peut être possible (c'est généralement le cas) d'utiliser la directive AddDefaultCharset localement dans un fichier .htaccess.

2. Les deux fonctions PHP que tu as repéré semblent utiliser l'encodage paramétré ailleurs dans l'application et l'utiliser pour appeler les fonctions htmlspecialchars ou htmlentities. Donc ça devrait être bon. Mais je connais trop mal PHP pour être catégorique.

3. Résultat des tests que tu as effectués: tes données sont probablement enregistrées dans la base de données dans des tables ou des colonnes marquées comme étant en latin1. Avec le paramètre de connexion par défaut (à priori latin1), tu obtiens un résultat correct. Avec une connexion en latin1, de même. Mais avec une connexion en utf8, les données sont corrompues.

Dis-moi, ces pages de test tu les as affichées dans un navigateur en précisant de les afficher en UTF-8? Si c'est le cas, tu es sans doute face à un cas classique de données UTF-8 enregistrées dans des tables marquées "latin1": MySQL fait alors une conversion si on lui demande de l'UTF-8, mais envoie les données telles quelles si on lui demande de l'ISO-8859-1 (latin1).

À l'inverse, si tu as affiché tes pages de test en ISO-8859-1 (ou si tu as oublié de préciser un encodage et que le navigateur a choisir ISO-8859-1 par défaut), cela signifie que:
- soit tes données sont bien en UTF-8 et sont marquées comme telles (connexion par défaut en latin1: MySQL convertit de utf8 à latin1, et tout va bien car on affiche la page en ISO-8859-1; connexion demandée en latin1: MySQL convertit de utf8 à latin1, et tout va bien car on affiche les pages en ISO-8859-1; connexion demandée en utf8: MySQL ne convertit pas les données, et tout va mal car tu affiches des données UTF-8 dans une page interprétée par le navigateur en ISO-8859-1);
- soit tes données sont des données ISO-8859-1 marquées comme telles, et dans le troisième cas de figure MySQL convertit en UTF-8 (et tu affiches en ISO-8859-1).

Je crois que j'ai fait le tour (le cas de figure données en ISO-8859-1 mais marquées comme étant en utf8 ne me semble pas possible, car je crois que tu obtiendrais des données corrompues pour les deux premiers tests).
Florent V. a écrit :
Dis-moi, ces pages de test tu les as affichées dans un navigateur en précisant de les afficher en UTF-8? Si c'est le cas, tu es sans doute face à un cas classique de données UTF-8 enregistrées dans des tables marquées "latin1": MySQL fait alors une conversion si on lui demande de l'UTF-8, mais envoie les données telles quelles si on lui demande de l'ISO-8859-1 (latin1).

À l'inverse, si tu as affiché tes pages de test en ISO-8859-1 (ou si tu as oublié de préciser un encodage et que le navigateur a choisir ISO-8859-1 par défaut), cela signifie que:
- soit tes données sont bien en UTF-8 et sont marquées comme telles (connexion par défaut en latin1: MySQL convertit de utf8 à latin1, et tout va bien car on affiche la page en ISO-8859-1; connexion demandée en latin1: MySQL convertit de utf8 à latin1, et tout va bien car on affiche les pages en ISO-8859-1; connexion demandée en utf8: MySQL ne convertit pas les données, et tout va mal car tu affiches des données UTF-8 dans une page interprétée par le navigateur en ISO-8859-1);
- soit tes données sont des données ISO-8859-1 marquées comme telles, et dans le troisième cas de figure MySQL convertit en UTF-8 (et tu affiches en ISO-8859-1).

Je crois que j'ai fait le tour (le cas de figure données en ISO-8859-1 mais marquées comme étant en utf8 ne me semble pas possible, car je crois que tu obtiendrais des données corrompues pour les deux premiers tests).


Je les aies affiché dans Firefox, sans préciser de les afficher en UTF-8, et en vérifiant dans Affichage/Encodage, elles sont affichées en ISO-8859-1 dans les 3cas.

Voilà une screen des tables :

http://img502.imageshack.us/img502/3534/screenbdqn7.th.jpg
http://img404.imageshack.us/img404/4007/screenbd2rf4.th.jpg

Avant le dump, les tables étaient dans un environnement latin1_german1_ci mais comportaient des caractères UTF-8 à l'intérieur. L'ensemble de la base était en latin1.

J'ai donc testé d'afficher avec le code UTF-8, et de passer l'encodage de Firefox en UTF-8. J'obtiens ceci :

http://img390.imageshack.us/img390/7659/resutf8wq5.th.jpg

On remarquera que l'espèce de caractère bizzare qui s'affichait avant a disparu... Etrange Smiley ohwell

Le cas est donc celui-ci :

a écrit :
tes données sont bien en UTF-8 et sont marquées comme telles (connexion par défaut en latin1: MySQL convertit de utf8 à latin1, et tout va bien car on affiche la page en ISO-8859-1; connexion demandée en latin1: MySQL convertit de utf8 à latin1, et tout va bien car on affiche les pages en ISO-8859-1; connexion demandée en utf8: MySQL ne convertit pas les données, et tout va mal car tu affiches des données UTF-8 dans une page interprétée par le navigateur en ISO-8859-1);


Pourtant quand j'affiche la racine du site web, Firefox se met tout seul en utf-8. Que dois-je faire, maintenant que nous avons trouvé le problème ?

(Merci mille fois au fait)
Modifié par eXtaZiuM (08 Apr 2008 - 13:56)
Eh bien nous avons trouvé (ou plutôt vérifié) qu'il n'y a pas de problèmes avec les données dans la base. Ce qu'il faut maintenant, c'est que la connexion avec MySQL se fasse bien en UTF-8 et pas en latin1 (ici, si elle se fait en latin1 c'est je pense parce que MySQL est configuré ainsi).

Deux solutions:
1. paramétrer le serveur MySQL pour avoir une connexion par défaut en UTF-8;
2. modifier ton application pour qu'elle utilise "SET NAMES utf8".

La deuxième solution est la moins lourde, mais ne sera simple à mettre en place que si l'application utilise un seul et même code (fonction) pour la connexion à MySQL. Si tu as des dizaines ou des centaines de mysql_connect() dans ton application, ça va être un peu difficile/chiant. Si tu as par contre une fonction de connexion à ta base MySQL qui est ensuite appelée depuis d'autres parties de l'application, il suffit de modifier cette fonction.

Pour la première solution, il faut voir du côté de la documentation de MySQL.
Modifié par Florent V. (08 Apr 2008 - 14:17)
Ouep alors j'ai essayé de mettre des mysql_query("SET NAMES 'utf8'"); là où il y a des connections à la base (recherche de "mysql_connect" dans tous les fichiers), je les ai mis dans ces fonctions de connection, le soucis c'est que ce sont des fonctions appartenant à des classes. Je ne sais pas si on peut mettre une query comme ça dans une fonction Smiley ohwell

Quand à "paramétrer le serveur MySQL pour avoir une connexion par défaut en UTF-8;" Ayant Windows, il y a très peu de documentation Smiley ohwell
Ça se passe dans le my.conf normalement pour la configuration de MySQL.
Dernièrement j'ai testé un paramétrage mais ça empêchait le script linux de démarrage de mysqld de se lancer Smiley decu

[ mysqld ]

# Set the default character set.
default-character-set=utf8

# Set the default collation.
default-collation=utf8_general_ci

# This one works fine
character-set-client=utf8

# Restarting MySQL (through ubuntu 7.10 init script)
# fails if I set any of these two:
#   character-set-results=utf8
#   character-set-connection=utf8
# It fails if I ask for latin1 — which is the
# default I think — as well.


Il faut peut-être tenter:
[ mysqld ]

default-character-set=utf8
default-collation=utf8_general_ci
character-set-client=utf8

[ client ]

character-set-results=utf8
character-set-connection=utf8
Mais j'ai pas testé.

Bien sûr relancer le serveur MySQL après tout changement de configuration dans my.conf.4

Nota: ne pas mettre d'espaces dans [ mysqld ] et [ client ] (ici c'est juste pour empêcher que le forum ne tente de transformer ça en smiley).
Modifié par Florent V. (09 Apr 2008 - 12:38)
Florent V. a écrit :
Ça se passe dans le my.conf normalement pour la configuration de MySQL.
Dernièrement j'ai testé un paramétrage mais ça empêchait le script linux de démarrage de mysqld de se lancer Smiley decu

[ mysqld ]

# Set the default character set.
default-character-set=utf8

# Set the default collation.
default-collation=utf8_general_ci

# This one works fine
character-set-client=utf8

# Restarting MySQL (through ubuntu 7.10 init script)
# fails if I set any of these two:
#   character-set-results=utf8
#   character-set-connection=utf8
# It fails if I ask for latin1 — which is the
# default I think — as well.


Il faut peut-être tenter:
[ mysqld ]

default-character-set=utf8
default-collation=utf8_general_ci
character-set-client=utf8

[ client ]

character-set-results=utf8
character-set-connection=utf8
Mais j'ai pas testé.

Bien sûr relancer le serveur MySQL après tout changement de configuration dans my.conf.4

Nota: ne pas mettre d'espaces dans [ mysqld ] et [ client ] (ici c'est juste pour empêcher que le forum ne tente de transformer ça en smiley).

J'ai essayé les 2 solutions séparéments, et aucun résultat... Je commence à désespérer Smiley ohwell
Tu as essayé avec SET NAMES dans les classes que tu as repérées? Tu peux peut-être tenter ça, après avoir sauvegardé tes fichiers source bien sûr. Smiley cligne

Sinon, il reste l'option script mal codé qui ne peut pas gérer correctement des données en UTF-8...
Bon merci pour ton aide, avec le boss on a décidé de laisser tomber car ça prenait beaucoup de temps à résoudre, alors qu'il s'agit certainement d'un problème de compatibilité Unix/Windows.

Merci Smiley cligne