Le kit pour créer les sites internet des laboratoires du CNRS


Accueil > Cahiers techniques > Bases de données

Convertir votre base de données du latin1 à l’utf8

par Equipe web, pverrier - publié le , mis à jour le

Sommaire :

Si vous avez créé votre site il y a assez longtemps, il s’est peut-être installé en encodage iso-8859-1 (aussi appelé “latin1”), qui était la configuration standard sur les anciennes versions. Il est dans ce cas conseillé de le convertir en utf-8, surtout si vous souhaitez migrer votre site SPIP 2 sur la version 3, ou si vous souhaitez mettre en place le multilinguisme.

Jeu de caractères (charset) et interclassement (collation)

(Pour en savoir plus sur le sujet, consultez la page “Comprendre les jeux de caractères et interclassements” sur openclassrooms.com.)

Les anciennes versions de SPIP installaient une base de données avec le jeu de caractères latin1 (=iso-8859-1) et l’interclassement latin1_swedish_ci, correspondant aux valeurs par défaut de MySQL.

SPIP 3 gère nativement l’utf-8, et il est très fortement conseillé de l’utiliser, d’autant plus si votre site est multilingue.

Vérifier l’encodage de vos données

Sur SPIP 2

→ Survolez « Configuration », puis cliquez sur « Gestion des langues »

Dans cet exemple, le site est en latin1 (=iso-8859-1) et il est nécessaire de le convertir.

Il est également conseillé de vérifier directement dans la base de données avec phpMyAdmin (voir ci-dessous).

Sur SPIP 3

→ Survolez « Configuration », puis cliquez sur « Langue principale du site »

Dans cet exemple, le site est déjà en utf8, il n’a pas besoin d’être converti.

Il est également conseillé de vérifier directement dans la base de données avec phpMyAdmin (voir ci-dessous).

Dans phpMyAdmin

Il est recommandé d’examiner directement les tables dans phpMyAdmin pour vérifier les informations obtenues dans SPIP ; vous pourrez d’ailleurs également y trouver l’interclassement mis en œuvre, sachant qu’il est conseillé d’utiliser l’utf8_general_ci (ou, pour certains langages particuliers l’utf8_unicode_ci qui gère mieux les expansions et les ligatures contre une petite baisse de performances - détails ici).

→ Dans phpMyAdmin, affichez la liste des tables de la base utilisée par votre site, et regardez la colonne “Interclassement” :

Tables en latin1
Tables en latin1
Tables en utf8
Tables en utf8

Vous pouvez également examiner le contenu des tables pour vous assurer que les caractères accentués sont affichés normalement ; si ce n’est pas le cas, il y a une incohérence entre l’encodage défini dans la structure des tables et les données stockées.

Les caractères accentués sont gérés normalement

Conversion du latin1 à l’utf8

Sauvegarde préalable, site clone

Avant toute chose, il est indispensable de faire une sauvegarde de votre base (structure + données) depuis phpMyAdmin. Il est en effet possible que le processus ne se déroule pas parfaitement au premier essai, et vous aurez besoin de réinstaller entièrement votre base pour recommencer, les données et/ou la structure ayant été impactées entretemps...

Nous vous conseillons même, si vous le pouvez, de travailler sur un site clone (sur un serveur de préproduction, ou sur un poste local avec WAMP ou EasyPHP) ; cela vous permettra de valider la procédure avant d’agir sur votre serveur de production. Le plus aisé est probablement de faire la conversion “finale” en local au lieu de la faire directement sur le serveur, et de remettre en place la base convertie via un dump phpMyAdmin ; dans ce cas n’oubliez pas de redéfinir la configuration générale du site, en particulier l’adresse du site public que vous aurez modifiée sur votre site clone.

Par ailleurs, pour être sûr que des utilisateurs ne procèdent pas à des enregistrements dans la base de données en même temps que vous réalisez cette conversion, il est sans doute plus sage de bloquer ponctuellement l’accès à votre site et à son backoffice ; par exemple, vous pouvez mettre en place une protection par mot de passe que vous serez le seul à connaître (voir Restreindre l’accès à mon site tant qu’il n’est pas finalisé).

