如果你正在構(gòu)建一個(gè)世界級(jí)的Web站點(diǎn),你是否想過只支持美語或英語?當(dāng)然不!世界上眾多的站點(diǎn)都支持多種語言,當(dāng)單擊對(duì)應(yīng)語言的鏈接時(shí),直接進(jìn)入該語言版本的站點(diǎn)。幸運(yùn)的是,Java自身的一些組件也提供了一些讓站點(diǎn)支持國際化功能的方法。在這里,我們使用Velocity的組件來輕松構(gòu)建國際化站點(diǎn)。在這一章里,我們只簡要介紹Java組件,之后重點(diǎn)介紹chapter 12里CD收藏管理示例的Velocity應(yīng)用程序版本。
Java國際化組件
在這一章里,我們將調(diào)試一些可用于國際化的Java組件。為了充分理解這個(gè)處理過程,請(qǐng)參考http://java.sun.com/docs/books/tutorial/i18n/的Java入門教程。在我們正式開始之前,讓我們把注意力集中于構(gòu)建一個(gè)可以使用英語和德語閱讀的Web應(yīng)用。
或許最簡便的方法就是為這兩種語言構(gòu)建兩張頁面。假定你已經(jīng)有了一個(gè)名叫index.html的原始的Web頁面。對(duì)于英語版本的,對(duì)應(yīng)的位置為/en/index.html下,在相同目錄的德語版本為indexgerman.html,當(dāng)然,也可以為他們建立不同的目錄,比如:英語版為/en/index.html,德語版為/de/index.html。
當(dāng)然,構(gòu)建兩張或20張頁面來完全這兩個(gè)語言版本的頁面不是太難,只是浪費(fèi)了一些時(shí)間而已。但如果是若干頁面,同時(shí)有些頁面需要進(jìn)行改動(dòng)該怎么辦?現(xiàn)在有一種好方法來為這兩種語言版本構(gòu)建頁面,那就是使用Java、Servlets以及Velocity,這是最好的解決方案。
Java本地類
Java本地(Locale)類用于包羅其他的Java類。這個(gè)本地(Locale)對(duì)象被傳遞給一個(gè)類,這個(gè)類知道如何處理世界上不同的地理位置。通過傳遞兩個(gè)參數(shù)來創(chuàng)建一個(gè)本地對(duì)象,這兩個(gè)參數(shù)是:你想使用的語言和國家。這兩個(gè)參數(shù)都使用只有2個(gè)字符的縮寫,比如:英語用en,德語用de。美國用US,德國用DE。
好,你現(xiàn)在可以用下面的代碼來創(chuàng)建一個(gè)本地對(duì)象:
Locale location = new Locale('en', 'US');
你可以在www.ics.uci.edu/pub/ietf/http/related/iso639.txt里查詢語言代碼的完整列表。國家代碼可以在www.chemie.fuberlin.de/diverse/doc/ISO_3166.html里查詢。
資源綁定(Bundles)
對(duì)Java國際化來說,大量工作都集中在ResourceBundle對(duì)象里。這個(gè)對(duì)象扮演了一個(gè)巨大的多維地圖,讓你提供一個(gè)關(guān)鍵字字符串和一個(gè)從Locale對(duì)象返回的值給bundle。ResourceBundle對(duì)象依靠properties files(屬性文件),該文件是一個(gè)文本文件,在其中定義了關(guān)鍵字和其關(guān)鍵值。在這里總是有一個(gè)名叫MessagesBundle.properties的默認(rèn)屬性文件。如果ResourceBundle對(duì)象不能找到其他和所提供位置匹配的屬性文件,那么,這個(gè)默認(rèn)的屬性文件(bundle)將被使用。讓我們首先來看一下,如何創(chuàng)建一個(gè)ResourceBundle對(duì)象。
message = ResourceBundle.getBundle("MessagesBundle", location);
The statement instantiates a ResourceBundle object based on the property filename of MessagesBundle and the provided Locale object. If you are planning to code a Web application for English/U.S. and German/Germany locations, you need two additional properties files:
語句初始化一個(gè)基于MessagesBundle的屬性文件名和所提供的本地對(duì)象的ResourceBundle對(duì)象,如果你計(jì)劃用English/U.S.和German/Germany編寫一個(gè)Web應(yīng)用,那么你需要兩個(gè)附加的屬性文件:
■ MessagesBundle_en_US.properties
■ MessagesBundle_de_DE.properties
ResourceBundle對(duì)象主要負(fù)責(zé)選擇屬性文件。正如我們?cè)峒暗囊粯樱恳粋€(gè)屬性文件包含了關(guān)鍵字和值對(duì)。比如:為了顯示一個(gè)對(duì)用戶的祝賀,你將在屬性文件里包含如下的實(shí)體:
Greet = Hello
當(dāng)然,你需要為默認(rèn)情況包含適當(dāng)?shù)膶?shí)體,即U.S.和德語文件。之后,在當(dāng)前Locale對(duì)象中查詢ResourceBundle對(duì)象以返回關(guān)鍵字“Greet”的值,比如:
String hello = messages.getString("Greet");
在這個(gè)代碼里,適當(dāng)?shù)淖YR詞被呈現(xiàn)給用戶。現(xiàn)在,讓我們看一如如何使用這些知識(shí)來構(gòu)建一個(gè)國際化Web站點(diǎn)。
一個(gè)國際化CD Web應(yīng)用
在之間的章節(jié)里,我們創(chuàng)建了一個(gè)應(yīng)用,以用于存儲(chǔ)和找回CD,以及他們的歌曲。和你回想的一樣,應(yīng)用顯示了一個(gè)主Web頁面以用于輸入CD和歌曲,同時(shí)顯示其對(duì)應(yīng)的信息。這個(gè)程序使用的語言是英語。現(xiàn)在,我們準(zhǔn)備對(duì)這個(gè)程序進(jìn)行國際化修改。
現(xiàn)在讓我們開始為這個(gè)主頁面創(chuàng)建一個(gè)允許用戶選擇語言和國家的操作,見Listing 13.1。顯示結(jié)果見Figure 13.1。
<HTML>
<BODY>
<form action="http://localhost:8080/cd/cdIndex">
<select name="country">
<option value="US">US</option>
<option value="DE">DE</option>
</select>
<BR>
<select name="language">
<option value="en">us</option>
<option value="de">de</option>
</select>
<input type="submit" value="submit">
</form>
</BODY>
</HTML>
Listing 13.1 The international.html file.

