Skip to main content

skip to main content

developerWorks  >  Java technology  >

Internationalize your MIDlets

Globalize your apps faster with the JSR-238 Mobile Internationalization API

developerWorks
Document options

Document options requiring JavaScript are not displayed

Sample code


Rate this page

Help us improve this content


Level: Introductory

Meng Wong, Software Engineer, IBM

14 Nov 2006

Globalization is more than just a trend -- it has become an essential requirement for application development. JSR-238 is designed to help Java™ Platform, Micro Edition (Java ME) developers minimize their internationalization efforts using Mobile Information Device Profile (MIDP)/Connected Limited Device Configuration (CLDC). In this article, discover a faster and easier way to internationalize your MIDlets.

Introduction

Have you ever tried to internationalize your MIDlets only to feel overwhelmed by your efforts? While localizing them using MIDP/CLDC does require a certain amount of work, Java Platform, Standard Edition (Java SE) features a mature API aimed at simplifying internationalization performance. The CDC Foundation provides most of the APIs to achieve internationalization and localization. However, if you want to achieve those things with MIDP/CLDC, it can be a miserable experience; there isn't even a ResourceBundle class available. There is an alternative -- JSR-238 provides classes that you can use directly for localized resources and data formatting.

To begin, take a look at the comparisons of globalization support between Java SE and Java ME, as Figure 1 shows. (The figure is reprinted from the article, "Considerations of Globalization Solutions in J2ME." See Resources for a link.)


Figure 1. Comparison of globalization support between Java SE and Java ME
Comparison of globalization support between Java SE and Java ME

Figure 1 shows that writing a Java SE application that supports globalization is easy; Java SE provides almost everything you need to develop globalized applications. The CDC Foundation provides some, but not all, APIs for writing globalized apps. For apps based on MIDP/CLDC, however, you need to implement almost all globalization classes yourself, as it only provides limited calendar- and time zone-related classes.

History of globalizing apps

To localize MIDlets, you would normally have to write the ResourceBundle and Locale using the MIDP core classes. There are many articles on how to do this, including "Globalize Your Embedded Apps" (see Resources).

To perform internationalization functions, that is, to display native languages based on different locales, you would need to write your own ResourceBundle class, which is essential to retrieving localized strings, such as "Hello" and "Bonjour" for various locales. As for data formatting, such as Currency, Numbers, and DateTime, you must also implement these programs. This takes a lot of effort because you have to collect large amounts of locale data information and you must be familiar with detailed cultural differences.



Back to top


Introducing the JSR-238 Mobile Internationalization API

Internationalizing MIDlets is one of the key requirements involved in reaching a wider market. The new JSR-238 Mobile Internationalization API offers a standard way to help you internationalize MIDlets faster and easier and provides the foundation API for internationalizing your MIDlets with MIDP/CLDC.

Please note: The JSR-238 API is an optional package. You must ensure your device supports this JSR before you deploy JSR-238 MIDlets to it.

JSR-238's goal statement

This statement was excerpted from the JSR-238 specification:

"The goal of the Mobile Internationalization API is to provide internationalization services to Java MIDlets running in MIDP over CLDC. While Java 2, Standard Edition provides extensive support for internationalization, this support is not included in the more limited configurations and profiles of Java 2, Micro Edition."

This API is designed to provide its services in a compact and generic form. It augments the MIDP application platform by bringing MIDP applications to a similar level with desktop applications in terms of internationalization.

Here are the important classes that the JSR-238 package, javax.microedition.global, provides:

  • class ResourceManager: Manages application resources
  • class Formatter: Creates locale-specific renditions of data items
  • class StringComparator: Compares two strings using locale-specific rules

I'll discuss these classes in more detail, but before I do that, you must know that you'll need the Sun Java Wireless Toolkit 2.5 for CLDC Beta, Nokia JSR-238 RI, or Eclipse to develop MIDlets with JSR-238. For this example, I'll use Eclipse.

