<f:viewparam>的验证/转换错误不会本地化为<f:view locale =“”>,而是默认语言环境</f:view> </f:viewparam>

时间:2013-08-28 18:34:43

标签: validation jsf jsf-2 localization viewparams

我在JSF页面上有一个<f:viewParam>标记,它在转换和验证后将GET参数设置为相应的托管bean。

如果发生转换或验证错误,则会从资源包中提取相应的错误消息并显示在<p:messages>上(也可能是<p:growl><h:messages>)。

该应用程序是多语言的。因此,当选择其他语言时,应以该语言显示消息,但它始终根据默认语言环境en(英语)显示消息。

Test.xhtml:

<!DOCTYPE html>
<html lang="#{localeBean.language}"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">

    <f:view locale="#{localeBean.locale}">
        <f:metadata>
            <f:viewParam name="id" converter="#{myConverter}" />
        </f:metadata>
        <h:head>
            <title>Test</title>
        </h:head>
        <h:body>
            <h:messages />
        </h:body>
    </f:view>
</html>

转换器:

@FacesConverter("myConverter")
public final class MyConverter implements Converter
{
    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value)
    {
        ResourceBundle bundle = context.getApplication()
            .evaluateExpressionGet(context, "#{messages}", ResourceBundle.class);
        String message = bundle.getString("id.conversion.error");
        throw new ConverterException(
            new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value)
    {
        throw new UnsupportedOperationException(); // Not relevant in this problem.
    }
}

<f:viewParam>的消息外,没有问题。所有其他类型的消息都以用户选择的语言显示。

<f:viewParam>有什么特别之处吗?

1 个答案:

答案 0 :(得分:6)

我可以重现你的问题。 Mojarra 2.1.25和MyFaces 2.1.12都暴露了同样的问题。因此,我不确定这是否是JSF impl中的错误或JSF规范中的疏忽。到目前为止,事实证明,在输入呈现响应阶段之前,尚未为GET请求设置viewroot语言环境。转换器在验证阶段运行,远远早于渲染响应,这解释了为什么它得到了默认的语言环境。我必须稍后进行调查,如有必要,向Mojarra报告问题。

同时,解决这个问题的最佳方法是按以下方式获取包,而不是EL评估<resource-bundle><var>

String basename = "com.example.i18n.message"; // Exactly the same as <resource-bundle><base-name>
Locale locale = context.getApplication().evaluateExpressionGet(context, "#{localeBean.locale}", Locale.class);
ResourceBundle bundle = ResourceBundle.getBundle(basename, locale);
// ...

更新:我已根据此问题报告了issue 3021。我仍然无法理解规范在这一点上所说的内容,但我发现实现的行为不直观。


更新2 :Mojarra和MyFaces的家伙同意这一点。对于Mojarra来说,根据2.2.5(没有2.1.x backport还是?)已经fixed,对于MyFaces来说,根据2.0.19,2.1.13和2.2.0,它是fixed