How to use multilanguage in JSF? (Cómo usar multilenguaje en JSF?)

Para la creación de una aplicación en JSF que soporte multilenguaje, se pueden seguir los siguientes pasos:


CREAMOS NUESTRO PROPERTIES

La creación de un archivo de texto properties, es para seguir un patrón a seguir por el framework y de esta forma estandarizar.

En este archivo se compone de una forma parecida a un hashmap, es decir, se tiene un key un value. Un ejemplo de este tipo de archivo:

Resources_es.properties

Mensaje1 = Hola

Boton = Seleccionar

Mensaje-Boton = Boton seleccionado

La parte que se encuentra a la izquierda del “=” es el key por el cual ubicaremos nuestro value, que en este caso es un string.

NOTA: No se puede colocar keys de la forma mensaje.submensaje, debido a que el punto “.” es reservado por JSF para obtener las propiedades de los objetos.

CONFIGURAR FACES-CONFIG.XML

El siguiente paso a seguir es el configurar nuestro Faces-Config.xml de tal manera que le indiquemos dónde se encontrará nuestro archivo de mensajes (el properties) y qué idiomas puede soportar, así como también el archivo de mensajes por default. Un ejemplo de configuración se puede ver a continuación:

Faces-config.xml

Ahora explicaremos cómo funciona esto:

El JSF va a tomar en cuenta el archivo que se indica en el message-bundle, el cual servirá para los idiomas respectivos.

El default-locale es el idioma que va a ser elegido por default si es que el locale del cliente no se encuentra dentro de los supported-locale, caso contrario, se elegirá ese supported-locale.

El uso de los locale es el siguiente. Supongamos el caso de Perú, la configuración de la PC está con español(Perú), entonces el locale que va a detectar la aplicación, va a ser “es”, por lo tanto, el archivo de mensajes que utilizará, no será el oracle.backing.pages.view.ApplicationResources.properties, sino que elegirá oracle.backing.pages.view.ApplicationResources_es.properties. Es decir, los archivos se tomarán de la siguiente forma

archivo_la_pa.properties

archivo = oracle.backing.pages.view.ApplicationResources

la = Representa el idioma o lenguaje que se tiene seteado en la configuración de la PC, para el caso de Perú es “es”, para USA “en”, etc.

pa = Representa el pais del cliente, el cual puede ser “pe”, “gb”, etc.

Entonces, teniendo este ejemplo, si es que el cliente es de USA, el archivo que tomará el framework será:

oracle.backing.pages.view.ApplicationResources_en_us.properties

Se deben de colocar tantos como archivos de properties se tenga.

¿CÓMO USAR EL MULTILENGUAJE?

Coloquemos este escenario para entenderlo mejor. El cliente se conecta desde Perú y su PC está configurada en español(Perú). Al momento de conectarse, debe de aparecer un mensaje diciéndole “Hola” en su idioma nativo.

Entonces el código debe de verse de la siguiente forma:

Explicación del código:

Se puede ver que se tiene que colocar un f:loadBundle para tener una variable con el archivo, en su propiedad “basename” colocamos el mismo direccionamiento que colocamos en el faces-config.xml, pero sin la extensión properties.

Y la forma de llamar a alguna de sus keys es con EL Expression, #{msg.Key}, donde Key es la llave que quieren visualizar, de esta forma se verá un mensaje de “Hola”.

¿Cómo modificar el idioma de forma dinámica?

Para la modificación del idioma o archivo de mensajes que utiliza el framework, se tiene que utilizar el siguiente código:

FacesContext miContexto = FacesContext.getCurrentInstance();

Locale miLocale = new Locale("en","us");

miContexto.getViewRoot().setLocale(miLocale);

Donde el constructor de Locale recibe como primer parámetro el lenguaje o idioma, mientras que el segundo parámetro es el país del cliente.

If you want to use multilanguage in JSF, you can follow the next steps:


LET’S CREATE OUR PROPERTIES FILES

Our properties file is like a hashmap, where we have a key and a value. This example is of my properties:

oracle.backing.pages.view.ApplicationResources_es.properties

Mensaje1 = Hola

Boton = Seleccionar

Mensaje-Boton = Boton seleccionado

The part on the left of the “=” is our key, on the right we have our values, this is a string.

NOTA: You can’t put the key of this way mensaje.submensaje, Because JSF uses “.” to get the property of a object.

CONFIGURATION faces-config.xml

The next step is configurate the faces-config.xml, we need to indicate it the browse of our properties and what languages can your application support, also, we need to indicate the language by default. Here we have an example:

