Internacionalización y localización en Java

¿Sabes cómo funciona la internacionalización y localización en Java? O, antes de continuar, ¿sabes qué son la internacionalización y localización en Java?

More...

Tanto la internacionalización y la localización se utiliza para mostrar tus programas en varios idiomas. Pero, antes de continuar, te aclararé qué es qué y, como bonus, te voy a explicar cómo hacerlo en IntelliJ.

Este, por cierto, es uno de los objetivos del examen OCP de Java.

Internacionalización y localización en Java

¿Qué son la internacionalización y la localización?

  • La internacionalización es el paso anterior a la localización. Consiste en utilizar en tu código no el texto literal que aparece en la interfaz, sino referencias a dicho texto.

Es decir, que tomas todo el texto que aparece en tu código (interfaz, menús, pop-ups...) y lo unes en un único documento. A cada cadena de texto le asignas una referencia y, el código, utilizas esta referencia en lugar del texto literal.

Y esto, ¿para qué?

Para pasar al siguiente paso:

  • La localización consiste en traducir esa lista de cadenas de texto y guardarlas en documentos en cuyo nombre se hace referencia al idioma e, incluso, a la región (en_US para el inglés de EEUU, en_UK para el inglés británico).

Así, partiendo del idioma del sistema operativo donde se ejecute tu programa, las referencias existentes en el código apuntarán a una lista de cadenas de texto u otra. O a una predeterminada, si no existe la traducción al idioma necesario.

Esto es algo que se utiliza continuamente en las apps de smartphones, ya que están disponibles para todo el mundo.

Existen dos maneras de realizar la internacionalización y la localización en Java: mediante archivos con la extensión .properties, o mediante una clase que extiende ListResourceBundle.

Internacionalización y localización en Java con archivos .properties

Estructura del archivo .properties

Los archivos con la extensión .properties no son más que archivos de texto que contienen la lista de cadenas de texto que vamos a utilizar en nuestro programa.

Las reglas para componerlos son pocas y sencillas.

Sintaxis del archivo .properties

  • La estructura es "referencia=cadena de texto". Entre ambos puede haber un espacio en blanco, dos puntos (:) o un signo de igual (=). Cada par referencia-elemento ocupa una nueva línea.
  • Las cadenas de texto solo pueden ser eso, Strings, nada más. Si colocas un valor numérico, igual se guarda como una String.
  • No utilices espacios en blanco al inicio (a excepción del espacio que separa la cadena de texto de su referencia, si lo utilizas) ni al final de la cadena de texto, ya que se eliminan.
  • Puedes utilizar símbolos como \t o \n.
  • Si una cadena de texto es muy larga, puedes dividirla en dos líneas utilizando la barra inclinada (\). No obstante, ten en cuenta que ese salto de línea no aparecerá en el programa. Sirve para hacer el documento más fácil de leer, sin líneas largas.
  • Los comentario comienzan por ! o #.

Cada uno de los textos de los botones contiene un tabulado y un símbolo.

Nombre del archivo .properties

Como ves, el archivo se llama Interfaz_es. Es decir, se utilizará cuando el idioma del sistema sea español, sea cual sea la región. Si lo hubiese llamado es_ES, se utilizaría solo para español de España. En ese caso, si el idioma del sistema fuera es_MX (español de México) obtendrías una bonita java.util.MissingResourceException.

Si no especificas la región en el nombre del archivo, Java lo utilizará si no encuentra un archivo con un nombre más específico. Es decir, como no existe Interfaz_es_MX, deja caer la región y utiliza Interfaz_es, que sí existe.

Un archivo .properties cuyo nombre no contenga ninguna referencia a idioma (es decir, que se llamase interfaz.properties) actuaría como idioma predeterminado.

Cómo utilizar las referencias recogidas en el .properties

Solo necesitas una línea de código:

Cómo hacerlo en IntelliJ

Con IntelliJ hay un par de pasos más que tienes que seguir para internacionalizar y localizar:

  • En primer lugar, especificar dónde se encuentran los archivos .properties.
  • En segundo lugar, establecer el texto de los elementos de la interfaz.

El primer paso lo realizas en Main.java de tu proyecto, dentro del método start(Stage primaryStage):

Para el segundo paso tienes dos opciones.

En primer lugar, puedes especificar la referencia en el código fxml. Si es un elemento que no vas a modificar de manera dinámica, como una etiqueta, quizá esta sea la opción más sencilla:

text="%name"

Si prefieres hacerlo en Java, puedes utilizar el método setText, setTitle o similar desde dentro del método initialize() en el Controller

Internacionalización y localización en Java con una clase

La ventaja de utilizar una clase es que puedes modificar la lista de cadenas de texto de manera dinámica y, además, puedes guardar cualquier Objeto, no solo Strings.

¿Qué tiene de especial esta clase?

  • El nombre de la clase ha de seguir la misma lógica que la del archivo .propertiesNombre_<idioma>_<REGIÓN> 
  • Extiende ListResourceBundle

Hay un método de ListResourceBundle que tu clase ha de implementar: Object[][] getContents().

Como el array[][] contiene objetos de tipo Object, para obtenerlos utiliza el método getObject() y un cast al tipo concreto:

Por último, ten en cuenta que, de haber empate (es decir, un properties y una clase que contienen la misma referencia), la clase tiene preferencia. Además, puedes tener unas referencias en un properties y otras en una clase; no es imprescindible que todas las referencias estén juntas. Si por idioma o región están disponibles, serán utilizadas de ser necesario.