Cómo se manifiesta el problema
Antes
INSERT INTO wp_posts (post_title) VALUES ('Menú de la canción – año nuevo');Después
INSERT INTO wp_posts (post_title) VALUES ('Menú de la canción – año nuevo');De dónde viene
WordPress guarda el texto como UTF-8. Sin embargo, muchas instalaciones antiguas crearon sus tablas en latin1 o se conectaron con latin1. Mientras la escritura y la lectura cometan el mismo error, nadie lo nota. Al cambiar a un servidor nuevo, exportar con phpMyAdmin o modificar el juego de caracteres de la conexión, cada letra con tilde se convierte de golpe en dos caracteres.
DB_CHARSETenwp-config.phpeslatin1o no coincide con las tablas.- El volcado se exportó como
latin1y se importó comoutf8mb4, o al revés. - Un plugin o un script de importación convirtió otra vez un texto ya dañado. Así surge el texto con doble codificación como
ó.
Reparar la exportación
- Haz una copia de seguridad de la base de datos antes de cambiar nada.
- Exporta las tablas afectadas como archivo
.sql, por ejemplo con phpMyAdmin o conmysqldump --default-character-set=utf8mb4. - Suelta el archivo en el recuadro de arriba. Mojibuster repara solo los puntos dañados y te muestra cada cambio.
- Descarga el archivo reparado e impórtalo con
utf8mb4en una base de datos de prueba nueva. - Revisa el sitio. Si todo se ve bien, impórtalo en la base de datos real.
El volcado nunca se sube a ningún servidor, algo importante porque suele contener cuentas de usuario, correos electrónicos y comentarios. Más información para empresas y delegados de protección de datos.
Cuidado con los datos serializados
WordPress guarda algunos ajustes de wp_options y wp_postmeta como valores PHP serializados, por ejemplo s:7:"Canción";. El número es la longitud en bytes. Cuando ó vuelve a ser ó, la longitud deja de coincidir y WordPress descarta el valor. Por eso conviene reparar primero las tablas de contenido como wp_posts, wp_comments y wp_terms. Para las opciones, wp search-replace de WP-CLI es mejor herramienta porque actualiza las longitudes.
Corregir la causa en MySQL
- Cambia tablas y conexión a
utf8mb4y definedefine('DB_CHARSET', 'utf8mb4');enwp-config.php. - Si una columna
latin1contiene bytes UTF-8, no la conviertas directamente: se codificaría por segunda vez. El camino habitual pasa por un tipo binario: primeroMODIFY … LONGBLOBy despuésMODIFY … LONGTEXT CHARACTER SET utf8mb4. - Prueba cada cambio antes en una copia de la base de datos.
Preguntas frecuentes
¿Puedo reparar toda una base de datos de WordPress de una vez?
Sí, incluso volcados SQL grandes. Eso sí, ten cuidado con los datos serializados de wp_options y wp_postmeta: WP-CLI los maneja mejor.
¿Se modifican los caracteres correctos del volcado?
No. Mojibuster solo repara secuencias claramente dañadas. El texto correcto se queda como está.
¿Qué diferencia hay entre utf8 y utf8mb4?
En MySQL, utf8 solo guarda caracteres de hasta tres bytes, así que los emojis se pierden. utf8mb4 es UTF-8 de verdad y la opción correcta para WordPress.
¿Sirve para sistemas distintos de WordPress?
Sí. Joomla, Drupal, Magento o tu propia aplicación sobre MySQL o MariaDB tienen el mismo problema y la misma solución.