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 名声不好。

4

7 回答 7

5

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

财产:

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

XHTML:

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

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

于 2008-09-19T08:31:51.047 回答
3

除了 outputFormat 之外,我从未遇到过另一种方法。不幸的是,它非常冗长。

我唯一可以建议的另一件事是在支持 bean 中创建消息,然后输出它而不是 messageFormat。

就我而言,我将 Spring 的 MessageSource 与 JSF 集成(使用MessageSourcePropertyResolver)。然后,在您的支持 bean 中获取参数化消息相当容易——您只需要知道您的用户所在的区域设置(同样,我已将区域设置绑定到支持 bean 属性,因此可以通过 JSF 或 Java 访问它)。

我认为参数——尤其是消息中的参数——是 JSF 真正可以做得更好的一件事!

于 2008-09-18T14:46:45.130 回答
3

我一直在思考这个问题,我突然想到我可能会编写自己的 JSTL 函数,该函数接受消息键和可变数量的参数:

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

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

#{my:message('label.widget.count', widgetCount)}
于 2008-09-19T07:35:59.387 回答
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"到您的视图中,一切就绪!

于 2009-03-17T23:11:09.247 回答
3

您可以使用接缝插值器:

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

它上面有@BypassInterceptors,所以性能应该没问题。

于 2009-04-07T12:10:33.080 回答
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;
    }
}

和...

您需要将 EL-Resolverfaces-config.xml从更改org.springframework.web.jsf.el.SpringBeanFacesELResolver

问候

<el-resolver>foo.ELResolver</el-resolver>
于 2014-02-16T06:52:58.340 回答
-1

使用 ResourceBundle 和属性文件。

于 2008-09-18T13:07:06.697 回答