First, you need to get the JSR-238 library, which comes with Sun WTK 2.5 beta and Nokia's JSR-238 RI. IBM® delivers JSR-238 in WebSphere® Everyplace Micro Environment porting kits, which are available to IBM business partners.

If you are using an older version of the WTK, which does not include the JSR-238 library, you will need to add the JSR-238 yourself. You could still write and compile in Eclipse but you will not be able to launch it due to class-loader limitations. To configure your Java ME project to include JSR-238 support:

  1. Launch Eclipse.
  2. Create a new Java ME project, as Figure 2 shows. In this example, I call it "Simple Globalization Midlets", and click Finish.

    Figure 2. Create a new Java ME project
    Create a new Java ME project

  3. Expand the "Simple Globalization Midlets" project in the Package Explorer view (as Figure 3 shows); notice that the JSR-238 library isn't there.

    Figure 3. Project tree
    Project tree

  4. Select the Java ME library node, right click, then select Build Path > Configure Build Path...
  5. Click Add External Jars..., select the JSR-238 jar file you've downloaded, and click OK.

    Figure 4. Add JSR-238 jar to build path
    Add JSR-238 jar to build path

That's it! You've now added the JSR-238 library to your development environment and are ready to start writing your internationalized MIDlet.



Back to top


Using ResourceManager

Now I'll show how you use ResourceManager to manage your resource files for different locales.

To display the native strings in different languages, you need to prepare the resource files for different locales. The resource files will contain the strings to localize. If you have images, include them in the resource as well. The resource files act like a properties file in Java SE, but in binary format. This has a few advantages:

  • It takes up less storage space when deploying to devices
  • It requires less memory when loading
  • It can contain embedded new lines

These advantages are important and effective for limited devices.

Now let's write a simple MIDlet that displays a string according to the locale as well as an image. Figure 5 shows the resource file structure. For the steps that follow, I will use WebSphere Everyplace Micro Environment 6.1 and the JSR-238 library of IBM WebSphere Everyplace Micro Environment porting kits.

Standards you need to know before you write the MIDlet.
  • Locale identifier The locale identifier must follow the format defined in the MIDP 2.0 spec and use dashes instead of underscores (for example, 'en-US').
  • Base name Group the related resources using a base name (for example, 'labels' and 'messages').
  • Resource file structure You must place the resource files for different locales under /global/{locale-identifier}.

Figure 5. Resource file structure
Resource file structure

Step 1: Prepare the resource file

The binary resource file has a strict format to follow (refer to the JSR-238 specification). You could use any binary editor or Nokia JSR-238 RI to create the resource file.

For demonstration purposes, I have used Nokia JSR-238 RI to generate the binary resource file, as Figure 6 shows. I want to display the string 'Welcome' and an image for locales zh-TW, de-DE, and es-ES. You could read the Nokia 238 RI readme for the steps, but basically, you need to write a resource xml file for your strings and image and run the ResourceMaker tool to get the binary file.


Figure 6. Resource file sample for Nokia JSR-238 RI
Resource file sample for Nokia JSR-238 RI

Step 2: Place binary resource files under the correct file structure

In Figure 7, the strings in the native language are stored in an individual locale folder, whereas the binary for the image is stored in \global\WelcomeMidlets.res. You wouldn't want the image binaries to reside in every resource file!


Figure 7. Place the resource files into the correct structure
Place the resource files into the correct structure

Step 3: Write the MIDlet

To retrieve the string and image from the resource file, you need to do the following:

  1. Construct an instance of ResourceManager. You can specify the locale or use the default System locale. Table 1 introduces two methods available for constructing a ResourceManager instance. The first method only requires the base name and it will use the default system locale. The second method lets you pass in both the base name and a specific locale.

Table 1. ResourceManager methods
public static final ResourceManagergetManager(java.lang.String baseName)
public static final ResourceManagergetManager(java.lang.String baseName, java.lang.String locale)

The following code returns an instance of ResourceManager with the base name "WelcomeMidlet" and a default system locale:

res = ResourceManager.getManager("WelcomeMidlet");
      

To retrieve the String, use the following code:

//STRING_WELCOME is the resource id in the resource file; in this case 1
StringItem desc = new StringItem(res.getString(STRING_WELCOME),"");
      

To retrieve the image, use this code:

//IMAGE_EILEAN is the resource id in resource file, in this case 111
byte[] imageData = res.getData(IMAGE_EILEAN);
      

Listing 1 demonstrates these steps.


Listing 1. String and image retrieval
try
{
  //Get the resource manager with the base name and default systemlocale
  res = ResourceManager.getManager("WelcomeMIDlet");
  //Retrieve the welcome string
  StringItem desc = new StringItem(res.getString(STRING_WELCOME),"");
  fmMain = new Form(res.getString(STRING_WELCOME));
  fmMain.append(desc);
  //Retrieve the Eilean image
  byte[] imageData = res.getData(IMAGE_EILEAN);
  Image eilean  = Image.createImage(imageData, 0, imageData.length);
  fmMain.append(eilean);
}catch(ResourceException re)
{
  System.out.println("Exception when retrieving resources");
  re.printStackTrace();
}

  1. Run the MIDlet. I ran it in Eclipse using the IBM J9 emulator.

Table 2 shows the results of "Welcome MIDlet" in locale zh-TW and locale de-DE.


Table 2. Welcome MIDlet
Locale zh-TWLocale de-DE
Welcome MIDlet zh-TW Welcome MIDlet de-DE

That's it! With the resource files, you could manage the localized strings for different locales and put the image binaries as a common resource for all locales. The ResourceManager class will load the resource files based on the system default locale or you could specify the locale in the constructor. Now you can localize menus, buttons, and messages in a faster, simpler way.



Back to top


Data formatting

Every locale has it own cultural way to display dates, times, numbers, percentages, and currency data. The Formatter class is all you need to format that data. Table 3 shows what this class provides.


Table 3. Data formatting methods
Date and timeformatDateTime(java.util.Calendar dateTime, int style)
Numbers and percentagesformatNumber(double number)
formatNumber(double number, int decimals)
formatNumber(long number)
formatPercentage(float value, int decimals)
formatPercentage(long value)
Currency valuesformatCurrency(double number)
formatCurrency(double number, java.lang.String currencyCode)

Now you'll write a simple MIDlet to display date and time, numbers, percentages, and currency data.

What you need to know
  • The currency code must follow the ISO-4217 currency code standards.
  • The MIDP specification allows you to list a locale as null. If you have passed a null value or an empty string for a locale in the Formatter constructor, it maintains neutral formatting. See the JSR-238 spec for more details.

Step 1: Construct an instance of Formatter

You can specify the locale or use the default System locale. Below is the code you need:

//Using system default locale
Formatter fmt = new Formatter();
//Specify the locale
Formatter fmt = new Formatter("zh-TW");
      

Step 2: Create editable text fields

You want to create editable text fields to allow the user to enter numbers, percentages, currency data, and so on. You need the contents of these text fields and the Formatter class methods to format them, as Listing 2 shows.


