关于Java:JSF / Facelets中的国际化标签

Internationalised labels in JSF/Facelets

Facelets是否具有通过使用JSF可以更整洁或更可读的国际化用户界面文本标签的功能?

例如,对于纯JSF,使用h:outputFormat是在消息中插入变量的非常冗长的方法。

说明:我知道我可以添加一个如下所示的消息文件条目:

1
label.widget.count = You have a total of {0} widgets.

并显示以下内容(如果我正在使用Seam):

1
2
3
<h:outputFormat value="#{messages['label.widget.count']}">
   <f:param value="#{widgetCount}"/>
</h:outputFormat>

但是输出一个句子会很混乱-只是那种使JSF不好名的东西。


由于您正在使用Seam,因此可以在消息文件中使用EL。

属性:

1
label.widget.count = You have a total of #{widgetCount} widgets.

XHTML:

1
<h:outputFormat value="#{messages['label.widget.count']}" />

这仍然使用outputFormat,但是不太冗长。


您可以使用接缝内插器:

1
<h:outputText value="#{interpolator.interpolate(messages['label.widget.count'], widgetCount)}"/>

上面带有@BypassInterceptors,因此性能应该可以。


您可以创建自己的faces标签库,以使其不再那么冗长,例如:

1
<ph:i18n key="label.widget.count" p0="#{widgetCount}"/>

然后在视图目录中创建taglib:/components/ph.taglib.xml

1
2
3
4
5
6
7
8
9
10
11
12
<?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>

创建/components/i18n.xhtml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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>

通过一些研究,您可能会找到一种传递论点的优雅方法。

现在在web.xml中注册新的taglib

1
2
3
4
5
6
<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>
        /components/ph.taglib.xml
    </param-value>
</context-param>

只需将xmlns:ph="http://peterhilton.com/core"添加到您的视图中,便一切就绪!


我一直在考虑这个问题,我想到我可能可以编写自己的JSTL函数,该函数需要一个消息密钥和可变数量的参数:

1
<h:outputText value="#{my:message('label.widget.count', widgetCount)}"/>

,如果我的消息功能在输出之前对结果进行HTML编码,则我什至不需要使用h:outputText

1
#{my:message('label.widget.count', widgetCount)}


除了outputFormat之外,我再也没有遇到过其他方法。不幸的是,它很冗长。

我只能建议的另一件事是在后备bean中创建消息,然后将其输出而不是messageFormat。

在我的情况下,我将Spring的MessageSource与JSF集成在一起(使用MessageSourcePropertyResolver)。然后,在支持bean中获取参数化消息非常容易-您只需要知道用户所在的语言环境即可(同样,我将Locale绑定到支持bean属性,因此可以通过JSF或Java对其进行访问)。铅>

我认为参数-特别是消息中的参数-是JSF确实可以做得更好的一件事!


如果对消息进行插值,则可以直接使用Bean。

1
2
3
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']}是整数。

使用Spring可以很好地工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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;
    }
}

然后...

您需要将faces-config.xml中的EL-Resolver从org.springframework.web.jsf.el.SpringBeanFacesELResolver更改为

致谢

1
<el-resolver>foo.ELResolver</el-resolver>


使用ResourceBundle和属性文件。