Java 2平台的国际化特性可以作为Web应用国际化功能的基础。不过,这并不是说在客户PC机上运行的独立Java应用与Web应用有同样的国际化需求。它们之间存在着如下一些共性:
l 存在本地化环境,而且要区分本地化环境。
l 根据需求使用不同的字符编码。
l 使用国际化资源包。
Java 2 平台使用本地化环境(locale)的概念来表示一组特定的本地化需求。本地化环境使用以下格式的字符串来指定:
xx_YY
其中,
q xx为语言代码,指定为一个ISO-639码。可以访问http://ftp.ics.uci.edu/pub/ietf/
http/related/iso639.txt得到完整的语言代码表。语言代码由两个小写字母组成。
q YY是使用该语言的国家(地区)代码,指定为一个ISO-3166码。国家(地区)代码表可以在www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-
en1.html查到。国家(地区)代码总是由两个大写字母组成。
例如,如果本地化环境为en_US,就表示使用的语言是美国英语,货币是美元(USD,U.S. dollar),采用美国样式的日期格式。尽管英国也使用英语,但是采用的货币完全不同,英国要使用英镑。
当然,对于诸如zh_CN等国际化本地化环境,相应的本地化需求更是大相径庭,要使用中文,货币是人民币,日期格式要采用中文显示。
表2-1描述了一些典型的本地化环境。
表2-1 典型的本地化环境
|
本地化环境 |
描 述 |
|
en_US |
英语,针对美国本地化 |
|
en_GB |
英语,针对英国本地化 |
|
es_MX |
西班牙语,针对墨西哥本地化 |
|
es_ES |
西班牙语,针对西班牙本地化 |
|
fr_FR |
法语,针对法国本地化 |
|
zh_CN |
中文,针对中国内地本地化 |
|
zh_TW |
中文,针对中国台湾本地化 |
本地化环境的语言代码和国家(地区)代码有时会用连字符(-)分隔,而没有采用下划线(_)。例如,可以是en-US。这两个格式是等价的。不过,本章只使用下划线分隔符。
对于在单个系统上运行的独立Java应用,可以由底层操作系统来设置本地化环境。系统本地化环境信息可以传递到运行这个应用的 Java 虚拟机,而且在该应用的生命期内,本地化环境不会改变。
在诸如Tomcat 5的服务器上运行Web应用和JSP页面时,Java虚拟机的本地化环境对于应用来说并不重要。应用收到的每个请求都可能来自不同的本地化环境。这意味着本地化必须针对每个请求来完成。
Java 2 本地化环境机制用于完成JSP应用的本地化。对于独立应用,Java虚拟机的本地化环境往往就是应用的本地化环境,而且不会改变;与独立应用不同,JSP应用的本地化环境要针对每个请求来决定和处理。
我们还没有回答如何确定请求的本地化环境以及怎么来维护这个信息的问题。本章第一个实验将展示一种确定本地化环境并处理本地化的方法。
实验1:显式确定本地化环境以及JSP的本地化
本例提供了一个表单给用户输入数据,并显示用户输入的数据。
与早先的类似例子有所不同,本例能够处理两个截然不同的本地化环境:
q 美国英语。
q 中国香港特别行政区所使用的中文(繁体中文)。
这个例子需要用到ch13.war文件。运行Tomcat 5服务器,然后在其上部署ch13.war。
(1)处理英语本地化
打开浏览器,访问以下URL:
http://localhost:8080/ch13/example1/index.jsp
主界面允许我们在两种语言中选择其一,可以采用英语也可以采用中文。如图2-3所示。

图2-3 为本地化用户界面选择英语或中文
选择English,这样就会用英语显示一个如图2-4所示的HTML表单(应用表单)。

图2-4 采用英语的应用表单
按表2-2在这个表单中输入数据,然后点击Submit Application(提交应用)按钮。
表2-2 表单中输入的数据
|
数 据 字 段 |
值 |
|
Last Name |
Smith |
|
First Name |
Bob |
|
Postal or Zip Code |
32817 |
|
Password |
basepass1 |
点击Submit Application按钮后,数据会提交给处理程序。在这里处理程序只是把提交的数据在一个HTML表格中打印出来,得到的输出类似于图2-5所示。

