Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning Apache Struts - From Novice To Professional (2006)

.pdf
Скачиваний:
56
Добавлен:
17.08.2013
Размер:
11.68 Mб
Скачать

148

C H A P T E R 1 2 I N T E R N A T I O N A L I Z A T I O N

However, for things like dates, currency values, or numbers, localizing validations may be necessary. This section contains my personal collection of hacks that I hope you will find useful.

The first hack is to test for each special locale in your ActionForm subclass (see Listing 12-1).

Listing 12-1. Localizing Validations by Brute Force

String locale = getLocale(); String date = getDate(); boolean dateOK = false;

if ("de".equals(locale)) {

dateOK = validateDate(date,"dd.mm.yyyy");

}else if("en-us".equals(locale)){

dateOK = validateDate(date,"mm/dd/yyyy");

}else{ //catch all date validation

dateOK = validateDate(date,"dd/mm/yyyy");

}

In Listing 12-1, getLocale() is a function on the ActionForm base class. validateDate() is a fictitious function that validates a date string given a second format string. This bruteforce method is OK for doing a few validations by locale, but it has many disadvantages, a maintenance nightmare being one of them!

A slightly more sophisticated way of doing the same thing is to use a HashMap to store the (locale,format) pairs. This removes the multiple if else statements, as shown in Listing 12-2.

Listing 12-2. Localizing Validations by Brute Force, Take 2

public MyActionForm(){

myDateFormats = new HashMap(); myDateFormats.put("en-US"," mm/dd/yyyy"); myDateFormats.put("de","dd.mm.yyyy"); myDateFormats.put("default","dd/mm/yyyy");

}

public ActionErrors validate(...){

...

C H A P T E R 1 2 I N T E R N A T I O N A L I Z A T I O N

149

boolean dateOK = false;

Object o = myDateFormats.get(getLocale()); if(null == o) o = myDateFormats.get("default");

dateOK = validateDate(getDate(), (String) o);

...

}

The second hack is a clever trick that appeared in an article by Mike Gavaghan in JavaWorld (see “Useful Links” at the end of this chapter). The idea is to embed the format string within the JSP, using the <html:hidden> tag, as shown in Listing 12-3.

Listing 12-3. Using Hidden Format Fields (JSP)

<bean:message key="myapp.jsp.prompt.date"/> <html:text property="date"/>

<html:hidden property="dateFormat"/>

Before this page is called, you need to populate the hidden field using an Action, with the locale's date format. Now, since the date format is stored in the form itself, you can retrieve it and run the validation with the format, as shown in Listing 12-4.

Listing 12-4. Using Hidden Format Fields (ActionForm)

public ActionErrors validate(...){

...

boolean dateOK = false;

dateOK = validateDate(getDate(), getDateFormat());

...

}

Listing 12-4 implies the addition of getDateFormat() and setDateFormat() functions on MyActionForm. This technique allows you to store your locale-specific formats along with the properties file for that locale. This solution is better than hard-coding formats into your ActionForm subclass.

150

C H A P T E R 1 2 I N T E R N A T I O N A L I Z A T I O N

Localizing Output

Localizing output is something Struts does very well. If you’ve been careful to use <bean:message> tags throughout your application’s JSPs (instead of using static text), then localizing your application’s output with Struts is easy.

Since all your application’s text is in the Application.properties file, here’s all you need to do to support a new language:

Translate the Application.properties file to the language for the new locale. The translation would leave the keys the same, and only affect the messages. If the translator used a character encoding other than ASCII, you will have to postprocess the translated file before you can use it. More on this shortly.

Append the locale identifier to the translated filename. For example, a Japanese translation must be called Application_jp.properties. The additional _jp identifies this translation as belonging to the Japanese locale.

Install the new properties file in the same folder as the default

Application.properties file (see Figure 12-1).

That’s it! When the user’s browser is set for the desired locale (say jp), Struts will use the right properties file (in this case, Application_jp.properties) for that user. All prompts, buttons, dialog boxes, and text will appear in Japanese.

Figure 12-1. Various installed Application.properties files

Note If you were writing an application for U.S. English (with the associated locale en_US), then the properties file would be Application_en_US.properties.

C H A P T E R 1 2 I N T E R N A T I O N A L I Z A T I O N

151

Before I show you how this selection is made, let’s tie up one loose end—the character encoding for the translated Application.properties.

Processing Translated Application.properties Files

The Java programming language only accepts source code and properties files in the ISO 8859-1 character encoding. I’m talking the actual source code here—not the internal representation of Java Strings, which are not restricted to this encoding.

The ISO 8859-1 (aka Latin 1) can encode most western European languages, and is for most intents and purposes like ASCII. More precisely, characters that are in both ASCII and ISO 8859-1 are given the same character codes.

Your Application.properties file must also be in this encoding. How do we represent other languages with this restrictive encoding? The answer is to use a tool called native2ascii. This program resides in the bin directory of your JDK.

When you receive the translated Application.properties file, it might likely not be in the ASCII or ISO 8859-1 encoding. The only sure way of getting this information is from the translator. Once you know the source encoding, you can use native2ascii:

native2ascii -encoding UTF-8 jp.properties Application_jp.properties

In this example, the translated file is jp.properties, which is given in the UTF-8 encoding. The final output is Application_jp.properties, which you can actually use.

The “magic” behind native2ascii is that it “escapes” non–ISO 8859-1 characters with the string Unicode version of it. This appears in your properties file as sequences of

