Internacionalization es un tema que tiene que estar presente en la cabeza de todos los desarrolladores de esta era tan globalizada. Por suerte Java nos da una API que es sumamente rápida de implementar y fácil de entender. En este tutorial corto pero efectivo vamos a ir paso a paso de como internacionalizar tu aplicación para poder ser vista en varios idiomas.

Vamos a plantear un escenario, una aplicación desktop donde el usuario elige el idioma que quiere durante la instalación. Ahora pensemos que nos llega el valor, lo que vamos a hacer primero que nada es setear el Locale object para que Java I18N haga el resto del trabajo.

String country = "AR";
String language = "es";

Ya tenemos el país (Argentina) y el lenguage (Español), ahora vamos al código de la implentación.

Vamos a saber que hay 2 tipos de implemetación para estos casos, files de traducción tipo Java o files tipo Properties. En mi caso prefiero los Java ya que son más rápidos (es un Map de key/values) y considero que cambiar un archivo y recompilarlo forma parte del mismo software lo cual sería el mismo update necesario que actualizar un properties file.

ResourceBundles son las clases que vamos a utilizar para la traducción, así se compone el mío en espanol:

import java.util.ListResourceBundle;
public class MyResourceBundle_es_AR extends ListResourceBundle {
  static Object[][] contents = {
    {"label.name", "Nombre"},
    {"label.phone", "Teléfono"},
  }
  protected Object[][] getContents() {
    return contents;
  }

Cabe destacar que es súper importante la nomenclatura de los archivos java. Como es esto ? bueno, sencillo, si tu archivo es de traducción para el espanol este se tiene que llamar MyResource_es y si es específico para Argentina MyResource_es_AR. En cambio si hay terminos para España, podemos nombrarlo MyResource_es_ES. Java busca los _language_COUNTRY en el final de los archivos para seleccionarlos.

Tu aplicación va a terminar con varios archivos de traducción como podemos ver acá:

MyResourceBundle_es.java // no importa el pais, si el idioma
MyResourceBundle_es_AR.java // si el locale fue seteado como es AR, este es el archivo seleccionado
MyResourceBundle_en.java // la traduccion al ingles.
MyResourceBundle_en_UK.java // implemento algunos terminos british.

Y ahora otra en en inglés.

import java.util.ListResourceBundle;
public class MyResourceBundle_en extends ListResourceBundle {
  static Object[][] contents = {
    {"label.name", "Name"},
    {"label.phone", "Phone"},
  }
  protected Object[][] getContents() {
    return contents;
  }

Ahora vamos a ver de que manera enlazamos lo que el usuario ve a la traducción, vamos a hacer un frame y mostremos los labels segun el idioma.

public class MyFrame() extends JFrame {
  public MyFrame() {
    JLabel nameLabel = new JLabel();
    nameLabel.setText(this.getResourceBundle().getString("label.name"));
    JLabel phoneLabel = new JLabel();
    phoneLabel.setText(this.getResourceBundle().getString("label.phone"));
    this.setLayout(new FlowLayout());
    this.add(nameLabel);
    this.add(phoneLabel);
    this.setSize(300, 100);
    this.pack();
    this.setVisible(true);
  }

  private ResourceBundle getResourceBundle() {
    if (this.resourceBundle != null) {
      String country = "AR";  // a setear por el usuario
      String language = "es";  // a setear por el usuario
      this.resourceBundle = ResourceBundle.getBundle("MyResourceBundle", new Locale(language, country));
    }
    return this.resourceBundle;
  }
}

De ésta manera segun el Locale que hayamos seteado vamos a ver la traducción correspondiente. Es importante destacar la instanciación del resource bundle.

ResourceBundle.getBundle("MyResourceBundle", new Locale(language, country));

Cuando pasamos el nombre de la clase al factory no le pasamos el nombre completo de la clase (MyResourceBundle_es_AR), sino solo el prefix (MyResourceBundle). Por que ? porque java decide que archivo seleccionar según el Locale que se haya pasado como parámetro.

Todo éste código debería ser suficiente para que comiencen a darse una idea de I18N. Espero les sirva.

Categories: java

Rodrigo Asensio

Apasionado por la tecnología

6 Comments

Pepe · July 10, 2009 at 7:37 pm

Rodrigo una pregunta no entiendo eso que pusiste de de setear el Locale object?? Copie tu codigo y no me anda, obviamente no hice eso de setera el Locale Object. La aplicación detecta solo el idioma o uno le tiene que especificar con un botón por ejemplo?. Saludos

Leandro · July 13, 2009 at 6:18 pm

Estoy realizando un sitio Web con internacionalización lo que me el problema es que los archivos (properties
) forma parte del proyecto y lo que yo necesito es que el administrador del sitio web pueda dar de altas nuevos idiomas y de esa forma traducir lo que ya se encuentra con un idioma por defecto. La idea es que esos datos se puedan guardar en una base de datos.

La duda es si los archivos properties ó . java como explicas en tu ejemplo se les puede definir el path donde yo los quiera localizar y configurar la aplicación para que tome dichos archivos desde ese path.

admin · July 14, 2009 at 8:35 am

Pepe, si o si tenes que setear el Locale object. Eso hace que cuando construis un resource bundle tome el que pertenece al Locale actual.

admin · July 14, 2009 at 8:38 am

Leandro, aca tenes un buen articulo que habla como usar la base de datos para externalizar los strings.
http://stackoverflow.com/questions/19295/database-backed-i18n-for-java-web-app

saludos

Goyo · October 1, 2009 at 5:00 am

La linea del codigo no esta terminado aqui cual es??
if (this.resourceBundle !=

roberto · October 10, 2009 at 11:06 pm

Hola amigos necesito ayuda por fabor tengo una aplicacion en java es para implementarlo a unas cabinas de internet, el problema es el siguiente quiero deshabilitar el teclado con codigo JAVA pero no encuentro como aserlo por fabor si alguien sabe como deshabilitar el teclado en especial las teclas WINDOWS, Ctrl+Alt, Ctrl+c, Ctrl+v enviarme el codigo fuente a mi correo robertocardenas8523@gmail.com muchas gracias…

Leave a Reply

Your email address will not be published. Required fields are marked *