当前位置: 首页 > 知识库问答 >
问题:

如何在JSF2.0中更改语言环境?

南宫喜
2023-03-14

在我的应用程序中,用户应该能够切换区域设置(用于在页面上呈现文本的语言)。大量教程使用FacesContext.get货币实例()。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
}

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>

为了给你更多信息,这里是配置文件。

<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>

同样,这是可行的。但是,我没有通过以任何方式调用任何应用编程接口来改变JSF本身的区域设置。这给我一种令人毛骨悚然的感觉。这是改变用户区域设置的正确方法吗?

共有3个答案

咸承教
2023-03-14

我最近遇到了一个相关的问题。在我的例子中,JSF实现忘记了由UIViewRoot设置的视图区域设置。导航到其他视图后,设置Locale()。我认为这是JSF IMPL中的一个bug,但我没有时间确定。

我不是特别喜欢<代码>

/**
 * PhaseListener that keeps the current view locale in the session while no request is being processed, to work around
 * bugs where JSF forgets the changed locale.
 */
public class SaveViewLocaleToSessionPhaseListener implements PhaseListener {

    private static final String key = "locale";

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        // do nothing
    }

    @Override
    public void afterPhase(PhaseEvent event) {
        PhaseId currentPhase = event.getPhaseId();
        if (currentPhase == PhaseId.RESTORE_VIEW) {
            viewRoot().setLocale((Locale) sessionMap().get(key));
        } else if (currentPhase == PhaseId.RENDER_RESPONSE) {
            sessionMap().put(key, viewRoot().getLocale());
        }
    }

    private  Map<String, Object> sessionMap() {
        return FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
    }

    private UIViewRoot viewRoot() {
        return FacesContext.getCurrentInstance().getViewRoot();
    }
}

然而,我不能提供任何确凿的证据来证明这真的比简单地使用更好。

但是,我没有以任何方式改变JSF本身的语言环境。

你当然知道: The

丰赞
2023-03-14

可以使用扩展javax的自定义视图处理程序。面孔。应用ViewHandlerWrapper并从calculateScale()方法返回用户的区域设置。

这绝对比从专有的SUN包com.sun.faces.application.view中扩展MultiViewHandler更好,无论您的建议中提到的《开始JSF 2 API》一书中描述了什么。除此之外,您最初的方法绝对可以:

public class MyViewHandler extends ViewHandlerWrapper {

  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);
  }
}

然后将其注册到人脸配置中。

    <application>
      <view-handler>com.package.MyViewHandler</view-handler>
      <!-- Other stuff ... -->
    </application>
荀豪
2023-03-14

好吧,冒着回答我自己问题的风险,我想总结一下我发现的所有不同的方法。

基本方法是我已经在做的事情。也就是说,在会话范围内有一个托管bean,它返回用户的语言环境。需要在每个XHTML中使用

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

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

方法2使用相位侦听器。@meriton在这里发布了解决方案。谢谢你。

方法#3使用自定义视图处理程序,该处理程序扩展了MultiViewHandler,并从calculateScale()方法返回用户的区域设置。这在Kent Ka-Iok Tong的《JSF 2 API和JBoss Seam开头》一书中有描述。以下是本书中一个稍加修改的例子:

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);
    }
}

然后将其注册到人脸配置中。

<application>
    <view-handler>com.package.MyViewHandler</view-handler>
<!-- Other stuff ... -->
</application>

这比phase listener更优雅。不幸的是,MultiViewHandler是com中的一个内部非API类。太阳面孔。应用查看软件包。这会带来一些风险。

无论使用#2还是#3,页面中都不需要f:view元素。

 类似资料:
  • 问题内容: 我有一个Action类,我想获取应用程序的语言环境并在此处进行更改,但是我不知道怎么做,也找不到答案。 我可以使用获取当前的语言环境 但是我不知道如何 设置语言环境 。 我想在上述Action类中直接为我的应用更改语言环境。我怎样才能做到这一点? 问题答案: 使用和将其放在HTTP会话中 。

  • 问题内容: 我在Edittext的addTextChangedListener方法中已自定义,一切正常,但是当我更改语言(语言环境)时,我的addTextChangedListener无法正常工作。 我搜索了我的问题并找到了解决方案: 但我不知道如何使用此代码。 问题答案: 您可以尝试先转换为,然后将其投射到

  • 我正在开发一个应用程序,使用3种语言的文本。英语、库尔德语和阿拉伯语。我试图在用户更改语言时动态更改布局。我有一个设置屏幕,用户可以在其中更改语言,即我不是在系统设置中更改语言,而是在我的应用程序中更改语言。例如,如果我从库尔德语切换到英语,布局应该从RTL更改为LTR,反之亦然。我尝试使用onConfigUserOnChanged(),但它没有被触发。 更改区域设置:强制活动重新加载资源?找到了

  • 问题内容: 我希望能够在运行时在Swing应用程序中更改语言环境,并使用来自新语言环境的ResourceBundle的本地化文本来更新屏幕上的所有文本元素。 是否可以在不自定义摆动组件或为处理呈现本地化文本的所有组件创建UIDelegates的情况下完成此操作? 如果没有,那么我可以考虑实施什么好的解决方案? 问题答案: 您有一种方法可用于更改应用程序区域设置(并可能保留新值),而另一种方法可用于

  • 问题内容: 我有一列是时间戳。 它记录如下内容: 然后我在php中使用它: 它可以输出如下内容: 我的问题是,如何更改日期文本,使其以另一种语言(特别是瑞典语)输出月份名称? 例如:1月为瑞典文Januari 谢谢 问题答案: 本地的PHP函数是 strftime() 。 %B 完整月份的名称,基于从1月到12月的语言环境 如果服务器不在瑞典语言环境中,请使用 setlocale() 。 也就是说

  • 我熟悉Java,但只是学习Android编程。我非常喜欢他们的Hello,LinearLayout示例中的颜色栏,所以我一直在尝试将其扩展为一个可以用于我13个月大的孩子的小程序。我让它显示七种颜色的标签和四行。我想做的一件事(因为我会双语),就是能够动态更改区域设置显示语言,而无需退出应用程序,加载新区域设置,然后再次启动应用程序(这很有效,但很乏味)。因此,七个颜色条的标签适合所选语言,但我希