Ejemplos java y C/linux

Tutoriales

Enlaces

Licencia

Creative Commons License
Esta obra está bajo una licencia de Creative Commons.
Para reconocer la autoría debes poner el enlace http://www.chuidiang.org

Internacionalización en Java

Es posible hacer que nuestras aplicaciones java cambien fácilmente de idioma. Si hacemos el código java de la forma correcta, nuestra aplicación aparecerá en inglés si el sistema operativo está en inglés y aparecerá en español si el sistema operativo está en español. Esto es lo que se llama internacionalización en java, el conseguir que nuestra aplicación salga en el idioma adecuado.

Para conseguirlo, evidentemente no podemos poner los textos alegremente en el código. Si ponemos como etiqueta de un botón, por ejemplo

boton.setText("Abrir");

da igual el idioma del sistema operativo y da igual todo lo demás. Ese botón siempre mostrará "Abrir".

¿Qué es lo que tenemos que hacer entonces?. Debemos en primer lugar, pensar un nombre para cada una de las etiquetas, por ejemplo, para el botón anterior y dando nombres largos para no equivocarnos, podemos decir que la etiqueta del botón abrir se va a llamar "etiqueta_boton_abrir". El valor de esta etiqueta, en español, será "Abrir". En inglés, la etiqueta será la misma, pero su valor sería "Open".

Una vez que tengamos todo esto decidido, debemos meter estas parejas de nombre de etiqueta y valor de la etiqueta o bien en una clase o bien en un fichero de propiedades. Vamos a ver con calma cómo se hace cada una de estas cosas.

Fichero de propiedades con las etiquetas: fichero.properties

En primer lugar elegimos el idioma por defecto para nuestra aplicación. Supongo que lo normal es que fuera inglés, pero a mí me gusta más el español. Creamos un fichero con el nombre que queramos y extensión .properties. Yo, por ejemplo, haré un fichero Etiquetas.properties. En este fichero pondremos varias líneas, todas las que hagan falta, con "<nombre_etiqueta>=<valor_etiqueta>". En el caso de nuestro botón, el fichero podría ser así

# Contenido de Etiquetas.properties
etiqueta_boton_abrir=Abrir
etiqueta_boton_cerrar=Cerrar
etiqueta_error=Error en la aplicacion

En estos ficheros, las líneas que empiezan por # se consideran comentarios y se ignoran. Además de la etiqueta del botón abrir, hemos puesto otras dos.

Una vez hecho esto, debemos empezar a crear ficheros similares para los idiomas que queramos que nuestra aplicación muestre. Los ficheros deben llamarse igual que este, pero añadiendo _xx o bien _xx_YY donde xx son dos letras que hacen referencia al idioma e YY dos letras que hace referencia al país donde se habla idioma. Y por supuesto, esas dos letras son estándar, así que no podemos inventárnoslas sobre la marcha. De esta forma, por ejemplo, tendremos

Una pequeña cosa buena de java: no es necesario repetir todas las etiquetas en todos los ficheros. Si, por ejemplo, el sistema operativo está en español de España, java buscará las etiquetas en Etiquetas_es_ES.properties. Si no encuentra la etiqueta ahí, las buscará en Etiquetas_es.properties. Y si no la encuentra ahí, la buscará en Etiquetas.properties.

Esto quiere decir que si Etiquetas.properties está en español de España, nos podemos ahorrar los ficheros Etiquetas_es_ES.properties y Etiquetas_es.properties. Y es más, por ejemplo, para el español de Argentina bastaría con que en Etiquetas_es_AR.properties pusiéramos sólo aquellas etiquetas que en Argentina se dijeran de otra forma.

Por supuesto, si Etiquetas.properties está en español de España, tendremos que hacer un Etiquetas_en.properties en inglés, por ejemplo, de Inglaterra. Luego bastaría con poner en un Etiquetas_en_US.properties sólo aquellas etiquetas que se digan distinto en Estados Unidos a como se dirían en Inglaterra.

Clase con las etiquetas: ListResourceBundle

Si decidimos usar clases, igual que hemos hecho con los ficheros, debemos elegir un idioma por defecto para la aplicación. También tendremos que crear varias clases, con el mismo critierio de nombres que los ficheros. Es decir, el nombre del idioma por defecto puede ser el que queramos, por ejemplo Etiquetas.class, y luego deberemos crear clases Etiquetas_es_ES.class, Etiquetas_es.class, etc.

