¿Matrix utiliza UTF-8?

Pelearse con la codificación de los caracteres en una aplicación web es pan nuestro de cada día. En un desarrollo sencillo uno puede olvidarse de ese detalle y dejar el trabajo de cloacas al navegador y el PHP. Pero en el momento en que entran en juego javascript y fuentes externas de datos, es entonces cuando la posibilidades de cagarla se multiplican.

Una de las formas más sencillas de prevenir problemas con la codificación es utilizar siempre UTF-8 para el desarrollo completo de la aplicación. Ésto incluye la base de datos, una línea al principio de todo script:

header('Content-type: text/html; charset=utf-8');

También en los HTML:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

Y por supuesto, que el fichero esté físicamente codificado en UTF-8, cosa que cada uno deberá hacer con el editor de código correspondiente (mi experiencia con Ultraedit en este sentido es inmejorable).

El horror comienza cuando no has hecho los deberes, y a una aplicación sencilla se le quiere empezar a meter AJAX y datos de diversas fuentes. Por defecto tu tinglado estará utilizando seguramente ISO 8859-1, la codificación del alfabeto latino, y éso es lo que va a estar esperando el navegador a no ser que le indiques lo contrario…

Mala codificación de los caracteres

Estos problemas de codificación se pueden deber a múltiples razones, sería imposible cubrirlas todas en un post, así que me centraré en las dos con las que he tenido que lidiar estos días:

  • API EXTERNA. Aquí no queda otra, Si la API no ofrece un parámetro para especificar la codificación, va a venir en UTF-8 prácticamente seguro y tocará hacer en el código, por ejemplo en PHP, un utf8_decode de lo que devuelva.
  • AJAX. La diversión con la codificación de caracteres cuando entra en juego el javascript puede no llegar a tener límite. Si, para más inri, utilizamos AJAX para comunicar con un script pongamos de PHP, entonces tenemos todos los ingredientes para la empanada de caracteres raros.

    Obviando detalles de bajo nivel como que el objeto XMLHttpRequest que se encarga de esta comunicación utiliza siempre UTF-8, o que dependiendo de si utilizas GET o POST e Internet Explorer o Firefox se usará una codificación u otra, vemos que las combinaciones pueden marear hasta la náusea, así que hay que buscar una solución que funcione independientemente de la codificación origen-destino, el navegador o el protocolo utilizado.

    Tras varios intentos, dí con una combinación que parece comerse cualquier barbaridad que se pueda poner en un formulario (una caja de texto que acepte código de programación, textos chinos o búlgaros… es un reto). El flujo sería el siguiente:

    1. Desde el javascript mandamos los datos codificados con la función encodeURIComponent (utilizar otra nos dará problemas con los caracteres & y +), por ejemplo:
      ajax.open('get','url_script.php?datos='+encodeURIComponent(datos),true);
    2. Dependiendo del lenguaje de programación que se utilice en el script que recibe los datos habrá que hacer una decodificación o no de los mismos. PHP automáticamente lo realiza para lo que recibe por GET, como en este ejemplo.
    3. Para devolver la respuesta, con PHP utilizamos rawurlencode para codificarla (esta función lo realiza de forma más estricta que urlencode). Por ejemplo:
      echo rawurlencode($respuesta);
    4. Finalmente, de vuelta a javascript, decodificamos la respuesta con decodeURIComponent, y ya tenemos una bonita cadena de caracteres lista para utilizar sin problemas de codificación. Por ejemplo:
      var respuesta = ajax.responseText;
      div.innerHTML = decodeURIComponent(respuesta);

En definitiva, hay que utilizar UTF-8, hay que dejarle al navegador muy claro que lo estamos haciendo, y tenemos que usar una serie de métodos para que en el trasiego de la información entre distintos lenguajes y scripts no se pierda la codificación.