Listing 2. Data formatting
public String formatNumber(double number){
     return fmt.formatNumber(number);
  }
  
  public String formatPercentage(float number, int decimals){
     return fmt.formatPercentage(number,decimals);
  }
 
  public String formatCurrency(double number){
     return fmt.formatCurrency(number);
  }
  
  .....

  //Process events
  public void commandAction(Command c, Displayable s)
  {
   if (c == cmExit)
   {
     destroyApp(false);
     notifyDestroyed();
   }
   else if( c == cmFormat)
   {
     //Number formatting
     double num = Double.parseDouble(tfNumeric.getString());
     siResultNum.setText(this.formatNumber(num));
     //Percentage formatting
     float percentage = Float.parseFloat(tfPercentage.getString());
     siResultPercent.setText(this.formatPercentage(percentage,2));
     //Currency formatting

     double curr = Double.parseDouble(tfCurrency.getString());
     siResultCurr.setText(this.formatCurrency(curr));
     //Display the result
     displayResult();
   }		 
		 		 		 

Now, run the MIDlet. Table 4 shows the result you should get. (Note: I am using a different font for zh-TW.)


Table 4. Formatter MIDlet
Locale zh-TWLocale de-DE
Formatter MIDlet zh-TW Formatter MIDlet de-DE

Different styles for date/time formatting

The Formatter class supports the following styles:

  • short date only
  • long date only
  • short time only
  • long time only
  • short date and time
  • long date and time

The Formatter class has defined the fields for different styles. For example, for short date only, Formatter.DATE_SHORT, you can just use these styles in the formatDate method.

Listing 3 shows a small MIDlet demonstrating date formatting.


Listing 3. Date format MIDlet
public String formatDateTime(Calendar c){
  //Short date format
  String result = fmt.formatDateTime(c,Formatter.DATE_SHORT);
  String result_set = "";
  result_set= result_set+"\n"+"formatDateTime(Calendar, DATE_SHORT) returns:"+result;

  //Long date format
  result = fmt.formatDateTime(c,Formatter.DATE_LONG);
  result_set = result_set+"\n"+"formatDateTime(Calendar, DATE_LONG)returns:"+result;
     
  //Long date and time
  result = fmt.formatDateTime(c,Formatter.DATETIME_LONG);
  result_set = result_set+"\n"+"formatDateTime(Calendar, DATETIME_LONG)returns:"+result;
      
  //Short date and time
  result = fmt.formatDateTime(c,Formatter.DATETIME_SHORT);
  result_set = result_set+"\n"+"formatDateTime(Calendar, DATETIME_SHORT) returns:"+result;

  //Long time
  result = fmt.formatDateTime(c,Formatter.TIME_LONG);
  result_set = result_set+"\n"+"formatDateTime(Calendar, TIME_LONG) returns:"+result;
    
  //Short time
  result = fmt.formatDateTime(c,Formatter.TIME_SHORT);
  result_set = result_set+"\n"+"formatDateTime(Calendar, TIME_SHORT) returns:"+result;
     
  return result_set;
}
  //Called by the application manager to start the MIDlet.
public void startApp()
{
  display.setCurrent(fmMain);
}
  
public void pauseApp()
{}
  
public void destroyApp(boolean unconditional)
{}
  
//Process events
public void commandAction(Command c, Displayable s)
{
  if (c == cmExit)
  {
    destroyApp(false);
    notifyDestroyed();
  }
  else if( c == cmFormat)
  { //Get the current system date and time
    Date dt = new Date();     
    Calendar cal = Calendar.getInstance();
    cal.setTime(dt);
    siResult.setText(this.formatDatetime(cal));
    displayResult();
  }
}

Table 4 shows the results of the DateTime format MIDlet in locales zh-TW and de-DE.


Table 4. DateTime format MIDlet
Locale zh-TWLocale de-DE
DateTime MIDlet zh-TW DateTime MIDlet de-DE


Back to top


Another useful class

You can use StringComparator to perform string sorting and comparison. Refer to the JSR-238 guide for the sorting programming sample.



Back to top


In conclusion

JSR-238 provides a faster and simpler way to internationalize your MIDlets with MIDP/CLDC. Use the ResourceManager, Formatter, and StringComparator classes in the package javax.microedition.global to perform localization and locale-specific data formatting. As a reminder, JSR-238 is provided as an optional package; make sure your device supports it. Now you should be familiar with JSR-238 and on your way to better developing!




Back to top


Download

DescriptionNameSizeDownload method
Sample code from this articlejsr-238sample.zip4KBHTTP
Information about download methods


Resources

Learn

Get products and technologies

Discuss


About the author

Photo of Meng Li Wong

Meng Li is a software engineer at the China Software Development Lab in Taipei. She focuses on Test Automation and WebSphere Everyplace Micro Environment projects. Her interests include Java programming, traveling, and music.




Rate this page


Please take a moment to complete this form to help us better serve you.



YesNoDon't know
 


 


12345
Not
useful
Extremely
useful
 


Back to top