开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