Gestionar soporte para internacionalización en mi proyecto

PEDRO DELGADO YARZA 2014/03/04 18:10

A la hora de desarrollar nuestra aplicación, los textos que queremos mostrar a los usuarios por pantalla han de estar regulados para que, en caso de ser necesario, podamos modificarlos de manera rápida o internacionalizar dichos mensajes. Para conseguir esto tenemos que evitar escribir los textos directamente sobre los ficheros java o los xhtml puesto que esta manera de proceder es incorrecta.

En concreto en Fundeweb 2.0, Seam hace uso de la librería FacesMessages cuando el mensaje se origine en un bean de respaldo, y de StatusMessages cuando el mensaje venga de los servicios o PAOs y DAS de la aplicación. De esta forma, podemos gestionar de manera cómoda, limpia y sencilla esta tarea.

Para ello hace uso de un fichero messages.properties donde podremos incluir todos nuestros mensajes de la forma: clave.del.mensaje=Texto concreto del mensaje. De esta manera tendremos una lista de pares clave-valor, que nos permitirán mapear en nuestro código de manera mas eficiente los mensajes que queramos mostrar.

En caso de querer aplicar internacionalización a nuestra aplicación haremos uso de este fichero (messajes.properties) pero creando uno por cada idioma y nombrándolos de la siguiente manera messages_localizaciónDelIdioma.properties. Por ejemplo: messages_es.properties (español), messages_en.properties (inglés), messages_fr.properties (francés)…

Estos ficheros deben estar contenidos dentro del módulo web en la ruta src/main/resources. A continuación mostramos un ejemplo del contenido de un fichero de este tipo:

...
validator.assertFalse=fallo de validación
validator.assertTrue=fallo de validación
validator.future=debe de ser una fecha posterior
...

Un detalle a tener enc uenta sobre estos valores, que proveen de más riqueza a los mensajes, es su capacidad de soportar parámetros de entrada. Con lo cual podemos personalizar el mensaje a nuestro gusto en todo momento.

Para poder introducir parámetros, en la parte donde escribimos el texto que queremos mostrar, añadimos #1, #2, #3… (o igual pero con {1}, {2}…) donde queremos que vayan los parámetros y el motor de mensajes ya se encargará de sustituir cada parámetro por su posición. Más adelante veremos un ejemplo de cómo hacerlo, no obstante un ejemplo de cómo quedaría un fichero messages.properties es el siguiente:

edit.header=Editar {0}
create.header=Crear {0}
manytoone.empty.table=No hay {0}s asociados a este {1}.
manytoone.change.table.action=Cambiar {0}
manytoone.select.table.action=Seleccionar {0}

Una vez que tenemos todos los ficheros de mensajes configurados, sólo queda ver cómo conseguimos que aparezcan en nuestra aplicación. Para ello bastará con hacer uso de los tags específicos si estamos en la parte de la vista (xhtml) o llamadas a FacesMessages si estamos en Java.

Ficheros xhtml/xml

Cabe destacar que los mensajes dispuestos en estos ficheros son de tipo estático, es decir cuando se renderiza la pantalla en cuestión se interpretan e incluyen en ese render de la página.

Los ficheros relacionados con la vista o utilizados en la misma no necesitan hacer una llamada explícita, sino simplemente introducirlos dentro de la expresión EL #{messages['claveDelMensaje']}.

Un ejemplo de fichero xhtml

  ...
<h:outputText value="#{messages['aceptar.pedido']}" />
  ...

Un ejemplo de un mensaje en una excepción situado en el fichero pages.xml

<exception class="org.jboss.seam.framework.EntityNotFoundException">
    <redirect view-id="/paginas/error.xhtml">
        <message severity="warn">
        	#{messages['error.entidad.noEncontrada']}
        </message>
    </redirect>
</exception>	

Ficheros Java

Los mensajes lanzados desde Java, son de tipo dinámico, es decir durante el transcurso de la aplicación, un código nuestro lanza un mensaje que aparece al usuario en la forma que hayamos configurado en la parte de la vista (una barra superior, un pop-up, etc…)

El primer paso que debemos dar para enviar mensajes desde Java, será importar la dependencia con FacesMessages para poder publicar los mensajes que queramos

@In
FacesMessages facesMessages

Una vez que tengamos la dependencia ya podemos invocar al método que publica en nuestra aplicación los mensajes que decidamos enviar. Para ello hacemos lo siguiente:

  //Busca el mensaje con clave "IDENTIFICADOR" añade los parámetros si se los indicamos y lo publica.
  facesMessages.addFromResourceBundle("IDENTIFICADOR", param1, param2, ...);
 
  //Como el anterior pero además añade el tipo de mensaje: info, aviso, error, etc..
  facesMessages.addFromResourceBundle(severity, "IDENTIFICADOR", param1, param2, ...);

También es posible inyectar mensajes como cadenas en un String directamente o como respuesta de una validación

@In("#{messages['IDENTIFICADOR']}");
private String mensaje;
 
@Length(max=5, message="#{messages['too.long']")
@Pattern(regex="[0-9]+")
@NotNull
public String getZip() {
     return zip;
}

Personalización de ficheros de mensajes

En ocasiones, para aplicaciones grandes que tienen muchos mensajes, no es óptimo tener un único fichero de mensajes enorme con todos. La mejor opción de la que disponemos, en caso que queramos mejorar la eficiencia, es dividirlo en varios ficheros e indicar en el código donde se usan.

Los ficheros de mensajes han de contenerse siempre dentro de la ruta src/main/resources usando los sufijos de idiomas si queremos soportar internacionalización.

Una vez creados y organizados todos los ficheros, el primer paso que debemos dar es modificar el fichero components.xml para indicarles que cargue los nuevos ficheros de mensajes. Para ello debemos descomentar el tag <core:resource-loader> e indicar dentro del mismo los ficheros de mensajes que queremos cargar, un ejemplo de esto se ve a continuación:

<core:resource-loader>
	<core:bundle-names>
		<value>mensajesPersonalizados</value>
		<value>fichero2</value>
		<value>fichero3</value>
	</core:bundle-names>
</core:resource-loader>

Como podemos ver en el ejemplo, sólo hay que indicar el nombre del fichero, por lo que la extensión “.properties” se excluye.

Importante: Al descomentar este tag, los ficheros de mensajes por defecto: messages.propertes, no se tendrán en cuenta salvo que se incluyan dentro de la lista. Con este tag, la aplicación sólo contemplará los ficheros que aparezcan en la lista, ignorando el resto.

En este punto en nuestra aplicación ya se cargan de manera independiente los diferentes ficheros de mensajes, por lo que sólo nos queda indicar cómo se selecciona el que vamos a utilizar. Esto lo hacemos en el fichero *.page.xml de cada página de la vista, en el tag <page> existe una propiedad llamada bundle que nos permite especificar el fichero de recursos que queremos usar para esa vista. Por ejemplo:

<page xmlns="http://jboss.org/schema/seam/pages" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://jboss.org/schema/seam/pages http://jboss.org/schema/seam/pages-2.3.xsd"
	bundle="mensajesPersonalizados.properties">
  • fdw2.0/fundeweb2.0/gt/gestionar_soporte_para_internacionalizacion_en_mi_proyecto.txt
  • Última modificación: 07/11/2017 10:46
  • (editor externo)