Spring internationalizable dropdown list

A further detail we might want to focus on is internationalization of our form. Spring MVC does not provide any i18n features for its form tags, there are however several issue reports addressing this (form:options tag does not support i18n, form:select does not provide I18N capabilities, Provide comprehensive I18N support for the Spring form tag library and many more, for a detailed list search for ‚i18n form‘ on https://jira.springsource.org/secure/IssueNavigator.jspa?mode=show&createNew=true). However these issues can be solved.
The internationalization of labels is pretty straight forward: You define the label tag wrapped arround a message tag:

<form:label path="list[${x.index}].label">
	<spring:message code="${item.label}"/>
</form:label>

A bit more complex it is when a select list should be internationalized. For that to achieve you have to iterate over all the options and put each option on its own. Up until now we used a Map to contain the options. Over a Map however cannot be iterated with the forEach and extracting an entry Set results in a mess of JSP code. I therefore created an EntryList which is as the name sugests a List of Entries. An entry is basically the same as defined by Map.Entry.

public class Entry<K,V> {

	private K key;
	private V value;	
	
	public Entry(K key, V value) {
		super();
		this.key = key;
		this.value = value;
	}
	public K getKey() {
		return key;
	}
	public void setKey(K key) {
		this.key = key;
	}
	public V getValue() {
		return value;
	}
	public void setValue(V value) {
		this.value = value;
	}
	
	...	
}

In the above code snipped I did not show the implementations of hashCode, equals and toString. The equals method only compares the key element.

public class EntryList<K,V> implements List<Entry<K,V>>{

	private List<Entry<K,V>> list = new ArrayList<Entry<K,V>>();
	/**
	 * Add a key value pair if the key is not already in the list
	 * @param key Key of the new entry
	 * @param value Value of the new entry
	 * @return true if the entry could be added
	 */
	public boolean put(K key, V value){
		Entry<K,V> entry = new Entry(key,value);
		if (list.contains(entry)){
			return false;
		} else {
			return list.add(new Entry(key,value));
		}
	}
	...	
}

In the above method I omitted the implementation of the List methods which are all delegated to list. I added a put method as a convenience for adding Entries by its key value pairs so they are unique in the list.
Using an EntryList of type <Integer,String> or <String,String> we can change the JSP from:

<form:select path="list[${x.index}].selected" items="${item.options}"></form:select>

to:

<form:select path="list[${x.index}].selected">
	<c:forEach items="${item.options}" var="option">
		<c:choose>
			<c:when test="${item.selected eq option.key }">
				<form:option value="${option.key}" selected="selected"><spring:message code="${option.value }"/></form:option>
			</c:when>
			<c:otherwise>
				<form:option value="${option.key}" ><spring:message code="${option.value }"/></form:option>
			</c:otherwise>
		</c:choose>
	</c:forEach>
</form:select>

Observe the selected attribute on the form:option tag to ensure that preselected values are displayed correctly.

Schreibe einen Kommentar