One day we decided to optimize the translation process of one of our web applications to reduce the number of resource files from three to two. Our web application supported two languages (Finnish and English), and the default resource file had the exactly same content than the resource file for the Finnish language. Of course this caused us extra work when new strings were added to the user interface. So, we decided to remove the resource file for the Finnish language to ease our pain. That worked perfectly well on the local development environment, but when the software was installed to our testing environment, it did not work. No matter what we did, the user interface was always translated to English.
It was time to think. We had following configuration in the configuration file of Spring application context:
1<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
2 <property name="defaultEncoding" value="UTF-8"/>
3 <property name="basenames">
4 <list>
5 <value>classpath:i18n/messages</value>
6 </list>
7 </property>
8</bean>
9
10<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
11 <property name="defaultLocale" value="fi" />
12</bean>
13
14<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
15 <property name="paramName" value="lang" />
16</bean>
After some digging and browsing the Javadocs of Spring Framework, I found out that we had forgotten the default behavior of java.util.ResourceBundle. The locale of the server was EN_US, and after the resource file for Finnish language was not found, resource file for English language was used instead. Luckily the Javadocs revelead that the org.springframework.context.support.RealoadableResourceBundleMessageSource class contains a property called fallbackToSystemLocale, which can be used to override the default behavior of java.util.ResourceBundle. When the value of this property is set to false, the default resource file is used, when the resource file for the asked locale is not found.
The working configuration is following:
1<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
2 <property name="defaultEncoding" value="UTF-8"/>
3 <property name="basenames">
4 <list>
5 <value>classpath:i18n/messages</value>
6 </list>
7 </property>
8 <property name="fallbackToSystemLocale" value="false"/>
9</bean>
10
11<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
12 <property name="defaultLocale" value="fi" />
13</bean>
14
15<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
16 <property name="paramName" value="lang" />
17</bean>
So, what did we learn from this:
- We were reminded of the default behavior of java.util.ResourceBundle (Remembering the basics is really important).
- We cannot really trust the locale if the deployment environment is the same than the locale of our locale development environment. Thus, in this use case the fallbackToSystemLocale property of the org.springframework.context.support.RealoableResourceBundleMessageSource class should always be set to false.