是否有<fmt:message key =“key”>?</fmt:message>的简写

时间:2010-07-04 10:28:31

标签: java jsp jstl el

写下这样的东西很乏味和丑陋:

<input type="button" value="<fmt:message key="submitKey" />" />

如果你想将消息标记嵌套在另一个标签的属性中,那就更糟了。

是否有任何简写。例如(如在JSF中):

<h:commandButton value="#{msg.shareKey}" />

(适用于spring-mvc的解决方案)

6 个答案:

答案 0 :(得分:12)

这感觉有点像黑客攻击,但你可以写一个java.util.Map的自定义实现,当调用get(key)时,它会从Spring MessageSource中获取消息。可以将Map添加到msg密钥下的模型中,以便您使用${msg.myKey}取消引用邮件。

也许还有一些其他的动态结构,而不是JSP EL认可的动态结构,而不是Map,但我想不出一个随意的结构。

public class I18nShorthandInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = Logger.getLogger(I18nShorthandInterceptor.class);

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private LocaleResolver localeResolver;

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {

        request.setAttribute("msg", new DelegationMap(localeResolver.resolveLocale(request)));

        return true;
    }

    private class DelegationMap extends AbstractMap<String, String> {
        private final Locale locale;

        public DelegationMap(Locale locale) {
            this.locale = locale;
        }

        @Override
        public String get(Object key) {
            try {
                return messageSource.getMessage((String) key, null, locale);
            } catch (NoSuchMessageException ex) {
                logger.warn(ex.getMessage());
                return (String) key;
            }
        }
        @Override
        public Set<Map.Entry<String, String>> entrySet() {
            // no need to implement this
            return null;
        }

    }
}

作为替代方案:

<fmt:message key="key.name" var="var" />

然后使用${var}作为常规EL。

答案 1 :(得分:4)

如果你想要的只是一个快捷方式,你可以创建一个标签文件,比如说btn.tag

<%@tag%>
<%@ attribute name="key" required="true" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>

<input type="button" value="<fmt:message key="${key}" />" />

并像这样使用

<%@ taglib tagdir="/WEB-INF/tags" prefix="tags"%>
...
<tags:btn key="submitKey" >
...

答案 2 :(得分:3)

没有。由于我不做Spring,所以我会在本回答中将其排除在外。有关Spring目标的答案,请参阅@skaffman。您可以创建一个extends ResourceBundle的类,使用Filter(基于请求路径?)自行管理加载,并将其存储在会话范围内。 ResourceBundle可以通常的JSP EL方式访问。您可以像Map一样访问它。每次访问都会调用handleGetObject()方法。

这是一个启动示例:

package com.example;

import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.servlet.http.HttpServletRequest;

public class Text extends ResourceBundle {

    private static final String TEXT_ATTRIBUTE_NAME = "text";
    private static final String TEXT_BASE_NAME = "com.example.i18n.text";

    private Text(Locale locale) {
        setLocale(locale);
    }

    public static void setFor(HttpServletRequest request) {
        if (request.getSession().getAttribute(TEXT_ATTRIBUTE_NAME) == null) {
            request.getSession().setAttribute(TEXT_ATTRIBUTE_NAME, new Text(request.getLocale()));
        }
    }

    public static Text getCurrentInstance(HttpServletRequest request) {
        return (Text) request.getSession().getAttribute(TEXT_ATTRIBUTE_NAME);
    }

    public void setLocale(Locale locale) {
        if (parent == null || !parent.getLocale().equals(locale)) {
            setParent(getBundle(TEXT_BASE_NAME, locale));
        }
    }    

    @Override
    public Enumeration<String> getKeys() {
        return parent.getKeys();
    }

    @Override
    protected Object handleGetObject(String key) {
        return parent.getObject(key);
    }

}

Filter

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    Text.setFor((HttpServletRequest) request);
    chain.doFilter(request, response);
}

JSP:

<p>${text['home.paragraph']}</p>

如果要从某个servlet或过滤器内部更改语言环境:

Text.getCurrentInstance(request).setLocale(newLocale);

相关/有意思方知:

答案 3 :(得分:0)

我找到了一种没有任何拦截器的方法:

${pageScope["org.springframework.web.servlet.tags.REQUEST_CONTEXT"]
    .getMessage("hello")}

但它太长了,并且“org.springframework.web.servlet.tags.REQUEST_CONTEXT”键可能与所有版本的弹簧不兼容。

答案 4 :(得分:0)

我为每种语言使用属性文件,以下效果很好:

<input type="button" value="${msg['myKey']}" />

答案 5 :(得分:0)

您可以在servlet中设置msg请求变量,或者使用资源包过滤,以通过这种方式在JSP代码中通过EL表达式获取消息${msg.messageKey}

import javax.servlet.jsp.jstl.core.Config;
import java.util.ResourceBundle;

...

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

  String STR_LOCALE = "es-MX"; // you can get this value from the http request to get the default browser locale.
  String LOCALE_BASENAME = "my.package.basename";
  Locale locale = Locale.forLanguageTag(STR_LOCALE);
  req.setAttribute("msg", ResourceBundle.getBundle(LOCALE_BASENAME, locale));

  // And you can setup the 'fmt' tag library from here to resolve parameterized messages.
  Config.set(req, Config.FMT_LOCALE, locale);
  Config.set(req, Config.FMT_LOCALIZATION_CONTEXT, LOCALE_BASENAME);

}

示例:

 ...
 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
 ...
 <h1>${msg.header}</h1>
 <h2>${msg[variableHeader]}</h2>
 <fmt:message key='messageWithVariable'>
    <fmt:param>The value</fmt:param>
 </fmt:message>

这适用于我的java servlet 2.5环境。