Frédéric Barboteu wrote
J'ai eu récemment un problème apparenté, et si je l'ai résolu dans mon
cas, je n'en ai pas tiré de ceritudes absolues et générales.
Manifestement, ça reste la bouteille à l'encre, avec plein de
témoignages amenant des tentatives d'explication finalement contradictoires.
Le vrai problème est qu'on ne dispose (à ma connaissance) d'aucune
référence officielle, énamant de l'équipe de développement de Spip,
quant à la stratégie retenue en la matière.
Je donne donc ici ma propre vision des choses, en insistant bien sur le
fait que ça ne prétend pas à l'universalité.
Est-ce que l'un de vous pourrait m'indiquer où se situe la
conversion de charset dans le core ?
En l'état de mes investigations, il me semble que Spip ne cherche
aucunement à se préoccuper d'adapter sa façon d'échanger les données
avec MySql (ni dans ses propres tables, ni dans les autres).
En effet, premier point : il n'y a pas le moindre "SET NAMES" dans le code.
J'avais cru pouvoir en déduire que Spip prenait les données comme elles
viennent, pour ensuite convertir celles qui le nécessitent, au cas par
cas pour chaque champ chaîne reçu.
Mais, deuxième point : je n'ai pas davantage réussi à trouver où sont
utilisées les fonctions figurant dans charset.php, et de toutes façons
des essais montrent clairement qu'en fait les données sont affichées par
Spip telles qu'il les a reçues.
Mes tests contredisent ce dernier point, voir plus bas.
Mon interprétation : Spip se base simplement sur le fait qu'a priori les
données qu'il lit sont toujours des données qu'il a écrites (le
contenu affiché dans l'espace public provient de ce qui a été saisi à
travers l'espace privé).
Autrement dit, peu lui importe qu'entre deux (à l'intérieur de la base),
les données effectives ne correspondent pas au codage qu'elles sont
censées avoir : l'oubli de conversion en écriture est exactement
compensé par l'oubli de reconversion en lecture.
Lorsque je fais un mysqldump les caractères accentués sortent nickel
pour ma table comme pour les tables spip
Pour moi, le "juge de paix" pour vérifier la réalité du contenu, c'est
la lecture directe par phpMyAdmin : je parierais que, dans ton cas,
l'affichage de la table spip_articles montre bel et bien des signes
exotiques à la place des caractères accentués.
C'est-à-dire que les champs, réputés être en latin1, contiennent en
réalité de l'utf8.
Et que par contre, le même phpMyAdmin affiche un contenu correct pour la
table non-Spip.
(j'admets que c'est bizarre par rapport à la constation en mysqldump,
mais là je sèche...)
Je vois très bien de quoi tu parles, je connais ce problème de charset dans
charset. Après tout ça n'est qu'une suite d'octets, et il m'est déjà arrivé par
erreur de coder de l'utf8 dans du latin1, etc...
Mais mes juge de paix à moi c'est les outils en ligne de commande mysql et
mysqldump
Il faut quand même voir qu'ils font partie de la distrib officielle
de MySQL, c'est les outils de référence.
Et non, le corps des articles de spip est correctement encodé. Bon, il y a
effectivement une erreur pour les données de spip_articles.titre, là l'encoding
est cassé (et pourtant ils s'affichent correctement..). Mais pour tout le reste
les données sont en latin1 dans des tables latin1 avec un charset client par
défaut en latin1. Et pourtant spip parle en utf8 avec le navigateur.
Effectivement je n'ai pas vu de SET NAMES ou similaire dans le log de mysqld,
donc il y a forcément une conversion qui est opérée par spip. Je me demande si
ça serait pas au niveau des balises #TITRE, #TEXTE, etc... en provenance des
tables spip.
Si je fais un SET NAMES 'utf8' juste avant la boucle ça résout le
problème pour
les données qui viennent de ma table (mais ça casse les données qui
proviennent
de boucles spip situées après). De toute façon c'est trop hackish à
mon gout.
Pour que ça marche totalement, il faut en plus du "SET NAMES 'utf8'"
avant la boucle, rajouter un "SET NAMES DEFAULT" après la boucle (bien
sûr, ça ne colle pas s'il faut traiter aussi des données Spip à
l'intérieur de la même boucle... là, faudrait creuser un peu plus...).
Pour moi, c'est bien ça la bonne solution.
Je fais un SET NAMES 'latin1' arpès la boucle, le "DEFAULT" est pas mal aussi...
Quant à être "trop hackish", je vois la chose différemment : en l'état
de cette absence de certitudes générales que j'évoquais plus haut, cette
façon de faire est la moins invasive qui soit.
Très ponctuelle, très visiblement attachée au problème qu'elle cerne,
facile à remettre en cause ultérieurement si l'on acquiert une meilleure
compréhension...
Oui, mais après tout dépend de ton degré et de ta perception de la hackitude 
Moi, j'aime pas ces #EVAL qu'il faut copier dans tous les templates où je
manipule l'une ou l'autre de mes tables (il y en a 4).
Je vais essayer de trouver un truc plus clean.
En tout cas, ça m'a l'air de bug(s) tout ça.
Merci pour ta réponse détaillée
--
Olivier Guilyardi / Samalyse