domingo, 12 de julho de 2009

Internacionalização de mensagens com JSF – Exemplo prático.

Nesta postagem vamos mostrar como fazer a internacionalização de mensagens utilizando JSF. Internacionalizar mensagens é uma maneira de isolar toda a mensageiria de uma aplicação em arquivos. Desta forma, pode-se definir mensagens em idiomas diferentes em arquivos separados sem que a aplicação sofra nenhum impacto.

Para exemplificar a internacionalização com JSF, vamos aproveitar a aplicação exemplo mostrada na postagem “Iniciando com JSF (Tutorial com exemplo prático)”.

Primeiramente deve-se definir os arquivos com as mensagens. Para isso foi criado um pacote com.sample.messages e lá foram colocados dois arquivos com as mensagens da aplicação (um com mensagens em inglês e outro em português).

A listagem 1 e 2 mostram como ficaram os arquivos com as mensagens da aplicação.

messages_en_US.properties (mensagens em inglês)
portuguese=Portuguese
english=English
save=Save
delete=Delete
name=Name
nationality=Nationality
title=JSF

Listagem 1

messages_pt_BR.properties (mensagens em português)
portuguese=Portugues
english=Ingles
save=Salvar
delete=Excluir
name=Nome
nationality=Nacionalidade
title=JSF

Listagem 2

O pacote com os arquivos de mensagens é ilustrado na figura 1:
Figura 1: Pacote mensagens


Agora temos que configurar o faces-config.xml para o funcionamento da mensageiria. Para isso basta adicionar o seguinte trecho no faces-config.xml conforme a listagem 3:

<application>
<resource-bundle>
<base-name>com.sample.messages.messages</base-name>
<var>msgs</var>
</resource-bundle>
<locale-config>
<default-locale>pt_BR</default-locale>
<supported-locale>en_US</supported-locale>
</locale-config>
<message-bundle>
com.sample.messages.messages
</message-bundle>
</application>

Listagem 3

Vamos agora criar um controller para gerenciar qual será o locale (idioma) usado na aplicação. Esse controller chamaremos de LocaleController e ficará dentro do pacote com.sample.controller do exemplo. A listagem 4 mostra a implementação do LocaleController.


package com.sample.controller;

import java.util.Locale;

import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;

public class LocaleController {
private Locale currentLocale = new Locale("pt", "BR");

public void englishLocale() {
UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
currentLocale = Locale.US;
viewRoot.setLocale(currentLocale);
}

public void portugueseLocale() {
UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
currentLocale = new Locale("pt", "BR");
viewRoot.setLocale(currentLocale);
}

public Locale getCurrentLocale() {
return currentLocale;
}
}

Listagem 4

Vamos também definir um managed-bean no faces-config.xml para o LocaleController (listagem 5).

<managed-bean>
<managed-bean-name>localeController</managed-bean-name>
<managed-bean-class>
com.sample.controller.LocaleController
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

Listagem 5

Agora vamos definir a página pessoa.jsp para testar a internacionalização (listagem 6).

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<html>
<f:view locale="#{localeController.currentLocale}">
<head>
<title><h:outputText value="#{msgs.title}" /></title>
</head>
<body>
<h:form>
<table>
<tr>
<td><h:commandLink value="#{msgs.portuguese}" action="#{localeController.portugueseLocale}" /></td>
<td><h:commandLink value="#{msgs.english}" action="#{localeController.englishLocale}" /></td>
</tr>
<tr>
<td><h:outputText value="#{msgs.name}" />:</td>
<td><h:inputText value="#{pessoaController.pessoa.nome}" /></td>
</tr>
<tr>
<td><h:outputText value="#{msgs.nationality}" />:</td>
<td><h:inputText value="#{pessoaController.pessoa.nacionalidade}" /></td>
</tr>
<tr>
<td><h:commandButton value="#{msgs.save}" action="#{pessoaController.save}" /></td>
</tr>
</table>
<h:dataTable value="#{pessoaController.pessoas}" var="p"
rendered="#{not empty pessoaController.pessoas}" border="1">
<h:column>
<f:facet name="header">
<h:outputText value="#{msgs.name}" />
</f:facet>
<h:commandLink value="#{p.nome}" action="#{pessoaController.edit}">
<f:param name="id" value="#{p.id}" />
</h:commandLink>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="#{msgs.nationality}" />
</f:facet>
<h:commandLink value="#{p.nacionalidade}" action="#{pessoaController.edit}">
<f:param name="id" value="#{p.id}" />
</h:commandLink>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="#{msgs.delete}" />
</f:facet>
<h:commandLink value="#{msgs.delete}" action="#{pessoaController.delete}">
<f:param name="id" value="#{p.id}" />
</h:commandLink>
</h:column>
</h:dataTable>
</h:form>
</body>
</f:view>
</html>

Listagem 6

Com as configurações mostradas acima podemos ver o comportamento da aplicação (figura 2).

Figura 2: Comportamento da aplicação


Em síntese, com a aplicação exemplificamos como internacionalizar mensagens.
Os fontes do exemplo completo estão disponíveis aqui.

Até!

12 comentários:

MyMind by Ronaldo Martins disse...

na minha aplicação está ocorrendo o seguinte erro: java.util.MissingResourceException: Can't find bundle for base name util.messages, locale en_US

MyMind by Ronaldo Martins disse...

resolvi o problema faltava colocar o código:



no build!

MyMind by Ronaldo Martins disse...

ops..aqui o código:
fileset dir="${class.dir}" includes="**/*.class, **/*.properties"

Anônimo disse...

Ótimo post!
Obrigado

Anônimo disse...

colocar o comando

fileset dir="${class.dir}" includes="**/*.class, **/*.properties"

no build? como assim?

Anônimo disse...

colocar esse comando (abaixo) no build? como assim?

fileset dir="${class.dir}" includes="**/*.class, **/*.properties"

Thiago disse...

No caso do exemplo não foi usado o ant.

Alexandre Bezão disse...

Valeu Thiago, excelente tutorial! Ta bem passo-a-passo mesmo, conseguiu me ajudar muito. Pretendo acompanhar mais daqui adiante. Parabéns pela iniciativa.

Unknown disse...

Meu caro, fiz como vc postou, funciona que é uma beleza.. só que qdo mais de um usuário acessa o sistema e altera o idioma, o último selecionado altera o idioma de todos os outros.. sabe me dizer como mantenho o idioma fixo na sessão sem ser alterado por outras sessões?

Anônimo disse...

Post excelente, parabéns.

Unknown disse...

Bacana mesmo Thiago!!!

Unknown disse...

Para projetos de localização usando arquivos .properties, eu recomendo esta plataforma de tradução do softwares - https://poeditor.com

É uma excelente ferramenta colaborativa para criando apps Java multi-idioma.