jokeymzx 发表于 2013-2-6 08:49:23

JSF1.2 中实现国际化

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"));
页: [1]
查看完整版本: JSF1.2 中实现国际化