Академический Документы
Профессиональный Документы
Культура Документы
Héctor Rivas
Por desgracia, el número de locales soportados por estas clases es limitado2 y si intentamos
formatear una fecha con un locale desconocido, obtendremos el texto formateado con el
locale por defecto del sistema.
import java.io.*;
import java.text.*;
import java.util.*;
fmt.setTimeZone(TimeZone.getDefault());
System.out.println("En galego:");
System.out.println("\u00a1Hola Mundo!");
System.out.println(fmt.format(new Date()));
}
}
Si compilamos y ejecutamos este código con un runtime sin soporte de gl_ES la salida es:
En galego:
¡Hola Mundo!
January 2, 2005 4:44:19 PM CET
Pero no todo está perdido, existe una forma de agregar nuestros propios locales de una
forma que, aun siendo poco ortodoxa, funciona correctamente y permite mantener la
independencia del código respecto al idioma.
Si analizamos el contenido de los ficheros .jar de la plataforma (jar –tvf), y en particular los
ficheros jre/lib/rt.jar y jre/lib/ext/localedata.jar , observamos que para todos los locale
soportados existen las siguientes clases:
...
sun/text/resources/LocaleElements_es_MX.class
sun/text/resources/LocaleElements_es_ES.class
sun/text/resources/LocaleElements_es_CA.class
...
sun/text/resources/DateFormatZoneData_es.class
sun/text/resources/DateFormatZoneData_et.class
sun/text/resources/DateFormatZoneData_fi.class
...
Seguramente estas son las clases que debemos añadir. Cabe preguntarse qué son estas
clases. Buceando por internet3 pronto descubrimos que ambas clases heredan de
java.util.ListResourceBundle, que son utilizadas por DateFormat para el formateo de las
fechas y que efectivamente deben existir ambas clases por cada locale formateado.
Sólo nos falta determinar los valores que deben contener estos ListResourceBundle.
Decompilar sería una opción si no lo prohibiese la licencia de SUN, pero por suerte
también resulta sencillo encontrar en internet una implementación de las mismas o,
simplemente, podemos consultar el método getContents() de dichas clases para el locale
por defecto:
import java.util.ResourceBundle;
import java.util.Locale;
import java.util.Enumeration;
System.out.println("LocaleElements:");
printResource(ResourceBundle.getBundle(
"sun.text.resources.LocaleElements",
Locale.getDefault()));
System.out.println("DateFormatZoneData:");
printResource(ResourceBundle.getBundle(
"sun.text.resources.LocaleElements",
Locale.getDefault()));
}
}
package sun.text.resources;
import java.util.ListResourceBundle;
/**
* Overrides ListResourceBundle
*/
public Object[][] getContents() {
return new Object[][] {
// locale id based on iso codes
{ "LocaleString", "gl_ES" },
(..)
{ "MonthNames",
new String[] {
"xaneiro", // january
(..)
},
{ "CollationElements", "@" }
};
}}
Una vez implementadas y compiladas, debemos agregarlas a la plataforma. El problema
ahora es que el paquete sun.text.resources es un paquete protegido, y la máquina virtual de
java no las cargará desde el classpath de usuario.
Para que las cargue, debemos construir un fichero .jar con nuestras clases y copiarlo en el
classpath del sistema, concretamente en el directorio de extensiones de Java (normalmente
$JAVA_HOME/jre/lib/ext).
Una vez instalado, ya estamos listos para probar nuestro nuevo locale simplemente
ejecutando el código anterior:
En galego:
¡Hola Mundo!
2 de xaneiro de 2005 16:46:52 CET
Tenemos ahora una máquina virtual parcheada que soporta nuestro nuevo idioma en la que
podemos emplear el API de internazionalización de Java y cualquier otro API o framework
que emplee internazionalización.
De todos modos esta solución plantea algunos problemas. Las clases LocaleElements y
DateFormatZoneData no entran dentro del API de Java, y su funcionamiento puede ser
modificado en futuras versiones de la plataforma. Además, no es posible extender los
locales a nivel de aplicación, sino que la máquina virtual debe parchearse instalando un
paquete en el directorio de extensiones, al cual no siempre tenemos acceso y además
complica la instalación y distribución de la aplicación.
La solución más elegante sería, sin duda, que el propio API de Java permitiese registrar
nuevos locale aparte de los ofrecidos por la plataforma. Mientras tanto, habrá que limitarse
a pequeños trucos como éste y a solicitar el soporte de nuestro locale a los fabricantes.
1
Todo lo comentado a continuación ha sido realizado y probado sobre Java 2 Platform
Standard Edition (J2SE) de Sun. »ir al texto
2
Podemos conocer los locale soportados por el runtime consultando la documentación
(lista de locale soportados por j2se 1.4.2) o consultando el método
Locale.getAvailableLocales(). »ir al texto