图2-5 成功提交英语表单
图2-5中的表格只是所输入数据的一个直接显示,介绍了应用的英语本地化。接下来将提供中文本地化用户界面。
(2)处理中文本地化
在浏览器上选择同一个URL:
http://localhost:8080/ch13/example1/index.jsp
我们再一次看到语言选择界面(见图2-3)。这一次点击另一个按钮,可以看到用中文汉字显示的应用表单。根据表意文字研究,汉字字符集中有不下30 000个不同的汉字。你所看到的表单如图2-6所示。

图2-6 中文本地化应用表单
通过与前面的英语表单相对照,我们应该能明白图2-6所示的各个字段是什么意思(当然,如果看得懂中文就另当别论了)。
除非计算机系统支持中文(最流行的输入法编辑器会使用书写笔和写字板),否则我们是无法向这些字段里输入中文汉字的。不过,我们完全可以从标签中剪切一些文本粘贴到字段中。
可以使用浏览器的剪切粘贴功能测试中文汉字的提交。剪切名字字段的标签(即“名字”),并粘贴到前两个字段中,同时还要用它作为密码的一部分,详细说明见表2-3。
表2-3 表单中输入的数据
|
数 据 字 段 |
值 |
|
姓 |
名字 |
|
名字 |
名字 |
|
郵政編號 |
32817 |
|
密碼 |
12名字34 |
当然,如果你懂中文,而且能够输入中文,也可以输入中文数据来完成这个测试。
下面,点击Submit Application(提交表格)按钮。这个按钮也采用中文标签,中文数据将提交给一个表单处理程序。这个表单处理程序只是用中文打印出所提交的数据值如图2-7所示。

图2-7 成功提交中文表单
在图2-7中,需要注意,提交的所有信息都作为汉字字符由表单处理程序接收。
这个基于JSP的表单应用是支持国际化的,目前它仅支持英语和中文,不过很容易使其支持更多的语言。下一部分将讨论如何让应用支持国际化,以及如何针对英语和中文进行用户界面的语言本地化。
实验解析
上述例子使用了一种相当直接而且可靠的方法来确定用户的本地化环境:询问用户想使用什么本地化环境。
(1)用户显式选择本地化环境
第一个页面index.jsp为用户提供了两种可供选择的语言。每个语言选择都用各自的语言显示。英语(English)选择就采用英语,中文(中文繁體)选择则采用中文书写。
此时不可能知道用户是否能够显示某种特殊语言,所以对于用户浏览器能否正确地显示汉字也无法做出假设。因此,这里的选择实际上使用了两个GIF图像文件:
q english.gif ,对应文本“English”。
q chinese.gif ,对应文本“中文繁體”。
采用这种选择方法,用户就可以选择一个特定的本地化环境。不过,在上述例子中,只提供了语言选择。
为用户提供最初的本地化环境选择时,不能假定用户可以显示其他语言的文本。建议使用图像文件(如国家的国旗)。
index.jsp文件位于<Tomcat安装目录>/webapps/ch13/example1/index.jsp。以下列出这个文件:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Select a language</title>
</head>
<body>
<h1>Please select a language:</h1>
<c:url value="en/application.jsp" var="engURL"/>
<a href="${engURL}">
<img src="english.gif"/>
</a>
<br/>
<br/>
<c:url value="zh/application.jsp" var="chineseURL"/>
<a href="${chineseURL}">
<img src="chinese.gif"/>
</a>
</body>
</html>
(2)链接到英语表单
通过分析代码,可以看到,这里使用了JSTL <c:url> 标记来生成一个URL变量。对于英语应用表单,代码如下:
<c:url value="en/application.jsp" var="engURL"/>
<a href="${engURL}">
<img src="english.gif"/>
</a>
使用<c:url>标记是为了确保对特殊的URL字符进行转义,而且会一直维护会话。要了解有关<c:url>动作的更多信息,请参见《JSP程序设计》第6章。
${engURL} 中生成的链接如下:
http://localhost:8080/ch13/example1/en/application.jsp
(3)链接到中文表单
类似于英语应用表单,这里也使用了一个JSTL <c:url>标记来生成链接,如以下代码所示:
<c:url value="zh/application.jsp" var="chineseURL"/>
<a href="${chineseURL}">
<img src="chinese.gif"/>
</a>
点击中文选择时生成的链接如下:
http://localhost:8080/ch13/example1/zh/application.jsp
把它与前面的英语链接相对照,可以发现英语和中文表单实际上存放在Web应用的不同目录下。在许多生产环境中,维护多组已翻译的JSP和HTML页面(每一组对应所支持的一种语言)是管理国际化内容的一种实用方法。
(4)使用多组已翻译页面进行国际化
图2-8显示了这个国际化应用中调用到的两组JSP应用页面。en目录和zh目录下都有application.jsp 和 procform.jsp页面。