Faces-config.xml

Let’s explain it:

JSF will take the file in message-bundle for the languages.

The default-locale is the language by default. If the language of the client is not in the list of supported-locale, JSF will take the default-locale.

How does locale work? Let’s think we are in Perú, we have español(Perú) in our PC configuration. So, the locale will detect “es” as a language, so JSF won’t use oracle.backing.pages.view.ApplicationResources.properties, else

oracle.backing.pages.view.ApplicationResources_es.properties.

Let’s explain more how JSF take the files:

file_la_co.properties

file = oracle.backing.pages.view.ApplicationResources

la = This is the language of the PC.

co = This is the country, like Pe(Perú), US(USA), etc.

So, if the client is from USA, JSF will take the file:

oracle.backing.pages.view.ApplicationResources_en_us.properties

You should have a propertie file for each supported-locale.

¿How to use multilanguage?

For example, if we are in Perú, JSf will show me just spanish messages like “hola”.

Then, we have the next example code:

Here we have f:loadBundle where we put the browse of the properties (this is the same of the faces-config,xml, but without the “.properties”).

The way to call a message is with a EL Expression, like #{msg.Key}.

In our example we well see the message “Hola” of our propertie file oracle.backing.pages.view.ApplicationResources_es.properties.

¿How to change the language of our application?

We can modif. the language or message file of our application with the next code:

FacesContext miContexto = FacesContext.getCurrentInstance();

Locale miLocale = new Locale("en","us");

miContexto.getViewRoot().setLocale(miLocale);

The constructor of Locale will receive (language, country)




ANEXO!!!!(ADITIONAL)
Bueno, comenzaré diciendo que el libro de "JSF IN ACTION" asegura que no se puede usar keys con punto, debido a que es reservado por JSF. Hasta cierto punto esto es cierto, pero hay una forma de seguir con el estándar de usar el punto. ¿Cómo realizarlo?
Para dar el ejemplo, utilizaré el mismo código de antes, pero esta vez haré el cambio. Supongamos que ahora mi properties, tiene un nuevo key que es así:

miKey.mensaje = Nuevo mensaje

Entonces, para llamar a un key de esta forma, modificaremos el código JSF de la siguiente forma



Como pueden ver, en el value del outputText ahora no se coloca msg.key, sino que se hace lo siguiente: msg['miKey.mensaje'], de esta forma mostraremos lo que habíamos colocado antes, es decir "Nuevo mensaje".

Entonces, de esta forma estaremos listos para utilizar los mensajes de una forma multilanguage.
Espero que haya servido esta aclaración, muchas gracias a Lennon Shimokawa por la duda que tuvo, porque sino no hubiese extendido esto para que les sirva más.

Sobre lo de no utilizar el f:loadBundle, creo que hay una forma de hacerlo, que es cargando el Bundle en el BackBean, mas o menos debes de buscarlo en el FacesContext.getCurrentInstance() y algo más, pero a las finales, eso te generará una variable, es decir, estarás haciendo lo mismo que el bundle, pero por backbean.

Yo por el momento para el proyecto en el cual estaremos, he propuesto colocar lo del load bundle en el template, de tal forma que no se tiene que escribir a cada momento.

Un gusto (Luego lo paso a inglés)


Muchas gracias por siempre estar leyendo estos humildes artículos que los hago con tiempo algo ajustado, espero sus opiniones, críticas y colaboraciones. Muy agradecido

Buen día


Thxs everyone for visit my blog and read my articles, i hope you enjoy the article and your comments, opinions, colaborations and others. Thxs =)

bye bye


Shinji


P.d. Does anyone know how to put tags without have problems in the blog?

15 comentarios:

Unknown dijo...

Buen post, personalmente no me gusta eso que mencionas de no poder utilizar '.' para los keys del properties, normalmente uno hace como namespaces para no tener problemas con los nombres. También eso de estar declarando el loadBundle por cada página JSF, no hay forma que obtenga el message-bundle por defecto?

Saludos

ShinjiDev dijo...

Esas 2 cosas que indicas ya las investigué, así que te daré la información apenas llegue a mi casa. Es que en el trabajo me tienen restringido el ingreso a los blogs.

Pero OJO, lo que voy a mostrar es una forma cómo seguir el estándar de pagina.subpagina.mensaje que normalmente dices que se utiliza, de tal forma que se pueda saltar la funcionalidad de JSF con el "."

A la media noche les tendré la información, ahorita ya no estoy en mi trabajo, sino en Cibertec.

