VRaptor + JSTL + Internacionalização

36 respostas
A

Olá,

Estou com alguns problemas com internacionalização de minha aplicação. Segui o exemplo do MyDvds e estou com um problema. Quando clico no link para mudar o locale, ele não muda tudo, somente parte da página. Ele só muda quando eu atualizo a página. No início pensei que era cache, então desabilitei o cache, mas mesmo assim o problema persiste.
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
	response.setHeader("Cache-Control","no-cache"); 
	response.setHeader("Pragma","no-cache"); 
	response.setDateHeader ("Expires", -1); 
%>
<fmt:setLocale value="${locale}"/>
<c:if test="${not empty param.language}">
	<fmt:setLocale value="${param.language}" scope="session"/>
</c:if>

<html>
	<head>
		<meta http-equiv="Pragma" content="no-cache" />
	</head>
	<body>
		<a class="languageFlag" href="?language=pt_BR" ><img src="${pageContext.request.contextPath}/img/br.png" alt="br"/></a>
		<a class="languageFlag" href="?language=en" ><img src="${pageContext.request.contextPath}/img/us.png" alt="en"/></a>
		...
	</body>
	<head>
		<meta http-equiv="Pragma" content="no-cache" />
	</head>
</html>

Não tenho idéia do porque ele está mantendo parte do conteúdo com o locale anterior.

Obrigado pela ajuda,

Augusto

36 Respostas

L

a página inteira está internacionalizada?

A

Sim.
Não sei se faz diferença ou se pode causar algum conflito, mas estou utilizando o tiles para fazer os templates.
No template:

<div id="topMenu">
	<tiles:insertAttribute name="topMenu"  defaultValue=""/>
</div>
<div id="theContent">
	<tiles:insertAttribute name="content" />
</div>

Nas páginas:

<tiles:putAttribute name="topMenu" value="/WEB-INF/jsp/top.jsp">
</tiles:putAttribute>
<tiles:putAttribute name="content">
conteudo internacionalizado
</tiles:putAttribute>

No top.jsp

<ul> <li><a href="${pageContext.request.contextPath}/" id="loverview" ><fmt:message key="menu.overview"/></a></li> ... </ul>

O conteúdo do top.jsp carrega normalmente quando eu mudo o locale. O restante da página só atualiza quando dou refresh no browser. E ainda o conteúdo internacionalizado que fica no template nunca muda. Somente os que estão no conteúdo.

L

isso pode ser por causa do jeito que vc está mudando o locale…

se vc seguiu o exemplo, vc deve estar fazendo session.setLocale… não sei como o tiles trabalha, mas pode ser que ele não olhe para esse mesmo locale… ou pode ser que ele só pegue o locale na primeira vez que ele roda…

tenta fazer uns request.setLocale(…) pra ver se funciona…

V

Eu estou com um problema “semelhante”.
Eu seto minha locale no JSP através de:

<c:if test="${not empty param.language}">
	<fmt:setLocale value="${param.language}" scope="session"/>
</c:if>

E tudo na view atualiza de acordo com a língua selecionada normalmente, no entanto em todos locais em que eu uso o validator do VRaptor está sendo utilizado o Locale default da máquina servidor.

Exemplo:

validator.checking(new Validations() {
			{
				that(result.size() > 0, "erro", "errors.noRecords");
			}
		});

Neste exemplo, mesmo que no browser eu tenha submetido o locale ‘en’ e o conteúdo de minha página, ao submeter o formulário, o erro citado no validator é respondido no Locale default, no caso ‘pt_BR’.

Eu pensei em tentar setar o Locale de acordo com o que o Lucas falou, mas não consegui.
O objeto request não possui um setLocale, e o session, caso seja o org.apache.catalina.Session, também não tem um setLocale.
Portanto fica a dúvida, como que eu posso informar para o VRaptor o novo locale escolhido?

L

o problema é que o q vc faz na jsp acontece depois q o vraptor já setou tudo…

pra setar o locale da tag fmt, vc precisa fazer:

request.setAttribute(Config.FMT_LOCALIZATION_CONTEXT, meuLocale);

onde tá request vc pode colocar session ou servletContext

V

Lucas Cavalcanti:

o problema é que o q vc faz na jsp acontece depois q o vraptor já setou tudo…

pra setar o locale da tag fmt, vc precisa fazer:

request.setAttribute(Config.FMT_LOCALIZATION_CONTEXT, meuLocale);

onde tá request vc pode colocar session ou servletContext

opa blz Lucas. Acho que você nãao entendeu o meu exato problema.
Eu não estou tendo problemas com o FMT. Como havia dito, utilizando apenas fmt:setLocale na jsp já está mudando o locale corretamente e todos os dados estáticos da view mudam normal, mas o que não está dando certo é com o validator do VRaptor. Minha dúvida é como eu faria pra mostrar pro VRaptor um novo locale setado?