en目录中的JSP页面采用英语,zh目录下的页面都预翻译为中文,这种机制显然可以扩展。例如,可以再创建一个es目录,将JSP页面预翻译为西班牙语,这样就能增加对西班牙语的支持。
这种方法的主要优点如下:
q 如果将来不太可能需要国际化,采用这种方法所需的额外工作会最少。
q 如果JSP页面中布局样式很丰富,而且包括复杂的客户端脚本元素,在这种方法下用所支持的各种语言对页面进行本地化和定制可以得到最佳外观。
以下是这种方法的主要缺点:
q 对于所支持的每一种语言/本地化环境,都必须重复建立所有的JSP页面,这就增加了需要管理的文件。
q 对于每种语言/本地化环境的页面,都必须做同样的代码调整。
q 对于包含大量代码的JSP页面,这种方法并不实用。
只需为所支持的每个本地化环境建立一组单独的JSP页面,就可以创建一个支持国际化的应用。每组本地化页面都应当预翻译为相关的语言。
(5)本地化英语页面
对于英语页面,表单application.jsp位于en目录中,具体位置是<Tomcat安装目录> /webapps/ch13/example1/en/application.jsp,下面将其列出:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Application Form</title>
</head>
<body>
<h1>Application Form</h1>
<br/>
<c:url value="procform.jsp" var="actionURL"/>
<form action="${actionURL}" method="post">
<table>
<tr>
<td>Last Name</td>
<td><input type="text" name="lastname" size="40"/></td>
</tr>
<tr>
<td>First Name</td>
<td><input type="text" name="firstname" size="40"/></td>
</tr>
<tr>
<td>Postal or Zip Code</td>
<td><input type="text" name="postcode" size="40"/></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="pass" size="40"/></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="Submit Application"/>
</td>
</tr>
</table>
</form>
</body>
</html>
这个页面只是显示HTML表单。我们再一次使用了JSTL <c:url> 标记来生成URL,这个URL要用作为HTML <form> 标记的action属性。下面我们要用这个JSP页面来处理表单:
<c:url value="procform.jsp" var="actionURL"/>
<form action="${actionURL}" method="post">
${actionURL} 请求作用域变量用于临时地保存表单处理程序的URL。实际上它包含以下内容:
http://localhost:8080/ch13/example1/en/procform.jsp
因为这个URL在en目录下,所以这是针对英语本地化环境进行本地化的表单处理程序版本。
l 英语表单处理程序
本地化的英语表单处理程序位于en目录,名为procform.jsp。这个文件的位置是<Tomcat安装目录>/webapps/ch13/example1/en/procform.jsp ,下面将其列出:
<html>
<head>
<title>Applicant Information</title>
</head>
<body>
<h1>Applicant Information</h1>
<br/>
<table border="1">
<tr>
<td>Last Name</td>
<td>${param.lastname}</td>
</tr>
<tr>
<td>First Name</td>
<td>${param.firstname}</td>
</tr>
<tr>
<td>Postal or Zip Code</td>
<td>${param.postcode}</td>
</tr>
<tr>
<td>Password</td>
<td>${param.pass}</td>
</tr>
</table>
</body>
</html>
这基本上就是一个HTML表格,其中打印了表单所提交的请求参数。请求参数的值通过上述代码清单中突出显示的EL表达式得到。注意,所有EL表达式都使用了EL中的param 隐式对象来直接访问请求参数。如果想回顾一下EL表达式和EL隐式对象,请参见《JSP程序设计》第5章。
(6)本地化中文页面
中文的应用表单页面application.jsp位于zh 目录。zh 是中文的ISO-639字母代码。虽然可以使用任何目录名,不过建议还是使用ISO-639字母代码作为目录名比较合适,这样从长远来看有利于维护。
本地化application.jsp 位于<Tomcat安装目录>/webapps/ch13/example1/zh/appli-
cation.jsp,下面将其列出,并突出显示了已翻译的本地化代码:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>申請表格 </title>
</head>
<body>
<h1>申請表格</h1>
<br/>
<c:url value="procform.jsp" var="actionURL"/>
<form action="${actionURL}" method="post">
<table>
<tr>
<td> 姓</td>
<td><input type="text" name="lastname" size="40"/></td>
</tr>
<tr>
<td>名字 </td>
<td><input type="text" name="firstname" size="40"/></td>
</tr>
<tr>
<td> 郵政編號 </td>
<td><input type="text" name="postcode" size="40"/></td>
</tr>
<tr>
<td> 密碼</td>
<td><input type="password" name="pass" size="40"/></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="提交表格 "/>
</td>
</tr>
</table>
</form>
</body>
</html>
在以上代码中可以看出,包含的所有文本都已经翻译为中文。不过,为了确保能够正确地显示和存储中文汉字,必须保证以下几点:
q 系统已经安装了适当的字体;Win32系统需要安装相应的补丁。
q 只能使用一个支持Unicode的编辑器来创建和编辑这个文件。大多数Win32和Linux系统上的记事本编辑器都是支持Unicode的,如果不清楚某个编辑器是否支持Unicode,需要查看该文本编辑器的相关文档。
q 在保存这些文件时,要存为UTF-8文件(UTF-8是目前Web支持最广、最可靠的Unicode格式)。
为了表示中文中的30 000余个汉字,文本文件所用的字符编码必须能够处理和表示这些汉字。Unicode字符集可以用于表示世界上大多数语言的文字,强烈建议在新开发的项目中使用Unicode。所有基于Win32的操作系统都支持Unicode,UNIX操作系统也是如此。另外当前所有主流浏览器的最新版本也能很好地支持Unicode。
目前有许多可用的字符编码。16位操作系统上运行的非常老的浏览器会使用基于页面的字符集来支持外国语言,其中的代码很有限。这样的字符集有很多,每个字符集只能支持很少的几种语言(都支持英语)。
有了32位微处理器以后,最为流行是Unicode字符编码,因为Unicode字符集可以表示世界上的大多数语言,而不需要切换字符集。
Unicode本身可以用一种8位格式或16位格式来编码。目前最常用而且支持最广的Unicode编码格式是UTF-8,这是Unicode字符的一种8位编码。如果需要,UTF-8会使用多个8位字符来表示一个字符。
在这个中文application.jsp 页面中,通过使用一个<meta>首部标记,为浏览器指定了UTF-8编码:
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
支持UTF-8的浏览器会接受这个首部以保证所发送的字符能适当地解码,并使用适当的Unicode字体正确显示。在Win32 或 UNIX系统上运行的所有主要浏览器都支持UTF-8编码。
为了节省运行时内存和磁盘存储空间,许多操作系统并不会预先安装显示外国字符集所需的字体,庞大的远东字符集更是如此。大多数操作系统上的浏览器不会管理自己的字体,而依赖于操作系统来提供字体。因此尽管大多数浏览器都支持 Unicode,但是如果没有所需的字体,可能也无法显示正确的字符。要想正确地看到这个例子,必须确保安装了中文 Big5字体支持补丁。在带有Internet Explore的Win32系统上,第一次访问使用这种字符的页面时会在线自动完成升级。
l 中文表单处理程序
用于处理表单数据以及显示输入数据的JSP页面也已本地化为中文,它位于zh目录,名为procform.jsp。具体位置是<Tomcat安装目录>/webapps/ch13/example1/zh/procform.jsp,以下将这个页面列出,并突出显示了翻译的本地化文本行:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>申請人資料 </title>
</head>
<body>
<h1>申請人資料</h1>
<br/>
<table border="1">
<tr>
<td>姓</td>
<td>${param.lastname}</td>
</tr>
<tr>
<td>名字</td>
<td>${param.firstname}</td>
</tr>
<tr>
<td>郵政編號</td>
<td>${param.postcode}</td>
</tr>
<tr>
<td>密碼</td>
<td>${param.pass}</td>
</tr>
</table>
</body>
</html>
再次留意<head>部分<meta> 标记的用法,该标记指定这个页面的字符集编码是UTF-8。与中文application.jsp 页面一样,这个文件必须用支持Unicode的编辑器来创建和编辑。当前大多数IDE都内置有能很好地处理Unicode文件的编辑器。
至此,第一个例子就介绍完了。下一个例子将展示可以采用另一种使JSP支持国际化,而无需复制应用中的所有JSP页面的方法。
实验2:使用Java 2的资源包实现本地化
本例与第1个例子的功能一样,也提供了支持两种本地化环境的表单提交功能。不过,这里不针对所支持的每种语言复制JSP页面,而只是使用了一组JSP页面。
首先要确保Tomcat 5服务器已经运行且部署了ch13.war,接着在浏览器上访问以下URL:
http://localhost:8080/ch13/example2/index.jsp
(1)尝试英语页面
此时会看到初始的欢迎页面,应该与第一个例子相同(见图2-3)。
选择英语页面,可以看到与图2-4所示表单类似的英语表单。不过,访问这个表单的URL不再像第1个例子中那样在en 子目录之下,而是:
http:// localhost:8080/ch13/example2/application.jsp
下面,在表单中输入表2-4中的数据:
表2-4 表单中输入的数据
|
数 据 字 段 |
值 |
|
Last Name |
Smith |
|
First Name |
Bob |
|
Postal or Zip Code |
32817 |
|
Password |
basepass1 |
点击Submit Application按钮,会调用 procform.jsp 页面来处理表单。这个页面与前例中的页面没有什么区别,它会打印出所提交的信息。最终显示界面与前面的图2-5类似。再次留意,访问这个最终页面的URL同样不在en子目录下。
(2)尝试中文本地化
下面,再访问以下URL来尝试中文页面:
http://localhost:8080/ch13/example2/index.jsp
这一次选择中文,应该能看到已翻译的本地化中文欢迎界面,如图2-6所示。请注意,这个页面的URL不再在zh 目录之下,而是与刚才显示英语表单的URL完全相同:
http://localhost:8080/ch13/example2/application.jsp
使用浏览器的剪切粘贴功能,剪切名字字段的标签(“名字”)文本,并把它作为输入值粘贴到表单中。可以根据表2-5来完成输入。
表2-5 表单中输入的数据
|
数 据 字 段 |
值 |
|
姓 |
名字 |
|
名字 |
名字 |
|
郵政編號 |
32817 |
|
密碼 |
12名字34 |
点击Submit Application按钮来提交表单数据,该按钮已经本地化为中文。点击后,中文数据会提交给表单处理程序。表单处理程序已本地化为中文,并如图2-7所示显示数据。
总的说来,第二个例子的操作与第一个例子的操作没有什么不同。不过,二者为国际化所做的具体准备截然不同。
实验解析
这个例子使用了Java 2平台中支持国际化资源包的功能。
1. Java 2资源包
资源包是Java 2提供的一种国际化机制,并作为Java 2 平台的一部分。资源包允许Java 应用使用与本地化环境相关的文本串资源。图2-9显示了资源包是如何工作的。
![]() |

