Introduction - Making your Applications Global

When developing applications that are ready to be used and reused effectively by everyone in the world, you must design your applications such that it is global. Making your application global involves many complex issues, most of which primarily arises from the large number of issues involved and also because language issues affect almost every application, component, third-party tool, code, document, help file etc. involved in releasing your application.

Making your applications global involves two primary steps – internationalization and then localization. Internationalization (i18n) is the process of generalizing your application to be as language-independent as required. This step involves the separation of your application's resources that require translation from the rest of your application's code. Performing this step allows you to offer your product in multiple languages, but coding for it only once initially.

Localization (l10n) is the next step in this process, and involves the customization of your application such that it supports the requirements of different languages and cultures. This step primarily comprises translating the user interface into the target languages. If you test your application accurately during the internationalization stage, your code typically requires minimum or no changes at the localization stage. In the following sections, we provide you information on how developers can leverage and use the Dekoh Internationalization API to create applications that are truly global.

Understanding Internationalization a little more

An Example Scenario

Pramati Technology writes an application for the Dekoh Platform, which allows users to share photos off their desktop without having to upload them anywhere on the internet. As the application becomes immensely popular in France, the company decides to make the same application available in the French language. If the code is not global, the entire application will need to be re-compiled to make it compatible with the new requirements.

Since the photo application has been internationalized, it can be localized by simply writing external resource files in the new language. Ensuring that the appearance and usability of the software does not offend these new users will also require only simple changes to a few external resource files.

Checklist for Internationalizing your Application

To prepare your application for internationalization, follow the given checklist and design your application in this unique way:
  • Identify Culturally Dependent Data: Identify the culturally dependent data in your application. This can be defined as any data that varies from one culture or country to another. Text is the most obvious and persistent example of data that is culturally sensitive, but there are various other formats such as date and time formats, number formats, sounds, labels on GUI components, graphics, icons, currencies, addresses, page layouts etc.
  • Separate Translatable Text from the rest of the code in Resource Bundles: Remove all text to be translated into various languages, using ResourceBundle objects. A ResourceBundle is a container that holds one or more locale-specific elements (made up of a language and region/country code) and is associated with one and only one locale.
The translatable text may include all your status, error or other forms of messages, log file entries, and any other image related labels.
  • Format Numbers, Currencies, Date and Time: If your application requires numbers, currencies, date and time, format them in a locale-independent manner. The Java programming language provides several classes that format all these.
  • Use Unicode Character Properties: Also, convert Non-Unicode text into Unicode: i18n uses the Unicode standard to identify character properties. Ensure that you use Unicode character properties, so that the code works appropriately in all languages. For example, the given code
char ch;
...
if ((ch >= 'a' && ch <= 'z') || 
    (ch >= 'A' && ch <= 'Z'))
does not work in languages other than English. Here, the if statement misses the character ü in the German word Grün. You should use something like this instead: {char ch; ... if (Character.isLetter(ch)) }}} You must also convert Non-Unicode Text into Unicode text because characters in the Java programming language are encoded in Unicode.
  • Set Language Preferences using Accept: Language request-header: When a reader’s browser reads data from the Web, it sends a HTTP request to the server where the information is stored. This also includes information about its language preference settings. The part of the HTTP request that holds this language preference information is called the “Accept-Language request-header”. If the Accept-Language header stores alternate versions of the page or resource in multiple languages, the browser retrieves this information in the user’s preferred language (if the specific language is available).

As a developer, you must include the Accept-Language header with information about all the languages that you offer in your application. The value in these headers are defined by RFC3066, typically as a two or three letter language code (for example, en for English), followed by optional sub codes representing such things as country (for example, en-us represents English as spoken in the United States).

Introducing Dekoh Internationalization API

Use the Dekoh Internationalization API to simplify the process of making your applications global. Your Dekoh applications can use the API to generate translatable bundles, use enumeration constants to map a key to its display text, and use the locale filter.

Benefits of Using Dekoh’s Internationalization API

Intercept all Incoming HTTP Requests

To make your HttpServletRequest's return a enumeration of locale objects - in decreasing order, starting with the preferred locale - that are acceptable to the client based on the Accept-Language header, you must implement a method getLocales(). From this enumeration of Locales, LocaleFilter will pick a matching ResourceBundle. If you use Dekoh Internationalizing API, you can just setup this filter up, such that the filter can intercept all incoming HTTP requests automatically.

