i18n in VM

Handling UI messages

They to localize UI messages is the use of java.util.ResourceLoader to load the right message bundle depending on user preferred language. Reference to the ResourceLoader object class can be passed to a Velocity template in it's context:

ResourceLoader rb = new ResourceLoader("_org.sakaiproject.tool.foobar.bundle.Messages_");
context.put("tlang", rb );

Then any strings can be referenced as standard velocity variables:

$tlang.getString("foo");

For Sakai 2.8 and newer you can also supply parameters to getFormattedMessage such as:

$tlang.getFormattedMessage("foo", $value)

Handling dates and times

In this case, the key is the use of TimeService to retrieve the user preferred TimeZone together with java.text.DateFormat class (and subclasses).
Reference to DateFormat object class can be passed to a VelocityTemplate in it's context:

DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, new ResourceLoader().getLocale());
df.setTimeZone(TimeService.getLocalTimeZone());
context.put("dateFormat", df );

Then any java.util.Date can be formatted using velocity variables:

$dateFormat.format($foo.date);

Handling number formats

In this case, the key is the use of ResourceLoader to retrieve the user preferred locale together with java.text.NumberFormat class (and subclasses).
Reference to NumberFormat object class can be passed to a VelocityTemplate in it's context:

NumberFormat nbFormat = NumberFormat.getInstance();
Locale locale = new ResourceLoader().getLocale();
nbFormat = NumberFormat.getNumberInstance(locale);
context.put("numberFormat", nbFormat );

or

NumberFormat nbFormat = NumberFormat.getInstance(new ResourceLoader().getLocale());
context.put("numberFormat", nbFormat );

Then any number can be formatted using velocity variables:

$numberFormat.format($foo.number);