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

Posted

技术标签:

【中文标题】<f:viewParam> 的验证/转换错误不会本地化到 <f:view locale>,而是本地化到默认语言环境【英文标题】:Validation/conversion errors of <f:viewParam> do not localize to <f:view locale>, but to default locale 【发布时间】:2013-08-31 23:39:00 【问题描述】:

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

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

该应用程序是多语言的。 Therefore when a different language is selected, a message should be displayed in that language but it always displays the message according to the default locale en (for English).

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.
    

除了&lt;f:viewParam&gt;的消息外,没有问题。所有其他类型的消息都以用户选择的语言显示。

&lt;f:viewParam&gt; 有什么特别之处吗?

【问题讨论】:

【参考方案1】:

我可以重现您的问题。 Mojarra 2.1.25 和 MyFaces 2.1.12 都暴露了同样的问题。因此,我不确定这是 JSF impl 中的错误还是 JSF 规范中的疏忽。到目前为止,在进入渲染响应阶段之前,没有为 GET 请求设置 viewroot 区域设置。转换器在验证阶段运行,远在渲染响应之前,这解释了为什么它改为使用默认语言环境。我必须稍后对其进行调查,并在必要时向 Mojarra 报告问题。

同时,解决此问题的最佳办法是按如下方式获取捆绑包,而不是通过 EL 评估 &lt;resource-bundle&gt;&lt;var&gt;

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 中是 fixed(还没有 2.1.x 反向移植?),对于 MyFaces,它是在 2.0.19、2.1.13 和 2.2.0 中的 fixed。

【讨论】:

我看不到这个方法evaluateExpressionGet(String expression)。我只能看到public &lt;T&gt; T evaluateExpressionGet(FacesContext context, String expression, Class&lt;? extends T&gt; expectedType) throws ELException。有吗? 抱歉,我发布了一个过于简单的示例(实际上,我使用了来自org.omnifaces.util.Faces 的静态导入)并错误地假设您会理解有关方法工作的提示。我更新了答案。 似乎在处理视图元数据时,没有考虑到外部的 f:view 标签,但理论上不应该这样,因为 f:view 是特殊的。对我来说似乎是一个错误。 @lu4242:感谢您的关注。是否已有针对此问题的 MyFaces 票证? @BalusC:我创建了这个问题MYFACES-3781 f:view tag must be processed when view metadata is created。

以上是关于<f:viewParam> 的验证/转换错误不会本地化到 <f:view locale>,而是本地化到默认语言环境的主要内容,如果未能解决你的问题,请参考以下文章

f:viewParam 具有多个值

当 URL 中没有参数时,将 f:viewParam 属性设置为 null

如何在不调用 <f:viewparam> 转换器的情况下调用 setter?

f:viewParam 在 ajax 调用后丢失

将 f:viewParam 与必需的属性和命令一起使用

如果位于 template.xhtml 中,JSF f:viewParam 不调用 setter