Architecture & DesignHow To Internationalize a Java Web Application

How To Internationalize a Java Web Application

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Java Internationalization support is the way to display textual elements in a format that conforms to various regional and cultural standards. The variety of data format is due to linguistic and cultural diversity. Specifically, the display of date, time, and currency format varies considerably region wise. For example, the date format for one region may be ‘dd-MM-yyyy’ and in another ‘MM-dd-yyyy’. The Java API library provides the functionality to support local standards of data presentation under changing circumstance with minimum effort. This Java Internationalization tutorial provides clues to explore the API library with some specific usage in view of application development.

An Overview

The term Internationalization is often abbreviated as i18n (because there are 18 characters between ‘I’ and ‘n’). In relation to i18n, there is another mechanism called Localization (abbreviated as l10n because there are 10 characters between ‘L’ and ‘N’). Localization helps an application adapt language- and region-specific content by adding locale-specific text components. The Java API provides the means to achieve it in a manner where we do not have to stoop to source code to reflect the regional and cultural portability of an application. There are ample classes and methods in the API library to support this mechanism. One of the primary classes that support this utility is java.util.Locales.

Working with Locales

The class java util.Locale plays an important role in customizing presentation- and display-formatted data. Instances of this class represents regional and linguistic variety of the world that affect interface language, collation, case mapping, date, time, number and currency formats, and so forth. Once geographical location is determined, it can be used to display data in the format expected by the user. The Locale class provides some important parameters that mould data presentation, such as:

  • Language code: An ISO 639 alpha-2 or alpha-3 language code, or a language sub tag up to 8 characters in length.
  • Country or Region code (optional): An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
  • Variant code (optional): Any arbitrary value used to indicate a variation of a Locale.

The Locale class provides three constructors:

  • Locale(String language)
  • Locale(String language, String country)
  • Locale(String language, String country, String variant)

There are a number of predefined static instances of most commonly used country codes. We can simply reference those rather than instantiating the Locale object afresh. Static instances can be references as follows.

Locale engUs=Locale.US;
Locale jpJapan=Locale.JAPAN;

A quick example to display data in localised format is as follows.

<%@page import="java.text.DateFormat"%>
<%@page import="java.util.Date"%>
<%@page import="java.text.NumberFormat"%>
<%@page import="java.util.Locale"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type"
   content="text/html; charset=UTF-8">
<title>Internationalization Demo</title>
<style type="text/css">
body {
   font-family: tahoma, helvetica, arial, sans-serif;
}

table, tr, td, th {
   font-size: .9em;
   border: 1px groove;
   padding: 5px;
   background-color: #dddddd;
}
</style>
</head>
<body>
   <table>
      <thead>
         <tr>
            <th>Code</th>
            <th>Name</th>
            <th>Currency</th>
            <th>Percentage</th>
            <th>Number</th>
            <th>Date</th>
            <th>Time</th>
         </tr>
      </thead>
      <tbody>
         <% Locale[] locale = { Locale.CANADA,
            Locale.CHINA, Locale.FRANCE, Locale.GERMANY,
            Locale.ITALY, Locale.JAPAN, Locale.KOREA,
            new Locale("hi", "IN") };
         for (Locale l : locale) { %>
            <tr>
               <td><%=l.getCountry()%></td>
               <td><%=l.getDisplayName()%></td>
               <td><%=NumberFormat.getCurrencyInstance(l)
                  .format(8736465.38)%></td>
               <td><%=NumberFormat.getPercentInstance(l)
                  .format(87.99)%></td>
               <td><%=NumberFormat.getNumberInstance(l)
                  .format(1234567890)%></td>
               <td><%=DateFormat.getDateInstance(DateFormat.LONG, l)
                  .format(new Date())%></td>
               <td><%=DateFormat.getTimeInstance(DateFormat.LONG, l)
                  .format(new Date())%></td>
            </tr>
            <% } %>
      </tbody>
   </table>
</body>
</html>

Support1
Figure 1: The HTML table that results from the preceding code

Alternatively, we can use the Locale.Builder class that contains a setter method to create locales that adhere to Best Common Practices (BCP) 47 languages tags. BCP47 defines the ISO standard for language, region, script, and variant identifiers. To use Locale.Builder, the preceding code can be modified as follows.