Cabe resaltar el agradecimiento a quienes aporten sus comentarios, sus dudas y me alegro que te haya gustado el artículo.

cya :3

Unknown dijo...

Hola Shinji chequee la actualización de tu blog, ya enlacé también mi blog al tuyo.

Anónimo dijo...

Hola. Buen post...

Tengo una problemilla con el uso de myfaces SANDBOX, es al usar este codigo:

< t: inputSecret id="clave2" required="true" >
< s: validateCompareTo for="clave" operator="eq" message="*****" />
< / t: inputSecret >

En la parte de message quiero poner el valor de una etiqueta de mi properties, pero si uso la etiqueta el control de validación asume el message por default, mas no la etiqueta; pero si pongo texto en duro si lo pinta.

Espero haber sido explicito. De ante mano gracias por tomarte un tiempo para postear una ayuda.

Saludos Alvaro.

ShinjiDev dijo...

Muchas gracias por el posteo =)

Sobre tu pregunta, mira, nunca he trabajado con Sandbox, lo que sé, es que es de Apache (como MyFaces y Tomahawk).

Mira, antes de ver el problema de forma más profunda te recomendaría lo siguiente.

1. Prueba si es que funciona bien lo de multilenguaje en tu página con controles de JSF, es decir un outputtext y demás.
2. Si es que funcionan bien, ahora prueba con controles sandbox si es que funciona debidamente.

Si es que todo funciona correctamente, avísame, para poder investigar un poco más el por qué este control no funciona debidamente, con mucho gusto lo haré.

Buen día =)

Anónimo dijo...

Gracias por la pronta respuesta.

Los controles funcionan bien (al parecer), pero igual seguire probando.

Estamos en contacto.

Saludos Alvaro.

PD. Feliz semana santa!

Anónimo dijo...

Hola ShinjiDev,
te escribo desde España.
Acabvo de leer tu post porque quiero hacer exactamente lo mismo en una página web que hago para un proyecto de la universidad.
La verdad es que creo que hago como lo dices pero me sale un error.
Te cuento:
1-creo el "Archivo.properties" y lo pongo en una carpeta del proyecto.
2-voy al "faces-config.xml" y pongo como predeterminado el "es".
3-voy a un archivo en concreto para ver si me funciona.Pongo en dicho archivo lo siguiente:f:loadBundle basename="xxx.xxx.xxxx.Archivo" var="missatge"
Donde las "xxx.xxx.xxxx" es la direccion donde encontrar el archivo "Archivo.properties".
4-Utilizo en el archivo de prueba un value="#{missatge.username}".
5-Intento cargar la pagina web y me sale el siguiente error:com.sun.facelets.tag.TagAttributeException: /layout/barraCapcalera.xhtml @10,121 f:loadBundle basename="remUniversitari.src.model.com.mydomain.remUniversitari.MissatgesAplicacio" Can't find bundle for base name remUniversitari.src.model.com.mydomain.remUniversitari.MissatgesAplicacio, locale es

Xavier.

Saludos y gracias

ShinjiDev dijo...

Buenas, estuve examinando mas o menos tu caso, y parece que estás utilizando facelets (al parecer por el archivo xhtml que pude ver), yo te recomendaría probar un ejemplo simple para que funcione, luego de eso ya colocar lo del loadbundle al modo que uno desee. Acá te dejo en rapidshare una aplicación que hice en mi trabajo como prueba para algunos componentes de ADF Rich Faces de Oracle, entre ellos está el Internacional.jspx que utiliza los mensajes del properties, aparte incluye el faces-config y los archivos properties que utilizé. Para esto hice uso de JDeveloper 11 TP2.
Suerte y espero te llegue a salir todo bien. Aunque creo que el error en sí es por direccionamiento, tendría que ver tu estructura de paquetes, si gustas lo subes a un servidor de archivos como rapidshare u otro, y me lo mandas para darle una ojeada. Pero indícame que IDE utilizaste por si aca.

Suerte

Link proyecto
http://rapidshare.com/files/110322350/AplicacionCreativa.rar.html

Anónimo dijo...

Hola ShinjiDev,
Ante todo muchas gracias por tu rápido comentario. Debo decirte que logré encontrar el fallo que hacia que no me funcionase. Era que en la carpeta "classes" no se me cargaba los archivos ".properties".

