当我使用<fmt:setlocale>时,为什么我的JSP不显示在德语(de_DE)语言环境中?</fmt:setlocale>

时间:2010-11-13 07:14:41

标签: jsp jstl locale resourcebundle setlocale

我创建了以下JSP:

<!-- WebContent/pages/ResourceBundlesJST.jsp -->
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="java.text.*" %>
<%@ page import="java.util.*" %>
<%@ page import="hu.flux.locale.LanguageToolkit" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%  
    Locale locale = LanguageToolkit.getLanguage(request);
    //String locale = LanguageToolkit.getLanguageString(request);
%>
<fmt:setLocale value="${locale}" />
<fmt:bundle basename="hu.flux.locale.resources.TestResources">
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Insert title here</title>
    </head>
    <body>
        <h1><fmt:message key="greetHeading"/></h1>
        <p><fmt:message key="welcomeText"/></p>
        <p>Your locale is <%= locale %>.</p>
        <form action="your_form_handler_here" method="post">
            <div>
                <label for="name"><fmt:message key="namePrompt"/></label>
                <input type="text" id="name" name="name">
            </div>
            <div>
                <label for="age"><fmt:message key="agePrompt"/></label>
                <input type="text" id="age" name="age">
            </div>
            <div>
                <label for="place"><fmt:message key="placePrompt"/></label>
                <input type="text" id="place" name="place">
            </div>
            <input type="submit" value="<fmt:message key="submitButtonText"/>">
        </form>
    </body>
    </html>
</fmt:bundle>

当我尝试使用此网址访问该网页时:

http://localhost:8080/SamsTeachYourselfJSP/pages/ResourceBundlesJSTL.jsp?languageOverride=de_DE

这将显示在屏幕上:

Hello!

Welcome to our web site. Please take a moment to fill out our survey

Your locale is de_DE.

What is your name:  
How old are you:  
Where do you live:  

该页面显然正在查找和使用英语属性文件而不是德语属性文件,即使服务器选择了我的参数来将语言环境设置为de_DE并接受命令来设置语言环境。

我希望它调用的资源包含:

# /src/hu/flux/locale/resources/TestResources_de.properties
namePrompt=Wie hei[gb]en Sie:
agePrompt=Wie alt sind Sie:
placePrompt=Wo wohnen Sie:
greetHeading=Guten Tag!
welcomeText= Willkommen bei unserer Web-Site.  Bitte, dauern Sie einen Moment Um unsere Umfrage auszufüllen
submitButtonText=Senden

我很确定问题不在我的LanguageToolkit类中,因为它适用于此页面的非JSTL版本,但如果有人想看到它:

/**
 * /src/hu/flux/locale/LanguageToolkit.java
 */
package hu.flux.locale;

import java.util.Locale;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;

/**
 * @author Brian Kessler
 *
 */
public class LanguageToolkit {

    /**
     * 
     */
    public LanguageToolkit() {
        // TODO Auto-generated constructor stub
    }

    public static Locale getLanguage(HttpServletRequest request)
    {
        Locale locale = Locale.getDefault();

        // Get the browser's preferred language.
        String acceptLangString = request.getHeader("ACCEPT-LANGAUGE");

        // Allow the user to override the browser's langauge setting.
        // This lets you test with tools such as Babelfish 
        // (which isn't that great at translating to begin with).
        String override = request.getParameter ("languageOverride");
        if (override != null) { acceptLangString = override; }

        // If there is an ACCEPT-LANGUAGE header, parse it.
        if (acceptLangString != null) 
        {  
            Locale acceptedLocale = parseLangString (acceptLangString);
            if (acceptedLocale != null) {locale = acceptedLocale;}
        }

        return locale;
    }

    public static String getLanguageString(HttpServletRequest request)
    {
        String locale = "EN-uk";

        // Get the browser's preferred language.
        String acceptLangString = request.getHeader("ACCEPT-LANGAUGE");

        // Allow the user to override the browser's langauge setting.
        // This lets you test with tools such as Babelfish 
        // (which isn't that great at translating to begin with).
        String override = request.getParameter ("languageOverride");
        if (override != null) { acceptLangString = override; }

        // If there is an ACCEPT-LANGUAGE header, parse it.
        if (acceptLangString != null)  {locale = acceptLangString;}

        return locale;
    }

    private static Locale parseLangString(String acceptLangString) 
    {
        // The accepted languages should be separated by commas, but also
        // add space as a separator to eliminate whitespace.
        StringTokenizer localeParser = new StringTokenizer(acceptLangString, " ,");

        // See whether there is a language in the list (you need only the first one).
        if (localeParser.hasMoreTokens())
        {
            // Get the locale.
            String localeStr = localeParser.nextToken();

            // The local should be in the format ll-CC where 11 is the language
            // and CC is the country, like en-US for English in the U.S. and
            // de-DE for German in Germany.  Allow the browser to use _ instead
            // of -, too.
            StringTokenizer localeSplitter = new StringTokenizer (localeStr, "_-");

            // Assume both values are blank.
            String language = "";
            String country = "";

            // See whether a language is specified.
            if (localeSplitter.hasMoreTokens()) {language = localeSplitter.nextToken(); }

            // See whether a country is specified (there won't always be one).
            if (localeSplitter.hasMoreTokens()) {country = localeSplitter.nextToken(); }

            // Create a local based on this language and country (if country is blank,
            // you'll still get locale-based text, but currencies won't display correctly.
            return (new Locale(language, country));
        }
        return null;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

}

为什么我会看到英语以及如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

有两个问题:

首先,fmt:setLocale TLDDOC说明如下:

  

value - java.lang.String - 字符串值被解释为区域设置的可打印表示形式,必须包含两个字母(小写)语言代码(由ISO-639)定义,并且可以包含两个字母(大写)国家代码(由ISO-3166定义)。语言和国家/地区代码必须用连字符( - )或下划线(_)分隔。

换句话说,您无法使用java.util.Locale设置它。

其次,在EL中无法访问使用 scriptlet 声明的任何内容。 EL只能通过其PageContext方法访问HttpServletRequestHttpSessionServletContextsetAttribute()中放置的属性。在封面下,EL基本上为${name}执行了pageContext.findAttribute(name)。从最少到最佳推荐顺序基本上有4种解决方案:

  1. <fmt:setLocale>
  2. 中使用 scriptlet 代替EL
  3. 将区域设置放在 scriptlet request.setAttribute("locale", locale);的请求范围内。
  4. Get rid scriptlets 并声明LanguageToolkit为EL函数。
  5. 创建一个Filter来完成工作。

  6. 也就是说,我建议在这种特殊情况下使用<fmt:setBundle>代替<fmt:bundle>,因为您似乎想要覆盖整个页面。我还建议使用HttpServletRequest#getLocale()而不是手动解析请求标头。正确的算法比你目前的算法更复杂。