sábado, 24 de diciembre de 2011

¿Recuerdan una entrada titulada "Migrando una página web ASP.NET de Windows a Linux"? Esta entrada es como una continuación de aquella así que si esta interesado en el tema tal vez prefiera leer esa primero a modo de antecedentes comenzare por relatar que tuve que migrar varias páginas web hechas en ASP.NET en Windows con NetFramework y servidas mediante IIS hacia servidores Linux con Mono y servirlas mediante Apache + Mod mono.


En el principio del proyecto original hace años se intento pero Apache pero en ese entonces no podía servir páginas ASP.NET por si mismo (aun no puede) y no existía algún complemento como Mod mono y aunque Mono tenia su propio servidor llamado XSP este no era lo suficientemente estable para soportar la carga de trabajo de una empresa como esta, de hecho aun no lo es todavia, y por eso ahora usamos Mod Mono.


Usando SharpDevelop en lugar de Visual Studio para probar las aplicaciones con Mono y XSP previamente a probar en los servidores Linux se pudo afinar las instrucciones y entonces si pasar a ambientes más reales donde solo que hubo que ajustar algunas características de seguridad que resultaron más altas que en Windows y entonces vino el problema. Parecía no haber poder humano que hiciera que los caracteres especiales, ñ y letras acentuadas se vieran correctamente.


La base de datos. Muchos trabajamos con bases de datos PostGreSQL y estas suelen ser creadas por default (desconozco si en algunas versiones pone alguna codificación por default más avanzada) con codificación (encoding) SQL_ASCII, que según la documentación de PostGreSQL con SQL_ASCII el servidor interpretara los valores 0 al 127 del estándar ASCII, así que más que una declaración de que juego de caracteres usar es una orden de ignorar la codificación lo que puede causar problemas cuando se usen caracteres no ASCII como letras acentuadas, la ñ o símbolos. Debido a esto de ser posible hay que tener cuidado de definir desde el principio la base de datos con un juego de caracteres, de preferencia UTF8, que es UNICODE porque es apto para todos los idiomas, y esto es importante independientemente del tipo de tecnología de su base de datos que ustedes utilicen.


Seguramente su manejador de base de datos tendrá alguna opción para consultar el juego de caracteres de su base de datos pero si no lo encuentran, en PostGreSQL pueden ver la codificación de su base de datos con la siguiente instrucción:

SELECT encoding FROM pg_database where datname='[nombre de la base de datos]';

Esto arrojara un número que puede traducirse así, por poner ejemplos de encodings comunes, aunque esta tabla es solo una muestra muy limitada.

0SQL_ASCII
6UTF8 (UNICODE)
8LATIN1
16LATIN9 (ISO 8859-15)

La codificación de la base de datos también puede hacerse a base de datos ya creadas actualizando (Update) el campo “encoding” de “pg_database” que consultamos con la instrucción anterior pero esto no afecta de inmediato y “automagicamente” a toda la información previamente guardada en las tablas de la base de datos, eso lo tendremos que ajustar por nuestros propios medios. Además de que las conexiones abiertas antes del cambio no se verán afectadas, para que tome efecto deberán ser cerradas y volver a establecer la conexión para que se conecten usando el nuevo juego de caracteres, y dependiendo del tipo de cambio de encoding en las consultas podría haber problemas al tratar de leer caracteres que no existen en un juegos de caracteres pero si en el otro o que en ambos encodings un mismo código represente caracteres diferentes y eso altere nuestra información; son cosas a tomar en cuenta.


Lo mejor, de ser posible es empezar la base de datos con el encoding adecuado y grabarle los datos desde un respaldo, si se pasa de SQL_ASCII a un encoding mayor como UTF8, Latin1 o Latin9 no debería haber problemas... en teoría, en la practica ya sabemos como son las cosas.

La codificación de la base de datos

ODBC y la conexión a la base de datos. Aunque los datos estén correctamente guardados en la base de datos estos no vienen solos a nuestras aplicaciones si no que necesitamos conectarnos y la mayoría de las veces lo hacemos usando un ODBC. No creo que halla necesidad de explicar eso pero si de recordar o advertir que hay ODBC ANSI y los hay UNICODE y tengo experiencias de que si consultas una base de datos con caracteres UNICODE usando una conexión ANSI los caracteres especiales no llegan bien sino que llegan símbolos de interrogación (?) y como ya vienen así para nuestras aplicaciones será imposible distinguir que símbolo era originalmente y eso será un gran problema. Los ODBC ANSI funcionan de maravilla con bases de datos SQL_ASCII pero si van a usar una con UNICODE asegúrense de que el ODBC valla a la par.


Además recuerden o sepan que en la cadena de conexión podemos dar indicaciones sobre la codificación de caracteres a utilizar al conectarnos a la base de datos. Así podemos indicarle si queremos que se conecte usando SQL_ASCII, Latin1, UTF8 o lo que sea que nuestra base de datos soporte.

DRIVER={[ODBC]};Server=[IP];Encoding=[Encoding];DATABASE=[DB];UID=[Usuario];PWD=[contraseña];

* Nota extra para desarrolladores en .NET: Ver tutorial para conectarse a bases de datos PostGreSQL sin utilizar ODBC.


Consultando la base de datos. Si no podemos controlar la codificación de caracteres en la base de datos o solo vamos a hacer unos pocos querys ocasionales que no ameriten tanto esfuerzo pero aun así necesitemos el texto consultado a la base de datos en un encoding especifico podemos recurrir a indicarlo dentro de la instrucción de consulta, por ejemplo con la función convert de SQL de la siguiente manera:

SELECT convert( 'texto', 'SQL_ASCII', 'UTF8')

El código anterior convierte el primer parámetro, 'texto' de su codificación original a UTF8.


La codificación de caracteres de las páginas web. Los navegadores web traducen el código de la página en algo visible al usuario y el texto también debe ser interpretado y para eso también manejan los estándares de codificación de caracteres que ya mencionamos antes como podemos ver en la imagen a continuación.


La mayoría de los navegadores te dejan elegir un juego de caracteres por default o ellos mismos lo ponen pero también tienen la capacidad de detectar el juego de caracteres usado por la página para mostrar correctamente el contenido ¿Y cómo es que las páginas le dicen al navegador cual es el estándar que deben usar? Usando una cabecera especial en su código fuente.

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

Aquí estamos indicando que el texto en la página es UTF8 y el browser así lo interpretará así que tómenlo en cuenta.


* Nota extra para desarrolladores en .NET: En el archivo Web.config de nuestras aplicaciones web podemos indicar explicitamente más detalles sobre el idioma de nuestra página agregando las siguientes configuraciones que ajustan el contenido de la página al formato regional del idioma y país además de en los caracteres especiales también en cosas como las fechas, los signos y formatos de moneda y cosas así.

<globalization
requestEncoding="utf-8"
responseEncoding="utf-8"
fileEncoding="utf-8"
uiCulture="es-MX"
culture="es-MX"
/>

Con lo anterior debería de bastar pero si además desean indicarle al compilador cual es el encoding que debe reconocer cuando genere su dll o ejecutable pueden hacerlo así, aunque en lo personal a mi me parece ya exagerar un poquito pero no esta demás eliminar los posibles cabos sueltos ¿verdad?

<compilation defaultLanguage="c#" debug="true">
<compilers>
<compiler language="cs;csharp"
extension=".cs"
type="Microsoft.CSharp.CSharpCodeProvider,System"
compilerOptions="/codepage:utf8" />
</compilers>
</compilation>

Y hablando de no dejar cabos sueltos, queda un ultimo punto que comentar que si bien no es exactamente el mismo tema de conservar información compatible entre sistemas y plataformas si puede ser un complemento para la parte visual de nuestras aplicaciones web.


HTML. El HTML no es un lenguaje de programación si no uno más limitado para la estructuración y formato de las páginas web donde indicamos donde va cada elemento en pantalla y como se debe de ver, y tiene sus limitaciones. Para HTML la ñ o la á no existen pero si en el código de tu página...

Para ver esto en pantalla...debes poner
á&aacute;
é&eacute;
í&iacute;
ó&oacute;
ú&uacute;
Á&Aacute;
É&Eacute;
Í&Iacute;
Ó&Oacute;
Ú&Uacute;
ñ&ntilde;
Ñ&Ntilde;
ü&uuml;
Ü&Uuml;

Claro, los caracteres arriba mencionados solo son unos pocos, y cambiarlos todos manualmente es tedioso pero podríamos hacer funciones para automatizar el cambio o mejor aún, aprovechar funciones ya incluidas en los lenguajes de programación, por ejemplo en C# tenemos la función HtmlEncode que reemplaza en una cadena de caracteres los caracteres que tienen algún equivalente en código HTML de modo que la cadena resultante donde se han reemplazado sea aceptada y bien interpretada por los navegadores, hasta cambia los saltos de linea por su código HTML.

Server.HtmlEncode(string);

En caso de usar PHP también tenemos un par de funciones que pueden hacer un trabajo similar. htmlspecialchars(string) y htmlentities(string) son algo "parecido pero diferente", pues estas funciones convierten ciertos caracteres que tienen un significado especial en HTML y deben ser representados por entidades HTML si se desea preservar su significado para que se muestren así en pantalla en lugar de ser tomados por código fuente, descuadren la página y no se vean. Estas funciones devuelven una cadena de caracteres con algunas de estas conversiones realizadas. htmlspecialchars solo afecta a los caracteres más útiles para la programación web.


Las traducciones realizadas son:


  • '&' (ampersand) se convierte en '&amp;'

  • '"' (comillas dobles) se convierten en '&quot;'

  • "'" (comilla simple) se convierte en '''

  • '<' (menor que) se convierte en '&lt;'

  • '>' (mayor que) se convierte en '&gt;'

En cambio se usa htmlentities si se requieren traducir todas las entidades de caracteres HTML. Ambas funciones son útiles para prevenir que texto suministrado por el usuario, un archivo o desde la base de datos contenga código HTML.


¿Algo más? Por ultimo recordarles que si su página además usa JavaScript para mostrar algo en pantalla consideren que también maneja códigos para representar los caracteres especiales y que no son iguales que los de HTML.

Para ver esto en pantalla...debes poner
áá
éé
íí
óó
úú
ññ

Para que lo tomen en cuenta si de repente en algún control dinámico les aparece un carácter extraño.


Y bueno, con eso finalizamos de revisar esta serie de puntos a considerar al desarrollar una página web lo más universal posible.

0 comentarios:

Publicar un comentario

Por favor trata de escribir bien, no te pido que no te falte ni un acento pero por favor evita escribir como metroflogger o facebookero. Este blog es un sitio decente. Gracias.

Subscribe to RSS Feed Follow me on Twitter!