Learn the basics of internationalization in a Spring application using ResourceBundleMessageSource to configure multiple resource bundle files and locale resolution.
1. MessageSource Interface
A Spring application to support internationalization (i18n), it requires the capability of resolving text messages for different locales. Spring’s application context is able to resolve text messages for a target locale by their keys. Typically, the messages for one locale should be stored in one separate properties file. These properties files are called resource bundles.
MessageSource
is an interface that defines several methods for resolving messages. The ApplicationContext
interface extends MessageSource
so that all application contexts are able to resolve text messages.
The Spring ApplicationContext
delegates the message resolution to a bean with the exact name messageSource
. ResourceBundleMessageSource
is the most common MessageSource
implementation to resolve messages from resource bundles for different locales.
2. Using ResourceBundleMessageSource
As an example, we can create the following resource bundle, messages_en_US.properties
, for the English language in the United States. Resource bundles are loaded from the application classpath so we can place the properties file in the /resources directory.
2.1. Create Resource Bundle
Create the following files in the classpath of the application. They contain the same message key in different locales.
msg.text=Welcome to howtodoinjava.com
msg.text=Bienvenue sur howtodoinjava com
2.2. Configure ResourceBundleMessageSource
Now configure ResourceBundleMessageSource
class as bean name "messageSource"
. Additionally, you have to specify the base name of the resource bundles for ResourceBundleMessageSource
.
@Configuration
public class AppConfig {
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasenames("messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
The equivalent XML configuration is as follows:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>messages</value>
</property>
</bean>
3. Resource Bundle Lookup Order
- First Spring tries to find the properties file matching the language and the country both. For this
messageSource
definition, if you look up a text message for the en_US locale whose preferred language is English, the resource bundlemessages_en_US.properties
, which matches both the language and country, will be considered first. Similarly, the messages_fr_CA.properties file will be picked up for locale lookup french_Canada. - If there’s no such resource bundle matching both (language and country), the one that matches the language will be considered. In the above example, if it is English speaking country, then
messages_en.properties
will be picked up. - If no matching resource bundle can be found, the default
messages.properties
for all locales will be chosen finally.
4. Demo
As mentioned earlier, we can use the ResourceBundle, MessageSource or even ApplicationContext to fetch the messages from the resolved properties file.
4.1. Fetch Message with en_US Locale
Now to check if messages can be loaded or not, run this code:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
String message = context.getMessage("msg.text", null, Locale.US);
System.out.println(message);
Program output:
Welcome to howtodoinjava.com
4.2. Fetch Message with fr_CA Locale
Now to check if messages can be loaded or not, run this code:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
String message = context.getMessage("msg.text", null, Locale.FR);
System.out.println(message);
Program output:
Bienvenue sur howtodoinjava com
5. Using ResourceBundle
To use the ResourceBundle bean, follow this code snippet.
Locale locale = new Locale("en", "US");
ResourceBundle resourceBundle = ResourceBundle.getBundle("messages", locale);
String message = resourceBundle.getString("msg.text");
6. Using MessageSourceAware
Great, so we are able to resolve messages. But, here we are directly accessing ApplicationContext
so it looks easy. If we want to access messages in some bean instance then we will need to implement either the ApplicationContextAware
interface or the MessageSourceAware
interface.
Something like this:
@RestController
public class EmployeeController implements MessageSourceAware
{
private MessageSource messageSource;
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
public void readLocaleSpecificMessage()
{
String englishMessage = messageSource.getMessage("msg.text", null, Locale.US);
//...
}
}
Now you can use this messageSource
instance to retrieve/resolve the text messages defined in class files.
7. Conclusion
In this short Spring tutorial, we learned to implement internationalization (i18n) in Spring applications using the ResourceBundleMessageSource bean. we learned how the resource bundles are resolved based on supplied locale names and saw an example in action.
Happy Learning !!