首先,我们将学习如何使用 JSTL Taglib 来本地化 JSP 页面。此外,我们还将演示如何使用请求参数、会话属性和 cookie 值在 JSP 页面中选择首选语言。此外,我们将使用Maven来设置该项目。因此,我们希望读者具备Java Web Application,JSP,JSTL和Maven的基本知识。您可以在 Phrase 的 GitHub 上找到本教程的完整实现。
内容
- 1. 项目设置
- 2. 本地化 JSP 页面
- 3. 动态选择区域设置
- 3.1. 使用请求参数作为区域设置
- 3.2. 使用会话属性作为区域设置
- 3.3. 使用浏览器 Cookie 作为区域设置
- 4. 结论
1. 项目设置
对于这个简单的JSP/Servlet Web应用程序,我们只需要将jstl和javax.servlet-api依赖项添加到我们的pom.xml文件中:
<properties>
<servlet.version>3.1.0</servlet.version>
<jstl.version>1.2</jstl.version>
</properties>
<dependencies>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
我们可以在Maven Central上找到这些依赖项的最新版本:jstl,javax.servlet-api
2. 本地化 JSP 页面
本地化 JSP 页面的基本方法是将 JSTL 与资源包结合使用。资源包是包含键值对的属性文件。每个值都是我们要在页面上显示的消息。而密钥将用于在我们的 JSP 页面上引用该值。因此,对于每种支持的语言,我们将有一个特定的属性文件。
现在,让我们在src/main/resources下创建一个默认的消息.属性文件,如下所示:
label.welcome = Welcome
接下来,我们创建一个欢迎.jsp页面,并将其放在 /webapp 文件夹下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page isELIgnored="false" %>
<fmt:setBundle basename="messages"/>
<html>
<head>
<title>PhraseApp - i18n</title>
</head>
<body>
<h2>
<fmt:message key="label.welcome" />
</h2>
</body>
</html>
在此页面中,我们使用<fmt:setBundle>标记来设置资源包。
因为我们的资源包文件是 messages.properties,所以,我们将 basename 属性的值设置为消息。此外,我们使用<ftm:message>标记来引用属性文件中定义的键。
在应用程序服务器上部署项目(在本例中为端口 8080 的 Tomcat 8.5)并访问欢迎.jsp页面上,我们将看到以下结果:
由于我们没有提到要用于页面的区域设置,因此将使用默认 messages.properties 文件中的消息。
现在,我们尝试通过添加另一个资源包文件来支持法语,该文件messages_fr.properties,如下所示:
label.welcome = Bienvenue
然后,我们修改了 welcome.jsp 页面以使用以下新语言:
.....
<fmt:setLocale value="fr"/>
<fmt:setBundle basename="messages" />
.....
在这里,通过使用<fmt:setLocale>标记将首选区域设置设置为fr,当我们加载页面时,将使用新的messages_fr.properties文件。因此,我们将看到以下结果:
在此之前,我们可以注意到资源包属性文件的名称将具有以下格式:
[basename]_[locale].properties
因此,我们可以通过添加messages_zh.properties和messages_de.properties来支持其他语言,例如中文和德语。
值得注意的是,如果我们将区域设置设置为不存在的资源包文件,则应用程序将使用 messages.properties 文件作为默认显示文件。
3. 动态选择区域设置
我们已经探讨了如何为 JSP 页面设置首选语言环境。如果我们知道如何动态地执行此操作,那将是有用的。在本节中,我们将了解如何使用请求参数、会话属性和浏览器 Cookie 设置页面区域设置。
3.1. 使用请求参数作为区域设置
让我们创建请求Locale.jsp如下所示:
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page isELIgnored="false"%>
<fmt:setLocale value="${param.lang}" />
<fmt:setBundle basename="messages" />
<html lang="${param.lang}">
<head>
<title>PhraseApp - i18n</title>
</head>
<body>
<h2>
<fmt:message key="label.chooseRequestLocale" />
</h2>
<p>
<fmt:message key="label.requestLocaleContent" />
</p>
<p>
<fmt:message key="label.changeLang" />
</p>
<ul>
<li><a href="?lang=en"><fmt:message key="label.lang.en" /></a></li>
<li><a href="?lang=de"><fmt:message key="label.lang.de" /></a></li>
<li><a href="?lang=fr"><fmt:message key="label.lang.fr" /></a></li>
<li><a href="?lang=zh"><fmt:message key="label.lang.cn" /></a></li>
</ul>
</body>
</html>
在此页中,我们将区域设置设置为请求参数 lang 的值。因此,当访问参数 lang=zh 的页面时,我们将看到以下结果:
3.2. 使用会话属性作为区域设置
同样,要使用 session 属性设置区域设置,我们可以实现 sessionLocale.jsp如下所示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page isELIgnored="false" %>
<%@ page session="true" %>
<fmt:setLocale value="${sessionScope.lang}"/>
<fmt:setBundle basename="messages"/>
<html lang="${sessionScope.lang}">
<head>
<title>PhraseApp - i18n</title>
</head>
<body>
<h2>
<fmt:message key="label.welcome" />
</h2>
<p>
<fmt:message key="label.sessionLocaleContent" />
</p>
</body>
</html>
在此示例中,我们将 sessionScope 中的属性 lang 称为首选区域设置。
因此,让我们创建一个 SessionLocaleFilter 来更新 session 属性 lang:
@WebFilter(filterName = "SessionLocaleFilter", urlPatterns = {"/*"})
public class SessionLocaleFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if (req.getParameter("sessionLocale") != null) {
req.getSession().setAttribute("lang", req.getParameter("sessionLocale"));
}
chain.doFilter(request, response);
}
public void destroy() {}
public void init(FilterConfig arg0) throws ServletException {}
}
此筛选器将检查请求参数 sessionLocale 是否可用于传入请求。如果是,筛选器会将当前会话的属性 lang 更新为该值。
现在,让我们创建一个 changeLocale.jsp 页面来帮助我们更新此会话属性:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page isELIgnored="false" %>
<fmt:setLocale value="${param.lang}"/>
<fmt:setBundle basename="messages"/>
<html lang="${param.lang}">
<head>
<title>PhraseApp - i18n</title>
</head>
<body>
<h2>
<fmt:message key="label.chooseSessionLocale" />
</h2>
<ul>
<li><a href="?sessionLocale=en"><fmt:message key="label.lang.en" /></a></li>
<li><a href="?sessionLocale=de"><fmt:message key="label.lang.de" /></a></li>
<li><a href="?sessionLocale=fr"><fmt:message key="label.lang.fr" /></a></li>
<li><a href="?sessionLocale=zh"><fmt:message key="label.lang.cn" /></a></li>
</ul>
<c:if test="${not empty param.sessionLocale}">
<fmt:message key="label.cookieChangeSuccess" />
<button><a href="sessionLocale.jsp"><fmt:message key="label.viewPage" /></a></button>
</c:if>
</body>
</html>
Then, we can run the application to access this changeLocale.jsp page and choose the German language. After that, we open our sessionLocale.jsp to see the result as below:
3.3. Using Browser Cookie As Locale
因此,使用相同的方法,我们可以实现一个使用浏览器cookie的值作为区域设置的页面。因此,我们有下面的cookieLocale.jsp页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page isELIgnored="false" %>
<%@ page session="true" %>
<fmt:setLocale value="${cookie['lang'].value}"/>
<fmt:setBundle basename="messages"/>
<html lang="${cookie['lang'].value}">
<head>
<title>PhraseApp - i18n</title>
</head>
<body>
<h2>
<fmt:message key="label.welcome" />
</h2>
<p>
<fmt:message key="label.cookieLocaleContent" />
</p>
</body>
</html>
假设我们通过键朗将区域设置存储在 Cookie 中。因此,我们通过使用表达式 cookie['lang'].value 来访问此 cookie 值。因此,我们的页面将使用该值作为首选区域设置。
此外,我们需要创建一个CookieLocaleFilter,以帮助我们在测试页面之前更改浏览器cookie值:
@WebFilter(filterName = "CookieLocaleFilter", urlPatterns = { "/*" })
public class CookieLocaleFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
if (req.getParameter("cookieLocale") != null) {
Cookie cookie = new Cookie("lang", req.getParameter("cookieLocale"));
res.addCookie(cookie);
}
chain.doFilter(request, response);
}
public void destroy() {}
public void init(FilterConfig arg0) throws ServletException {}
}
对于每个传入的请求,上面的过滤器将检查参数cookieLocale是否可用。如果是,则其值将设置为带有键 lang 的浏览器 cookie。
同样,让我们更新更改Locale.jsp以允许我们更改此cookie值:
...
<h2>
<fmt:message key="label.chooseCookieLocale" />
</h2>
<ul>
<li><a href="?cookieLocale=en"><fmt:message key="label.lang.en" /></a></li>
<li><a href="?cookieLocale=de"><fmt:message key="label.lang.de" /></a></li>
<li><a href="?cookieLocale=fr"><fmt:message key="label.lang.fr" /></a></li>
<li><a href="?cookieLocale=zh"><fmt:message key="label.lang.cn" /></a></li>
</ul>
<c:if test="${not empty param.cookieLocale}">
<fmt:message key="label.cookieChangeSuccess" />
<button><a href="cookieLocale.jsp"><fmt:message key="label.viewPage" /></a></button>
</c:if>
...
同样,让我们运行应用程序并打开此更改Locale.jsp选择中文作为cookie区域设置。然后,我们可以访问 cookieLocale.jsp以查看结果:
4. 结论
在本文中,我们探讨了如何在基本的 Java Web 应用程序上本地化 JSP 页面。此外,我们还学习如何通过使用请求参数、会话属性和浏览器 Cookie 动态选择区域设置。
我们的方法是将JSTL与资源包结合使用,我们使用<ftm:setLocale>和<ftm:setBundle>来引用资源包属性文件。
请查看我们的 Github 存储库,了解本文的完整实现。
如果您对有关 Java Web 应用程序的国际化和本地化的高级主题感兴趣,请查看其他博客文章,如 Spring MVC I18N。