如何在JSF 2.0中更改语言环境?

Raj*_*ajV 8 jsf jsf-2

在我的应用程序中,用户应该能够切换语言环境(用于在页面上呈现文本的语言).大量的教程正在使用FacesContext.getCurrentInstance().getViewRoot().setLocale().例如:http://www.mkyong.com/jsf2/jsf-2-internationalization-example/.但是,这根本不适用于JSF 2.0(它确实在1.2中工作).语言永远不会切换.没有错误或任何东西.相同的代码在JSF 1.2中运行良好.

什么是正确和明确的方法?我拼凑了一个解决方案,但不确定这是否正确.这很好用.用户点击英语或法语后语言切换.这是代码片段,为您提供一些想法.

@ManagedBean(name = "switcher")
@SessionScoped
public class LanguageSwitcher {
    Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
    public String switchLocale(String lang) {
        locale = new Locale(lang);

        return FacesContext.getCurrentInstance().getViewRoot().getViewId() +
            "?faces-redirect=true";
    }
    //getLocale() etc. omitted for brevity
}
Run Code Online (Sandbox Code Playgroud)

XHTML:

<f:view locale="#{switcher.locale}">
    <h:outputText value="#{msg.greeting}" />
    <h:commandLink value="English" action="#{switcher.switchLocale('en')}" />
    <h:commandLink value="French" action="#{switcher.switchLocale('fr')}" />
</f:view>
Run Code Online (Sandbox Code Playgroud)

只是为了给你更多信息,这是配置文件.

<application>
    <locale-config>
        <supported-locale>en</supported-locale>
        <supported-locale>fr</supported-locale>
    </locale-config>
    <resource-bundle>
        <base-name>com.resources.Messages</base-name>
        <var>msg</var>
    </resource-bundle>
</application>
Run Code Online (Sandbox Code Playgroud)

再次,这是有效的.但是,我没有以任何方式调用任何API来改变JSF本身的语言环境.这给了我一些令人毛骨悚然的感觉.这是更改用户区域设置的正确方法吗?

Raj*_*ajV 8

好的,冒着回答我自己的问题的风险,我想总结一下我找到的所有不同的方法.

基本方法就是我已经在做的事情.也就是说,在会话范围内有一个托管bean,它返回用户的Locale.需要在每个XHTML中使用此语言环境<f:view locale="...">.我从BalusC的一篇文章中学到了这个技术,所以谢谢你的到来.

现在,关注的是使用f:view元素.这需要在每一页中重复,如果错误地省略,则可能是缺陷的潜在来源.我找到了几种解决这个问题的方法.

方法#1:创建一个Facelet模板并在那里添加f:view元素.单个模板用户页面不必担心添加此元素.

方法#2使用阶段监听器.@meriton已经在这里发布了解决方案.谢谢你.

方法#3使用自定义视图处理程序,该处理程序扩展MultiViewHandler并从calculateLocale()方法返回用户的语言环境.这在Beginning JSF 2 API和JBoss Seam By:Kent Ka Iok Tong一书中有所描述.以下是本书中略有修改的示例:

public class MyViewHandler extends MultiViewHandler {
    public Locale calculateLocale(FacesContext context) {
        HttpSession session = (HttpSession) context.getExternalContext()
            .getSession(false);
        if (session != null) {
            //Return the locale saved by the managed bean earlier
            Locale locale = (Locale) session.getAttribute("locale");
            if (locale != null) {
                return locale;
            }
        }
       return super.calculateLocale(context);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在faces config中注册它.

<application>
    <view-handler>com.package.MyViewHandler</view-handler>
<!-- Other stuff ... -->
</application>
Run Code Online (Sandbox Code Playgroud)

这比阶段监听器更优雅.不幸的是,MultiViewHandler是com.sun.faces.application.view包中的内部非API类.这会带来一些风险.

使用方法#2或#3,页面中不需要f:view元素.

  • *现在,关注的是使用f:view元素.这需要在每一页中重复,如果错误地省略,则可能是缺陷的潜在来源.*只需使用Facelets模板化? (2认同)