Eu achei que o VRaptor fosse ler o atributo que você citou ‘Config.FMT_LOCALIZATION_CONTEXT’, mas parece que não ta lendo, porque eu fiz um TESTE aqui setando um atributo em sessão e recuperando ele a cada request, mas mesmo assim não deu certo. Veja:

String requestLocale = request.getParameter("language");
	if (requestLocale != null) {
		request.getSession().setAttribute(Config.FMT_LOCALIZATION_CONTEXT, new Locale(requestLocale));			
	}
	Object sessionLocale = request.getSession().getAttribute(Config.FMT_LOCALIZATION_CONTEXT);
	if(sessionLocale != null)
		request.setAttribute(Config.FMT_LOCALIZATION_CONTEXT, new Locale(sessionLocale.toString()));

Veja que eu seto o atributo na última linha igual você mencionou, mas parece que o VRaptor não lê esse atributo aí né?

Hehe veja bem que eu só quero que o VRaptor exiba os erros das validações de acordo com um novo locale setado ^^ .

L

faça isso no seu controller:

@Resource
public class BlahController {

    public BlahController(...., Localization localization) {
      this.localization = localization;
    }

    public void metodoComValidacao(....) {
        this.validator.checking(new Validations(localization.getLocale()) {{
            //validações
        }}
        //...
    }
}

acho que isso funciona

V

Lucas Cavalcanti:
faça isso no seu controller:

@Resource
public class BlahController {

    public BlahController(...., Localization localization) {
      this.localization = localization;
    }

