代码之家  ›  专栏  ›  技术社区  ›  Peter Hilton

JSF/Facelets中的国际化标签

  •  5
  • Peter Hilton  · 技术社区  · 16 年前

    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 回复  |  直到 16 年前
        1
  •  3
  •   Daan van Yperen    15 年前

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

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

    然后在视图目录中创建taglib:/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中注册新的taglib

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

    只要添加 xmlns:ph="http://peterhilton.com/core" 以你的观点,你已经准备好了!

        2
  •  5
  •   Sietse    16 年前

    既然你用的是Seam, you can use EL 在消息文件中。

    财产:

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

    XHTML:

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

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

        3
  •  3
  •   user7094    16 年前

    除了输出格式,我从来没有遇到过其他的方法。不幸的是,它相当冗长。

    我唯一能建议的另一件事是在一个支持bean中创建消息,然后输出该消息,而不是messageformat。

    在我的例子中,我将Spring的messagesource与JSF集成(使用 MessageSourcePropertyResolver )。然后,在你的后援bean中很容易得到参数化的消息——你只需要知道你的用户所在的区域(同样,我已经把区域绑定到了一个支持Bean的属性,所以它可以通过JSF或Java访问)。

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

        4
  •  3
  •   Peter Hilton    16 年前

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

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

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

    #{my:message('label.widget.count', widgetCount)}
    
        5
  •  3
  •   Damo    15 年前

    可以使用接缝插值器:

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

    它上面有@bypass拦截器,所以性能应该可以。

        6
  •  1
  •   Grim    11 年前

    如果插入消息,可以直接使用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']} 是真的。

    这一款使用弹簧效果很好:

    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解析器 faces-config.xml org.springframework.web.jsf.el.SpringBeanFacesELResolver

    当做

    <el-resolver>foo.ELResolver</el-resolver>
    
        7
  •  -1
  •   Javaxpert    16 年前

    使用ResourceBundle和属性文件。