欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JSF1.2 中实现国际化

程序员文章站 2022-05-24 09:48:29
...

JSF的<f:view>标签中可以通过locale属性来指定语言和区域信息来实现国际化,如:<f:view locale="#{indexBean.locale}">。
在实践中发现这个属性不起作用,后台IndexBean的locale已经改变,但是前台界面显示的语言没有跟这变化。
简单的跟踪一下代码发现大致的原因如下:

以index.jsp为例来说明:

1、第一次打开index.jsp页面,系统创建一个UIViewRoot对象,根据#{indexBean.locale}(默认为zh_CN)设置UIViewRoot对象locale值,这种情况下页面显示是正确。
2、在页面通过按钮或者选择列表改变#{indexBean.locale}的值为"en_US",按照设想页面显示的语言应该为英文,但实际情况还是中文。
  
   跟踪代码发现问题在UIComponentClassicTagBase.java的findComponent()方法中

      //获取UIViewRoot对象

      parentComponent = context.getViewRoot();

      if (null == parentComponent.getAttributes().get("javax.faces.webapp.CURRENT_VIEW_ROOT"))
      {
        try
        {
          //这个方法里面会用#{indexBean.locale}的值来设置UIViewRoot对象locale值
          //第一次打开index.jsp时,UIViewRoot对象是新建的所以parentComponent.getAttributes().get("javax.faces.webapp.CURRENT_VIEW_ROOT")==null
          //执行此方法。当通过通过触发页面上的按钮或者下拉列表重新绘制index.jsp时,由于JSF会保存的组件的状态而且可以恢复,此时的 UIViewRoot对象还是上次
          //创建的对象,所以 parentComponent.getAttributes().get("javax.faces.webapp.CURRENT_VIEW_ROOT")==null 这个条件不满足,因此也不会执行此方法。

          setProperties(parentComponent);
        }
        catch (FacesException e) {
          if (e.getCause() instanceof JspException) {
            throw ((JspException)e.getCause());
          }
          throw e;
        }

        if (null != this.id) {
          parentComponent.setId(this.id);
        }
        else {
          assert (null != getFacesJspId());
          parentComponent.setId(getFacesJspId());
        }
        parentComponent.getAttributes().put("javax.faces.webapp.CURRENT_VIEW_ROOT", "javax.faces.webapp.CURRENT_VIEW_ROOT");

        this.created = true;
      }
      else if (hasBinding()) {
        try {
          setProperties(parentComponent);
        }
        catch (FacesException e) {
          if (e.getCause() instanceof JspException) {
            throw ((JspException)e.getCause());
          }
          throw e;
        }

      } 
 


3、这个问题在MyFaces中没有发现,不知道是参考实现中的BUG还是使用方法的错误。

4、一个替代的解决方法是加入一个PhaseListener,然后在PhaseId.RENDER_RESPONSE之前直接调用UIViewRoot对象的setLocale方法来改变语言和区域信息。
    
     FacesContext.getCurrentInstance().getViewRoot().setLocale(new Locale("zh","CN"));

相关标签: JSF JSP F#