图2-9 使用Java 2资源包实现国际化
在图2-9中,应用不包含任何需要翻译的文本串。与此不同,会为这些串指定特定的名,并创建一个资源包。资源包中,对于每个名可能包含多组翻译串,每组文本串分别对应应用支持的各种语言。可以利用串名从资源包中获取相应的国际化文本。为了说明这一点,下面使用一个名为getLocalizedText()的假想函数。从资源包获得的实际文本与当前本地化环境有关。Java 2 平台提供了一个具体的API来设置当前本地化环境,而且能从资源包获取与本地化环境相关的文本串。
例如,在图2-9中,如果当前本地化环境是en_US,调用getLocalizedText(“LastName”)会得到英语文本串“Last Name”。不过,如果本地化环境是zh_HK,调用getLocalizedText (“LastName”)就会得到中文文本串(“姓”)。
2. 创建资源包
Java 2资源包可以实现为属性文件,也可以实现为Java类。要包含国际化串,最简单的方法就是使用属性文件。Java 2属性文件中各行的一般格式如下:
<property name>=<property value>
例如,包含英语国际化文本串的属性文件为app.properties(位于<Tomcat安装目录>/webapps/ch13/example2/WEB-INF/classes/app.properties)。其内容如下:
newTitle=Application Form
lastName=Last Name
firstName=First Name
postalCode=Postal or Zip Code
password=Password
submitForm=Submit Form
appInfo=Applicant Information
为了使应用能够使用资源包,服务器必须能找到并加载属性文件。如果Web应用在Tomcat 5服务器上运行,必须能在Web应用的类路径(classpath)上找到这些属性文件。Tomcat 5服务器上运行的各个Web应用都可以有自己单独的类路径。这种按应用划分有一个很好的副作用,可以保证一个应用的国际化串独立于其他应用的国际化串。由于资源包必须在类路径中,国际化属性文件通常如下处理:
q 开发时放在WEB-INF/classes目录下,这样就能在测试时很快地修改。
q 在生产部署期间归档为JAR文件,并置于应用的WEB-INF/lib目录下。
为了能容易地访问和修改属性文件,在这个例子中,我们把这些属性文件放在应用的WEB-INF/classes目录中。前面所示的app.properties文件放在<Tomcat安装目录>/we-
bapps/ch13/example2/WEB-INF/classes目录中就是这个原因。
3. Java 2如何选择国际化串
每组特定的本地化环境的文本串都存储在一个单独的属性文件中。Java 2运行时会基于当前本地化环境来选择要使用哪一组文本串。例如,包含本地化中文文本串的属性文件为app_zh.properties。这个文件同样位于<Tomcat安装目录>/webapps/ch13/example2/WEB- INF/classes目录中,下面给出这个属性文件的内容:
newTitle=\u7533\u8acb\u8868\u683c
lastName=\u59d3
firstName=\u540d\u5b57
postalCode=\u90f5\u653f\u7de8\u865f
password=\u5bc6\u78bc
submitForm=\u63d0\u4ea4\u8868\u683c
appInfo=\u7533\u8acb\u4eba\u8cc7\u6599
很容易发现:
q 这些属性名与英语app.properties 文件中的属性名完全相同。
q 这个文件中没有UTF-8中文字符。
第一点无足为奇。如果locale设置为zh_HK或另一种采用zh中文的本地化环境,就会使用app_zh.properties 中的文本串。如果locale 设置为其他本地化环境,则使用默认的app.properties文件。如果应用要修改为支持另外一种语言,比如法语,就需要创建一个新的app_fr.properties文件,其中包含已翻译的法语文本串。
第二点很奇怪。为什么包含中文字符的属性文件不是UTF-8文件呢?在Java 2 平台上,对属性文件有一个限制,属性文件只能包含ASCII字符。
4. 创建中文本地化属性文件
由于Java 2 只能处理基于ASCII的属性文件,所以所有Unicode编码文件都要转换一下,使用ASCII转义代码。
如果你使用了IDE或专用的资源编辑器,可以直接使用这些工具生成属性文件。
如果没有能直接生成ASCII属性的资源编辑器,可以使用Unicode编辑器结合一个名为native2ascii的工具来达到目的,这个工具可以在Java 2 SDK的bin目录中找到。
例如,考虑Unicode 属性文件app_zh.ucd,它位于<Tomcat安装目录>/webapps/ch13/ example2/WEB-INF/ classes/app_zh.ucd。下面列出这个文件的内容:
newTitle=申請表格


