在JSF中使用多个资源包



我试图从一个JSF页面访问多个资源包。我有两个资源包:

  • general_messages.properties
  • module_message.properties

我想在一个JSF文件中访问这两个资源包。一种方法是为每个bundle定义特定的属性:

<f:loadBundle basename="com.sample.general_messages" var="general"/>
<f:loadBundle basename="com.sample.module_message" var="module"/>

是否有一种方法可以使用相同的变量名访问这两个资源束。比如:

<f:loadBundle basename="com.sample.general_messages, com.sample.module_message" var="general"/>

或者其他访问多个资源包的最佳方式吗?

你用Spring标记了你的问题,所以我建议你使用Spring MessageSource。Spring MessageSource甚至可以分层地聚合许多属性文件。它比旧的java ResourceBundle有很多优点。

您可以在您的spring-config.xml中像这样定义spring MessageSource:

<!--
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>

然后你可以定义你的Class扩展ResourceBundle像这样(需要一些清理和重构):

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);
    }
}

最后在faces-config.xml用上面的Class声明你的资源包。像这样:

<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>

在JSF中使用Spring MessageSource。

如果两个资源包包含相同的键,那么应该使用哪个资源包来解析这个键?所以,在我看来,我不认为相同的变量名可以分配给多个资源包。

也许,您可以在构建过程中将所有.properties合并为单个.properties(确保合并属性文件中的所有键都是唯一的,例如,通过在每个键中添加一些前缀)。然后在整个应用程序中使用这个合并的.properties

(据我所知),JSF为同一个bundle检查多个文件的唯一情况是,如果您为多个地区提供bundle(请参阅提供本地化消息和标签)。

您可以将f:loadBundle标记指向扩展ResourceBundle的类,而不是属性文件,并使用该类引用多个属性文件。我还没试过呢。

此外,如果你正在使用Seam,它提供了注册多个"全局"捆绑包的能力,以及可以与多个视图(facelets)相关联的捆绑包,所有这些都可以使用messages引用,例如这里描述的#{messages.my_message}(这是为Seam 2,它可能在Seam 3中略有不同)。我认为这就是你想要的。

相关内容

  • 没有找到相关文章

最新更新