Memo from cmcclanahan on 12 August 1999, 15:15 Thursday
To: JSP-INTEREST
cc: (bcc: Hai-Bang Pham)
Subject: Creating Internationalized JSP-Based Applications
>Several people have asked questions about writing internationalized
apps
>with JSP. Having just done so (only with Western European languages so
>far), I have learned some things that may be interesting to others in
>the same situation. The basic components of my approach were as
>follows:
>
>(1) All internationalized strings are stored in resource bundles
>
>I used property resource files named Resources.properties (the default
>translation, which was English), and Resources_xx.properties (where
"xx"
>is the ISO code of the language), following the ResourceBundle naming
>conventions. I heavily used the parameter replacement features like
{0}
>to synthesize internationalized messages that contained elements that
>originated in the database.
>
>(2) Accessing the resource bundles from the web application
>
>I created a JavaBean called "BundleBean" that had a series of methods
>with calling sequences like this:
>
> String message = bundleBean.getMessage(locale, "label.username");
>
>and it looked in the correct resource bundle for the language of this
>locale. The bundle bean is stored in the application context in a
>startup servlet, by calling:
>
> getServletContext().setAttribute("bundleBean", bundleBean);
Why not use the session? Which engine are you using? The reason I ask
is because I don't think WebSphere 2.02 supports the setAttribute()
method through the servlet context (correct me if I'm wrong!).
>
>to make it available to both servlets and JSP pages.
>
>(3) Internationalize the business logic
>
>We had to deal with things like the fact that many European cities have
>different names in different languages, so our business object for a
>city has two different property getters for the name:
>
> String getName() returns the name in the language of the default
>Locale
> String getName(Locale locale) returns the name in the language of
>the
> specified Locale, if it is different, or in the "canonical"
>language.
>
>(4) Store a Locale object for the user's preferrred language in the
>user's session
>
>When a user logs on, one of the things we know is their preferred
How about before they login? How do you handle the default situation?
I take it then that your first page (portal into the system) isn't
internationalized?
>language (they can switch later, if they want). To record that
>knowledge, we store a java.util.Locale instance based on that language
>in the session object, under key "localeBean". If the user exercizes
>the option to change languages, we just update the locale and the next
>page display is auto-magically done in the newly chosen language.
>
>(5) Separate business logic and presentation logic
>
>I'm a big beliver in this separation, and it paid off in this
>application. All my form submits go to a processing servlet (in the
>real app, it's actually an action procedure called by a single servlet)
>that does the appropriate business logic, which is mostly independent
of
>language choice, then stores appropriate beans in the session or
>request, and forwards to an appropriate JSP page to display the next
>result, using RequestDispatcher.forward().
>
>(6) A simplified internationalized login page using the above features,
>then, looks something like this:
>
> <%@ page language="java" buffer="8kb" session="true" %>
>
> <jsp:useBean id="attemptBean" scope="request"
> class="com.mycompany.AttemptBean" />
> <%-- Contains username and password from previous attempt, if any
>--%>
>
> <jsp:useBean id="bundleBean" scope="application"
> imports="java.util.Locale"
> class="com.mycompany.BundleBean" />
>
> <%
> Locale localeBean = (Locale) session.getValue("localeBean");
> if (localeBean == null) {
> localeBean = Locale.getDefault();
You might want to consider grabbing the Accept-Language header and
use these values as the default(s) instead. Then you can use the
user's settings. This way you get the client's defaults instead of
the server's. BTW, following (5) of separating business logic from
presentation logic shouldn't this chunk of code sit inside a servlet?
> session.putValue("localeBean", localeBean);
> }
> %>
>
> <head>
> <title>Logon Page</title>
> </head>
> <body>
> <form action="/logon"> // Logon processing servlet
> <table border=0>
> <tr>
> <th align=right>
> <%= bundleBean.getMessage(localeBean, "label.username")
%>
>
> </th>
> <td>
> <input type="text" name="username"
> value="<%= attemptBean.getUsername() %>">
> </td>
> </tr>
> <tr>
> <th align=right>
> <%= bundleBean.getMessage(localeBean, "label.password")
%>
>
> </th>
> <td>
> <input type="password" name="password"
> value="<%= attemptBean.getPassword() %>">
> </td>
> </tr>
> <tr>
> <td> </td>
> <td>
> <input type="submit" value="<%=
>bundleBean.getMessage(localeBean, "button.LogOn") %>">
> <input type="reset" value="<%=
>bundleBean.getMessage(localeBean, "button.Reset") %>">
> </td>
> </tr>
> </table>
> </form>
> </body>
>
>NOTE: In pages other than the login page, I use the presence or
absence
>of a Locale in the session as an indicator that the session has
expired,
>and forward control to the login page if it's missing. The logic looks
>like this:
>
> <%
> Locale localeBean = (Locale) session.getValue("localeBean");
> if (localeBean == null) {
> %>
> <jsp:forward page="/login.jsp" />
> <% } %>
>
We also tried to have a single JSP handle i18n but the major problem we
found was the translation messed up our interface. As an example,
"Cancel" in german might be "Abbrechen" and "Password" in french might
be "Mot de pass". The length of these translated words alone suggested
that having a single template isn't going to cut it. Imaging the above
template on languages such as Arabic or Japanese.
Cheers,
-Hai
To: [EMAIL PROTECTED]@Internet
cc: (bcc: CN=Hai-Bang Pham/OU=TOR/OU=CA/OU=JHMarsh/O=MMC)
From: [EMAIL PROTECTED]
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JSP-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".