CHAPTER 13 Velocity和國際化
如果你正在構建一個世界級的Web站點,你是否想過只支持美語或英語?當然不!世界上眾多的站點都支持多種語言,當單擊對應語言的鏈接時,直接進入該語言版本的站點。幸運的是,Java自身的一些組件也提供了一些讓站點支持國際化功能的方法。在這里,我們使用Velocity的組件來輕松構建國際化站點。在這一章里,我們只簡要介紹Java組件,之后重點介紹chapter 12里CD收藏管理示例的Velocity應用程序版本。
Java國際化組件
在這一章里,我們將調試一些可用于國際化的Java組件。為了充分理解這個處理過程,請參考http://java.sun.com/docs/books/tutorial/i18n/的Java入門教程。在我們正式開始之前,讓我們把注意力集中于構建一個可以使用英語和德語閱讀的Web應用。
或許最簡便的方法就是為這兩種語言構建兩張頁面。假定你已經有了一個名叫index.html的原始的Web頁面。對于英語版本的,對應的位置為/en/index.html下,在相同目錄的德語版本為indexgerman.html,當然,也可以為他們建立不同的目錄,比如:英語版為/en/index.html,德語版為/de/index.html。
當然,構建兩張或20張頁面來完全這兩個語言版本的頁面不是太難,只是浪費了一些時間而已。但如果是若干頁面,同時有些頁面需要進行改動該怎么辦?現在有一種好方法來為這兩種語言版本構建頁面,那就是使用Java、Servlets以及Velocity,這是最好的解決方案。
Java本地類
Java本地(Locale)類用于包羅其他的Java類。這個本地(Locale)對象被傳遞給一個類,這個類知道如何處理世界上不同的地理位置。通過傳遞兩個參數來創建一個本地對象,這兩個參數是:你想使用的語言和國家。這兩個參數都使用只有2個字符的縮寫,比如:英語用en,德語用de。美國用US,德國用DE。
好,你現在可以用下面的代碼來創建一個本地對象:
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)
對Java國際化來說,大量工作都集中在ResourceBundle對象里。這個對象扮演了一個巨大的多維地圖,讓你提供一個關鍵字字符串和一個從Locale對象返回的值給bundle。ResourceBundle對象依靠properties files(屬性文件),該文件是一個文本文件,在其中定義了關鍵字和其關鍵值。在這里總是有一個名叫MessagesBundle.properties的默認屬性文件。如果ResourceBundle對象不能找到其他和所提供位置匹配的屬性文件,那么,這個默認的屬性文件(bundle)將被使用。讓我們首先來看一下,如何創建一個ResourceBundle對象。
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:
語句初始化一個基于MessagesBundle的屬性文件名和所提供的本地對象的ResourceBundle對象,如果你計劃用English/U.S.和German/Germany編寫一個Web應用,那么你需要兩個附加的屬性文件:
■ MessagesBundle_en_US.properties
■ MessagesBundle_de_DE.properties
ResourceBundle對象主要負責選擇屬性文件。正如我們曾提及的一樣,每一個屬性文件包含了關鍵字和值對。比如:為了顯示一個對用戶的祝賀,你將在屬性文件里包含如下的實體:
Greet = Hello
當然,你需要為默認情況包含適當的實體,即U.S.和德語文件。之后,在當前Locale對象中查詢ResourceBundle對象以返回關鍵字“Greet”的值,比如:
String hello = messages.getString("Greet");
在這個代碼里,適當的祝賀詞被呈現給用戶。現在,讓我們看一如如何使用這些知識來構建一個國際化Web站點。
一個國際化CD Web應用
在之間的章節里,我們創建了一個應用,以用于存儲和找回CD,以及他們的歌曲。和你回想的一樣,應用顯示了一個主Web頁面以用于輸入CD和歌曲,同時顯示其對應的信息。這個程序使用的語言是英語。現在,我們準備對這個程序進行國際化修改。
現在讓我們開始為這個主頁面創建一個允許用戶選擇語言和國家的操作,見Listing 13.1。顯示結果見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里有兩個重要的操作,第一在<form>標記里。當用戶單擊submit按鈕里,他們將發送給一個名叫cdIindex的新Servlets。這個Servlets主要負責為請求的語言獲取用于顯示的文本。同時也要注意國家和語言選擇框。這個輸入窗體被傳遞給cdIndex servlet,以便讓Servlets知道當前需要的是哪個屬性文件(即需要是什么語言版本)。
從cdIndex servlet里輸出的是一個用于顯示輸入信息和顯示CD的Velocity模板。Listing 13.2顯示了這個模板的代碼。
<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.
這個顯示頁面被劃分為四個任務。每一個任務顯示一個指示和幾個字段。所有在頁面上的文本顯示被轉換到Velocity引用。這些Velocity引用被cdIndex servlet進行填充,見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有兩個任務:第一,當被用戶調用時,用于從<form>獲取語言和國家信息,同時利用這些信息來構建一個Locale對象。這個Locale對象被用于獲取一個ResourceBundle對象。依靠語言和國家的選擇,這個ResourceBundle要么選擇默認的屬性文件(U.S.文件,見Listings 13.4),要么選擇德語(German)文件(Listings 13. 6)。這些文件都擁有相同的目錄。
第二個任務對Servlets來說或許是最為重要的任務,它主要負責向上下文中填充適當的應用或他們的值。你可以在代碼看到,每一個引用連同其對應的值(通過使用messages.getString(String)方法調用)一起被加入到上下文中。最后的結果是所有cdIndex Velocity模板需要引用被填充到上下文中。
當用戶選擇US時,顯示結果見Figure 13.2。如果選擇的是German,顯示結果見Figure 13.3。正如你所見的一樣,為你的應用增加國際化支持是一件非常輕松的事。比如,現在需要增加西班牙語支持,只需在HTML選擇里包含適當的標識符,并創建適當的屬性文件即可。
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.
本章小結和下章介紹
在這一章里,我們顯示了如何在Velocity中聯合Java的國際化特性來構建一個世界級的Web站點,讓你的用戶能夠獲得多種語言的支持。在下一章里,我們將研究在Turbine里使用Velocity,Turbine是一個應用程序框架,它提供了一個讓你構建企業級應用的工具。
posted on 2008-10-27 18:46 KINGWEE 閱讀(1245) 評論(0) 編輯 收藏 所屬分類: Velocity