如何从Java代码中设置JSTL的语言环境?

18
我想设置JSTL语言环境,用于<fmt:formatNumber>等标签。我知道可以用<fmt:setLocale>实现,但我需要动态设置(根据从我的数据库检索到的用户数据)并且更喜欢使用Java代码 - 确切地说,是一个筛选器类。
我认为将会话属性javax.servlet.jsp.jstl.fmt.locale设置为我想要的Locale实例就可以解决问题,但这被忽略了:JSTL标记继续使用浏览器语言环境。
我验证了没有同名的页面上下文或请求属性。
那么我做错了什么?还是我真的需要从JSP中实现?
阅读JSTL代码,我找到了对LocalizationContext的引用,并认为我需要设置一个LocalizationContext。尽管如此,我无法弄清楚它具体如何适用于图像,也无法弄清楚如何设置一个LocalizationContext

你尝试过通过request.setAttribute()将Java值设置到请求中吗?JSTL(也可以)读取请求范围。 - Reporter
我刚才试了一下,但它没有改变任何东西。 - Jens Bannmann
5个回答

30

需要设置第二个:

JSTL区域设置的3种方式: /以及默认应用程序资源包、时区和数据源/

  1. 通过JSTL操作进行设置 - 这允许使用作用域属性指定范围。

<fmt:setLocale value="en_US" scope="session"/>
  • 编程设置 - 通过Config API允许范围的指定。

  • import javax.servlet.jsp.jstl.core.Config;
    (...)
    Config.set( session, Config.FMT_LOCALE, new java.util.Locale("en", "US") )
    // or Locale.forLanguageTag("en-US") (java 1.7 and later)
    
  • 上下文初始化参数设置 - 如果在任何标准范围内都找不到设置,则指定要使用的值。

  • <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.locale</param-name>
        <param-value>en_US</param-value>
    </context-param>
    

    jstl-quick-reference(PDF)


    12
    你可以在<fmt:setLocale>中使用EL表达式,不需要硬编码或其他方式。
    以下是一个示例:
    <c:set var="language" value="${not empty param.language ? param.language : not empty language ? language : pageContext.request.locale}" scope="session" />
    <fmt:setLocale value="${language}" />
    

    如果请求参数中提供了名称为language的语言,则将其设置。否则,如果会话中已经通过属性名称language设置了语言,则使用该语言。否则,使用请求标头中提供的用户提供的区域设置。
    如果您在过滤器代码中执行session.setAttribute("language", language),则将使用它——如果没有设置请求参数的话。
    另请参阅:

    我知道设置Locale时不需要硬编码的值。但是我仍然更喜欢在Java类中使用“干净”的解决方案。 - Jens Bannmann
    1
    我真的不明白从控制器内部调整视图标签库特定类如何更加“干净”。 - BalusC
    这显然是个品味问题。我个人更喜欢不依赖于JSP(包括)来做正确的事情。另一方面,Java代码可以通过单元测试进行覆盖,可以使用工具支持进行重构等等... - Jens Bannmann
    BalusC,也许OP想要的是在DRY传统中避免在每个JSP中调用<fmt:setLocale>的需要。 - Tahir Akhtar
    @Jens: 只需在过滤器中设置必要的属性,并在<fmt:setLocale>中引用它?我不明白这样会如何破坏单元测试或重构。 @Tahir:明智地使用模板/<jsp:include> - BalusC

    3
    据我所知,“javax.servlet.jsp.jstl.fmt.locale”被浏览器的语言环境所覆盖。JSTL使用浏览器的语言环境,如果找不到,则使用备用的语言环境。因此,您可以设置一个请求属性来指定该语言环境。将以下行添加到您的控制器中即可:
    request.setAttribute("javax.servlet.jsp.jstl.fmt.fallbackLocale.request", "en-us");
    

    使用这个将设置JSTL将使用的区域设置。请注意属性名称中的 .request ,如果将此属性设置为其他范围,则必须使用不同的后缀。对于HttpSession,后缀是 .session ,对于ServletContext,后缀是 .application

    0

    还有另一种方法。在servlet中,您可以通过创建会话属性来设置区域设置,如下所示:

    request.getSession().setAttribute("javax.servlet.jsp.jstl.fmt.locale.session", "ko-KR");
    

    0
    如果您依赖于数据库中的数据,可能有更好的方法将此逻辑插入到您的“路由器”或“控制器”中(取决于您使用的框架)。只需使用参数?lang='en'扩展URL即可。
    希望这可以帮助到您。

    我不明白这如何帮助JSTL。我仍然需要在JSP中添加fmt:setLocale标签,对吗?这正是我想避免的事情。 - Jens Bannmann

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接