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)
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.
If all you want is a shortcut, you can create a tag file, say 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}" />" />
And use it like this
<%@ taglib tagdir="/WEB-INF/tags" prefix="tags"%>
...
<tags:btn key="submitKey" >
...
There isn't. Since I don't do Spring, I'll leave it out of the context in this answer. For the Spring-targeted answer, see @skaffman. You can create a class which extends
ResourceBundle
, manage the loading yourself with help of a Filter
(based on request path?) and store it in the session scope. The ResourceBundle
is accessible the usual JSP EL way. You can access it as if it's a Map
. The handleGetObject()
method will be invoked on every access.
Here's a kickoff example:
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);
}
}
The 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>
If you want to change the locale from inside some servlet or filter:
Text.getCurrentInstance(request).setLocale(newLocale);
ResourceBundle#Control
to read files using UTF-8ResourceBundle
filesResourceBundle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With