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

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.
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.
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.
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:
- Launch Eclipse.
- 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
- 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
- Select the Java ME library node, right click, then select Build Path > Configure Build Path...
- 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
That's it! You've now added the JSR-238 library to your development environment and are ready to start writing your internationalized MIDlet.
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.
Figure 5. 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

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

To retrieve the string and image from the resource file, you need to do the following:
- Construct an instance of
ResourceManager. You can specify the locale or use the default System locale. Table 1 introduces two methods available for constructing aResourceManagerinstance. 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 ResourceManager | getManager(java.lang.String baseName) |
| public static final ResourceManager | getManager(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();
}
|
- 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-TW | Locale 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.
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 time | formatDateTime(java.util.Calendar dateTime, int style) |
| Numbers and percentages | formatNumber(double number)formatNumber(double number, int decimals)formatNumber(long number)formatPercentage(float value, int decimals)formatPercentage(long value) |
| Currency values | formatCurrency(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.
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-TW | Locale 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-TW | Locale de-DE |
![]() | ![]() |
You can use StringComparator to perform string sorting and comparison. Refer to the JSR-238 guide for the sorting programming sample.
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!
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample code from this article | jsr-238sample.zip | 4KB | HTTP |
Information about download methods
Learn
-
Read the Redbook e-business Globalization Solution Design Guide: Getting Started to learn more about globalization.
-
Read the article "Considerations of Globalization Solutions in J2ME" (developerWorks, Apr 2004) for an overview of Java ME globalization.
-
Read the article "Globalize Your Embedded Apps" (developerWorks, Jan 2006) to understand how to internationalize MIDlets without JSR-238.
Get products and technologies
-
Read the JSR-238 spec.
-
Visit the IBM WebSphere Everyplace Micro Environment page, which provides the foundation for the deployment of e-business applications to small mobile devices.
-
Download WebSphere Everyplace Micro Environment Trial and Evaluation Runtimes to develop your embedded apps.
Discuss
-
Check out the developerWorks
blogs and get involved in the developerWorks community.
Comments (Undergoing maintenance)