Enfin, il est possible que les scripts de conversion soient interrompus par le serveur à cause de la durée du traitement, qui peut prendre beaucoup plus de temps qu’un traitement normal ; pour vous en prémunir, vous pouvez modifier la valeur de max_execution_time dans votre php.ini (vous n’y aurez accès que sur votre serveur local) en indiquant (recherchez la ligne correspondante pour la modifier) :
max_execution_time = 0
qui signifie que le script ne sera jamais interrompu. Pensez à remettre la valeur précédente une fois vos conversions réalisées.

Si vous ne pouvez pas agir sur ce “timeout” d’exécution, vous devrez recharger la page jusqu’à ce qu’elle indique que le traitement est terminé, ce cas est apparemment prévu dans le traitement.

Sur SPIP 2

La version 2 de SPIP contient les scripts PHP qui vont vous permettre de réaliser cette conversion.

Étape 1 : conversion des données

→ Revenez sur la page « Gestion des langues » (du menu « Configuration ») ; en bas, constatez la présence d’un lien « page de conversion vers l’utf-8 » qui vous donne accès au processus de conversion des données (notez l’URL correspondante http://monsite.fr/ecrire/?exec=convert_utf8).

Attention : ce processus ne prend en charge que les tables standard de votre site, et ignorera purement et simplement d’autres données qui peuvent avoir été mises en place par certains plugins. C’est typiquement le cas de la table spip_evenements qui est créée par le plugin Agenda (utilisé par Séminaire). Pour la prise en charge de ces tables supplémentaires, voir plus bas Convertir aussi la table spip_evenements.

→ Cliquez sur le lien (ou accédez à l’URL http://monsite.fr/ecrire/?exec=convert_utf8), et suivez les indications à l’écran.

→ Voyons les changements dans phpMyAdmin (cliquez sur « Actualiser ») :

Les caractères accentués sont mal représentés

La bonne nouvelle, c’est qu’on constate un changement. La mauvaise, c’est qu’il n’est (à priori) pas normal que les caractères accentués soient ainsi affichés.

Note : à ce stade, contrôlez également l’état des tables susceptibles d’avoir été ajoutées par des plugins (ex : spip_evenements) ; si vous n’avez pas fait en sorte qu’elles soient prises en charge (Cf. Convertir aussi la table spip_evenements plus bas), vous constarez que leurs accents sont normaux : en fait, leurs données n’ont pas été converties en UTF-8 ; vous devez ajouter ces tables dans la liste à traiter, et relancer le processus (après avoir restauré votre base d’origine).

Astuce : Pour savoir facilement ce qui a été traité ou non, le plus efficace consiste à comparer les dumps SQL avant et après traitement, à l’aide d’un comparateur de fichiers (de type WinMerge ou Beyond Compare).

Exemple de comparaison de dumps
Constatez les modifications liées à l’encodage ici dans la table articles. Soyez attentif aux tables qui sont identiques bien qu’elles contiennent des caractères accentués (ex : spip_evenements), car cela signifie qu’elles n’ont pas été traitées.

Si nous affichons la liste des tables, nous constatons que les tables sont toujours en latin1_swedish_ci. Il est donc finalement normal que nous voyons de tels codes sur les caractères accentués : les affichages de type é sont typiques du traitement en latin1 de caractères accentués stockés en utf8 (codés sur deux caractères spéciaux, le premier étant souvent Ã). Nous devons donc maintenant modifier les structures pour les convertir en utf8, et ainsi accorder contenu et contenant.

Étape 2 : conversion des structures

SPIP 2 intègre également le script permettant de convertir les structures de données, mais ne fournit pas de lien pour y accéder, comme précédemment.

→ Vous devez taper l’url http://monsite.fr/ecrire/?exec=convert_sql_utf8 dans votre navigateur (notez ici le _sql_ supplémentaire).

→ Suivez les indications à l’écran.

→ Réaffichez la liste des tables dans phpMyAdmin : vous constaterez qu’elles ont toutes été converties en utf8_general_ci.

Jetez également un œil sur les champs (dans la structure interne des tables) pour vous assurer qu’ils sont également passés en utf8 (si ce n’est pas le cas, c’est que le processus a rencontré des erreurs, référez-vous au paragraphe Détection des erreurs de conversion de structure ci-dessous).

Exemple de conversion incomplète
Tous les champs, sans exception, auraient dû passer en utf8 !

→ Réaffichez les données, vous constaterez que les accents sont maintenant affichés normalement, car ils sont maintenant stockés ET traités en utf8.

Par contre, l’interclassement par défaut de la base n’a pas été modifié ; il est plus prudent le passer aussi en utf8_general_ci, pour cela :

→ Cliquez sur l’onglet « Opérations » ;
→ Dans « Interclassement », sélectionnez utf8_general_ci, puis « Exécutez ».

Sur SPIP 3

Les scripts PHP qui vont vous permettre de réaliser cette conversion ne sont plus livrés dans SPIP 3, mais dans le plugin Grenier ; il vous suffira donc de l’installer sur votre site, le temps de faire cette opération.

→ Installez le paquet de Grenier : http://files.spip.org/core/grenier.zip

→ Le principe est identique à celui réalisé sur SPIP 2, excepté les URLs qui permettent de réaliser les conversions :

  • http://monsite.fr/ecrire/?exec=base_convert_utf8 pour la conversion des données ;
  • http://monsite.fr/ecrire/?exec=base_convert_sql_utf8 pour la conversion des structures.

→ Une fois vos conversions réalisées avec succès, vous pouvez désinstaller complètement le plugin Grenier.

Convertir aussi la table spip_evenements

Il faut ici modifier le script PHP qui réalise la conversion ;

  • sur SPIP 2 : /ecrire/base/convert_utf8.php
  • sur SPIP 3 : /plugins/auto/grenier/base/convert_utf8.php

→ Éditez le fichier dans un éditeur texte et ajoutez la table spip_evenements dans la liste des tables à traiter, après la ligne spip_articles (ligne 46) :
   'spip_evenements' => 'titre', // ligne ajoutée

→ Enregistrez les modifications, cette table sera prise en charge lors de la prochaine conversion des données en UTF-8.

Note : concernant le processus de conversion des structures de données, il n’y a pas de modification à apporter au script convert_sql_utf8.php, car il balaye l’ensemble des tables de la base. Mais nous vous conseillons quand même d’apporter les quelques améliorations présentées ci-après.

Détection des erreurs de conversion de structure

Si des erreurs MySQL sont rencontrées lors de la conversion des structures, elles ne seront pas affichées par le script.

Nous vous conseillons donc de modifier :

  • sur SPIP 2 : /ecrire/base/convert_sql_utf8.php
  • sur SPIP 3 : /plugins/auto/grenier/base/convert_sql_utf8.php

en ajoutant la ligne ci-dessous juste après l’affichage des requêtes de conversion exécutées :
if (!_DEBUG_CONVERT && sql_errno()!=0)  print '<p style="color:red;">'.sql_error ().'</p>';

Soit, à ces trois emplacements :

Vous obtiendrez l’affichage en rouge des erreurs rencontrées, par exemple :

Pour votre information, l’erreur Column 'nom_champ' cannot be part of FULLTEXT index indiquée ici vient du fait que sur cet exemple, des index FULLTEXT ont été mis en place (Cf. plugin Fulltext), et que l’ensemble de leurs champs doivent tous être dans le même encodage (Cf. doc MySQL) ; le processus de conversion consistant à changer le jeu de caractères des différents champs un à un, MySQL refuse l’opération. Il faut donc dans ce cas supprimer ces index FULLTEXT avant conversion, puis les rétablir après.

Ci-joint une version un peu plus élaborée pour la remontée d’erreurs, suite à des problèmes liés à la conversion intermédiaire des champs en BLOB (pour plus de détails voir le post sur contrib.spip.net) :

convert_sql_utf8.php du plugin grenier (v0.2.4) modifié pour afficher les erreurs MySQL