Saturday, August 2, 2008

Grails with Multi Language Select Lists

Lets say you have a customer who has multiple languages spoken in their country. They need their system to support all three languages. The user will choose the language when they log in. This is easy to solved for labels by using the i18n message files.

It is not so straight forward when you need to support Select lists. In this example, I'm going to show how we can handle Address Type using i18n message files in Grails. This same concept can be applied to other type of data. E.g. Day of Week, Country.

Lets define my class. Notice, how the constraint for addressType has values of RESIDENTIAL or POSTAL. This corresponds to values in the messages.properties and messages_fr.properties(I want to support french for this application. Everyone knows the French hate speaking English).


class Address {
String addressType
String addressLine1
String addressLine2
String townCity
String postCode
String toString() {"${this.addressLine1+" "+ this.addressLine2+" "+ this.townCity}"}

static constraints = {
addressType(blank:false,inList: ['RESIDENTIAL','POSTAL'])
addressLine1(blank:false)
addressLine2()
townCity(blank:false)
postCode()
}
}


My message.properties...

address.addressType.RESIDENTIAL=Residential
address.addressType.POSTAL=Postal


My message_fr.properties...

address.addressType.RESIDENTIAL=RésidentieM
address.addressType.POSTAL=Postal


Now I need to change my gsp pages to reference the new entries in message.properties.

Firstly Create.gsp and Update.gsp, I've change the input to a select...

<tr class="prop">
<td valign="top" class="name">
<label for="addressType">Address Type:</label>
</td>
<td valign="top" class="value ${hasErrors(bean:address,field:'addressType','errors')}">
<g:select name="addressType" from="${['RESIDENTIAL','POSTAL']}" valueMessagePrefix="address.addressType" value="${fieldValue(bean:address,field:'addressType')}"/>
</td>
</tr>


Show.jsp also needs to be changed....

<tr class="prop">
<td valign="top" class="name">Address Type:</td&gt
<td valign="top" class="value"><g:message code="address.addressType.${fieldValue(bean:address, field:'addressType')}"/></td>
</tr>


And finally list.jsp...

<td><g:message code="address.addressType.${fieldValue(bean:address, field:'addressType')}"/></td>


Hope this solution helps. Comments appreciated.


2 comments:

Lee said...

Thanks for that Chris, I was going to have to do the same thing on an app I'm working on in the coming weeks.

Unknown said...

Hey, we don't hate speaking english... it's just that we prefer to speak french ! :-)

Anyway, your message_fr.properties should be:

address.addressType.RESIDENTIAL=Résidentielle
address.addressType.POSTAL=Postale

"Adresse" is a feminine word in french.
Other than that, there is a '>' character displayed as '&' 'g' 't' ';' sequence of chars.

Thanks for this article and "Bien le bonsoir de Montréal !"