It has been a busy year so far. Every year I start out thinking that I really need to relax because the previous year was too hectic, but every year it ends up being much more hectic. Anyway, I thought I’d post a JSF quick time that might shave some headache for people developing internationalised applications.
Most JSF developers are aware of the resource-bundle tag in faces-config. Using this tag you can specify a resource bundle that should be available to all your pages using a given variable. For example, the code below will make a variable, msgs, available in all your pages without having to use the loadBundle tag.
<faces-config version="1.2">
...
<application>
<resource-bundle>
<base-name>my.class.path.Messages</base-name>
<var>msgs</var>
</resource-bundle>
</application>
...
</faces-config>
So, say that Messages.properties contains the following:
HELLO_WHAT_IS_YOUR_NAME=Hello, what’s your name?
you can from any page reference this text by writing:
<h:outputText value=”#{mgs.HELLO_WHAT_IS_YOUR_NAME}” />
or
<h:outputText value=”#{mgs[‘HELLO_WHAT_IS_YOUR_NAME’]}” />
I prefer the former as my favourite IDE (NetBeans) support code completion for all the messages in a managed resource bundle.
So far so good. But what if you want to do something a bit more advanced, such as outputting “Hello Allan, welcome to my site. Your last visit was 7. February 2009 at 10:45”. You are not limited to static text in your resource bundle. You can provide placeholders for content that will be replaced at run-time. Let’s have a look at the Message.properties:
WELCOME_MESSAGE=Hello {0}, welcome to my site. Your last visit was {1,date,long} at {1,time,short}
You’ll notice that the message is parameterised using two parameters. The first parameter we are expecting a string containing the name of the user, the second parameter is a java.util.Date containing both the date and time when user last visited the site. Notice that I’ve reused the second paramenter ({1}), one time for the date and the other for the time. On your JSF page you would use the message as follows (imaging that you have a bean called welcome containing a property for getting the name of the user and last visit):
<h:outputFormat value=”#{msgs.WELCOME_MESSAGE}”>
<f:param value=”#{welcome.userName}” />
<f:param value=”#{welcome.lastVisit}” />
</h:outputFormat>
Pretty neat, eh?
What about the classical case of singular and plural messages? Imagine that you want to display the number of records in a table “There are 10 records in the table”. If the Message.properties contained:
RECORDS_IN_TABLE=There are {0} records in the table
You’d end up an embarrassing problem if there was only one record in the table:
“There are 1 records in the table” (This sentence is grammatical incorrect)
Instead you would want it to output:
“There is 1 record in the table”
To do this, you have to use the choice pattern:
RECORDS_IN_TABLE=There {0, choice, 0#are|1#is|2#are} {0} {0, choice, 0#records|1#record|2#records}
The format might look a bit awkward, but once you have understood the pattern it is simple:
{0,choice | means, taking the first parameter and base the output on a choice of formats |
0#are | if the first parameter contains 0 (or below), then it should print “are” |
|1#is | or, if the first parameter contain 1, then it should print “is” |
|2#are} | or, if the first parameter contains 2 (or above), then it should print “are” |
Now, that is nice! So let’s examine the output of these examples:
| There are 0 records in the table |
| There is 1 record in the table |
| There are 2 records in the table |
| There are 10 records in the table |
Enjoy!
7 comments:
Many thanks Allan!
Very good article.
But, i can view messages (just!) with #{mgs[‘my_mess_prop’]}.
If I use #{mgs.my_mess_prop}, then appServer (Glassfish) threw exception:
javax.el.PropertyNotFoundException: The class 'java.lang.String' does not have the property 'my_mess_prop'.
Ayrat.
at javax.el.BeanELResolver.getBeanProperty(BeanELResolver.java:547)
ets.
Sounds like mgs is set up as a backing bean rather than a resource bundle?
I don't know Al :)
I have experience with JSF just second day.
But i18n set up in config file as
<application>
<resource-bundle>
<base-name>i18n.messages</base-name>
<var>msgs</var>
</resource-bundle>
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
</application>
Ayrat
:-) Okay, I'll be easy on you then.. Since your var is called msgs you should also use this variable on the page, e.g. {#msgs.NAME_OF_MESSAGE}
hi Al
Yes, I use 'msgs'.
#{msgs[‘my_mess_prop’]} is correct, but #{msgs.my_mess_prop} not works.
Probably, some EL-library needed.
Thanks
Hi,
Do you know if it is possible to change the message when you use a onClick="if (confirmDeleteSelectedRows() == false) return false;"
over a button to put the alert on different languages?
Thanks indeed.
Yes, you can include messages in your JavaScript as well. Since this JavaScript method is producing your confirm box: confirmDeleteSelectedRows(), I can't tell you exactly how to i18n the confirm box for that. But you could create it simply like this:
onclick="if (!confirm('#{msgs.MY_CONFIRM_MESSAGE}')) return false;"
Post a Comment