原文链接:http://www.ibm.com/developerworks/cn/java/wi-midapi/index.html#resources
==================================================================================================================================
MIDlet 国际化
使用 JSR-238 Mobile Internationalization API 更快地全球化您的应用程序
简介: 国际化不仅仅是一个趋势 —— 它已经成为应用程序开发的必要需求。JSR-238 的目的是帮助 Java?Platform,Micro Edition(Java ME)开发人员利用 Mobile Information Device Profile(MIDP)/Connected Limited Device Configuration(CLDC)将其国际化工作减至最少。通过这篇文章发现一种国际化 MIDlet 的更便捷方法。
发布日期: 2007 年 1 月 25 日
级别: 初级
访问情况 1050 次浏览
建议: 0 (添加评论)
简介
您是否曾尝试过国际化 MIDlet,却以失败告终?使用 MIDP/CLDC 本地化 MIDlet 需要完成大量的工作,Java Platform,Standard Edition(Java SE)以成熟的 API 简化国际化工作。CDC Foundation 提供了大量 API 来完成国际化和本地化工作。而如果使用 MIDP/CLDC 来完成这些工作,将是一次非常痛苦的经历;甚至没有一个可用的 ResourceBundle
类。还好有另外一个选择 —— JSR-238 提供了可直接用于资源本地化和数据格式化的类。
作为开始,看一下 Java SE 和 Java ME 对全球化支持的对比,如 图 1所示。(本图是从 “Considerations of Globalization Solutions in J2ME” 文中转载的。参见 参考资料中的链接。)
图 1. Java SE 和 Java ME 全球化支持的对比
图 1显示出,编写一个支持全球化的 Java SE 应用程序是十分简单的;Java SE 提供了开发全球化应用程序所需的几乎所有东西。CDC Foundation 提供了一些用来编写全球化应用程序的 API ,但不是全部。然而建立在 MIDP/CLDC 基础上的应用程序仅提供有限的日历和时区的相关类,您需要亲自编写几乎所有的全球化类。
全球化应用程序的历史
要本地化 MIDlet,通常需要使用 MIDP 核心类编写 ResourceBundle
和 Locale
。有很多关于如何完成这一任务的文章,包括 “Globalize Your Embedded Apps”(参见 参考资料)。
为了实现国际化功能,就是说根据不同的地区显示其当地语言,您需要编写自己的 ResourceBundle
类,这对检索本地化字符串是很必要的,例如面向不同地区的 “Hello” 和 “Bonjour”。对于数据格式化,例如 Currency、Numbers 和 DateTime,您也需要实现这些程序。这将耗费大量的精力,因为您不得不收集大量的地区数据信息,还必须熟知具体的文化差异。
回页首
JSR-238 Mobile Internationalization API 简介
国际化 MIDlet 是接触更广阔市场的一个关键条件。新的 JSR-238 Mobile Internationalization API 提供了一种标准方法帮助您更快、更轻松地实现 MIDlet 国际化,还提供了用 MIDP/CLDC 实现 MIDlet 国际化的基础 API。
请注意:JSR-238 API 是一个可选的软件包。开始向其部署 JSR-238 MIDlet 之前,必须确保您的设备支持它。
JSR-238 包,javax.microedition.global 提供的一些重要类如下:
- ResourceManager 类:管理应用程序资源
- Formatter 类:创建数据项特定于地区的翻译
- StringComparator 类:使用特定于地区的规则比较两个字符串
我将具体讨论这些类,但在此之前您必须了解,您将需要使用 Sun Java Wireless Toolkit 2.5 for CLDC Beta、Nokia JSR-238 RI 或 Eclipse 来配合 JSR-238 开发 MIDlet。本例将使用 Eclipse。
首先,您需要获得 JSR-238 库,它是随 Sun WTK 2.5 Beta、Nokia 的 JSR-238 RI 一起提供的。IBM?在 WebSphere?Everyplace Micro Environment 移植包中提供了 JSR-238,IBM 业务合作伙伴都可以使用。
如果您现在使用的是 WTK 的老版本,其中不包括 JSR-238 库,您需要自己添加 JSR-238。您依然可以在 Eclipse 编写和编译,但由于类加载器的限制,Eclipse 是无法启动的。要配置 Java ME 项目以包含 JSR-238 支持:
- 启动 Eclipse。
- 创建一个新的 Java ME 项目,如 图 2所示。在这个例子中,我把它命名为 “Simple Globalization Midlets”,单击 Finish。
图 2. 创建一个新的 Java ME 项目
- 在 Package Explorer 视图中展开 “Simple Globalization Midlet” 项目(如 图 3所示),请注意 JSR-238 库不在这里。
图 3. 项目树
- 选中 Java ME 库节点,右击并选择 Build Path > Configure Build Path...
- 单击 Add External Jars...,选择已下载的 JSR-238 jar 文件,然后单击 OK。
图 4. 将 JSR-238 jar 添加到构建路径中
就是这样!您已经将 JSR-238 库添加到开发环境中可,现在就可以开始编写 MIDlet 国际化程序了。
回页首
使用 ResourceManager
现在我将演示如何使用 ResourceManager
来管理不同地区的资源文件。
要用不同的语言来显示本地字符串,就需要准备不同地区的资源文件。资源文件包括要本地化的字符串,如果有图片的话,也要将其包含在资源文件里面。资源文件就像 Java SE 的属性文件,但是是二进制格式。它有以下优点:
- 部署到设备时占用较少的存储空间。
- 装载时需要较少内存。
- 它可以包含嵌入的新行。
对于条件有限的设备来说,这些优点是十分重要和有效的。
现在让我们编写一个简单的 MIDlet,根据地区显示字符串和图片。图 5显示了资源文件结构。在以下步骤中,我将使用 WebSphere Everyplace Micro Environment 6.1 和 IBM WebSphere Everyplace Micro Environment 移植包的 JSR-238 库。
图 5. 资源文件结构
步骤 1:准备资源文件
二进制的资源文件必须遵守严格的格式。(参考 JSR-238 规范)。可以使用任何一种二进制文件编辑器或者 Nokia JSR-238 RI 创建资源文件。
为演示起见,我使用 Nokia JSR-238 RI 来创建二进制资源文件,如 图 6所示。我想为 zh-TW,de-DE 和 es-ES 这几个地区显示 “Welcome” 字符串和一幅图片。可以阅读 Nokia 238 RI 的自述文件了解相关步骤,但基本上,您需要为字符串和图片编写一个 xml 资源文件,运行 ResourceMaker 工具获得二进制文件。
图 6. Nokia JSR-238 RI 示例资源文件
步骤 2:将二进制资源文件放在正确的文件结构中
在 图 7中,采用当地语言的字符串存储在一个地区文件夹中,图片的二进制文件存储在 \global\WelcomeMidlets.res 中。您不会希望图像的二进制文件存储在每一个资源文件中!
图 7. 将资源文件放到正确的结构中
步骤 3:编写 MIDlet
为了从资源文件检索字符串和图片,您需要执行下列步骤:
- 构造一个
ResourceManager
实例。您可以指定一个地区,也可以使用系统默认的地区。表 1介绍了可用于构建一个ResourceManager
实例的两种方法。第一种方法只要求基本名称,它将使用系统默认的地区。第二种方法要求基本名称和特定地区。
表 1. ResourceManager 方法
public static final ResourceManager | getManager(java.lang.String baseName) |
public static final ResourceManager | getManager(java.lang.String baseName, java.lang.String locale) |
以下代码返回具有 “WelcomeMidlet” 基本名称以及系统默认地区的 ResourceManager
实例:
res = ResourceManager.getManager("WelcomeMidlet"); |
使用以下代码检索字符串:
//STRING_WELCOME is the resource id in the resource file; in this case 1 StringItem desc = new StringItem(res.getString(STRING_WELCOME),""); |
使用下列代码检索图片:
//IMAGE_EILEAN is the resource id in resource file, in this case 111 byte[] imageData = res.getData(IMAGE_EILEAN); |
清单 1演示了这些步骤。
清单 1. 字符串和图片检索
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(); } |
- 运行 MIDlet。我在 Eclipse 中使用 IBM J9 仿真器运行它。
表 2展示了在 zh-TW 和 de-DE 地区显示 “Welcome MIDlet” 的结果。
表 2. Welcome MIDlet
zh-TW 地区 | de-DE 地区 |
就是这样!使用资源文件管理不同地区的本地化字符串,将图片的二进制文件转换为所有地区都可以使用的通用资源。ResourceManager
类将根据系统默认地区或您在构造函数中指定的地区来装载资源文件。现在您可以使用一种更快、更简单的方法来本地化菜单、按钮和消息了。
回页首
数据格式化
每一个地区都有自己的文化,都采用自己的方式显示日期、时间、数字、百分数和货币数据。Formatter
类可以满足格式化此类数据的全部需求。表 3显示了它所提供的类。
表 3. 数据格式化方法
日期和时间 | formatDateTime(java.util.Calendar dateTime, int style) |
数字和百分比 | formatNumber(double number) formatNumber(double number, int decimals) formatNumber(long number) formatPercentage(float value, int decimals) formatPercentage(long value) |
货币值 | formatCurrency(double number) formatCurrency(double number, java.lang.String currencyCode) |
现在将编写一个简单的 MIDlet 程序来显示日期、时间、数字、百分比和货币数据。
步骤 1:构造一个 Formatter 实例
您可以指定地区,也可使用系统默认地区。下面是所需要的代码:
//Using system default locale Formatter fmt = new Formatter(); //Specify the locale Formatter fmt = new Formatter("zh-TW"); |
步骤 2:创建可编辑文本字段。
您希望创建可编辑的文本文件以使用户输入数字、百分数、货币数据等等。您需要这些文本字段的内容和对其进行格式化的Formatter
类方法,如 清单 2所示。
清单 2. 数据格式化
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(); } |
现在运行 MIDlet。表 4显示了应获得的结果。(注意:我为 zh-TW 使用了一种不同的字体。)
表 4. Formatter MIDlet
zh-TW 地区 | de-DE 地区 |
格式化日期 / 时间的不同风格
Formatter
类支持以下风格:
- 仅 short date
- 仅 long date
- 仅 short time
- 仅 long time
- short date 和 time
- short date 和 time
Formatter
类为不同的风格定义了字段。例如,对于仅 short date 这种风格定义了 Formatter.DATE_SHORT
,您在 formatDate
方法里使用这些风格就可以了。
清单 3给出了一个简单的 MIDlet,它示范了日期格式化。
清单 3. 日期格式化 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(); } } |
表 4展示了 DateTime format MIDlet 在 zh-TW 和 de-DE 这两个地区的显示结果。
表 4. DateTime format MIDlet
zh-TW 地区 | de-DE 地区 |
回页首
另一个有用的类
可以使用 StringComparator
执行字符串的排序和比较操作。相关的排序编程示例,请参考 JSR-238 指南。
回页首
结束语
JSR-238 提供了一种更快、更简单的方法,利用 MIDP/CLDC 来国际化您的 MIDlet。使用 javax.microedition.global 包中的ResourceManager
、Formatter
和 StringComparator
类来进行本地化工作以及特定于地区的数据格式化。提醒一下,JSR-238 是一个可选包;务必确保您的设备支持它。现在您应该熟悉了 JSR-238,可以去更出色地完成开发工作了!