Construir un ResourceBundle con Ficheros de Propiedades

Esta sección pasea a través de un programa de ejemplo llamado PropertiesDemo. El código fuente del programa está en PropertiesDemo.java. También podrías encontrar útil examinar la salida generada por este programa.

1. Crear el Fichero de Propiedades por defecto

Un fichero de propiedades es un sencillo fichero de texto. Los ficheros de propiedades se pueden crear y mantener con un sencillo editor de texto.

Siempre se debe crear un fichero de propiedades por defecto. El nombre de este fichero empieza con el nombre base del ResourceBundle y termina con el sufijo .properties. En el programa PropertiesDemo, el nombre base es LabelsBundle. Por lo tanto, el fichero de propiedades por defecto se llama LabelsBundle.properties. Este fichero contiene las siguientes líneas:

# This is the default LabelsBundle.properties file
s1 = computer
s2 = disk
s3 = monitor
s4 = keyboard
En este fichero se puede observar que las líneas de comentarios empiezan con una almohadilla (#). Las otras líneas contienen parejas de clave-valor. Las claves están en el lado izquierdo del signo igual y los valores en el lado derecho. Por ejemplo, "s2" es la clave que corresponde con el valor "disk". Esta clave es arbitraria. Podríamos haberla llamado algo como "msg5" o "diskID.", por ejemplo. Sin embargo, una vez definida, la clave no debería cambiar porque es referenciada dentro del código fuente. De echo, cuando los localizadores crean un nuevo fichero de propiedades para acomodar idiomas adicionales, traducirán los valores a diferentes idiomas, pero no las claves.

2. Crear Ficheros de Propiedades Adiciones si son Necearios

Para soportar una nueva Locale, los localizadores crearán un nuevo fichero de propiedades que contenga los valores traducidos. No se necesita cambiar el código fuente, ya que el programa referencia las claves, no los valores.

Por ejemplo, para añadir soporte para el idioma Alemán, los localizadores tendrán que traducir los valores de LabelsBundle.properties y situarlos en un fichero llamado LabelsBundle_de_DE.properties. Observa que el nombre de este fichero, al igual que el fichero por defecto, empieza con el nombre base LabelsBundle y termina con el sufijo .properties. Sin embargo, como el fichero se ha creado para una localidad específica, el nombre base es seguido por el código del idioma (de) y el código del país (DE). El contenido de LabelsBundle_de_DE.properties es éste:

# This is the LabelsBundle_de_DE.properties file
s1 = Computer
s2 = Platte
s3 = Monitor
s4 = Tastatur
Hemos lanzado tres ficheros de propiedades con el programa de ejemplo PropertiesDemo:
LabelsBundle.properties
LabelsBundle_de_DE.properties
LabelsBundle_fr.properties

3. Especificar la Localidad

En el programa PropertiesDemo hemos creado los objetos Locale de esta forma:
Locale[] supportedLocales = {
    new Locale("fr","FR"),
    new Locale("de","DE"),
    new Locale("en","US")

Locale currentLocale = new Locale("fr","FR");
Para cada uno de estos objetos hemos específicado un código de idioma y un código de país. Esto códigos corresponden con los ficheros de propiedades creados en los pasos anteriores. Por ejemplo, el Locale creado con los códigos de y DE corresponde con el fichero LabelsBundle_de_DE.properties.

4. Crear el ResourceBundle

Este es el paso que muestra como se relacionan, la localidad, los ficheros de propiedades y el ResourceBundle. Para crear el ResourceBundle, llamamos al método getBundle, especificando el nombre base y la localidad:
ResourceBundle labels =
   ResourceBundle.getBundle("LabelsBundle",currentLocale);
El método getBundle primero busca un fichero de clase que corresponda con el nombre base. Si no puede encontrar el fichero de clase, comprueba los ficheros de propiedades. En el programa PropertiesDemo, hemos constituido el ResourceBundle con ficheros de propiedades en vez de ficheros de clases. Cuando el método getBundle localiza el fichero de propiedades correcto, devuelve un objeto PropertyResourceBundle cargado con las parejas clave-valor del fichero de propiedades.

Si no existe un fichero de propiedades para la localidad específicada, getBundle selecciona el fichero de propiedades con la correspondencia más cercana. La siguiente tabla identifica los ficheros de propiedades que buscará el programa PropertiesDemo para cada localidad:
Parámetros LocaleFichero de PropiedadesExplicación
de   DE
LabelsBundle_de_DE.propertiesCorrespondencia Exacta.
fr   FR
LabelsBundle_fr.propertiesLabelsBundle_fr_FR.properties no existe, pero es la correspondencia más cercana.
en   US
LabelsBundle.propertiesSe selecciona el fichero por defecto porque los parámetros de la localidad no corresponden.

En lugar de llamar a getBundle, podríamos haber creado el objeto PropertyResourceBundle llamando a su constructor, que acepta un InputStream como argumento. Para crear el InputStream debemos específicar el nombre exacto del fichero de propiedades en la llamada al constructor de FileInputStream. Crear el PropertyResourceBundle llamando al método getBundle es más flexible, porque buscará los ficheros de propiedades con la correspondencia más cercana a la localidad específicada.

5. Obtener el Texto Localizado

Para recuperar los valores traducidos desde el ResourceBundle, llamamos al método getString:
String value  = labels.getString(key);
El String devuelto por getString corresponde con la clave que hemos especificado. El String está en el idioma apropiado, proporcionado por un fichero de propiedades existente para la localidad específicada. Como las claves no cambian, los localizadores añaden ficheros de propiedades adicionales posteriormente,. Nuestra llamada a getString no necesita cambiar.

6. Iterar a través de todas las Claves

Si queremos recuperar los valores para todas las claves de un ResourceBundle, necesitamos llamar al método getKeys. Este método devuelve una Enumeration con todas las claves de un ResourceBundle. Se puede iterar a través de la Enumeration y recuperar cada valor con el método getString. Las siguientes líneas de código del programa PropertiesDemo, muestran como se hace esto:
ResourceBundle labels =
   ResourceBundle.getBundle("LabelsBundle",currentLocale);

Enumeration bundleKeys = labels.getKeys();

while (bundleKeys.hasMoreElements()) {
   String key = (String)bundleKeys.nextElement();
   String value  = labels.getString(key);
   System.out.println("key = " + key + ", " +
     "value = " + value);
}

Ozito