Using Multiple Resource bundles in JSF
I am trying to access multiple resource bundles from a JSF page. I have two resource bundles:
general_messages.properties
module_message.properties
I want to access both these resource bundles in a JSF file. One way I can do this is to define specific properties for each of these bundles:
<f:loadBundle basename="com.sample.general_messages" var="general"/>
<f:loadBundle basename="com.sample.module_message" var="module"/>
Is there a way I can access both these resource bundles using the same variable name. Something like:
<f:loadBundle basename="com.s开发者_开发百科ample.general_messages, com.sample.module_message" var="general"/>
Or any other best way to access multiple resource bundles?
You tagged your question with Spring, so I recommend you using Spring MessageSource. Spring MessageSource can aggregate many property files even hierarchically. It gives you many advantages over old java ResourceBundle
.
You can define spring MessageSource
in you spring-config.xml
like this:
<!--
Application messages configuration.
-->
<bean id="messageSource" name="resourceBundle"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
p:fallbackToSystemLocale="false"
p:cacheSeconds="0">
<property name="basenames">
<list>
<value>/messages/Messages</value>
<!-- <value>${application.messages}</value>-->
</list>
</property>
</bean>
Than you can define your Class
which extends ResourceBundle
like this (Needs some cleaning and refactoring):
public class SpringResourceBundle extends ResourceBundle
{
private MessageSource messages;
private FacesContext fc;
private Locale locale = null;
public SpringResourceBundle()
{
fc = FacesContext.getCurrentInstance();
WebApplicationContext webAppCtx = (WebApplicationContext) fc.getExternalContext().getApplicationMap().get(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
messages = (MessageSource) webAppCtx.getBean("messageSource");
}
@Override
public Locale getLocale()
{
Locale loc = fc.getELContext().getLocale();
if (fc.getExternalContext() != null) {
loc = fc.getExternalContext().getRequestLocale();
}
try {
UIViewRoot viewRoot = fc.getViewRoot();
if (viewRoot != null) {
loc = viewRoot.getLocale();
}
if (loc == null) {
loc = fc.getApplication().getDefaultLocale();
}
} catch (Throwable th) {
System.out.println(th.getMessage());
loc = locale;
}
locale = loc;
return loc;
}
@Override
protected Object handleGetObject(String key)
{
try {
return messages.getMessage(key, null, getLocale());
} catch (NoSuchMessageException e) {
return "???" + key + "???";
}
}
@Override
public Enumeration<String> getKeys()
{
return Collections.enumeration(Collections.EMPTY_LIST);
}
}
Finnaly in faces-config.xml
declare your resource bundle with Class above. Something like this:
<application>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>cs</supported-locale>
<supported-locale>de</supported-locale>
<supported-locale>en</supported-locale>
</locale-config>
<message-bundle>your.package.SpringResourceBundle</message-bundle>
</application>
Here you go Spring MessageSource in JSF. Hope it's understandable.
If two resource bundles contain the same key , then which resource bundles should be used to resolve this key ? So ,IMO ,I don't think the same variable name can be assigned to multiple resource bundles.
Perhaps , you can merge all the .properties
into a single .properties
in your build process (make sure all keys in the merged properties file is unique , for example , by adding some prefix in each key.) . Then you use this single merged .properties
throughout the application.
The only situation (that I know of) in which JSF checks multiple files for the same bundle is if you are providing bundles for multiple locales (see Providing Localized Messages and Labels).
You might be able to point the f:loadBundle
tag to a class that extends ResourceBundle
instead of a properties file and use that class to reference multiple properties files. I haven't tried that before though.
Also, if you are using Seam, it provides the ability to register multiple 'global' bundles as well as bundles that can be associated with one of more views (facelets), all of which can be referenced using messages
e.g. #{messages.my_message}
as described here (that's for Seam 2, it may be a little different in Seam 3). I think that's what you're after though.
精彩评论