I\'m using Java + Spring for an international website.
The 2 languages are ZH and EN (Chinese and English).
I have 2 files: messages.properties (for English
You could create your own Custom MessageSource for this purpose.
Something like:
public class SpecialMessageSource extends ReloadableResourceBundleMessageSource {
@Override
protected MessageFormat resolveCode(String code, Locale locale) {
MessageFormat result = super.resolveCode(code, locale);
if (result.getPattern().isEmpty() && locale == Locale.CHINESE) {
return super.resolveCode(code, Locale.ENGLISH);
}
return result;
}
@Override
protected String resolveCodeWithoutArguments(String code, Locale locale) {
String result= super.resolveCodeWithoutArguments(code, locale);
if ((result == null || result.isEmpty()) && locale == Locale.CHINESE) {
return super.resolveCodeWithoutArguments(code, Locale.ENGLISH);
}
return result;
}
}
and configure this messageSource bean in spring xml as
<bean id="messageSource" class="SpecialMessageSource">
.....
</bean>
Now to get resolved Label you will be invoking MessageSource's
either of the below methods
String getMessage(String code, Object[] args, Locale locale);
String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
resolveCode()
will be called when your message label has arguments and you pass those arguments via args
parameter like below
invalid.number= {0} is Invalid
and you invoke messageSource.getMessage("INVALID_NUMBER", new Object[]{2d}, locale)
resolveCodeWithoutArguments()
will be called when your message label does not have arguments and you pass args
parameter as null
validation.success = Validation Success
and you invoke messageSource.getMessage("INVALID_NUMBER", null, locale)
@harrybvp's answer got me on the right track. This is the code that seems to work for me (and is unit-testable when you mock the methods that call "super"):
public class GracefulMessageSource extends org.springframework.context.support.ReloadableResourceBundleMessageSource {
final static private Locale defaultLocale = Locale.ENGLISH;
@Override protected MessageFormat resolveCode(final String code, final Locale locale) {
MessageFormat result = superResolveCode(code, locale);
if (result.toPattern().isEmpty() && !locale.equals(this.defaultLocale)) {
result = superResolveCode(code, this.defaultLocale);
}
return result;
}
@Override protected String resolveCodeWithoutArguments(final String code, final Locale locale) {
String result = superResolveCodeWithoutArguments(code, locale);
if (result.isEmpty() && !locale.equals(this.defaultLocale)) {
result = superResolveCodeWithoutArguments(code, this.defaultLocale);
}
return result;
}
protected MessageFormat superResolveCode(final String code, final Locale locale) {
return super.resolveCode(code, locale);
}
protected String superResolveCodeWithoutArguments(final String code, final Locale locale) {
return super.resolveCodeWithoutArguments(code, locale);
}
}
and in my webmvc-config.xml:
<bean id="messageSource" class="com.mycode.fe.web.GracefulMessageSource">
<property name="basename">
<value>${content.path.config}/WEB-INF/messages</value>
</property>
<property name="defaultEncoding" value="UTF-8" />
<property name="cacheSeconds" value="2"/>
<property name="fallbackToSystemLocale" value="true"/>
</bean>
Then in my Velocity view templates:
For a normal key with no arguments: #springMessage('menu_item1')
For a key that accepts arguments: #springMessageText('male_to_female_ratio' [3, 2])
Then in the messages.properties (English translations):
male_to_female_ratio = There is a {0}:{1} male-to-female ratio.