Localized strings in Java / Spring

2. 11. 2013 Johan Hornof

Most common storage type is the .properties file and its well known format:

some.code = Some value

You always need one unique code for every string. There are basically no limitations about the format of the code but good convention is to group the strings by the place of their usage or purpose. Like this:

registration.email.label = Please enter your email address
registration.email.placeholder = optional field
registration.email.error = Wrong email format
account.address.street = Street
account.address.city = City
button.signin = Sign in
button.close = Close window

JSP templates

When you need to translate strings inside the JSP file, let's assume that you are using the Web Project. First, you need to open the file named applicationContext.xml or applicationContext-something.xml located in project-folder/src/main/webapp/WEB-INF:

Inside the beans tag, include new bean:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
  <property name="useCodeAsDefaultMessage" value="true" />
  <property name="basenames">
  <list>
    <value>classpath:lang/messages</value>
  </list>
  </property>
  <property name="cacheSeconds" value="0" />
  <property name="defaultEncoding" value="UTF-8"></property>
</bean>

You can customize the properties if needed, I believe their names are pretty self-explanatory.

Noe create the messages.properties file. If you need more languages, name the files messages.en.properties, messages.fr.properties and so on.

Fill in the text strings you need and open the .jsp file where your strings should be displayed. You need to include fmt tag library in the file header:

<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

Now, you can insert the string wherever you want with the message tag where key is the code of your string, even as html attribute value:

<a href="#" title="<fmt:message key="button.close"/>">Blah</a>

Sometimes, you might need to have the translated string inside the variable:

${buttonClose}

This code won't output the string but create a new variable containing the translated string:

<fmt:message key="button.close" var="buttonClose"/>

Inside the Java code

Inside the *.java files, the access to translated strings is different. First, create the language file in the project-folder/src/main/resources/lang directory:

Register the bean the (same way as above) in the applicationContect.xml file which is usually in the directory project-folder/src/main/resources:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
  <property name="useCodeAsDefaultMessage" value="true" />
  <property name="basenames">
  <list>
    <value>classpath:lang/mails</value>
  </list>
  </property>
  <property name="cacheSeconds" value="0" />
  <property name="defaultEncoding" value="UTF-8"></property>
</bean>

Open the *.java file and add the following import:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;

Autowire the MessageSource inside the class:

@Autowired
private MessageSource messageSource;

and now use its getMessage method (which returns the translated string) anywhere in the class:

messageSource.getMessage("account.address.street", null, null);

Validator messages

Validation messages are usually placed in the annotations like this:

@AssertTrue(message = "Passwords do not match.")
@NotEmpty(message = "Passwords cannot be empty.")

If you need to translate them, create the .properties file in the directory project-folder/src/main/resources named as follows:

ValidationMessages.properties

and put the proper content inside. e.g.:

faq.topic.titleblank = Title cannot be blank.
form.passwd.match = Passwords do not match.
form.passwd.empty = Passwords cannot be empty.

You can then use it in annotations as Hibernate Validator Constraint message:

@AssertTrue(message = "{form.passwd.match}")
@NotEmpty(message = "{form.passwd.empty}")

or as default messages:

String message() default "{faq.topic.titleblank}";


(Folder structure images are from the NetBeans IDE)