Is there a shorthand for <fmt:message key="key" />?

Bozho picture Bozho · Jul 4, 2010 · Viewed 10.3k times · Source

It's tedious and ugly to write things like:

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

And in case you want to nest the message tag in another tag's attribute it becomes even worse.

Is there any shorthand for that. For example (like in JSF):

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

(spring-mvc-only solutions applicable)

Answer

skaffman picture skaffman · Jul 4, 2010

This feels like a bit of a hack, but you could write a custom implementation of java.util.Map which, when get(key) is called, fetches the message from the Spring MessageSource. This Map could be added to the model under the msg key, allowing you to dereference the messages using ${msg.myKey}.

Perhaps there's some other dynamic structure than is recognised by JSP EL that isn't a Map, but I can't think of one offhand.

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

    }
}

As an alternative:

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

Then use ${var} as a regular EL.