Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: updating some of the dead and ancient javadoc links

Localization is something more and more web sites are having to deal with. Localization is never easy, but Stripes does what it can to make it as painless as possible. In this document we'll cover:

Table of Contents

Determining the Locale to use

The first challenge you're likely to face when building a localized application is to figure out what Locale to use for a given request. Chances are you will support a limited number of languages and locales. When a user submits a request, the request can contain a ordered list of locales that the user prefers. Somehow you have to decide, based upon your supported locales, and the user's preferred locales, what locale to serve them with. This is all compounded by the fact that locales can be one, two or three segments long, denoting the language, locale and variant.

Stripes uses a LocalePicker to determine the locale to use for a request. The LocalePicker is executed from the Stripes Filter, so it will execute even for direct-to-JSP navigation (read: you don't have to go through an ActionBean to take advantage of it). Once the LocalePicker has determined the locale to use, Stripes uses a HttpServletRequestWrapper to makes make calls to request.getLocale() and request.getLocales() to return only the chosen locale. This means that not only will Stripes will use the correct locale without having to re-determine it, but that any other localization tool that relies on request.getLocale[s]() should also default to the correct locale. This includes the JSTL fmt:* tags - cool huh?

Stripes uses the DefaultLocalePicker by default. The DefaultLocalePicker uses a configured list of locales to determine the locales that the system supports. If no list is supplied it will be defaulted to a single locale equal to the system locale, i.e. the one obtained by calling java.util.Locale.getDefault(). An example list for a site that supports English (of the American variety) and Japanese might look like this:

Code Block
xml
xml
 
<init-param> 
	<param-name>LocalePicker.Locales</param-name> 
	<param-value>en_US,ja</param-value> 
</init-param> 

...

To assist in this process, Stripes allows you to designate a character encoding per Locale; simply follow the Locale with a colon and then the name of the character encoding. For example:

Code Block
xml
xml
 
<init-param> 
	<param-name>LocalePicker.Locales</param-name> 
	<param-value>en_US:UTF-8,ja:Shift_JIS</param-value> 
</init-param> 

...

Stripes recognizes two types of localizable information that it uses. The first type is error messages. The second is field names. Each type of information is looked up using a resource bundle. If you are writing a localized application it is worth spending some time understanding resource bundles in depth - I'm not going to explain everything about them here. Suffice to say that probably the most common type of resource bundle is the PropertyResourceBundle which is simply a set of properties files with similar names.

...

There's actually not a huge deal to be said about localized validation. The built in number and date type converters use the localization capabilities of the java.text package to perform localized type conversion. So, if a user is being served pages localized into frenchFrench, it is expected that the user is inputting numbers and dates appropriate to the French locale.

...

If you don't define field names, Stripes will attempt to provide something vaguely user-friedly friendly by decomposing the form field name. But this will never be localized. The better alternative is to provide localized values for your field names. This is done in the field name bundle (by default StripesResources). The syntax is:

No Format
 
actionPath.fieldName=Field Name 
# or just... 
fieldName=Field Name 

This allows you to be specific about field names within a form, but to also define field names that are used in many places just once. For example, if you have a form with action="/security/login.action", and a field called user.password, Stripes will first look for a resource declaration like:

No Format
 
/security/login.action.user.password=Secret Magic Word 

If it cannot find the above resource, it will then look for a resource declaration like:

No Format
 
user.password=Secret Magic Word 

...

Localized buttons and labels are really just a special case of localized field names as described in the 'Localized Error Messages' section above. Stripes provides the following tags for generating form buttons: <stripes:button.../>, <stripes:submit.../> and <stripes:reset.../>, and a single tag for generating form field labels: <stripes:label.../> . While each of these tags allow you to determine the value displayed to the user directly on the page, they also support localized values using field name lookups. At the risk of repeating what was said above, if you have a form like:

Code Block
xml
xml
 
<stripes:form action="/security/login.action"> 
<stripes:label for="username"/>: <stripes:text name="username"/> 
<stripes:submit name="login"/> <stripes:reset name="reset"/> 
</stripes:form> 

then you will probably want to define the following resources in your field name bundle:

No Format
 
# Like this... 
/security/login.action.username=Username 
/security/login.action.login=Log In 
/security/login.action.reset=Clear Form 

# Or Maybe just like this... 
username=Username 
login=Log In 
reset=Clear Form 

If neither of the possible localization resources are available for a given button or label, the tag will then examine both the body of the tag and the value attribute. If the body is non-null and non-empty that will be used, otherwise the value attribute will be used. This means that if you need to use a localization bundle or property names that do not line up with the way Stripes expects them, you can do something like this:

Code Block
xml
xml
 
<stripes:submit name="save"><fmt:message bundle="MyBundle" key="button.save"/></stripes:submit> 

...

If you are using the Layout features of stripes you may want to pass localized values to the layout. See the section Passing additional information to the layout for more information about how to pass arbitrary formated formatted (including localized) content to a layout.

...

Firstly, there is absolutely nothing wrong with using the same resource bundle(s) to provide Stripes with localized resources and to provide localized resources through the JSTL tags. There are no issues with doing this, so for example, if you need field names displayed in other places on the page, there's no reason not to access the StripesResources bundle (or whatever you are using). Configure the JSTL localization by specifying the name of the stripes resource bundle in your web.xml:

Code Block
xml
xml
 
<context-param> 
	<param-name> 
		javax.servlet.jsp.jstl.fmt.localizationContext 
	</param-name> 
	<param-value>StripesResources</param-value> 
</context-param> 

...