为国际客户设计 Java Server Pages(
JSP)应用程序更像是一门艺术,而不像是科学,但所涉及的内容不仅仅能满足眼球。成功的关键是理解与
国际化有关的独一无二的服务器端问题。 Java 开发人员 Sing Li 将阐述这个重要问题,并给出两个经过考验确实有效的解决方案。
世界经济日益全球化推动了人们对基于 Web 的软件的需求,因为许多国家的用户都能访问 Web 软件。这些用户使用的语言、显示、数据录入、表示和文化需求等都可能存在很大的差异。
国际化(缩写为 i18n)是一种
创建为分散用户群工作的应用程序的艺术。
也许有点让人感到惊讶,当不作任何定制修改就在服务器端使用时,J2SE 对
国际化的内建支持会表现出一些不足。一般来说,服务器端的
国际化仍然是一门艺术,而不是一项科学,它常常涉及一些专用的或用户自主开发的解决方案。
本文把服务器端基于
JSP 的应用程序的
国际化需求与 J2SE 应用程序的
国际化需求区别开来。本文将介绍导致服务器端需求明显不同的各种客户机/服务器技术。然后,还将查看实际代码,这些代码展示了用来解决基本问题的、广泛采用的两个解决方案。
超越 J2SE 地区
J2SE 用地区(locale) 的概念(请参阅Notation for a locale)进行
国际化。在一台机器上,地区代表用户选择的显示语言(例如,英语或西班牙语),以及日期、时间、货币等方面的格式化约定。通常,由底层操作系统管理地区选项设置,并在运行的时候把它传递给 J2SE。
如果运行的服务器在本地机器上,或者是在局域网上,那么特定于机器的地区的概念就很好用。包含的所有客户机和服务器都在同一地区,所以它们都使用相同的显示语言、日期约定等。这些场景都不会带来麻烦的
国际化问题。但是如果想用同一台服务器为多个国际位置上的用户提供服务的话,那么情况就变得很复杂。
服务器端
国际化问题
当为了进行
国际化访问而部署服务器应用程序时,该应用程序必须同时为不同的地区提供支持。图 1 显示了一种可能的场景。每台机器 —— 服务器以及可在任何时间访问服务器的客户机 —— 都可能有自己的地区设置,而这些地区是不同的。
图 1. 为不同地区的用户提供服务的服务器
在图 1 中,服务器机器位于 San Francisco,特定于机器的地区是 en_US(美国英语)。来自纽约和达拉斯的用户都使用 en_US 地区,所以没有额外的
国际化需求。但是,来自汉城的用户期望看到用韩语表示的应用程序提示,他们的地区是 ko_KR。同时,来自上海的用户想看到中文表示的应用程序文本,他们的地区是 zh_CN。来自东京的用户期望用日语显示应用程序,他们的地区是 ja_JP。所有这些用户的需求都必须通过运行在 San Francisco 服务器上的
JSP 应用程序来得到满足。
在服务器端,您对于服务器机器自己的地区拥有全部控制权,但您无法改变客户机的地区或强行将它转换成某个特定地区。相反,应用程序必须识别出用户的地区,并保证
JSP 页面以正确的本地化形式出现(请参阅 Detecting client locale)。
更多地区判断的复杂情况
就在您以为可以安全地判断客户机地区,并据此呈现
JSP 时,新的问题出现了。请考虑以下这些非常现实的场景。
来自东京的一位访问人员工正在使用位于中国上海的销售办公室的机器,机器的地区是 zh_CN。因为不熟悉书面中文,所以她想用日语访问 Web 应用程序。关于这种情况的说明,参见图 2(a)。
图 2. 用户期望的地区与客户端机器上的地区不同
在图 2(a),San Francisco 服务器的地区是 en_US。客户端机器在上海,地区是 zh_CN。但是
JSP 应用程序需要用 ja_JP 地区显示,对用户才有用。
再看另外一个更加怪异但并非不可能的场景。
国际化 JSP 应用程序的开发人员正在一项调试。在一个地区为 en_US 的客户端系统上,打开了三个运行
JSP 应用程序的浏览器实例。服务器机器在局域网上,地区也是 en_US。但是,现在要为中文和日语用户测试应用程序的处理能力。所以在一台 en_US 客户端机器上,一个浏览器实例用的是英文(en_US),一个用的是日语(ja_JP),还有一个用的是中文(zh_CN)。图 2(b)演示了这种情况。
目前为止,基本的
国际化问题应当很清楚了:在处理显示
国际化应用程序的任意特殊实例所需的实际地区时,客户机地区和服务器地区都有些力不从心。只有用户才能说清要用哪个地区显示页面。
但是谢天谢地,通常可以肯定地假设在使用应用程序期间,用户不会改变显示语言。所以通常可以把地区与会话关联起来。
解决特定于地区的语言的显示问题
对于
JSP 应用程序,至少有两种处理不同语言的显示问题的普遍接受方法可以使用:
存储多组
JSP,每组
JSP 都用不同的语言编码,然后根据用户的地区选择在这些
JSP 之间切换。
分离所有使用的字符串,代之以从资源绑定获得一个特定于地区的字符串。(这种方式使用了 J2SE 特定于地区的资源绑定处理方式。)
本文提供了示例代码的两个版本,分别对应上面的两种方法。示例应用程序是一个叫做 developerWorks Email 的虚构的电子邮件服务的登录屏幕。首先,会用语言选择屏幕提示电子邮件系统的用户,让他确定所需的当前会话地区。可以进行的选择包括英语、韩语、日语和中文,如图 3 所示。如果想试试代码的效果,请用 address>/dwi18n/multdir/index.
JSP 这个 URL 访问该页面。
图 3. 进行显式地区选择的语言选择屏幕
在图 3 中,语言选择屏幕用 4 个图片表示 4 个地区选择(请参阅 Using images for initial language selection)。登录屏幕使用用户在这里选择的语言进行显示。图 4 显示了日语的登录屏幕。
图 4. 日语登录屏幕
使用多组冗余的特定于语言的
JSP 集
示例的第一个版本位于示例代码发行包的 webapps/dwi18n/multdir/ 目录中,它运用了多组
JSP 页面。图 5 显示了这个应用程序的目录结构。
图 5. dwi18n/multdir 的目录结构显示了特定于地区的目录
在图 5 中,每个地区都有对应的子目录。与 en_EN 地区对应的用英文编码的
JSP 在 en 子目录中。与 ko_KR 地区对应的用韩语编码的
JSP 在 ko 子目录中。对于 ja_JP 地区,用日语编码的
JSP 在 ja 子目录中。zh_CN 地区则用 zh 子目录中用中文编码的
JSP 表示。每个子目录都既包含登录屏幕的
JSP(login.
JSP),也包含数据确认
JSP(confirm.
JSP)。
数据确认
JSP 只显示在这个简单的示例中输入的数据。例如,如果在中文登录屏幕中输入了信息,然后单击按钮,那么数据确认
JSP 就会显示输入的数据,如图 6 所示。
图 6. 中文的确认页面
编写
JSP 代码
地区选择
JSP 叫做 index.
JSP,它直接链接到特定于语言的一组
JSP。这个版本的 index.
JSP 的代码在清单 1 中:
清单 1. 地区选择
JSP 直接链接到特定于语言的页面
<%@ taglib prefix="c" uri=" <head>
<title>Select a language</title>
</head>
<body>
<table>
<tr>
<td colspan=4 bgcolor="black">
<br/>
<center><font face="arial" size=+2 color="white">
<b><i>developer</i>Works Email</b></font>
</center>
<br/>
</td>
</tr>
<tr><td>
<c:url value="en/login.
JSP" var="englishURL"/>
<a href="$">
<img src="english.gif"/>
</a>
</td>
<td>
<c:url value="ja/login.
JSP" var="japaneseURL"/>
<a href="$">
<img src="japanese.gif"/>
</a>
</td>
<td>
<c:url value="ko/login.
JSP" var="koreanURL"/>
<a href="$">
<img src="korean.gif"/>
</a>
</td>
<td>
<c:url value="zh/login.
JSP" var="chineseURL"/>
<a href="$">
<img src="chinese.gif"/>
</a>
</td>
</tr>
</table>
</body>
</html>
注意,清单 1 中使用了来自
JSP 标准标签库(JSTL)的 <c:url> 标签来
创建链接 URL。这可以确保会话管理得到恰当的处理。(请参阅参考资料,以了解关于 JSTL 和 <c:url> 标签的更多信息。)
每组 login.
JSP 和 confirm.
JSP 都用特定于地区的语言编写代码。清单 2 显示了 ja_JP 地区的 login.
JSP(与 图 4 对应):
清单 2. ja_JP 地区的登录页面(login.
JSP)
<%@ taglib prefix="c" uri="" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/ht