Problemas de tildes relacionados con UTF8, ISO-8859-1, PHP y Eclipse...

Esto es lo que pasa cuando tienes entornos que no son homogéneos y cada aplicación se encuentra ubicada en distintas márgenes de un "río virtual", en una ribera las más antiguas soportando por defecto el viejo ISO-8859-1 y en la otra, un poco más actualizadas a los tiempos modernos, las que incluyen el soporte de UTF-8.

En un mundo ideal, donde todos los servidores y las estaciones de trabajo se actualizan a la par, contemplando los últimos cambios tecnológicos, obtendremos con el uso de UFT-8 la posibilidad de trabajar con cualquier tipo de "caracteres especiales", incluyendo los famosos "tildes" (que abundan en nuestro castellano) sin tener que usar "codificaciones html" para representarlos.

¿Quién no sufrió tener que escribir "día" y "año" para representar "día" y "año"?

En el mundo real, obviamente, sucede todo lo contrario: tu estación de trabajo puede estar con la última versión de tu sistema operativo y aplicativos, y todas ellas usarán desde hace pocos años por defecto el juego de caracteres UTF-8...

PERO... como es lógico y habitual, los servidores no se acostumbran a actualizar a la par de la tecnología (al menos no completamente de cero), puesto que si brindan servicios (que generalmente son siempre críticos) actualizar completamente un software de base o sus aplicativos sin una justificación fundamentada sería arriesgarse a que algo pudiera dejar de funcionar.

Eso lleva a que es completamente habitual encontrar que existen diferencias en las versiones de software entre desarrolladores y sus propios servidores, lo cual hay que tener en cuenta que al editar un archivo con formato ISO que incluye tildes y caracteres especiales escritos sin usar codificación html y grabarlos en una herramienta que use UTF-8 genera la pérdida completa de los mismos.

Existen muchas alternativas para paliar estos problemas:
  • Usar utilidades que tomen archivos en formatos ISO y los transformen en formato UTF, con la única contra de que no se podrá aplicar si los servidores son antiguos y desconocen el nuevo formato,
  • Migrar los servidores y las aplicaciones para unificar el formato de caracteres, pero raramente este tipo de problemas es razón suficiente para poner en riesgo toda una instalación de servidores (web, base de datos, servidores de aplicación, etc).
  • Codificar internamente todos los caracteres especiales (tildes, símbolos, etc) con su correspondiente representación en "código html", lo cual si no encontramos un editor que nos ayude a trabajar de forma transparente con ellos, nos obliga a hacerlo "a mano", con todos los caracteres. La otra contra posible es que si mañana se unifica todo a formato UTF, perderíamos la posibilidad de usar libremente cualquier caracter, lo que deberíamos entonces buscar algo que lo traduzca al nuevo formato.
  • Cambiar a todas las aplicaciones que usan por defecto UTF-8 al antiguo ISO-8859-1 para que nuestros archivos en este último formato no pierdan todos los caracteres especiales.
Esta última es la opción generalmente más elegida.

En el caso concreto de Eclipse

Hace mucho tiempo que el IDE Eclipse (el cual uso para desarrollar con PHP5) usa por defecto UTF-8, y en su momento he tenido varios problemas para cambiar "completamente" todos los lugares donde hace referencia a este juego de caracteres (sí, en más de un lado):
  • En la "configuración general" con qué formato editas los archivos.
  • El formato con el cual se graba el archivo.
Todavía no me cierra porqué se podría querer editar en un formato y grabarlo en otro, pero bueno, alguien tal vez lo pueda necesitar.

A pesar de estos cambios, los caracteres se seguían perdiendo. También hay que cambiar en:
  • Configuración -> Content Type, y para cada tipo de archivo donde diga "Default Encoding":
Por ejemplo, tenía en mi configuración por defecto:
  • Java prefs = "ISO-8859-1"
  • Javascripts = "US-ASCII"
  • XML = "UTF8"
  • DTD = "UTF8"
La mayoría dice UTF8, pero...
  • HTML = "vacío"
  • PHP Source File = "vacío"
Que asumo se debería tomar "alguna configuración general", pero al haberlas -creo- cambiado todas, les agregué el valor "ISO-8859-1".

Hasta ahora no volví a perder ningún tilde.

Resumiendo

Todo esto no sucedería si todos los aplicativos trabajaran con el mismo juego de caracteres, en particular UTF-8, el cual permite insertar caracteres especiales de forma directa y no a través de un código particular que después será traducido por el navegador de turno.

También, según como codifiques los caracteres, tienes distintos tipos de problemas:
  • Si en ISO usas literalmente los caracteres especiales, en UTF se pierden (quedan convertido en "basura").
  • Si en ISO usas los "códigos html" que corresponden con los caracteres especiales no se pierden al pasar a UTF, pero en algún momento deberás cambiarlos a caracter literal para poder sacarle provecho al formato.
  • Que no solo depende del editor de turno que formato usa, también del servidor.
Y que en Eclipse hay muchos lados para cambiar esta configuración, lo cual debo recordar para volver atrás en algún momento futuro.

Un detalle sobre PHP6 y UTF

En muchos lados se comenta como "la panacea " que la nueva versión de PHP, la versión 6, será 100% compatible con UTF-8 (sus funciones, el manejo de información de salida y entrada, etc), lo cual siempre me dio la impresión de algo menor (habiendo tantas otras cosas del lenguaje que se podrían agregar, como los namespaces). También me había sorprendido que decían que el trabajo era "una obra titánica" por la cantidad de código que tenían que modificar para incorporar ese soporte...

...pero luego de vivir este tipo de problemas y saber que hace mucho tiempo todas las aplicaciones recientes lo usan, y que de aquí en más se soluciona cualquier problema de caracteres (por lo que tengo entendido podríamos escribir directamente en japonés y debería soportarlo sin más)...

... ahora comprendí cuan grave y necesario es (aunque sigo pensando -de terco que soy- que "namespaces" debería estar en esta versión).

9 comentarios:

WebNewbie dijo...

Saludos PHP Senio.
Hace más de un año cuando intenté migrar los datos de mi antiguo base de datos, tuve problemas con los caracteres latinos, toda mi data usaban codificación UTF-8, algunas ISO-8859-1, generándome los llamados "caractéres raros":
España --> España
UTF-8 --> lee como codificado en ISO-8859-1.
Jesús Pérez --> Jes?s P?ez
ISO-8859-1 --> lee como codificado en UTF-8

La idea de solución que tuve en aquel entonces, es encontrar la manera de sanear aquellos caracteres raros, luego codificarlos por Referencias Numéricas de Caracter (NCR), antes de guardarlo en mi nueva base de datos, todo eso ocurrión cuando se hicieron cambios en la versión de MySql.

Preferí el tipo de codificación NCR ya que para cualquier tipo de codificación de documento, se podía visualizar bien los caractéres. Aunque la desventaja es que ocupa mucho espacio en la base de datos y en el peso de los documentos XHTML.

La solución en PHP Script fue lo siguiente: (Sólo es un ejemplo)


<?php
if (!empty($_POST)) {
foreach($_POST as $k => $v) {
echo "<strong>Antes: $v</strong><br />\n";
$v = preg_replace('/[^!-%\x27-;=?-~<>&\x09\x0a\x0d\x0B ]/e', '"&#".ord("$0").chr(59)', $v);
$$k = preg_replace('/Ã&#([0-9]+);/e', '"&#".((int) \\1 + 64).";"', $v);
echo "Después: ". $$k ." <br />\n";
}
}
>

Para probar el código, crea un formulario con un campo - textarea - en un documento XHTML enviándolo con la cabecera aplication/xml.
Envía los datos del formulario con el método POST al script que lo procesará. En dicho script debe estar el código del ejemplo anterior.

Fue un placer escribir un prolijo comentario.
Saludos.

WebNewbie dijo...

El códigoa anterior debe ser así:
<?php
if (!empty($_POST)) {
foreach($_POST as $k => $v) {
echo "<strong>Antes: $v</strong><br />\n";
$v = preg_replace('/[^!-%\x27-;=?-~<>&\x09\x0a\x0d\x0B ]/e', '"&#".ord("$0").chr(59)', $v);
$$k = preg_replace('/&#195;&#([0-9]+);/e', '"&#".((int) \\1 + 64).";"', $v);
echo "Después: ". $$k ." <br />\n";
}
}
>

Cesar Carbonara dijo...

Y sí... mañana se unifica todo a formato ISO?

enrique_place dijo...

Estimado Cesar:

El formato en desuso es ISO, el nuevo formato que soluciona todos los problemas de "caracteres rotos" es UTF-8... lo que se está unificando (hace muchos años) es hacia este último.

Dunei dijo...

Buenas,
el problema que yo tengo es que genero unos ficheros .sql con el SQL File Editor del Eclipse Ganymedes, en propiedades de este fichero están en UTF-8. En el default encoding para ficheros .sql he puesto UTF-8, el encoding del workspace es UTF-8, cierro el eclipse, vuelvo a abrirlo, abro el fichero .sql con el SQL File Editor y me aparecen caracteres raros donde van los acentos y las eñes.
La única cosa que no he encontrado por ningún lado es lo que dices sobre como configurar el encoding al grabar el fichero.

Una ayudita please.
Saludos,
Vanesa.

Norant dijo...

Estimado Enrique:
El último post data del año pasado, pero bueno, tengo un problema con las eñes que de seguro ya te haz topado y es que cuando intento comparar un valor de un campo text de un campo de la base de datos, si esta con tilde o eñe, no lo encuentra, es decir si dice: Peña no lo encuentra por mas que Peña si este en la db mysql, esto me sale con PDO, te pego mi codigo:
public function verificarSiExistePelicula($pelicula_titulo)
{
try {
$dbh = Database::getInstance();
$sql = "SELECT pelicula_titulo FROM pelicula WHERE pelicula_titulo = ? ";
$sth = $dbh->prepare($sql);
$sth->execute(array($pelicula_titulo));
$datos= $sth->fetchObject();
return $datos;
}catch (PDOException $e) {
die( 'Fallo en query '.__METHOD__.': ' . $e->getMessage() );
}

}
Bueno es probable que encuentre la solución, esa es la idea.

Saludos.

Fernando Torterolo dijo...

Muchas gracias.
UTF-8 funciono correctamente en proyecto Eclipse.

Fernando Torterolo dijo...

Muchas gracias, dio resultado en mi proyecto eclipse juno.

pete dijo...

ay ay ay me estaba volviendo loco y era en el eclipse, muchas gracias!!
Yo estoy usando eclipse 4.3.1 y para cambiar la condificacion en los archivos actuales debe uno seleccionar el directorio raiz edit-> Set Encoding.

Saludos

Entradas populares