Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java EE i18n and default project structure

I am Python Django devel

I want to try Java a little bit.

In django I used to do my translation as it follows:

from django.utils.translation import ugettext_lazy as _

and then if translation is specified in .po file in locale/en/django.po file

_("hello world")

Question 1: Is there similar thing in Java?

I have found those:

  • gnu.gettext.GettextResource
  • java.util.ResourceBundle
  • Spring 3 MVC i18n and i10n

but none of them is what I am looking for

I did as in example

import java.util.ResourceBundle;
import java.util.MissingResourceException;

public class i18n {
    private static ResourceBundle myResources = ResourceBundle.getBundle("messages");

    public static String _ (String originalStr) {
        try {
            return myResources.getString(originalStr);
        } catch (MissingResourceException e) {
            return originalStr;
        }
    }

}

And later

import static i18n._;

Question 2: But where to put messages.properties file?

  • I would like to have a separate locale directory with those files.
  • translations from whole package and sub-packages

    • locale/messages_en_US.properties
    • locale/messages_en_UK.properties
    • locale/messages_en_AU.properties
    • and so on...

Question 3: This part with Exception catching seems not working, do you know why?

Question 4: Is there a JavaEE standard for i18n?

I thought that java EE should have a standardized app directory layout, i18 and war directory content, but for few days fooling around with java I find it very chaotic. Therefore every sample open source code I am able to find on the Internet is completely different. Starting from Google Wave Protocol project, to end with sample small apps.

Question 5: Is there JavaEE coding philosophy or best practices?

I found Strategy for Web Applications but developers seems not to care about it. Tests placement, same thing. Everybody have them in different places. Logic like sql queries in templates, WTF...

like image 411
Matt Harasymczuk Avatar asked Mar 27 '11 15:03

Matt Harasymczuk


1 Answers

There is no one true place to put resource files; this is usually a decision for the application developer. Putting all files in one standard place may not make sense in all architectures so the specification does not add needless constraints.

Exactly how you should load and reference resource bundles can be influenced by what frameworks you are using. For example, in a JSTL application, you might use the bundle tag; in a JSF application you might use the loadBundle tag. Other view technologies will define their own mechanisms.

In general...

ResourceBundle.getBundle loads resources from the classpath, so if you want to use a directory, it or one of its parents should be on the application classpath. In a WAR, the bundles should be in a JAR file in the WEB-INF/lib directory or in the WEB-INF/classes directory.

So, for the bundle set...

 /WEB-INF/classes/locale/messages.properties
 /WEB-INF/classes/locale/messages_fr.properties
 /WEB-INF/classes/locale/messages_de.properties

...you would load the bundle by getting the request Locale and calling:

ResourceBundle.getBundle("locale.messages", locale);

It is a defect to assign the bundle to a single static variable:

//BUG! this loads the properties file for the server default locale only!
private static ResourceBundle myResources = ResourceBundle.getBundle("messages");

You must get the user's locale from the request. A static assignment would only be appropriate in a client application (like an IDE).


Note that it is generally a good idea to provide a root messages.properties base file as a fallback for unsupported locales.

As a general localization aside, the approach of using the original string as a key would only be OK if the key was unique for the bundle. Otherwise, it would conflict in cases where there were identical source strings that were translated differently due to context.

like image 79
McDowell Avatar answered Oct 17 '22 13:10

McDowell