Reputation: 2459
I want to use Spring's i18n utility in a manner that all languages are separated by folders. I plan to use this kind of folder structure to keep things more organized than having all in one folder:
i18n
fr
Is this possible?
Upvotes: 3
Views: 816
Reputation: 24590
Is this possible?
Yes it is.
A simple solution I initially thought of was to setup a message source with the basenames
property, something like this:
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="useCodeAsDefaultMessage" value="true" />
<property name="basenames">
<list>
<value>i18n.en.messages</value>
<value>i18n.en.application</value>
<value>i18n.fr.messages</value>
<value>i18n.fr.application</value>
</list>
</property>
</bean>
Giving it a second thought though, I realized the above won't work. Based on the ResourceBundle
s strategy to instantiate bundles, given a name for a bundle, the first name in the bundle list would resolve the bundle (e.g. looking for messages_fr.properties
the strategy will look for i18n/en/messages_fr.properties
and then get resolved to i18n/en/messages.properties
as the default when messages_fr.properties
is not found).
You will need something that discovers your bundles based on a custom folder configuration. You will have to write your own MessageSource implementation and use it in your application instead of the default ones provided by Spring. A basic implementation could look like this:
package pack.age;
import java.util.Locale;
import java.util.ResourceBundle;
import org.springframework.context.support.ResourceBundleMessageSource;
public class ByFolderResourceBundleMessageSource extends ResourceBundleMessageSource {
private String rootFolder;
@Override
protected ResourceBundle getResourceBundle(String basename, Locale locale) {
String langCode = locale.getLanguage().toLowerCase();
String fullBaseName = this.rootFolder + "." + langCode + "." + basename;
ResourceBundle bundle = super.getResourceBundle(fullBaseName, locale);
if (bundle == null) {
String defaultBaseName = this.rootFolder + ".Default." + basename;
bundle = super.getResourceBundle(defaultBaseName, locale);
}
return bundle;
}
public void setRootFolder(String rootFolder) {
this.rootFolder = rootFolder;
}
}
Configuration like:
<bean id="messageSource"
class="pack.age.ByFolderResourceBundleMessageSource">
<property name="useCodeAsDefaultMessage" value="true" />
<property name="rootFolder" value="i18n" />
<property name="basenames">
<list>
<value>messages</value>
<value>application</value>
</list>
</property>
</bean>
And with a folder setup like:
i18n
├───Default
│ ├─── application.properties
│ └─── messages.properties
│
├─── en
│ ├─── application.properties
│ └─── messages.properties
│
└─── fr
├─── application.properties
└─── messages.properties
Upvotes: 1