JSF/Facelets中的国际化标签

5

Facelets是否有更整洁或更易读的国际化用户界面文本标签功能,以比使用JSF时更好地完成此操作?

例如,对于普通的JSF,使用h:outputFormat是一种非常冗长的方法来插入消息中的变量。

澄清:我知道我可以添加一个类似于消息文件条目的条目:

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

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

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

但是为了输出一句话而产生这么多杂乱的代码 - 这正是使JSF声名狼藉的原因。

7个回答

5

由于您使用的是Seam框架,您可以在消息文件中使用EL表达式

属性:

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

XHTML:

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

这仍然使用outputFormat,但不那么冗长。


这种方法的唯一限制是你必须使用#{widgetCount}标签或者显式地输出"widgetCount"才能使用它。 - Damo

3
您可以使用Seam Interpolator:
<h:outputText value="#{interpolator.interpolate(messages['label.widget.count'], widgetCount)}"/>

它上面有@BypassInterceptors,因此性能应该还好。


3
您可以创建自己的面部标签库,使其更简洁明了,例如:
您可以创建自己的面部标签库,使其更简洁明了,例如:
<ph:i18n key="label.widget.count" p0="#{widgetCount}"/>

然后在您的视图目录中创建标签库:/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>

创建/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>

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

现在在web.xml中注册您的新标签库。

<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>
        /components/ph.taglib.xml
    </param-value>
</context-param>

只需在您的视图中添加xmlns:ph="http://peterhilton.com/core",您就可以开始了!


很好的答案,接近我们目前所做的。主要问题是你不能在属性值内使用它。 - Peter Hilton

3

我思考了一下,发现我可以自己编写一个JSTL函数,该函数接受消息键和可变数量的参数:

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

如果我的消息函数在输出结果之前对HTML进行编码,那么我甚至不需要使用h:outputText。

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

如果你能够完成这个并使其正常工作,请给我发电子邮件分享代码 ;) 说真的,如果你能够在某处发布这个,它将成为一个很好的资源。 - user7094

3
我从未遇到过除了outputFormat之外的其他方法。不幸的是,这种方法相当冗长。
我唯一能建议的是在后备bean中创建消息,然后输出该消息,而不是使用messageFormat。
在我的情况下,我将Spring的MessageSource与JSF集成(使用MessageSourcePropertyResolver)。然后,在您的后备bean中获取参数化消息相当容易-您只需要知道用户所在的Locale(再次,我将Locale绑定到后备bean属性中,因此可以通过JSF或Java访问)。
我认为参数-特别是在消息中-是JSF可以真正做得更好的一件事!

1
如果您插入消息,可以直接使用Bean。
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时非常好用:

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 更改为

问候

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

请注意:可能会导致无限循环,请知道你在做什么。 - Grim

-1
使用ResourceBundle和属性文件。

你能再详细解释一下吗?我不明白你的意思,因为楼主已经说他正在使用那个了。 - Sietse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接