Ahora lo que me gustaria es poder hacer unos botones en la página inicial para poder traducir la web a diferentes idiomas como el inglés el francés o el alemán.
Para eso he encontrado que tendria que hacer un botón con la siguiente información a poner:"ShinjiDev"
¿es correcto?,¿cómo lo tendria que hacer?. Y si es correcto de qué manera se tendria que poner exactamente?.

Muchas gracias.

ShinjiDev dijo...

Bueno Xavier, el menu de seleccion de idioma lo puedes hacer de diferentes formas, desde botones hasta combobox puedes utilizar para eso. En el caso que coloque en rapidshare lo estoy haciendo con un boton, asi que es de libre seleccion.
Muchisima suerte en tu proyecto, espero te gusten las demas entradas que coloque en el blog mas adelante =)

Anónimo dijo...

¿Pero qué tendria que poner exactamente en el botón?
h:commandButton
action=UIViewRoot
viewRoot=FacesContext.getCurrentInstance().getViewRoot();viewRoot.setLocale(newLocale("en"));
value="English"
/h:commandButton

Esto que he puesto no me funciona,qué debería poner?
Estoy haciendo un botón para canviar el Locale a inglés.

Muchas gracias.

Anónimo dijo...

Hola ShinjiDev,
soy Xavier de España.
Me podrias ayudar en el último tema escrito en cuestión?
Supongo que ya estás al corriente de mi problema. Tengo una web que su idioma por defecto está en español y lo que quiero es hacer botones en la página principal para canviar a diferentes idiomas: inglés, francés, etc.
¿Exactamente cómo lo tengo que hacer?.
Si necesitas enviarme un mail me lo dices y te lo doy.
Muchisimas gracias por tu ayuda.
(Es un poco urgente)

ShinjiDev dijo...

Hey Xavier, sorry por no haberte contestado antes, estaba replicando tu problema en la compu de mi trabajo y a las finales pude hacer lo de multilenguaje en todas las páginas. Para esto, se tiene que crear un bean de Session, que tenga una propiedad que sea String y que se coloque en el atributo locale del f:view.

Para mayor información, te dejo un blog que visité pa resolver esto:

http://richardbrenner.com/joomla/index.php?option=com_content&task=view&id=56&Itemid=

Pero OJO, yo tuve un problema muy incómodo, si es que hacía un return null, osea volvía a la misma página para que ésta se refresque con el nuevo idioma, no me lo cambiaba, en cambio si iba a cualquier otra página, normal, aparecía el idioma cambiado. Lo que hice fue hacer un "chiche", mandar a una página que haga un forward a mi página, osea un ir y volver para que se refresque completamente la página y recomiendo tener precaución con la caché.

Eso es todo, espero te dé resultados.

cya :3

P.d. feliz día del trabajo a todos xD

Anónimo dijo...

Hola ShinjiDev,
Te cuento lo que he echo,ya que básicamente he "copiado" lo que pone el blog que me has pasado.

1.Pongo en el archivo que quiero y en el lugar que quiero lo de..."f:form id=changelanguageform" etc. Esto me servirá para poder cambiar el lenguaje de toda la web al que quiera.
2.Hago una classe en java y la meto en el package donde tengo todos los archivos ".java". Esta classe es la que llama "SessionBean".Pongo la misma clase.
3.Pongo el "managed-bean" correspondiente que me dice el blog que me mandaste.

Echo esto lo ejecuto y no me hace nada de nada. Tampoco me da error pero no me cambia a ninguno de los idiomas elegidos.
Lo que tampoco he puesto y no sé dónde ponerlo es la parte que pone..."f:view locale=#{Session.locale}".

Me podrias decir quál puede ser mi error o que me falta.

Muchísimas gracias por tu ayuda.

Anónimo dijo...

Hola ShinjiDev,
soy Xavier de España, otra vez.

Primero decirte que muchas gracias por los consejos,pues finalmente conseguí hacer la página we multi-idioma.
Ahora y avanzando en el proyecto, necesito controlar los logins y passwords.
Es decir, en mi proyecto se dan de alta Clubs de Remo y al darse de alta se ponen un usuario y password.
Luego para hacer otras cosas (entrar a otras páginas del proyecto) requeriré que entren el usuario y password.
¿cómo lo puedo hacer?
En el proyecto tengo una clase "Authenticator.java" y el usuario y password de las Entidades están en la tabla "Entidad" de la base de datos. También tengo, claro está, la clase "Entidad.java".

¿Me puedes ayudar?,porque he mirado los libros "jboss seam", "practical jboss seam projects" y "JavaServer Faces JSF in Action" y no me aclaro

Muchas gracias!!