Google Analytics

sábado, 9 de octubre de 2010

La maldita codificación de caracteres

Esta semana he estado trabajando en un proyecto y me vino a la cabeza este artículo de Joel Spolsky sobre codificación de caracteres, porque nuestra aplicación (que por suerte está en fase de desarrollo) mostraba serios problemas de codificación en los diferentes navegadores con los que probábamos.

Vamos a ver, todos nuestros ficheros estaban en UTF-8 y los ficheros JSP tenían su correspondiente encabezado con la etiqueta meta indicando que la codificación es efectivamente UTF-8, ¿por qué razón el navegador detecta que están en ISO-8859-1?

Después de estar un rato buscando y leyendo información al respecto, he encontrado este interesante filtro creado por la gente de Spring que permite forzar la codificación de caracteres en el descriptor de la aplicación (web.xml).


   <filter>
      <filter-name>encodingFilter</filter-name>
      <filter-class>
         org.springframework.web.filter.CharacterEncodingFilter
      </filter-class>
      <init-param>
         <param-name>encoding</param-name>
         <param-value>UTF-8</param-value>
      </init-param>
      <init-param>
         <param-name>forceEncoding</param-name>
         <param-value>true</param-value>
      </init-param>
   </filter>

   <filter-mapping>
      <filter-name>encodingFilter</filter-name>
      <url-pattern>*</url-pattern>
   </filter-mapping>

Al introducir esta modificación en la aplicación, el navegador ya detecta que las páginas están en codificación UTF-8 ... !problema resuelto! ... pues no, en realidad ahora estamos peor que antes, no se ve bien en UTF-8 y se ve aún peor en ISO-8859-1. ¿Qué está ocurriendo aquí? A mi compañero Pablo se le ocurre abrir los fichero en un editor diferente al IDE que estamos utilizando, IntelliJ IDEA, y nos sorprende ver que la codificación es ... ANSI as UTF-8?!?!?! por lo que cambiamos a UTF-8 y volvemos a cargar la página, ahora todo se ve correctamente. Si a ti también te ha pasado esto seguro que te has quedado con la misma cara de incógnita que Pablo y yo, pero bueno ya tenemos la solución, y decidimos dejar el filtro encodingFilter porque nos asegura que aunque se nos olvide utilizar el tag meta con la información de codificación de las páginas, la aplicación funcionará bien.

Un rato más tarde estamos realizando la tarea de internacionalización de la aplicación, cambiando los literales por las etiquetas de los messages.properties correspondientes (los ficheros son cargados por el message source de Spring, ya que estamos usando Spring MVC) y cuando probamos la aplicación, resulta que la codificación es errónea de nuevo. Hoy no es nuestro día, pero el error debe estar en los ficheros .properties para la internacionalización, pues no, están perfectamente codificados y el resto no se ha cambiado. Aquí hay algo que no hemos visto o alguien no nos ha contado, de nuevo a googlear para ver cual es el problema y encontramos este fantástico artículo, sencillo y directo al grano. Pues claro ... si Java carga los .properties como ISO-8859-1 aunque el resto sea UTF-8 tenemos un problema, pero aquí llega de nuevo Spring a nuestro rescate y basta con cambiar ResourceBundleMessageSource por ReloadableResourceBundleMessageSource en nuestro applicationContext.xml o el fichero que se haya utilizado en cada caso concreto, y todo funciona de nuevo.


   <bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource">
      <property name="basename" value="classpath:messages">
      <property name="defaultEncoding" value="UTF-8">
   </bean>

Cual es la moraleja de hoy, pues primero desquitarme con IntelliJ IDEA porque nos ha tenido un rato más perdidos que un pulpo en un garaje, y segundo recordar a todo aquel que no haya leído el artículo del señor Spolsky que lo haga :-) Querido Joel ... nosotros ya hemos resuelto nuestros problemas de codificación, no nos ponga en su lista negra :-P

7 comentarios:

Sergio dijo...

Yo pensaba que estás locuras en la codificación de caracteres era solo de .NET. Mira que tardé en darme cuenta que el Encoding.UTF8 no servía para nada y que la única solución es usar Encoding.Auto, y que sea .NET el que decida como interpretar el "Stream". Veo que en Java ocurre lo mismo, así que, mal de muchos, consuelo de tontos.

Yeray Darias Camacho dijo...

Pues sí, esto es propio de todos los lenguajes y entornos de desarrollo en realidad. Es más el autor del artículo al que hago referencia (Joel Spolsky) trabajó durante muchísimo tiempo en Microsoft (o lo que en USA es mucho tiempo :-)

Fran Serrano dijo...

Hola Yeray, ante todo gracias por tu artículo. Muy bueno.
El caso es que nosotros tenemos un problema no descrito pero del mismo tipo con el tema de los encodings. Tenemos aplicado el filtro para encodings de Spring y todo funciona perfecto en los submit y en la recuperacion dedes base de datos.
Resulta que en el metodo "setupForm" de un formulario, usando Spring MVC, intentamos poner como valor por defecto en el campo del pais "España", con la sorpresa de que cuando se carga el formulario nos aparece "Espa√±a". Ya no se por donde buscar.
A ver si tuvieras una idea de por donde tirar.
Gracias de antemano.
Saludos.

Fran Serrano dijo...

Ya lo he solucionado por fin. El error estaba en el encoding de compilacion del proyecto. Si no se indica nada Maven lo compila con el encoding base del sistema, así que especificandole a mano el encoding a usar (UTF-8) en el plugin "maven.compiler" se ha solucionado todo.
Gracias en cualquier caso y espero que le sirva a alguien mas.

Yeray Darias Camacho dijo...

Buenas Fran, muchas gracias por leer la entrada y siento mucho no haber llegado a tiempo para responderte, de todas maneras no tenía claro cual podía ser el problema.

La verdad es que no habría pensado en Maven (estaba pensando más bien la codificación de los ficheros fuentes o similar) aunque cierto es que nosotros también probamos por ese lado en nuestro caso aunque sin efecto alguno, porque como has podido leer nosotros teníamos otro problema diferente.

De todas maneras muchas gracias por la aportación que espero que sirva a alguien.

Yeray Darias Camacho dijo...

Buenas Fran, muchas gracias por leer la entrada y siento mucho no haber llegado a tiempo para responderte, de todas maneras no tenía claro cual podía ser el problema.

La verdad es que no habría pensado en Maven (estaba pensando más bien la codificación de los ficheros fuentes o similar) aunque cierto es que nosotros también probamos por ese lado en nuestro caso aunque sin efecto alguno, porque como has podido leer nosotros teníamos otro problema diferente.

De todas maneras muchas gracias por la aportación que espero que sirva a alguien.

Yeray Darias Camacho dijo...

Pues sí, esto es propio de todos los lenguajes y entornos de desarrollo en realidad. Es más el autor del artículo al que hago referencia (Joel Spolsky) trabajó durante muchísimo tiempo en Microsoft (o lo que en USA es mucho tiempo :-)