\uxxxx.

When Struts creates the HTML page to be delivered to the user, the encoding specified on the page with the <%@ page ... directive is used:

<%@ page contentType="text/html; charset=UTF-8" %>

or, you could use the <controller> tag in your struts-config.xml (see Chapter 9):

<controller contentType="text/html; charset=UTF-8" />

In both these cases, the UTF-8 character encoding is used to encode the HTML pages delivered to the user.

Selecting a Locale from the Browser

Most modern browsers allow the user to select a default locale. Figures 12-2 and 12-3 show this for Mozilla and Internet Explorer.

152

C H A P T E R 1 2 I N T E R N A T I O N A L I Z A T I O N

Figure 12-2. Adding a new locale with Mozilla

Figure 12-3. Adding a new locale with Internet Explorer

C H A P T E R 1 2 I N T E R N A T I O N A L I Z A T I O N

153

You may notice that these web browsers don’t always give the correct locale string. For example, U.S. English is incorrectly displayed as en-us, when it is in fact en_US.

Switching Locales with a Link

Getting users to change the locale on their web browser may not always be desirable or even possible. In such situations, you might want them to click a link instead that tells the server to switch to the desired locale. The way to do this is to encode the locale as a parameter on the link. For example:

<a href="/ChangeLocale.do?language=ta">In Tamil</a>

In this link, ChangeLocale is a form handler, which has no associated form bean. The declaration in struts-config.xml would be

<action path="/ChangeLocale" type="com.mycompany.myapp.ChangeLocaleAction">

<forward name="success" path="/index.jsp"/> </action>

ChangeLocaleAction is an Action subclass with the following execute():

public ActionForward execute(...){

String language = request.getParameter("language");

String country = request.getParameter("country");

if(null == country){

setLocale(request, new Locale(language)); }else{

setLocale(request, new Locale(language,country));

}

return new ActionForward(mapping.findForward("success"));

}

When the user clicks the link (which contains the new language, and optionally, the new country code), control passes to ChangeLocaleAction, which sets the default locale for that user’s session to the desired combination. Note that java.util.Locale is a built-in Java class.

154

C H A P T E R 1 2 I N T E R N A T I O N A L I Z A T I O N

Switching Locales with LocaleAction

Yet another way to allow users to switch locales is to use the Struts class LocaleAction. To use this class effectively, you’ll have to first understand dynamic forms (see Chapter 16), so I’ve postponed the discussion of LocaleAction to Chapter 17.

Lab 12: LILLDEP for the Malaysian Market

In this lab, you’ll see how easy it is to port LILLDEP for the Malaysian (or Indonesian) market.

1.In the Source Code section of the Apress website, found at http://www.apress.com, copy lab12.zip to your main LILLDEP development folder. This zip file should contain a single file called Application_ms.properties; ms is the locale string for Malay, the language spoken in Malaysia (and a slight variant of it is spoken in Indonesia). Unzip the contents of this zip file to .\web\resources\.

2.Compile and redeploy LILLDEP.

3.Open Internet Explorer, then choose Tools Internet Options Languages (see Figure 12-2). If you’re using Mozilla or another browser, you’ll have to locate this setting yourself. Add Malay (ms) and remove all other languages.

4.Close all instances of Internet Explorer, then open one and navigate to the LILLDEP page. You should see all prompts and buttons in Malay (see Figure 12-4).

Figure 12-4. LILLDEP in Malay

C H A P T E R 1 2 I N T E R N A T I O N A L I Z A T I O N

155

Useful Links

“End-to-end internationalization of Web applications: Going beyond the JDK,” by Mike Gavaghan: http://www.javaworld.com/javaworld/jw-05-2004/ jw-0524-i18n.html

ISO 639 language codes: http://en.wikipedia.org/wiki/ISO_639

ISO 3166 country codes: http://en.wikipedia.org/wiki/ISO_3166

Unicode: www.unicode.org

UTF-8 and related encodings: http://en.wikipedia.org/wiki/UTF-8

Summary

Localizing occurs in four areas: input, validations, output, and communication with other programs, like databases.

Struts provides support for localizing output but poor or nonexistent support for the other areas.

Localizing output is as simple as getting the Application.properties file translated.

The properties file needs to be encoded in ISO 8859-1 (Latin 1). You might have to use the native2ascii tool to “escape” other encodings into this one.

C H A P T E R 1 3

■ ■ ■

Review Lab: Editing Contacts

in LILLDEP

Congratulations! You’ve made it halfway through this book. Before moving on to more advanced topics, I’d like to give you the opportunity to review some of the material in the preceding chapters.

In this review lab, you’ll make it possible to edit Contacts in LILLDEP’s database. Specifically, you’ll build on the “full listing” page (listing.jsp), so that when a user clicks on a company name, they are taken to a page displaying the Contact’s full details. These details may be changed and resubmitted, causing the database entry to be updated.

Try your best to answer questions 1–4:

1.If you turn the company name into a link, how will you determine which company was clicked? (Hint: Look at the source code for BaseContact.)

2.You obviously want to reuse full.jsp to display the data that’s going to be edited. Do you need to make any changes to it to support updating contact information? Why?

3.Can you similarly reuse ContactForm and ContactAction? Do you need to make changes to them to support updating?

4.What other classes would you need to complete the editing facility? (Hint: What creates the populated form for editing?)

Compare your answers to the ones in Appendix D before proceeding.

157