rótulos internacionalizados em JSF / Facelets
-
01-07-2019 - |
Pergunta
O Facelets tem todas as características para mais puro ou rótulos internacionalizados mais legíveis texto de interface de usuário que o que você caso contrário pode fazer usando JSF?
Por exemplo, com JSF simples, usando h:. OutputFormat é uma maneira muito detalhada para variáveis ??Interpolar em mensagens
Esclarecimento: Eu sei que eu posso adicionar uma entrada de arquivo de mensagem que se parece com:
label.widget.count = You have a total of {0} widgets.
e exibir este (se eu estou usando Seam) com:
<h:outputFormat value="#{messages['label.widget.count']}">
<f:param value="#{widgetCount}"/>
</h:outputFormat>
mas isso é um monte de lixo para a saída de uma frase -. Exatamente o tipo de coisa que dá JSF um mau nome
Solução
Você pode criar sua própria biblioteca rostos tag para torná-lo menos extenso, algo como:
<ph:i18n key="label.widget.count" p0="#{widgetCount}"/>
Em seguida, crie o taglib na sua opinião dir: /components/ph.taglib.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "https://facelets.dev.java.net/source/browse/*checkout*/facelets/src/etc/facelet-taglib_1_0.dtd">
<facelet-taglib xmlns="http://java.sun.com/JSF/Facelet">
<namespace>http://peterhilton.com/core</namespace>
<tag>
<tag-name>i18n</tag-name>
<source>i18n.xhtml</source>
</tag>
</facelet-taglib>
criar /components/i18n.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:outputFormat value="#{messages[key]}">
<!-- crude but it works -->
<f:param value="#{p0}" />
<f:param value="#{p1}" />
<f:param value="#{p2}" />
<f:param value="#{p3}" />
</h:outputFormat>
</ui:composition>
Você pode provavelmente encontrar uma maneira elegante de passar os argumentos com um pouco de pesquisa.
Agora registrar seu novo taglib em web.xml
<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>
/components/ph.taglib.xml
</param-value>
</context-param>
Basta adicionar xmlns:ph="http://peterhilton.com/core"
a seus pontos de vista e está tudo pronto!
Outras dicas
Uma vez que você estiver usando Seam, você pode usar EL no arquivo de mensagens.
propriedade:
label.widget.count = You have a total of #{widgetCount} widgets.
XHTML:
<h:outputFormat value="#{messages['label.widget.count']}" />
Este ainda usa outputFormat, mas é menos detalhada.
Eu nunca me deparei com uma outra maneira de fazê-lo diferente de outputFormat. Infelizmente, é bastante detalhado.
A única outra coisa que posso sugerir é criar a mensagem em um bean de apoio e, em seguida, a saída que ao invés de MessageFormat.
No meu caso eu tenho MessageSource da Primavera integrado com JSF (usando MessageSourcePropertyResolver ). Então, é bastante fácil em seus beans de apoio para obter mensagens parametrizados - você só precisa saber que Locale seu usuário está em (novamente, eu tenho o Locale vinculado a uma propriedade backing bean por isso é acessível através JSF ou Java) <. / p>
Eu acho parâmetros - particulares em mensagens - são uma coisa JSF poderia realmente fazer melhor
!Eu estive pensando sobre isso mais, e ocorre-me que eu provavelmente poderia escrever minha própria função JSTL que leva uma chave de mensagem e um número variável de parâmetros:
<h:outputText value="#{my:message('label.widget.count', widgetCount)}"/>
e se a minha função de mensagem HTML-codifica o resultado antes da saída, eu não teria sequer precisa usar o h: outputText
#{my:message('label.widget.count', widgetCount)}
Você pode usar o Seam Interpolator:
<h:outputText value="#{interpolator.interpolate(messages['label.widget.count'], widgetCount)}"/>
Tem @BypassInterceptors sobre ele para que o desempenho deve ser ok.
Você pode usar o feijão diretamente se você interpolar as mensagens.
label.widget.count = You have a total of #{widgetCount} widgets.
label.welcome.message = Welcome to #{request.contextPath}!
label.welcome.url = Your path is ${pageContext.servletContext}.
${messages['label.widget.count']}
é enougth.
Este funciona muito bem usando Spring:
package foo;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ExpressionFactory;
import javax.el.ResourceBundleELResolver;
import javax.faces.context.FacesContext;
import org.springframework.web.jsf.el.SpringBeanFacesELResolver;
public class ELResolver extends SpringBeanFacesELResolver {
private static final ExpressionFactory FACTORY = FacesContext
.getCurrentInstance().getApplication().getExpressionFactory();
private static final ResourceBundleELResolver RESOLVER = new ResourceBundleELResolver();
@Override
public Object getValue(ELContext elContext, Object base, Object property)
throws ELException {
Object result = super.getValue(elContext, base, property);
if (result == null) {
result = RESOLVER.getValue(elContext, base, property);
if (result instanceof String) {
String el = (String) result;
if (el.contains("${") | el.contains("#{")) {
result = FACTORY.createValueExpression(elContext, el,
String.class).getValue(elContext);
}
}
}
return result;
}
}
E ...
Você precisa mudar o EL-Resolver em faces-config.xml
de org.springframework.web.jsf.el.SpringBeanFacesELResolver
para
Saudações
<el-resolver>foo.ELResolver</el-resolver>
Use arquivos ResourceBundle e propriedade.