弹簧 - 获取所有可解析的消息键

2022-09-03 13:58:21

我有一个使用Spring MVC的Web应用程序。我希望我的界面只包含一个页面,该页面通过AJAX以JSON形式动态检索所有数据。我的问题是国际化。当我在jsps中呈现内容时,我可以使用JSTL标签来解析我的密钥(使用Spring MVC非常容易):

<fmt:message key="name"/>: ${name}
<fmt:message key="title"/>: ${title}
<fmt:message key="group"/>: ${group}

配置正确后,它在芬兰语区域设置中呈现为

Nimi: yay
Otsikko: hoopla
Ryhmä: doo

现在,当我使用json时,我只有这个来自服务器:

{
 name: "yay", 
 title: "hoopla",
 group: "doo"
}

没有键名!但我必须以某种方式提供它们。我考虑过将键名更改为其本地化形式或将本地化键名添加到json输出中(例如name_localized=“Nimi”),但这两个选项都感觉很糟糕。我正在使用jackson json自动将我的域对象解析为json,我喜欢它提供的封装。

我想出的唯一可行的解决方案是:动态创建一个javascript文件,其中本地化的键名作为变量。

<script type="text/javascript">
var name="Nimi";
var title="Otsikko";
var group="Ryhmä";
</script>

加载后,我现在在我的javascript中拥有了处理json的所有信息!但有一个问题:我的字段名称列表是动态的。因此,实际上 jsp 中的静态渲染如下所示:

<c:forEach var="field" values="${fields}">
 <fmt:message key="${field.key}"/>: ${field.value}
</c:forEach>

我需要查找在我的 messages.properties 中指定的所有消息。Spring MessageSource接口仅支持按键检索消息。如何在我的JSP中获取呈现本地化javascript变量的键名列表?


答案 1

好吧,我通过扩展ResourceBundleMessageSource“解决了”我的问题。

package org.springframework.context.support;

import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Set;

public class ExposedResourceBundleMessageSource extends
        ResourceBundleMessageSource {
    public Set<String> getKeys(String basename, Locale locale) {
        ResourceBundle bundle = getResourceBundle(basename, locale);
        return bundle.keySet();
    }
}

现在我可以访问密钥,但是除了必须指定消息源基名称之外,我还必须在控制器中执行丑陋的强制转换。呃,这是很多耦合。

Set<String> keys = 
  ((ExposedResourceBundleMessageSource)
  messageSource).getKeys("messages", locale);

答案 2

我已经解决了这个问题。


public class ExposedResourceBundleMessageSource extends
        ResourceBundleMessageSource {
    public static final String WHOLE = "whole";
    private Set baseNames;
    private Map> cachedData = new HashMap>();

    public Set getKeys(String baseName, Locale locale) {
        ResourceBundle bundle = getResourceBundle(baseName, locale);
        return bundle.keySet();
    }

    public Map getKeyValues(String basename, Locale locale) {
        String cacheKey = basename + locale.getCountry();
        if (cachedData.containsKey(cacheKey)) {
            return cachedData.get(cacheKey);
        }
        ResourceBundle bundle = getResourceBundle(basename, locale);
        TreeMap treeMap = new TreeMap();
        for (String key : bundle.keySet()) {
            treeMap.put(key, getMessage(key, null, locale));
        }
        cachedData.put(cacheKey, treeMap);
        return treeMap;
    }

    public Map getKeyValues(Locale locale) {
        String cacheKey = WHOLE + locale.getCountry();
        if (cachedData.containsKey(cacheKey)) {
            return cachedData.get(cacheKey);
        }
        TreeMap treeMap = new TreeMap();
        for (String baseName : baseNames) {
            treeMap.putAll(getKeyValues(baseName, locale));
        }
        cachedData.put(cacheKey, treeMap);
        return treeMap;
    }

    public void setBasenames(String[] basenames) {
        baseNames = CollectionUtils.arrayAsSet(basenames);
        super.setBasenames(basenames);
    }


}