i18n in JSP and JSF

Handling UI messages

JSF based tools

Each tool's properties file should be loaded as a managed-bean in it's faces-config.xml file:

<managed-bean>
      <description>
         Dynamic Resource Bundle Loader
      </description>
      <managed-bean-name>msgs</managed-bean-name>
      <managed-bean-class>org.sakaiproject.util.java.ResourceLoader</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>
      <managed-property>
         <description>Bundle baseName</description>
         <property-name>baseName</property-name>
         <value>_org.sakaiproject.tool.foobar.bundle.Messages_</value>
      </managed-property>
</managed-bean>

An alternative to modifying the faces-config.xml file is to insert the following into the jsf file:

<jsp:useBean id="msgs" class="org.sakaiproject.util.ResourceLoader" scope="session">
<jsp:setProperty name="msgs" property="baseName" value="_org.sakaiproject.tool.foobar.bundle.Messages_"/>
</jsp:useBean>

Any reference to <f:loadBundle> should be removed from all JSF template files.
Localized strings in properties files are referenced using standard JSF variable syntax:

<h:outputText value="#{msgs.foo}"/>

JSP based tools

The ResourceLoader can be initialized by inserting the following into the jsp file:

<jsp:useBean id="msgs" class="org.sakaiproject.util.ResourceLoader" scope="session">
<jsp:setProperty name="msgs" property="baseName" value="_org.sakaiproject.tool.foobar.bundle.Messages_"/>
</jsp:useBean>

Any reference to <fmt:setLocale> or <fmt:setBundle> should be removed from all JSP template files.
Localized strings in properties files are referenced using standard JSP variable syntax:

<c:out value="${msgs.foo}"/>

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).

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

In this point, DateFormat is fully internationalized, so we can format any java.util.Date object:

df.format(foo.getMyDateProperty());

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). Then any number can be formatted using velocity variables:

NumberFormat nbFormat = NumberFormat.getInstance();
Locale locale = new ResourceLoader().getLocale();
nbFormat = NumberFormat.getNumberInstance(locale);
nbFormat.format(foo.getMyNumberProperty());

or

NumberFormat nbFormat = NumberFormat.getInstance(new ResourceLoader().getLocale());
nbFormat.format(foo.getMyNumberProperty());