MIDlet 国际化

来源:互联网 发布:杭州淘宝大学地址 编辑:程序博客网 时间:2024/05/01 22:33

原文链接:http://www.ibm.com/developerworks/cn/java/wi-midapi/index.html#resources


==================================================================================================================================

MIDlet 国际化

使用 JSR-238 Mobile Internationalization API 更快地全球化您的应用程序

Meng Wong, 软件工程师, EMC

简介: 国际化不仅仅是一个趋势 —— 它已经成为应用程序开发的必要需求。JSR-238 的目的是帮助 Java™Platform,Micro Edition(Java ME)开发人员利用 Mobile Information Device Profile(MIDP)/Connected Limited Device Configuration(CLDC)将其国际化工作减至最少。通过这篇文章发现一种国际化 MIDlet 的更便捷方法。

标记本文!

发布日期: 2007 年 1 月 25 日 
级别: 初级 
访问情况 1050 次浏览 
建议: 0 (添加评论)

1 star2 stars3 stars4 stars5 stars 平均分 (共 1 个评分 )

简介

您是否曾尝试过国际化 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 全球化支持的对比
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 目标声明

此声明引自 JSR-238 规范:

“Mobile Internationalization API 的目标是为运行在 CLDC 上 MIDP 中的 Java MIDlet 提供国际化服务。Java 2 Standard Edition 提供对国际化的广泛支持,JAVA 2,Micro Eition 更具局限性的设置和配置文件并不包括这种支持。”

这种 API 被设计为以简洁通用的形式提供服务。在国际化方面,它使 MIDP 应用程序达到一个与桌面应用程序类似的级别,从而扩充了 MIDP 应用程序平台。

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 支持:

  1. 启动 Eclipse。
  2. 创建一个新的 Java ME 项目,如 图 2所示。在这个例子中,我把它命名为 “Simple Globalization Midlets”,单击 Finish。 

    图 2. 创建一个新的 Java ME 项目
    创建一个新的 Java ME 项目 

  3. 在 Package Explorer 视图中展开 “Simple Globalization Midlet” 项目(如 图 3所示),请注意 JSR-238 库不在这里。 

    图 3. 项目树
    项目树 

  4. 选中 Java ME 库节点,右击并选择 Build Path > Configure Build Path...
  5. 单击 Add External Jars...,选择已下载的 JSR-238 jar 文件,然后单击 OK。 

    图 4. 将 JSR-238 jar 添加到构建路径中
    将 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 库。

编写 MIDlet 程序之前需要知道的标准。

  • 地区标识符地区标识符必须符合 MIDP 2.0 规范定义的格式,使用短横线而不是下划线(例如,“en-US”)。
  • 基本名称使用基本名称将相关资源分组(例如,“labels” 和 “messages”)。
  • 资源文件结构必须将不同地区的资源文件放到 /global/{ 地区标识符 } 目录下。

图 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 示例资源文件
RNokia JSR-238 RI 示例资源文件 

步骤 2:将二进制资源文件放在正确的文件结构中

在 图 7中,采用当地语言的字符串存储在一个地区文件夹中,图片的二进制文件存储在 \global\WelcomeMidlets.res 中。您不会希望图像的二进制文件存储在每一个资源文件中!


图 7. 将资源文件放到正确的结构中
将资源文件放到正确的结构中 

步骤 3:编写 MIDlet

为了从资源文件检索字符串和图片,您需要执行下列步骤:

  1. 构造一个 ResourceManager实例。您可以指定一个地区,也可以使用系统默认的地区。表 1介绍了可用于构建一个ResourceManager实例的两种方法。第一种方法只要求基本名称,它将使用系统默认的地区。第二种方法要求基本名称和特定地区。

表 1. ResourceManager 方法
public static final ResourceManagergetManager(java.lang.String baseName)public static final ResourceManagergetManager(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();  } 

  1. 运行 MIDlet。我在 Eclipse 中使用 IBM J9 仿真器运行它。

表 2展示了在 zh-TW 和 de-DE 地区显示 “Welcome MIDlet” 的结果。


表 2. Welcome MIDlet
zh-TW 地区de-DE 地区Welcome MIDlet zh-TWWelcome MIDlet 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 程序来显示日期、时间、数字、百分比和货币数据。

您需要了解的知识

  • 货币代码必须遵守 ISO-4217 货币代码标准。
  • MIDP 规范允许您列入一个空地区。如果您在Formatter构造函数中为一个地区使用了空值或空字符串,它将保留为中立格式(Neutral formatting)。参阅 JSR-238 规范以获得更多细节。

步骤 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 MIDlet zh-TWFormatter MIDlet 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 地区DateTime MIDlet zh-TWDateTime MIDlet de-DE

另一个有用的类

可以使用 StringComparator执行字符串的排序和比较操作。相关的排序编程示例,请参考 JSR-238 指南。

结束语

JSR-238 提供了一种更快、更简单的方法,利用 MIDP/CLDC 来国际化您的 MIDlet。使用 javax.microedition.global 包中的ResourceManagerFormatter和 StringComparator类来进行本地化工作以及特定于地区的数据格式化。提醒一下,JSR-238 是一个可选包;务必确保您的设备支持它。现在您应该熟悉了 JSR-238,可以去更出色地完成开发工作了!


原创粉丝点击