Figure 13.1 The language/country select page.
在Listing 13.1里有兩個(gè)重要的操作,第一在<form>標(biāo)記里。當(dāng)用戶單擊submit按鈕里,他們將發(fā)送給一個(gè)名叫cdIindex的新Servlets。這個(gè)Servlets主要負(fù)責(zé)為請(qǐng)求的語言獲取用于顯示的文本。同時(shí)也要注意國家和語言選擇框。這個(gè)輸入窗體被傳遞給cdIndex servlet,以便讓Servlets知道當(dāng)前需要的是哪個(gè)屬性文件(即需要是什么語言版本)。
從cdIndex servlet里輸出的是一個(gè)用于顯示輸入信息和顯示CD的Velocity模板。Listing 13.2顯示了這個(gè)模板的代碼。
<HTML>
<HEAD>
<TITLE></TITLE>
<link rel="stylesheet" type="text/css" href="default.css">
</HEAD>
<BODY BGCOLOR="#3A6BA5" link="ffffff" alink="999999" vlink="ffffff">
<table border="1" >
<tr><td>
$createstring<BR>
<form action="http://localhost:8080/cd/cdVelocityHandler"
method="post">
<table>
<tr><td>$title</td><td><input name="title"></td></tr>
<tr><td>$artist</td><td><input name="artist"></td></tr>
<tr><td>$tracks</td><td><input name="tracks"></td></tr>
</table>
<input type="submit" name="submit" value="new">
</form>
</td>
<td valign="top">
$displaystring<BR>
<form action="http://localhost:8080/cd/cdVelocityHandler" method="post">
<table>
<tr><td>$artist</td><td><input name="artist"></td></tr>
</table>
<input type="submit" name="submit" value="obtain">
</form>
</td>
</tr>
<tr>
<td valign="top">
$viewstring<BR>
<form action="http://localhost:8080/cd/cdVelocityHandler" method="post">
<table>
<tr><td>$ID</td><td><input name="id"></td></tr>
</table>
<input type="submit" name="submit" value="tracks">
</form>
</td>
<td valign="top">
$addstring<BR>
<form action="http://localhost:8080/cd/cdVelocityHandler"
method="post">
<table>
<tr><td>$ID</td><td><input name="id"></td></tr>
<tr><td>$name</td><td><input name="name"></td></tr>
<tr><td>$length</td><td><input name="length"></td></tr>
</table>
<input type="submit" name="submit" value="addtrack">
</form>
</td>
</tr>
</table>
</BODY>
</HTML>
Listing 13.2 The index.vm Velocity template.
這個(gè)顯示頁面被劃分為四個(gè)任務(wù)。每一個(gè)任務(wù)顯示一個(gè)指示和幾個(gè)字段。所有在頁面上的文本顯示被轉(zhuǎn)換到Velocity引用。這些Velocity引用被cdIndex servlet進(jìn)行填充,見Listing 13.3。
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.velocity.Template;
import org.apache.velocity.context.Context;
import org.apache.velocity.servlet.VelocityServlet;
import org.apache.velocity.exception.*;
import javax.naming.*;
import javax.ejb.*;
import cd.*;
import org.apache.velocity.app.Velocity;
public class cdIndex extends VelocityServlet {
protected Properties loadConfiguration(ServletConfig config )
throws IOException, FileNotFoundException
{
Properties p = new Properties();
String path = config.getServletContext().getRealPath("/");
if (path == null) {
System.out.println(
" SampleServlet.loadConfiguration() : unable to "
+ "get the current webapp root. Using '/'. Please fix.");
path = "/";
}
p.setProperty( Velocity.FILE_RESOURCE_LOADER_PATH, path );
return p;
}
public Template handleRequest( HttpServletRequest req,
HttpServletResponse res, Context context ) {
Template template = null;
String country = req.getParameter("country");
String language = req.getParameter("language");
Locale currentLocale = new Locale(language, country);
ResourceBundle messages =
ResourceBundle.getBundle("MessagesBundle", currentLocale);
context.put("title", messages.getString("title"));
context.put("artist", messages.getString("artist"));
context.put("ID", messages.getString("ID"));
context.put("name", messages.getString("name"));
context.put("length", messages.getString("length"));
context.put("tracks", messages.getString("tracks"));
context.put("createstring", messages.getString("createstring"));
context.put("displaystring", messages.getString("displaystring"));
context.put("viewstring", messages.getString("viewstring"));
context.put("addstring", messages.getString("addstring"));
try {
template = getTemplate("index.vm");
} catch( Exception e ) {
e.printStackTrace();
}
return template;
}
}
Listing 13.3 cdIndex.java.
cdIndex servlet有兩個(gè)任務(wù):第一,當(dāng)被用戶調(diào)用時(shí),用于從<form>獲取語言和國家信息,同時(shí)利用這些信息來構(gòu)建一個(gè)Locale對(duì)象。這個(gè)Locale對(duì)象被用于獲取一個(gè)ResourceBundle對(duì)象。依靠語言和國家的選擇,這個(gè)ResourceBundle要么選擇默認(rèn)的屬性文件(U.S.文件,見Listings 13.4),要么選擇德語(German)文件(Listings 13. 6)。這些文件都擁有相同的目錄。
第二個(gè)任務(wù)對(duì)Servlets來說或許是最為重要的任務(wù),它主要負(fù)責(zé)向上下文中填充適當(dāng)?shù)膽?yīng)用或他們的值。你可以在代碼看到,每一個(gè)引用連同其對(duì)應(yīng)的值(通過使用messages.getString(String)方法調(diào)用)一起被加入到上下文中。最后的結(jié)果是所有cdIndex Velocity模板需要引用被填充到上下文中。
當(dāng)用戶選擇US時(shí),顯示結(jié)果見Figure 13.2。如果選擇的是German,顯示結(jié)果見Figure 13.3。正如你所見的一樣,為你的應(yīng)用增加國際化支持是一件非常輕松的事。比如,現(xiàn)在需要增加西班牙語支持,只需在HTML選擇里包含適當(dāng)?shù)臉?biāo)識(shí)符,并創(chuàng)建適當(dāng)?shù)膶傩晕募纯伞?/span>
title = Title:
artist = Artist:
ID = ID:
name = Name:
length = Length:
tracks = Tracks:
createstring = To Create a New CD:
displaystring = To display CDs for an Artist
viewstring = To see all Tracks for a CD
addstring = To add a new track
Listing 13.4 MessagesBundle.properties.

Figure 13.2 The U.S. display page.

Figure 13.3 The German display page.
title = Title:
artist = Artist:
ID = ID:
name = Name:
length = Length:
tracks = Tracks:
createstring = To Create a New CD:
displaystring = To display CDs for an Artist
viewstring = To see all Tracks for a CD
addstring = To add a new track
Listing 13.5 MessagesBundle_en_US.properties.
title = Titel
artist = Kônstler
ID = IDENTIFIZIERUNG
name = Name
length = L?nge
tracks = Spuren
createstring = Um eine neue CD zu schaffen
displaystring = Um CDS fôr einen Kônstler darzustellen
viewstring = Um CD Spuren anzusehen
addstring = Um Spuren hinzuzufôgen
Listing 13.6 MessagesBundle_de_DE.properties.
本章小結(jié)和下章介紹
在這一章里,我們顯示了如何在Velocity中聯(lián)合Java的國際化特性來構(gòu)建一個(gè)世界級(jí)的Web站點(diǎn),讓你的用戶能夠獲得多種語言的支持。在下一章里,我們將研究在Turbine里使用Velocity,Turbine是一個(gè)應(yīng)用程序框架,它提供了一個(gè)讓你構(gòu)建企業(yè)級(jí)應(yīng)用的工具。