...
<%
   String[][] lr = { { "ca", "CA" }, { "ch", "CH" },
      { "fr", "FR" }, { "gr", "GR" }, { "it", "IT" },
      { "jp", "JP" }, { "kr", "KR" }, { "bn", "BD" } };
   Locale.Builder builder = new Locale.Builder();
   Locale l=null;
   for (String[] str : lr) {
   builder.clear();
   builder.setLanguage(str[0]).setRegion(str[1]);
   l=builder.build();
%>
...

There is another way to create Locale instances, such as using the static Locale.forLanguageTag() method. Here, we can use the BCP47 language tag arguments in the following manner.

...
<%
   String[] bcp47LangTags={"fr-FR","gr-GR","it-IT",
      "jp-JP","kr-KR","hi-IN"};

   Locale l=null;
   for (String tag : bcp47LangTags) {
   l=Locale.forLanguageTag(tag);
%>
...

Using the Locale Filter

When programming, often we need to filter and match a key tag from a list of available locales. For example, assume that there are many comma-separated lists of locales in string format. In this, case we can apply a filter to the string and retrieve only those locales that meet the criteria. The following code snippet demonstrates the idea.

...

List<Locale.LanguageRange> tagList=Locale.LanguageRange.parse
      ("fr-FR,gr-GR,it-IT,jp-JP,kr-KR,hi-IN");
   System.out.println("Range of list: ");
   tagList.stream().forEach((lang)->{
      System.out.print(lang.getRange()+",");
   });
   System.out.println("");

   List<String> locList=new ArrayList<>();
   locList.add("jp-JP");
   locList.add("en-UK");

   List<String> tags=Locale.filterTags(tagList, locList);
   System.out.println("Found tag");
   tags.stream().forEach((tag)->{
      System.out.println(tag);
   });

...

Output

Range of list:
fr-fr,fr-fx,gr-gr,it-it,jp-jp,kr-kr,hi-in,
Found tag
jp-jp

The Bundle Classes

There are three more important classes in the java.util package that help in incorporating internationalization features in a program. They are ResourceBundle, ListResourceBundle, and PropertyResourceBundle.

  • ResourceBundle is an abstract class that provide methods to manage a collection of locally sensitive resources. For example, the caption of a UI element may be changed according to the language in use. The caption may be formatted to use the language English, French, Chinese, and so on, with each translation set in its own bundle. The bundle is an external file loaded at runtime to reflect the current locale and use the string construct in the user interface.
  • PropertyResourceBundle is a subclass of ResourceBundle that manages resources by using a property file.
  • ListResourceBundle is also a subclass of ResourceBundle. It manages resources in a key/value pair array.

The Need for Implementing Internationalization

Cultures affect every aspect of life, including the display of textual elements from a computer program. Data is the means and their form, combined with regional shading, makes the presentation effective. A computer is a dumb machine and the programs that run on it are not intelligent, either. The good part is that a computer can be manipulated in a manner to bridge the gap between man-machine interactions to a level high enough to fool ourselves with its versatility. Humans have languages to communicate and, for better or worse, there are too many languages. Each language has its own syntactic and semantic standard. Internationalization is the mechanism to capture this idea and help bridge the gap of man-machine interaction in a fashion more conducive to human understanding. It provides the ability to define the proper form of presenting contextual information in a manner expected by the user. The end result is the enhancement of user-friendly software usage where an application program compliments regional standards. Commercial applications targeting global customers can greatly benefit from this feature. Software that interacts in French is more acceptable to a French person and the like.

This feature, however, is not meant to improve performance; rather, it provides a way to ameliorate user interaction with the software system. The interaction occurs in a format that the end user is more accustomed to deal with that is also in a language spoken by the user. This not only improves message readability and usability but also augments user acceptability of the system considerably.

Conclusion

Internationalization is a large topic. This article gave a glimpse of what we can achieve from the Java API library of Internationalization support. With numerous culturally appropriate formats worldwide, it’s a challenge to create a consistent presentation. Perhaps the greatest challenge is to meet with appropriate syntactical collation of various languages. They are not only tricky but also difficult to attain. However, the standard formats to display date, time, and currency according to regional standard is well met through the Java API library.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories