Ya sé que esto no tiene que ver específicamente con linux, puesto que PHP es un lenguaje de programación multiplataforma, pero si es uno de los más usados en entornos linux para desarrollos web (evidentemente también hay otros como Perl, Python, Java, etc…). Por eso y por los problemas que pueden surgir con la codificación e internacionalización de caracteres es que creo que éste es un tema delicado.

Últimamente casi todas las distribuciones (mandriva 2007, ubuntu feisty, opensuse, …) funcionan enteramente de manera nativa con sistema utf-8 para evitar los típicos problemas con los “caracteres especiales”, o lo que los americanos/ingleses consideran que es especial simplemente porque no corresponde con su alfabeto. Muchas veces esos caracteres se pueden evitar, sobre todo en idiomas como el castellano o cualquier otro que use el mismo alfabeto, simplemente no incluyendo acentos, eñes, etc… pero otras veces es más complicado, no siempre se puede escribir según qué evitando todo eso. Y es peor en otros idiomas que usan distintos alfabetos, estos son los que promueven el uso del alfabeto utf-8 que es mucho más lógico.

El problema surge de la codificación interna que se hace de los caracteres: en el estándar ASCII el juego de caracteres es de 128 (esto incluye todo el alfabeto latino básico en minúsculas y mayúsculas, signos de puntuación, números, etc… pero no acentos, eñes, ç, etc…) y por tanto se pueden usar únicamente 7 bits para representar cualquier símbol ode la tabla; el ASCII extendido llega a 256 y contiene (dependiendo del código de página) los caracteres especiales de los alfabetos latinos de otros idiomas, y esto se guarda en 8 bits lo cual es comodísimo para manejar el texto y hacer cálculos sobre cadenas usando expresiones regulares o funciones sencillas. ¿¿¿Y que pasa con el resto??? ¿¿¿Debemos cambiar continuamente de página de códigos cada vez que nos aparezca un texto de otro sitio???

La solución la aportaron los desarrolladores de utf-8: codificación multibyte!! Esto es, una extensión del ascii, de modo que sea compatible con lo básico y para los caracteres extra se usan dos bytes pudiendo así guardar hasta 65535 caracteres diferentes. ¿¿¿Porqué no 65536 que es lo que permiten 16 bits??? Porque hace falta reservar un carácter que permita marcar que extendemos a 16 bits. También hay soluciones de tamaño fijo para los sistemas en que es habitual trabajar con más de 256 símbolos, estos no reservan nada y todos los caracteres representados ocupan 2 ó 3 bytes.

Todo esto no sería un problema si trabajasemos únicamente en nuestro ordenador de casita donde todo puede estar perfectamente sincronizado para funcionar siempre con el mismo juego de caracteres. Pero cuando desde PHP (o cualquier otro lenguaje) accedemos a una BDD o a un recurso remoto en otra máquina nos encontramos con el problema de no tenerlo todo en el mismo juego de caracteres, aquí es donde entran las herramientas de conversión, ya que PHP nativamente (al menos por ahora) no funciona en utf8 aunque sí es capaz de manejar los datos.

Aunque mejor de lo que lo he explicado yo, y con buenos ejemplos, lo explica ésta página que está en inglés pero que es muy completita.