Publicado por Juan Pablo el 2.Abr.2006 | Comentarios (18)
Hola, bienvenido a la segunda parte y final de la historia sobre la Iñtërnâçiônàlizæçiøn de nuestro intercambio de información sin problemas de codificación. La entrega pasada tuvo mucho exito, espero cumplir vuestras expectativas para el final de la historia.
Para es artículo definiremos algunas convenciones de notación:
Si quieres realizar tus propios cálculos entre bases numéricas puedes ayudarte de Google:
Algunas ideas de la entrega pasada para refrescar la memoria.
Ahora definiremos oficialmente el sistema de codificación Unicode llamado UTF-8, además ilustraremos los problemas típicos y sus soluciones. Terminaremos migrando un weblog corriendo en Wordpress con ISO-8859-1 a UTF-8, como vez hay mucho paño que cortar asi que... ponte cómodo.
Para los que leyeron el artículo anterior se dieron cuenta que nunca mencioné el juego de caracteres ISO-8859-1, debo ser honesto y reconocer que se me quedó en el tintero, pero aquí me reivindico.
¿Se acuerdan de la desaparecida empresa Digital?, la que luego fue comprada por Compaq. Bueno, Digital fue una empresa pionera en la industria de la computación, entre sus muchos aportes desarrollaron un terminal llamado VT220 que traía consigo un juego de caracteres que ellos llamaron Set de caracteres Multinacional que fue desarrollado por ECMA. En 1992 IANA presentó el mapa de caracteres ISO_8859-1:1987, más conocido como el ISO-8859-1 el mismo que fue la base para los VT220 ahora era la base para la naciente Internet. El ISO-8859-1 es un set de caracteres de 8 bit de longitud, define la codificación del alfabeto latino incluyendo los diacríticos (á,é,ñ,ç) y letras especiales (ß, Ø) necesarios para las lenguas:
Por esta razón el ISO-8859-1 también es conocido como el Latin 1. La inmensa mayoría de los sitios web de occidente utilizan éste juego de caracteres pero ¿qué ocurre con los sitios de oriente?, donde el ISO-8859-1 no sirve. Para sintetizar tenemos el mismo escenario de problemas ocurrido en la entrega pasada de este artículo y la carta de mi primo Aristóteles: ¡aunque exista ISO-8859-1 todavía no tenemos un estándar!.
Como habíamos descrito en la entrada anterior Unicode es el estándar que albergaba todas las lenguas de la tierra, sin excepciones, pero ¿cómo representamos Unicode para no provocar problemas en nuestros sistemas?; un gran dilema; hasta que llegó el señor Ken Thompson (el mismísimo patriarca de Unix) acolitado por Rob Pike. Estos señores inventaron la forma de codificar Unicode mientras cenaban en un restaurant de Austin, Texas ¿Pero de qué se trataba tal genialidad?, aquí vamos:
Más claro que eso imposible ¿verdad?, era una broma (risas por favor). De los puntos anteriores se genera la siguiente tabla de tranformación:
Rango Unicode | UTF-8 secuencia de octetos (hexadecimal) | (binario) --------------------+--------------------------------------------- 0000 0000-0000 007F | 0xxxxxxx 0000 0080-0000 07FF | 110xxxxx 10xxxxxx 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 0020 0000-03FF FFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 0400 0000-7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
Me encantan los ejemplos, vamos con algunos:
Eso es UTF-8 y cómo trabaja, una cosa más: el número "8" equivale a la longitud de cada octeto, 8 bits. Debo mencionar —o mejor dicho clarificar—que UTF-8 es una forma más de representar Unicode, otras alternativas son UTF-16, UTF-7, SCSU.
Muy bien, hasta aquí todo ha sido un mar de aburrida teoría, ataquemos los problemas del mundo real. Imagino que te has dado cuenta que soy un instigador del uso de UTF-8, ¡usa UTF-8! ...¿convencido?—excelente. ¿Por donde comenzar?, aquí vamos:
Texto codificado hay en todos lados: en un email, en una página web o en un script; supongamos que tienes una página web codificada con ISO-8859-1 al igual que la inmensa mayoría de las páginas web de occidente, para cambiarte a UTF-8 debes:
La w3c dice que todo documento transmitido por HTTP que sea de tipo texto— texto plano, html, etc —debe tener un parámetro charset
que especifique la codificación de caracteres del documento, dicha línea es la siguiente:
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
Abre el archivo con tu editor favorito —el Bloc de Notas de Windows 2000/XP resulta ser muy útil— y cambia la línea mencionada por:
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
Da exactamente lo mismo si lo escribes con mayúscula (UTF-8) o minúscula (utf-8) (ver especificaciones en IANA)
Si no usas Vim, te recomiendo ver cómo se configura la codificación en otros editores.
En un entorno Unix/Linux tenemos otra alternativa para cambiar la codificación de nuestra página web, y se llama iconv, el comando sería:
iconv -f iso-8859-1 -t utf-8 entrada-iso.html -o salida-utf.html
-f: from, -t: to. o: out. Si quieres conocer la lista completa de los sistemas de codificación soportados por iconv tipea: iconv -l
charset
(mira el punto 1 del ejemplo para Windows).Veamos más problemas típicos relacionados con el sistema de codificación de nuestras páginas webs. Es muy común que ocurran conflictos de codificación entre nuestro servidor web y las páginas cuando decidimos cambiarnos a UTF-8. Cuando un servidor web es instalado, el administrador le dice qué sistemas de codificación son aceptados y cuál es el sistema por defecto. En un servidor Apache la línea de configuración es la siguiente ( la cual está dentro del archivo httpd.conf):
AddDefaultCharset
Ésta directiva acepta tres (3) valores: On|Off|charset
Supongamos los siguientes escenarios, pero antes: El Administrador es el señor que configura nuestro servidor web y nos permite alojar nuestra página web, el Desarrollador es quién hace la página web. El Administrador configura la directiva AddDefaultCharset, el Desarrollador configura el charset de la página (su codificación) y ahora veamos que sucede con las diferentes combinaciones que se pueden dar:
AddDefaultCharset on Charset = utf-8
Cuando AddDefaultCharset está en on quiere decir que sea cual sea la codificación que usemos en nuestra página web el servidor siempre servirá la página en ISO-8859-1 —que es la codificación por defecto. Me da para pensar que estamos frente a un Administrador retrógrado y un Desarrollador visionario.
AddDefaultCharset Off Charset = utf-8
En este caso nuestro Administrador es un tipo liberal, y da todo el poder de decisión a quienes alojamos nuestra página en su servidor para elegir libremente la codificación (ver todas las codificaciones permitidas por IANA). Por ejemplo, en el hosting donde se aloja actualmente juque.cl mi administrador tiene ésta configuración.
AddDefaultCharset utf-8 Charset = iso-8859-1
Ahora tenemos un Administrador visionario, quién entiende la importancia de tener una codificación estándar en su servidor, pero el Desarrollador aún tiene la mente en los años 90 y continúa desarrollando para ISO-8859-1.
AddDefaultCharset utf-8 Charset = utf-8
Finalmente tenemos un dúo vanguardista, visionario y con un pensamiento estándar además de ser asiduos visitantes de los mejores weblogs de Internet.
El test del Ñandú está disponible para descarga (2 archivos html: ISO y UTF) si quieres probar en tu propio servidor.
Bajaste el test del Ñandú y te diste cuenta que tu caso es el A—el peor de todos— además tienes alojado tu sitio web en un servidor compartido donde no tienes acceso al httpd.conf ¿qué haces?.
En la raíz de tu sitio web, crea un archivo bautizándolo como .htaccess (nótese el punto al inicio). Éste archivo es especial, su nombre técnico es "archivo de configuración distribuido", por decirlo de algún modo es un httpd.conf local, especialmente configurado para un directorio "x", a pedido, moldeado para. Siguiendo el caso D dentro del .htaccess ponemos:
AddDefaultCharset utf-8
Guarda y ¡voila!. Si no lo haz hecho aún, cambia la codificación y el charset de todas tus páginas webs y todo tu sitio web gozará ahora de una dulce atmósfera UTF-8.
Unas líneas más arriba migramos una página web de ISO-8859-1 a UTF-8 paso a paso, en un ambiente Windows y en uno Unix/Linux. Ahora haremos lo mismo pero por lotes. Para automatizar la migración de una gran cantidad de páginas he creado un script en Bash que cambia el sistema de codificación existente (configurable) a UTF-8 —usando iconv— además cambia el charset de cada una de las páginas codificadas—usando ex. Los pasos para usar el script son:
El CMS para weblog's más popular es Wordpress, así que lo usaré de ejemplo para migrarlo de ISO-8859-1 a UTF-8. Para el ejemplo debes tener necesariamente acceso SSH a tu servidor.
En panel de administración vamos a : Options → Readings, en Encoding for pages and feeds cambiamos la codificación a: UTF-8
Si en este momento miramos nuestro weblog luce de la siguiente forma:
No entres en pánico, ahora lo arreglamos.
Te conectas a tu servidor, una vez en la línea de comandos tipeas:
mysqldump --add-drop-table -u tu-usuario -ptu-contraseña -h tu-hosting tu-bd > wp.sql
Explicación de cada parámetro:
Ahora cambiaremos la codificación del archivo wp.sql usando iconv, igual como lo hicimos antes.
iconv -f iso-8859-1 -t utf-8 wp.sql -o wp-utf8.sql
Sólo nos queda un paso más. Ahora sólo tenemos que volver a subir el archivo a nuestra base de datos, pero ahora usando el archivo recién codificado: wp-utf8.sql. Lo que hacemos posible usando el siguiente comando:
mysql -u tu-usuario -ptu-contraseña -h tu-hosting tu-bd < wp.utf8.sql
Mientras hacía las pruebas de rigor en mi laboratorio (que sonó pomposo eso ¿verdad?) tuve algunos problemas. La migración que leiste anteriormente fue hecha en MySQL 3.23, que es la versión que tengo montada en mi casa, la versión de mysqldump es la 8.22. Luego del exito de la migración decidí hacer exactamente lo mismo en Dreamhost (mi empresa de hosting) pero el resultado no fue el mismo, no funcionó la migración.
Mi hosting tiene montada la versión 4.1.14 de MySQL y el mysqldump es la version 10.1. Cuando realicé el paso 2 de la migracion me di cuenta que el archivo valcado ya estaba codificado en UTF-8, de esto no estoy seguro (¿alguién me ayuda?) pero al parecer mysqldump versión 10.1 vuelca siempre en UTF-8 a menos que se le especifique otro juego de caracteres. Entonces quedé plop. Realizando una típida prueba y error comenzé a eliminar algunos comentarios que mysqldump deja en el archivo volcado (wp.sql). Cuento corto, cuando eliminé la línea:
/*!40101 SET NAMES utf8 */;
y después de subir nuevamente el archivo (paso-4) funcionó perfectamente. No hubo necesidad de usar iconv. Mi conocimiento no es muy fuerte en MySQL, si alguién sabe la respuesta por favor deje su comentario. Aunque al parecer es un problema de mi hosting.
Espero haber cubierto casi todo el tema Unicode y UTF-8 con estos dos artículos. Los invito a todos a cambiarse a UTF-8 para que nuestro intercambio de datos sea único para todo el mundo, nuestras aplicaciones ajax's no tengan problemas y nuestros archivos XML sean iguales para cualquier tipo de sistema. Acuérdense de mi cuando vean esos trackbacks o pingbacks ininteligibles (con símbolos extraños), uno de esos dos bloggers es un retrógrado.
Enlace Permanente, Comentarios (18), Publicada en: Estándares
Weblogs que han referenciado la ASCII, Unicode, UTF-8 y la Iñtërnâçiônàlizæçiøn - parte II:
» ASCII, Unicode, UTF-8 y la Iñtërnâçiônàlizæçiøn - parte II de meneame.net
Entrega anterior: http://meneame.net/story.php?id=4670 [continuar leyendo]
» ASCII, Unicode, UTF-8 y la internacionalización de Garbage In, Garbage Out
...i.html">ASCII, Unicode, UTF-8 y la internacionalización, parte 1
ASCII, Unicode, UTF-8 y la internacionalización, parte 2<... [continuar leyendo]
no quiero ser chupamedias, pero la verdad es que debe ser el post más notable y claro que he leído respecto de los trabalenguas de la codificación.
mis felicitaciones, juque.
¡Me emocionas hasta las lágrimas Juque! ¡Qué articulazo!
/me se saca el sombrero ;)
notable..una de las mejores explicaciones que he leido sobre el tema ..
en el muy bizarro caso que necesitaran hacer dicha conversion en dentro de un mismo archivo PHP que se esta ejecutando , seria algo asi:
final.
je. mientras escribia este codigo, pille un BUG en APC (http://www.php.net/apc/) pero alguien mas ya lo reportó :)
aqui : http://www.onfocus.cl/judas/iso2utf8.py hay otro script en python que serviria para la conversion.
find . -name "*.html" | iso2utf8.py
Saludos.
lametablemente el ejemplo en PHP tu blog se lo devoró :D aqui esta el link http://www.onfocus.cl/judas/iso2utf8-inline.phps
Muy buen articulo, se podria desarrollar una 3º parte un poco mas tecnica en relacion a la programacion y UTF-8, que tambien tiene mucha chicha aunque a lo mejor es menos interesante.
Excelente articulo, supongo que las dos partes iran en la seccion de recursos.
Efectivamente MySQLDump guarda el archivo como utf-8, yo importé la base de datos con el phpMyAdmin de Dreamhost, importandola desde el archivo(es decir no fue copy&paste) e indicando la codificación del archivo(utf-8). Y funciono perfecto.
ahh..y con repecto al asunto de mysql, no esperes que mysql 3 haga nada bien.. ¡¡atento tierra ¡¡ ya va a salir mysql 5.1 ¡¡ :P estas a 7 años de diferencia.. no es precisamente "visionario" usar mysql 3 . je :)
En dos palabras: im-presionante
enhorabuena por este peazo de artículo
Totalmente notable el artículo. Un "must-read" para los desarrolladores criollos (me incluyo).
Excelente artículo. Y superútil en un momento en que migraba de windows a linux un entorno Apache-PHP-MySql y me estaba volviendo loco. Sólo he encontrado a faltar un pequeño detalle: Porqué no explicas el significado del "Default Character Encoding" del Mozilla Firefox?
@pep: Cuando Apache sirve una página la envía usando la codificación que él tiene configurado (Véase el caso A,B y C). El sistema de codificación seleccionado por Apache será el que el Firefox (o cualquier navegador) tome por defecto.
Buenisimo!!
Realmente estoy en apuros con esto y sin esta información no hubiera tenido como amañármelas (arreglarmelas).
Espero ansioso el capítulo sobre XML (espero no pedir demasiado), y los líos que generan las hojas de estilo (XSL) llamadas desde un objeto del servidor. (Específicamente: usar un XSL desde el XMLDOM de ASP.)
Muchas gracias por tu aporte, beneficioso para esta nube de programadores de habla castellana.
@pep : Ya sea apache o cualquier otro servidor web, este suele enviar un encabezado HTTP ( en ingles "header") que contiene una cierta cantidad de información que el cliente debe o puede interpretar.
en este caso el servidor web enviaría el encabezado "Content-Type" que dentro de sus valores deberia contener el charset en cuestion de el documento, este sera interpretado por cualquier navegador ( inclusive los de texto )
y no se trató sobre el UTF-8 con BOM... aún me ronda la cabeza qué es exactamente