Spring I18N

The ApplicationContext interface extends an interface called MessageSource, and therefore provides messaging (i18n or internationalization) functionality. Together with the HierarchicalMessageSource, capable of resolving hierarchical messages, these are the basic interfaces Spring provides to do message resolution. Some of the methods defined here are:

  1. String getMessage(String code, Object[] args, String default, Locale loc): the basic method used to retrieve a message from the MessageSource. When no message is found for the specified locale, the default message is used. Any arguments passed in are used as replacement values, using the MessageFormat functionality provided by the standard library.
  2. String getMessage(String code, Object[] args, Locale loc): essentially the same as the previous method, but with one difference: no default message can be specified; if the message cannot be found, a NoSuchMessageException is thrown.
  3. String getMessage(MessageSourceResolvable resolvable, Locale locale): all properties used in the methods above are also wrapped in a class named MessageSourceResolvable, which you can use via this method.

When an ApplicationContext gets loaded, it automatically searches for a MessageSource bean defined in the context. The bean has to have the name ‘messageSource’. If such a bean is found, all calls to the methods described above will be delegated to the message source that was found. If no message source was found, the ApplicationContext attempts to see if it has a parent containing a bean with the same name. If so, it uses that bean as the MessageSource. If it can’t find any source for messages, an empty DelegatingMessageSource will be instantiated in order to be able to accept calls to the methods defined above.

Spring currently provides two MessageSource implementations. These are the ResourceBundleMessageSource and the StaticMessageSource. Both implement HierarchicalMessageSource in order to do nested messaging.

The StaticMessageSource is hardly ever used but provides programmatic ways to add messages to the source. The ResourceBundleMessageSource is more interesting and is the one we will provide an example for:

<beans>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>format</value>
<value>exceptions</value>
<value>windows</value>
</list>
</property>
</bean>
</beans>

This assumes you have three resource bundles defined on your classpath called format, exceptions and windows. Using the JDK standard way of resolving messages through ResourceBundles, any request to resolve a message will be handled. For the purposes of the example, lets assume the contents of two of the above resource bundle files are-

# in 'format.properties'
message=Spring rock!
# in 'exceptions.properties'
argument.required=The '{0}' argument is required.

Some (admittedly trivial) driver code to exercise the MessageSource functionality can be found below.

Remember that all ApplicationContext implementations are also MessageSource implementations and so can be cast to the MessageSource interface.

public static void main(String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("message", null, "Default", null);
System.out.println(message);
}

The resulting output from the above program will be

Spring  rock!

The MessageSource is defined in a file called ‘beans.xml’ (this file exists at the root of your classpath). The ‘messageSource’ bean definition refers to a number of resource bundles via its basenames property; the three files that are passed in the list to the basenames property exist as files at the root of your classpath (and are called format.properties, exceptions.properties, and windows.properties respectively).

Lets look at another example, and this time we will look at passing arguments to the message lookup; these arguments will be converted into Strings and inserted into placeholders in the lookup message. This is perhaps best explained with an example:

<beans>
<!-- this MessageSource is being used in a web application -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="test-messages"/>
</bean>
<!-- let's inject the above MessageSource into this POJO -->
<bean id="example" class="com.java.Example">
<property name="messages" ref="messageSource"/>
</bean>
</beans>
public class Example {
private MessageSource messages;
public void setMessages(MessageSource messages) {
this.messages = messages;
}
public void execute() {
String message = this.messages.getMessage("argument.required",
new Object [] {"userDao"}, "Required", null);
System.out.println(message);
}
}
The resulting output from the invocation of the execute() method will be...
The 'userDao' argument is required.

With regard to internationalization (i18n), Spring’s various MessageResource implementations follow the same locale resolution and fallback rules as the standard JDK ResourceBundle. In short, and continuing with the example ‘messageSource’ defined previously, if you want to resolve messages against the British (en-GB) locale, you would create files called format_en_GB.properties, exceptions_en_GB.properties, and windows_en_GB.properties respectively.

public static void main(final String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("argument.required",
new Object [] {"userDao"}, "Required", Locale.UK);
System.out.println(message);
}

The resulting output from the running of the above program will be… Ebagum lad, the ‘userDao’ argument is required, I say, required.

The MessageSourceAware interface can also be used to acquire a reference to any MessageSource that has been defined. Any bean that is defined in an ApplicationContext that implements the MessageSourceAware interface will be injected with the application context’s MessageSource when it (the bean) is being created and configured. 


Mathematics, Technology and Programming are my passion. I am a part of Java Ecosystem and through this blog, I contribute to it. I am here to blog about my interests, views and experiences. I am on Google+ and Facebook. I feel proud to be listed as a "National Memory Record Holder" in the Limca Book of Records, 2009 and have attempted for an International Memory record in the Guiness Book of Records. I can remember the value of PI upto 10,000 digits after the decimal (3.1415.....). You can contact me on javagenious.com(At)gmal.com ; I would like to hear from you :)

Share This Post

Related Articles

Powered by WordPress · Designed by Theme Junkie
You might also likeclose