View / i18n

Supersizing i18n

I was wondering if there is a way to store a relatively big amount of text (which can't be fitted in one single line) assigned to some variable in the ApplicationResources.properties file. This text eventually will be local-sensitive that's why I want to put it into the .properties file.

[Ted Husted] The standard message resource object (org.apache.struts.util.PropertyMessageResources) is implemented as a HashMap. The resource is loaded into memory for each locale (when 1 or more users need it). 

Whether its a good idea to store a relatively big amount of text this way depends on the resources you have available, and  how often the text is used.

Alternatives would include creating seperate JavaServer Pages for different locales, and having the Action select the appropriate page for the user. Or, having the view look at the locale and include the text at runtime (or view-time).


The Map is not the Locale

My boss wants me to set up one of my apps written using struts for a demo. He wants to have a web page with a couple of flags. The use clicks on of the flags and enters the program using the language they selected.
 
Not having gone down this road before any idea what that would entail. I know I would have to create multiple localisation files for the languages. But how do I specify for each user what file to use and can you have multiple users all accessing your program concurrently viewing it in different languages.

[Craig McClanahan] The technical information on how to do this (modify the Locale in the user's session) is correct -- I just wanted to make a social comment on your boss's request.

When I built an app in Europe a couple of years ago (which is where a lot of the basic ideas for Struts came from :-), I was told that the use of flags to select languages was pretty offensive to people living in countries that were officially multilingual -- such as Belgium, where large portions of the population speak Dutch and French. Using flags for The Netherlands and France would not really have been appropriate.

I ended up using a little SELECT element listing all of the languages that were supported by the app, with a little JavaScript "onchange" handler that submitted it whenever a change was made. This also took lots less space on the screen.


Is it possible to change a language on-line. For example one user uses English language with his browser, then he switchs to French. Can Struts handle this? I think, in your document the properties file is loaded in the beginning ActionServlet startup.

[Oleg V Alexeev] JVM load all files in properties bundle at once and all this resources can be used in run time. Example of switching to another locale -

public class ChangeLanguageAction extends Action {

public ActionForward perform(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {

String country = ((ChangeLanguageForm) form).getCountry();
String language = ((ChangeLanguageForm) form).getLanguage();
String source = ((ChangeLanguageForm) form).getSource();
HttpSession session = request.getSession();
ActionForward forward = null;

setLocale( request, new Locale( language, country ) );

if( source==null )
    forward = (mapping.findForward("success"));
else {
    forward = new RedirectingActionForward();
    forward.setPath( source );
}

return forward;
}
}


Logging On The Fly

Basically I have a requirement for a user to be able to switch between languages on the fly but also being able to set an initial locale preference when they log in. The Struts framework handles the switching without a problem (which is really cool) its the initial display that I'm wondering about since they may have us_english for a machine setting, browser setting for spanish and an initial application locale preference for French. 

[Craig McClanahan]  In the absence of being able to use Filters, the only thing I can think of would be to create your own specialized version of the <html:html> tag that looked for the persistent cookie and set the locale appropriate, if the cookie was there and the Locale was not set yet. You'd also want to create your own custom subclass of ActionServlet, and override the processLocale() method to do the same thing, in case the initial request was sent to a "*.do" URI instead of to a JSP page. 


Setting the locale for an individual user

How can I set the locale for each individual user session before the first  page displays? I've tried putting the session.setAtttribute(Action.Locale_key,<locale>) but it always displays in the default locale of the machine? Changing the machine locale causes the correct properties file to be used so I know that  is not the problem.

[Craig McClanahan] In the Struts example app, this is done by including the following tag on the index.jsp page (actually, on every page):

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html:html locale="true">
... page content ...
</html:html>

This causes that <html:html> tag to consult the "Accept-Language" header sent by the browser, and set up a Locale in the user's session if it is not already there -- exactly the same way that the controller servlet does this if you configure it to.

NOTE: There are currently problems with this on servlet containers that do not correctly implement the JSP 1.1 requirements for converting custom tag attribute values. I have heard problem reports about JRun 3.0 and ATG in this regard.


Multiple Users and Resource Bundles

I have a simple question about localisation :  If there is multiple users using the same localisation parameters : do  they share a common ResourceBundle instance or do they have their own  one. It seems to me that each user has his own ResourceBundle instance but  does that affect the performance of the application.

[Craig McClanahan] The application's message resource bundles are shared across all of the users of a particular Struts-based web application. The only thing that is unique to a particular user is the java.util.Locale object (stored in the user's session) that represents his or her current Locale preferences.