我正在尝试从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 :(得分:5)
您使用Spring标记了您的问题,因此我建议您使用Spring MessageSource。 Spring MessageSource甚至可以分层地聚合许多属性文件。与旧的Java ResourceBundle
相比,它具有许多优势。
您可以在MessageSource
中定义弹簧spring-config.xml
,如下所示:
<!--
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。希望这是可以理解的。
答案 1 :(得分:0)
如果两个资源包包含相同的密钥,那么应该使用哪些资源包来解析此密钥?所以,IMO,我认为不能将相同的变量名分配给多个资源包。
也许,您可以在构建过程中将所有.properties
合并到单个.properties
中(确保合并属性文件中的所有键都是唯一的,例如,通过在每个键中添加一些前缀。)然后在整个应用程序中使用此单个合并的.properties
。
答案 2 :(得分:0)
JSF为同一个bundle检查多个文件的唯一情况(我所知道的)是你为多个语言环境提供包(请参阅Providing Localized Messages and Labels)。
您可以将f:loadBundle
标记指向扩展ResourceBundle
的类而不是属性文件,并使用该类引用多个属性文件。我之前没有尝试过。
此外,如果您正在使用Seam,它可以注册多个“全局”包以及可以与一个或多个视图(facelets)相关联的包,所有这些包都可以使用{{1}引用例如messages
如here所述(适用于Seam 2,在Seam 3中可能略有不同)。我认为这就是你所追求的目标。