Manage your Key Mappings Easily

Typical Java programs use Properties files along with the Resource Bundles to map the Java program keys with the appropriate translated text that will be displayed. Since these keys are simple strings, typographical errors remain unchecked during the compilation stage and result in loss of information at runtime. These property files are also difficult to maintain and developers display disinterest in introducing new keys to the property files.

Dekoh Internationalization API uses enumeration constants to map these java program keys to the translated text. As both the key and the display text (in the default language) is written in the same place, it becomes easier to maintain the code. The display text is also treated as a Java String, which means it becomes easier to edit these in any modern Java IDE and errors in typing these text (enum constants) are caught during compilation.

For Example:

Automatically generate template properties file using a customized Ant Script

Once you complete creating your resource bundles, you will also need to generate the template properties files manually for all the locales. Dekoh provides a customized ANT script that will allow you to automatically generate these properties files for all the locales, provided the English ResourceBundle.

For example, executing the following task

<!--Load the task def -->
  <taskdef classname="com.pramati.devutil.antutil.i18n.CreateLocaleResourceBundleAntTask" name="rb" classpath="${dekoh.jar.location}"/>  

<target name”gen.resource.bundles”>
    <rb basename="com.mycompany.i18n.MyAppResourceBundle" classpath="${project.class.path}" toLocales="fr, de" destdir="${destdir.for.compiled.classes}" ></rb>
</target>

will generate the property files, MyAppResourceBundle_fr and MyAppResourceBundle_de (if they do not already exist) and place them in the directory ${destdir.for.compiled.classes}/com/mycompany/i18n/ In case these files already exist, executing the above task will only lookup the original English ResourceBundle file for any updates, and add any new or modified message keysto these existing properties files. Message keys that have been deleted in the updated English ResourceBundle will be deleted from the properties files as well.

Internationalizing your application in Dekoh

Creating enums

If you want your application to use the Dekoh i18n API, you must provide a set com.pramati.bfly.cas.util.i18n.MessageEntry instance to the EnumResourceBundle. We recommend that you have an enum to implement this interface, where the enum will contain one constant for each of your internationalized message.
   
public enum Messages implements MessageEntry {
       TITLE("myapplication.title", "Title of application"), //(Key, Value)
      }

private String key;
    private String value;

    private Messages(String key, String value)
    {
        this.key = key;
        this.value = value;
        //$Fixme!$ if a key is repeated twice ... report error ... ideally compilation time?!
    }

    public String getKey()
    {
        return key;
    }

    public String getValue()
    {
        return value;
    }

    public static String getMessage(Messages id, Object... args)
    {
        ResourceBundle rb = getPhotosResourceBundle();
        MessageFormat mf = new MessageFormat(rb.getString(id.getKey()), rb.getLocale());
        return mf.format(args);
    }

    public static String getMessage(Messages id)
    {
        ResourceBundle rb = getPhotosResourceBundle();
        return rb.getString(id.getKey());
    }

Supply EnumSet.allOf(Messages.class)to the EnumResourceBundle.

Java API

If your application contains Java code, and you would like to internationalize the same, you application must further use something like the one given below to retrieve the translated message from your locale file.

For example:

Messages.getMessage(Messages.TITLE);

JSP API

If your application contains JSP code, and you would like to internationalize the same, you can use Apache's i18n tag library.
  1. To import the taglib definition from the Apache tag library, use <%@ taglib uri="http://jakarta.apache.org/taglibs/i18n-1.0" prefix="i18n" %>
  2. You must also provide the name of your base resource bundle implementation:
For example, if your base resource bundle implementations are called PhotosResourceBundle_fr, PhotosResourceBundle_en etc., you can provide the base resourcebundle name as given here: <i18n:bundle baseName="dekoh.photo.i18n.PhotosResourceBundle" scope="request" changeResponseLocale="true"/>
  1. To retrieve the translated message from your locale file, use may use something like the code given here: <i18n:message key='<%=Messages.TITLE.getKey()%>'/>

Generate Template Properties File

Once you complete all the previous steps, you will need to generate the template properties files for all the locales. You may do this manually, or use the customized ANT script provided by Dekoh to generate these properties files automatically for all the locales (given the English ResourceBundle).