Ken Finnigan's Blog

June 2010 Previous month Next month

The Seam International module aims to simplify the usage of i18n and l10n within Java EE 6 applications.  This first Alpha release is focussed on delivering the core functionality that was present within the Seam 2 codebase for i18n.

TimeZones

To support a more developer friendly way of handling TimeZones we have incorporated the use of Joda-Time through their DateTimeZone class.  Don’t worry, it provides convenience methods to convert to JDK TimeZone if required.

 

Starting at the application level the module provides a DateTimeZone that can be retrieved with:

 

@Inject
DateTimeZone applicationTimeZone;

 

It can also be accessed through EL by the name "defaultTimeZone"!

 

By default the TimeZone will be set to the JVM default, unless you override the DefaultTimeZoneProducer Bean through XML Config.  For instance, adding this XML into seam-beans.xml or beans.xml will change the default TimeZone of the application to be Tijuana!

 

<beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:s="urn:java:seam:core" 
   xmlns:tz="urn:java:org.jboss.seam.international.timezone"
   xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee 
      http://docs.jboss.org/cdi/beans_1_0.xsd">

    <tz:DefaultTimeZoneProducer>
        <s:specializes/>
        <tz:defaultTimeZoneId>America/Tijuana</tz:defaultTimeZoneId>
    </tz:DefaultTimeZoneProducer>
</beans>

 

We also have a DateTimeZone that is scoped to the User Session which can be retrieved with:

 

@Inject
@UserTimeZone
DateTimeZone userTimeZone;

 

It can also be accessed through EL using "userTimeZone".

 

By default the TimeZone will be the same as the application when the User Session is initially created.  However, changing the User’s TimeZone is a simple matter of firing an event to update it.  An example would be:

 

@Inject
@Changed
Event<DateTimeZone> tzEvent;

public void setUserTimeZone()
{
     DateTimeZone tijuana = DateTimeZone.forID("America/Tijuana");
     tzEvent.fire(tijuana);
}

 

We've also provided a list of available TimeZones that can be accessed via:

@Inject
List<DateTimeZone> timeZones;

Locales

In a similar fashion to TimeZones we have an application locale retrieved by:

 

@Inject
java.util.Locale lc;

accessible via EL with "defaultLocale".

 

By default the Locale will be set to the JVM default, unless you override the DefaultLocaleProducer Bean through XML Config.  Here are a few examples of XML that can be used to define the various types of Locales that are available...

 

This will set the default language to be French:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:s="urn:java:seam:core" 
   xmlns:lc="urn:java:org.jboss.seam.international.locale"
   xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee 
      http://docs.jboss.org/cdi/beans_1_0.xsd">

    <lc:DefaultLocaleProducer>
        <s:specializes/>
        <lc:defaultLocaleKey>fr</lc:defaultLocaleKey>
    </lc:DefaultLocaleProducer>
</beans>

 

This will set the default language to be English with the country of US:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:s="urn:java:seam:core" 
   xmlns:lc="urn:java:org.jboss.seam.international.locale"
   xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee 
      http://docs.jboss.org/cdi/beans_1_0.xsd">

    <lc:DefaultLocaleProducer>
        <s:specializes/>
        <lc:defaultLocaleKey>en_US</lc:defaultLocaleKey>
    </lc:DefaultLocaleProducer>
</beans>

 

As you can see from the previous examples, you can define the locale with lang_country_variant.  It's important to note that the first two parts of the locale definition are not expected to be greater than 2 characters otherwise an error will be produced and it will default to the JVM Locale.

 

The Locale associated with the User Session can be retrieved by:

 

@Inject
@UserLocale
java.util.Locale locale;

which is EL accessible with "userLocale".

 

By default the Locale will be the same as that of the application when the User Session is initially created.  However, changing the User’s Locale is a simple matter of firing an event to update it.  An example would be:

 

@Inject
@Changed
Event<java.util.Locale> localeEvent;

public void setUserLocale()
{
     Locale canada = Locale.CANADA;
     localeEvent.fire(canada);
}

 

We've also provided a list of available Locales that can be accessed via:

@Inject
List<java.util.Locale> locales;

 

The locales that will be returned with this can be defined with XML configuration of the AvailableLocales Bean such as:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:s="urn:java:seam:core" 
   xmlns:lc="urn:java:org.jboss.seam.international.locale"
   xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee 
      http://docs.jboss.org/cdi/beans_1_0.xsd">

    <lc:AvailableLocales>
        <s:specializes/>
        <lc:supportedLocaleKeys>
            <s:value>en</s:value>
            <s:value>fr</s:value>
        </lc:supportedLocaleKeys>
    </lc:AvailableLocales>
</beans>

Status Messages

There are currently two ways to create a message within the module.

 

The first would mostly be used when you don't want to add the generated message directly to the UI, but want to log it out, or store it somewhere else:

@Inject
MessageFactory factory;

public String getMessage()
{
     MessageBuilder builder = factory.info("There are {0} cars, and they are all {1}; {1} is the best color.", 5, "green");#
     return builder.build().getText();
}

 

The second is to add the message to a list that will be returned to the UI for display:

@Inject
Messages messages;

public void setMessage()
{
     messages.info("There are {0} cars, and they are all {1}; {1} is the best color.", 5, "green");
}

 

Either of these methods supports the four message levels which are info, warning, error and fatal.

 

Both the MessageFactory and Messages classes support four ways in which to create a Message:

  1. Directly adding the message
  2. Directly adding the message and replacing parameters
  3. Retrieving the message from a bundle
  4. Retrieving the message from a bundle and replacing parameters

 

Examples for each of these are:

  1. messages.info("Simple Text");
  2. messages.info("Simple Text with {0} parameter", 1);
  3. messages.info(new BundleKey("org.jboss.international.seam.test.TestBundle", "key1"));
  4. messages.info(new BundleKey("org.jboss.international.seam.test.TestBundle", "key2"), 1);

 

The above examples assume that there is a properties file existing at org.jboss.international.seam.test.TestBundle.properties with key1 being a simple text string and key2 including a single parameter.

 

Get Started

 

As with all Seam 3 module releases, the Seam  International module is published to the central Maven 2 repository.  Here is the dependency entry you will need for your POM to include the module in your own project:

<dependency>
   <groupId>org.jboss.seam.international</groupId>
   <artifactId>seam-international</artifactId>
   <version>3.0.0.Alpha1</version>
</dependency>

 

As this is an early release, we can’t guarantee that the APIs or syntax won’t change.  On the up side this means if you have any great ideas or thoughts on how to improve the module don’t be afraid to get in touch with us!  We have carte blanche to make this the best module it can be, so come and lend a hand, or maybe a leg too!

 

What’s Next

Some of the areas we will be looking at include:

  • Support for properties within a database
  • Introduction of type safe checking of message keys

 

Let us know the features you want to see in up coming releases!

 

More information on future plans and ideas is available on the Seam International module page at SeamFramework.org.