    public void metodoComValidacao(....) {
        this.validator.checking(new Validations(localization.getLocale()) {{
            //validações
        }}
        //...
    }
}

acho que isso funciona

Para que possa contribuir com o conteúdo do tópico, vou postar informações complementares às soluções das duas questões apresentadas aqui.

Sobre a dúvida do ACDias, eu andei pesquisando e vi que o problema sobre internacionalizar apenas em uma página e esperar que o TILES fizesse para todas as outras onde se era incluído é que a API age de maneira errada fazendo a leitura da JSP que possui a validação

<c:if test="${not empty param.language}">  
    <fmt:setLocale value="${param.language}" scope="session"/>  
</c:if>

antes de fazer o “include” da mesma em outra JSP. Portanto caso queira continuar utilizando o TILES a validação do JSTL/FMT deve ser feita em todas JSPS que possuem conteúdo a ser internacionalizado.

__

Já sobre o problema de informar ao VRaptor um certo locale, a única diferença a ser feita no código do Lucas é que ao invés de passar para o construtor do Validatons um locale, deve-se passar um ResourceBundle e pra conseguí-lo dá pra fazer da seguinte maneira:

Locale loc = new Locale("pt","BR");
ResourceBundle bundle = ResourceBundle.getBundle("messages", loc );

Flw

L

o localization.getLocale() pega o locale setado na requisição, sessão ou context, nessa ordem… e sim, precisa passar o ResourceBundle, não o locale… erro meu =(

faça

new Validations(localization.getBundle()) {{...}}

ao invés disso…

J

Estou passando por um problema parecido.
O que estou achando estranho é que a internacionalização está funcionando perfeitamente, porém, mesmo eu estando em outra lingua quando chamo o localization.getLocale() o retorno é pt-Br.

Alguma suspeita?

JB

L

qual versão do VRaptor?

e essa outra lingua que vc está falando está configurada aonde?

F

Ola, vocês não tem uma aplicação funcionando?

L

várias delas, pq?

F

Eu quero saber mais específicamente de alguma aplicação que a internacionalização funcione. Ainda não entrou na minha cabeça que nenhuma classe faça este controle. Por isso desejo saber se vocês tem outras, pq eu testei a mydvds no aspecto da internacionalização e não percebi a alteração de idioma.

L

você criou os vários bundles?

algo como:

messages_pt_BR.properties
messages_en_US.properties

vc está com o Locale setado corretamente?

F

Eu criei os arquivos messages_en_US.properties e messages.properties coloquei no web.xml o

javax.servlet.jsp.jstl.fmt.localizationContext
messages

E de novo nada ocorre. Não sei o que eu estou fazendo de errado?

L

o locale estah correto? estao aparecendo as mensagens de qual bundle?

F

O bundle que aparece a resposta é o pt_BR.

O que eu acho estranho no VRaptor é o automatismo dele. No problema estudado o problema está na troca do português para o inglês. O texto em português aparece, mas não é convertido para o inglês quando eu peço.

L

então o locale está setado para pt_BR

F

Correto, pois ele pega as definições do xml, não?

L

não só, você pode mudar isso em tempo de execução…

F

Eu percebi que as últimas modificações que fiz modificaram a linguagem do cabeçalho, mas não de toda a página. Como altero o texto da página como um todo?

L

tente algo como setar o locale na sessão do usuário

F

Como eu faço isso?

L

procura por Config.setLocale

L

Estou com um problema muito parecido.

Tenho 2 arquivos de properties:
messages.properties
messages_pt_BR.properties

E quando altero no jsp o locale, todas as mensagens de internacionalização funcionam normalmente (altera entre as duas línguas).

Mas quando uso o Validator ele SEMPRE pega as mensagens em português.

Fiz um teste no controller e obtive o seguinte:
localization.getLocale().toString() - en_US
localization.getBundle().getLocale() - null
Debuguei o localization com o Eclipse e descobri um “delegate” dentro do localization.getBundle() que mostra - pt_BR

Mesmo usando o:

validator.checking(new Validations(localization.getBundle()) {

O que eu faço para ele pegar as mensagens de acordo com o que eu seto no locale?

L

se você está usando o VRaptor 3.4, não passe o bundle pro construtor das validations. Ele vai conseguir passar o bundle depois, teoricamente usando o locale certo…

antes do 3.4 tinha esse bug sim

L

Lucas Cavalcanti:
se você está usando o VRaptor 3.4, não passe o bundle pro construtor das validations. Ele vai conseguir passar o bundle depois, teoricamente usando o locale certo…

antes do 3.4 tinha esse bug sim

Atualizei para o 3.4 e continua com o mesmo problema, precisa atualizar algum jar fora o do vraptor? (Não estou usando maven por forças maiores…)

L

troque isso:

validator.checking(new Validations(localization.getBundle()) {

por isso:

validator.checking(new Validations() {

e para garantir, dê um clean no projeto e no servidor.

L

Ainda pega pt_BR mesmo que o locale esteja para en_US.
Eu coloquei um breakpoint no construtor do Validations e lá ele usa o:

ResourceBundle.getBundle("messages")

Ele está pegando o Locale.getDefault(). Não seria isso? Será que não teria que passar o Locale setado na sessão?

Abraços!

L

se vc está com o vraptor 3.4, o validator vai passar o bundle correto no método getErrors, e as mensagens vão ficar com o locale correto.

se quiser ver o que está acontecendo, dá uma olhada no que o localization.getLocale() e localization.getBundle() estao retornando

L

depurei o “validator.getErrors()”, dentro tem um list com uma mensagem, dentro desta mensagem um blundle e um delegate, lá o locale continua pt_BR mesmo eu tendo setado o locale com en_US, como disse anteriormente.

o “localization.getBundle()” tem um delegate, também com pt_BR.
já o “localization.getLocale()” está com language “en” e country “US”.

Pode me ajudar?

L

a implementação do Localization leva em conta o Locale:


(método extractUnsafeBundle)

você está com o vraptor 3.4 mesmo?

pior dos casos vc pode usar a sua própria implementação do Localization que seta o bundle do jeito que vc quiser.

L

Sim estou usando o VRaptor 3.4.

Fiz outro teste, baixei o Mydvds do site (me certifiquei que está com 3.4) e rodei aqui.

Primeiro tive que remover a primeira linha do “header.jsp”:

<fmt:setLocale value="${locale}"/>

Porque com isso ele nunca pegava outro idioma que não o português de maneira alguma, sabe por quê isso?

Sem esta linha os links “English” e “Português” funcionam normalmente. Mas ocorre o mesmo problema que estou tendo com a minha aplicação. O Validations não pega o Locale que eu setei no JSP, a mensagem fica sempre em português.

Alguma ideia?

Obrigado!

L

Acho que eu sei qual é o problema então.

O JSP roda depois que o VRaptor fez todo o seu trabalho. A ordem de execução está assim:

  • execução da sua lógica
  • geração da lista de erros <- pegando o locale atual
  • redirect pra sua jsp
  • jsp seta o locale

no ponto em que a jsp seta o locale não adianta mais.

É um bug/feature não planejada do VRaptor mesmo, precisamos gerar as mensagens de forma mais lazy ainda!
Cria uma issue lá pra isso por favor?

Se quiser ajudar com a implementação, creio que teríamos que mexer aqui:

e setar o bundle no último momento possível.

Workaround seria tentar setar o locale antes de ir pro jsp (se possível antes de chegar no controller, num interceptor por exemplo)

G

Lucas Cavalcanti:
É um bug/feature não planejada do VRaptor mesmo, precisamos gerar as mensagens de forma mais lazy ainda!
Cria uma issue lá pra isso por favor?
http://github.com/caelum/vraptor/issues

Não vejo isso como um bug. Até porque é gambiarra setar o locale dentro da view. Obvio que o JSTL tem uma tag para isso, mas não é porque o JSTL faz que isso seja uma coisa boa.

O mais correto nisso é trocar o locale no controller, assim tudo será no mesmo locale e acaba com os problemas.

Criado 28 de janeiro de 2010
Ultima resposta 15 de dez. de 2011
Respostas 36
Participantes 7