2011-07-22 68 views
6

我想从JSF页面访问多个资源包。我有两个资源包:在JSF中使用多个资源包

  • general_messages.properties
  • module_message.properties

我想在JSF文件来访问这两个资源包。我能做到这一点的方法之一是为每个包的定义特定属性:

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

或者访问多个资源捆绑任何其他最好的方法?

+0

我在想如果Spring Framework有这个解决方案吗? – Abdul

回答

5

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

你可以在你spring-config.xml定义春天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); 
    } 
} 

Finnaly在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。希望这是可以理解的。

0

如果两个资源包含相同的密钥,那么应该使用哪个资源包来解析此密钥?所以,国际海事组织,我不认为相同的变量名称可以分配给多个资源包。

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

+0

这就是解决方案之一,但如果有人将应用程序模块化,并且当有很多字段时,将一个属性文件中的所有内容都变得笨拙且难以管理。真的必须有解决方案来解决这个问题。我正在努力探索如何使其工作。快速思考:Spring Framework是否为我们提供了解决方案? – Abdul

0

JSF为同一捆绑包检查多个文件的唯一情况是(如果您要提供多个区域设置的捆绑包,请参阅Providing Localized Messages and Labels)。

您可能可以将f:loadBundle标记指向延伸ResourceBundle而不是属性文件并使用该类引用多个属性文件的类。尽管如此,我还没有尝试过。另外,如果您使用Seam,它提供了注册多个'全局'包以及可以与一个或多个视图(facelets)关联的包的功能,所有这些都可以使用messages(例如messages)引用。 #{messages.my_message}here所述(对于Seam 2来说,它在Seam 3中可能有点不同)。我认为这就是你想要的。