Estas clases deben construirse de una forma especial. Deben heredar de la clase ListResourceBundle y deben redefinir el método public Object[][] getContents() que es abstracto en la clase padre. El array doble de objetos contendrá como primer índice tantas posiciones como etiquetas haya. El segundo índice podrá ser 0 para obtener el nombre de la etiqueta y 1 para obtener su valor.

Dicho de otra forma, una implementación de esta clase para el español de España podría ser así

import java.util.*;

public class Etiquetas_es_ES extends ListResourceBundle
{
   public Object[][] getContents()
   {
      return contenido;
   }
   private Object[][] contenido = {
      { "etiqueta_boton_abrir", "Abrir"},
      { "etiqueta_boton_cerrar", "Cerrar"},
      { "etiqueta_error", "Error en la aplicacion"}
   };
}

Podemos poner o no la clase en un paquete. Deberíamos, además, igual que con los ficheros, hacer varias clases con los distintos idiomas.

Usar ficheros y clases desde java

Bien, suponemos que ya tenemos todo esto preparado, bien clases, bien ficheros o incluso, por qué no, una mezcla de las dos cosas o las dos a la vez.

El código correcto para poner la etiqueta a nuestro botón sería este

boton.setText (ResourceBundle.getBundle("Etiquetas").getString("etiqueta_boton_abrir"));

¿Esto qué hace exactamente?.

En primer lugar, puesto que no se lo estamos pasando como segundo parámetro, ResourceBundle.getBundle("Etiquetas") determina el idioma y país por defecto, que suele ser el del sistema operativo. En mi caso, obtendría español de España, es decir _es_ES. Al método getBundle() podríamos pasárle como segundo parámetro el Locale que nos interese. Por ejemplo, si queremos inglés de Estados Unidos en vez de el idioma por defecto, podríamos poner ResourceBundle.getBundle("Etiquetas", Locale.US).

Luego, ResourceBundle.getBundle("Etiquetas") compone "Etiquetas" con el idioma y país, para buscar una clase Etiquetas_es_ES.class que no esté en un paquete. Si hubiesemos puesto ResourceBundle.getBundle("chuidiang.ejemplos.Etiquetas"), entonces buscaría en el paquete chuidiang.ejemplos una clase Etiquetas_es_ES.class

Si no encuentra la clase, buscará un fichero Etiquetas_es_ES.properties en el directorio de ejecución de nuestro programa. Si hubiésemos puesto ResourceBundle.getBundle("chudiang.ejemplos.Etiquetas"), buscaría en el directorio actual de ejecución de nuestro programa un subdirectorio chuidiang, debajo de ese un subdirectorio ejemplos y debajo de ese un fichero Etiquetas_es_ES.properties.

Finalmente, ResouceBundle.getBundle("Etiquetas") devuelve una clase ResourceBundle con todos los nombres de etiquetas y valores de las mismas. La llamada a getString("etiqueta_boton_abrir") buscará la etiqueta de nombre "etiqueta_boton_abrir" y devolverá su valor "Abrir". Si no la encuentra, probará con Etiquetas_es y si no hay suerte, con Etiquetas.

Si nuestro idioma por defecto hubiera sido inglés de Estados Unidos, la misma llamada habría buscado la clase o fichero Etiquetas_en_US y el mismo getString("etiqueta_boton_abrir") habría devuelto "Open" o lo que quiera que hubiésemos puesto en ese fichero o clase.

Insisto en algunos detalles

Aunque está más o menos contado, es importante la hubicación de los ficheros y de las clases. Si buscamos getBundle("chudiang.ejemplos.Etiquetas"), las clases Etiquetas deben tener

package chuidiang.ejemplos;
public class Etiquetas_es_ES extends ListResourceBundle {
...
}

y si son ficheros, deben estar en el directorio de ejecución en los subdirectorios adecuados

./aplicacion.jar
./chuidiang/ejemplos/Etiquetas.properties
./chuidiang/ejemplos/Etiquetas_es.properties
./chuidiang/ejemplos/...

y otra tontería más que conviene saber. Los IDEs serios, como eclipse o netbeans, ayudan a hacer estas cosas. Si escribimos la etiqueta de mala manera, como dijimos al principio del artículo, y luego le damos en el IDE a "internacionalizar", el IDE nos ayudará a buscar todas esas etiquetas, dará automáticamente nombres a las etiquetas -que luego podremos cambiar- y nos cambiará el código de la llamada por el mostrado aquí de ResourceBundle.getBundle(). El IDE, además, creará el fichero .properties para nuestro idioma.

Estadísticas y comentarios

Numero de visitas desde el 4 Feb 2007: