`
beike
  • 浏览: 356916 次
社区版块
存档分类
最新评论

Java国际化——资源包的使用

    博客分类:
  • Java
阅读更多

在 编写应用程序的时候,需要面对的一个问题是如何来处理与locale相关的一些信息。比如,页面上的一些静态文本就希望能够以用户习惯的语言显示。最原始 的做法是将这些信息硬编码到程序中(可能是一大串判断语句),但是这样就将程序代码和易变的locale信息捆绑在一起,以后如果需要修改locale信 息或者添加其它的locale信息,你就不得不重新修改代码。而资源包可以帮助你解决这个问题,它通过将可变的locale信息放入资源包中来达到两者分 离的目的。应用程序可以自动地通过当前的locale设置到相应的资源包中取得所要的信息。资源包的概念类似于Windows编程人员使用的资源文件 (rc文件)。

一般来说,资源包需要完成两个功能:和具体的locale进行绑定以及读取locale相关信息。

ResourceBundle类


你可以把资源包看作为一个由许多成员(子类)组成的大家庭,其中每个成员关联到不同的locale对象,那它是如何完成关联功能的呢?

资源包中的每个成员共享一个被称作基名(base name)的名称,然后在此基础上根据一定的命名规范进行扩展。下面就列出了一些成员的名称:
    LabelResources
         LabelResources_de
         LabelResources_de_CH
         LabelResources_de_CH_UNIX
可 见这些子类依据这样的命名规范:baseName_language_country_variant,其中language等几个变量就是你在构造 Locale类时所使用的。而资源包正是通过这个符合命名规范的名称来和locale进行关联的,比如LabelResource_de_CH就对应于由 德语(de)和瑞士(CH)组成的locale对象。

当你的应用程序需要查找特定locale对象关联的资源包时,它可以调用ResourceBundle的getBundle方法,并将locale对象作为参数传入。

  1. Locale  currentLocale = new  Locale ("de""CH""UNIX" );
  2. ResourceBundle  myResources =
  3.       ResourceBundle .getBundle("LabelResources" , currentLocale);


如 果该locale对象匹配的资源包子类找不到,getBundle将试着查找最匹配的一个子类。具体的查找策略是这样的:getBundle使用基 名,locale对象和缺省的locale来生成一个候选资源包名称序列。如果特定locale对象的语言代码、国家代码和可选变量都是空值,则基名是唯 一的候选资源包名称。否则的话,具体locale对象(language1,country1和variant1)和缺省 locale(language2,country2和variant2)将产生如下的序列:


  • baseName + "_" + language1 + "_" + country1 + "_" + variant1
  • baseName + "_" + language1 + "_" + country1 
  • baseName + "_" + language1 
  • baseName + "_" + language2 + "_" + country2 + "_" + variant2 
  • baseName + "_" + language2 + "_" + country2 
  • baseName + "_" + language2 
  • baseName 


然 后,getBundle方法按照产生的序列依次查找匹配的资源包子类并对结果子类初始化。首先,它将寻找类名匹配候选资源包名称的类,如果找到将创建该类 的一个实例,我们称之为结果资源包。否则,getBundle方法将寻找对应的资源文件,它通过候选资源包名称来获得资源文件的完整路径(将其中的“.” 替换为“/”,并加上“.properties”后缀),如果找到匹配文件,getBundle方法将利用该资源文件来创建一个 PropertyResourceBundle实例,也就是最终的结果资源包。与此同时,getBundle方法会将这些资源包实例缓存起来供以后使用。

如果没有找到结果资源包,该方法将抛出MissingResourceException异常。所以为了防止异常的抛出,一般来说都需要至少实现一个基名资源包子类。

注 意:基名参数必须是一个完整的类名称(比如LabelResources,resource.LabelResources等),就相当于你引用一个类时 需要指定完整的类路径。但是,为了和以前的版本保持兼容,在使用PropertyResourceBundles时也允许使用“/”来代替“.”表示路 径。

比如你有以下这些资源类和资源文 件:MyResources.class, MyResources_fr_CH.properties, MyResources_fr_CH.class,

 MyResources_fr.properties, MyResources_en.properties, MyResources_es_ES.class。 你利用以下的locale设置来调用getBundle方法,你将会得到不同的结果资源包(假设缺省locale为 Locale(“en”, “UK”)),请参考表13.4。
       表13.4 locale设置与结果资源包
locale设置        结果资源包
Locale("fr", "CH")    MyResources_fr_CH.class
Locale("fr", "FR")        MyResources_fr.properties
Locale("de", "DE")        MyResources_en.properties
Locale("en", "US")        MyResources_en.properties
Locale("es", "ES")        MyResources_es_ES.class

创建了具体的资源包子类实例以后,就需要获得具体的信息。信息在资源包中是以键值对的方式存储的,表13.5列出的是LabelResources.properties文件的内容。

表13.5 LabelResources.properties

  1. # This is LabelResources.properties file
  2. greetings = 您好!
  3. farewell = 再见。
  4. inquiry = 您好吗?


其中等号左边的字符串表示主键,它们是唯一的。为了获得主键对应的值,你可以调用ResourceBundle类的getString方法,并将主键作为参数。此外,文件中以“#”号开头的行表示 注释 行。

ListResourceBundle 和PropertyResourceBundle子类


抽象类ResourceBundle具有两个子类:ListResourceBundle 和PropertyResourceBundle,它们表示资源包子类两种不同的实现方式。

PropertyResourceBundle是和资源文件配对使用的,一个属性文件就是一个普通的文本文件,你只需要为不同的locale设置编写不同名称的资源文件。但是,在资源文件中只能包含字符串,如果需要存储其它类型对象,你可以使用ListResourceBundle

ListResourceBundle 是将键值对信息保存在类中的列表中,而且你必须实现ListResourceBundle 的具体子类。

如果ListResourceBundle 和PropertyResourceBundle不能够满足你的需要,你可以实现自己的ResourceBundle子类,你的子类必须覆盖两个方法:handleGetObject和getKeys。

使用资源文件


使用资源包最简单的方法就是利用资源文件,利用资源文件一般需要以下几个步骤:
1、创建一个缺省的资源文件
为了防止找不到资源文件,你最好实现一个缺省的资源文件,该文件的名称为资源包的基名加上.properties后缀。
2、创建所需的资源文件
为你准备支持的locale设置编写对应的资源文件。
3、设置locale
你必须在程序中的某个地方提供locale的设置或者切换功能,或者将其放入配置文件中。
4、根据locale设置创建资源包
ResourceBundle resource =
        ResourceBundle.getBundle("LabelBundle",currentLocale);
5、通过资源包获取locale相关信息
String value = resource.getString("welcome");

注 意:在使用基名的时候,特别要注意给出完整的类名(或者路径名),比如你的应用程序所在的类包为 org.javaresearch.j2seimproved.i18n,而你的资源文件在你的应用程序下的resource子目录中,那你的基名就应该 是org.javaresearch.j2seimproved.i18n.resource.LabelBundleBundle而不是 resource.LabelBundleBundle。

使用ListResourceBundle


使用ListResourceBundle 和使用资源文件的步骤基本上一样,只不过你需要用ListResourceBundle 子类来替换相应的资源文件。比如你的应用程序的基名是LabelBundle,而且准备支持Locale("en","US")和Locale("zh","CN"),那你需要提供以下几个Java 文件,注意类名和locale的对应关系。
LabelBundle_en_US.java
LabelBundle_zh_CN.java
LabelBundle.java (缺省类)

代码13.3列出的是LabelBundle_zh_CN.java 的源代码,相对于资源文件中“key = value”的写法,在此文件中你首先利用键值对来初始化一个二维数组,并在getContents方法中返回该数组。
      
代码13.3:LabelBundle_zh_CN.java

  1. package  org.javaresearch.j2seimproved.i18n;import  
  2. java .util.ListResourceBundle ;
  3. public  class  LabelBundle_zh_CN extends  ListResourceBundle  {   
  4.   public  Object [][] getContents() {     
  5.     return  contents;   
  6.   }   
  7.   private  Object [][] contents = {      
  8.     {"title""称谓" },      
  9.     {"surname""姓" },      
  10.     {"firstname""名" },   
  11.   };
  12. }



创 建完资源类以后,同样需要设置locale以及根据locale来创建资源包。在通过资源包获取具体值的时候,你不能再使用getString方法,而应 该调用getObject方法,而且由于getObject方法返回一个Object对象,你还需要进行正确的类型转换。其实,为了你的程序通用性,我们 建议在使用资源文件的时候你也应该调用getObject方法,而不是getString方法。

  1.     String  title = (String )resource.getObject("title" );


关于ListResourceBundle 的详细使用,可以参考本书所附代码中国际化一节的ListResourceBundleSample.java 程序。

MessageFormat类


上面我们讲到利用资源文件来分离代码和可变的信息。但是在实际过程中,有些信息并不能够完全事先定义好,其中可能会用到运行时的一些结果,最典型例子的就是错误提示代码,比如提示某个输入必须在一定范围内。利用上面所讲的资源文件并不能够很好地解决这个问题,所以Java 中引入了MessageFormat类。

MessageFormat提供一种语言无关的方式来组装消息,它允许你在运行时刻用指定的参数来替换掉消息字符串中的一部分。你可以为MessageFormat定义一个模式,在其中你可以用占位符来表示变化的部分,比如你有这样一句话:

您好,peachpi !欢迎来到Java 研究组织网站!当前时间是:2003-8-1 16:43:12。

其中斜体带下划线的部分为可变化的,你需要根据当前时间和不同的登录用户来决定最终的显示。我们用占位符来表示这些变化的部分,可以得到下面这个模式:

您好,{0}!欢迎来到Java 研究组织网站!当前时间是:{1,date} {1,time}。

占 位符的格式为{ ArgumentIndex , FormatType , FormatStyle },详细说明可以参考MessageFormat 的API说明文档。这里我们定义了两个占位符,其中的数字对应于传入的参数数组中的索引,{0}占位符被第一个参数替换,{1}占位符被第二个参数替换, 依此类推。
最多可以设置10个占位符,而且每个占位符可以重复出现多次,而且格式可以不同,比如{1,date}和{1,time}。而通过将这些模式定义放到不同的资源文件中,就能够根据不同的locale设置,得到不同的模式定义,并用参数动态替换占位符。

下面我们就以MessageFormatSample.java 程序(源文件见本书所附代码)为例,来详细说明其中的每个步骤。
1、找出可变的部分,并据此定义模式,将模式放入不同的资源文件中。
比如针对上面的模式,定义了下面两个资源文件:
MessagesBundle_en_US.properties
Welcome = Hi, {0}! Welcome to Java  Research Organization!
MessagesBundle_zh_CN.properties
Welcome = 您好,{0}!欢迎来到Java 研究组织网站!

2、创建MessageFormat对象,并设置其locale属性。

  1.       MessageFormat  formatter = new  MessageFormat ("" );
  2.       formatter.setLocale(currentLocale);


3、从资源包中得到模式定义,以及设置参数。

  1. messages =     ResourceBundle .getBundle(
  2.   "org.javaresearch.j2seimproved.i18n.resource.MessagesBundle" ,currentLocale);
  3. Object [] testArgs = {"peachpi" ,new  Date ()};


4、利用模式定义和参数进行格式化。

  1.       System .out.println(formatter.format(messages.getString("welcome" ),testArgs));

 

关于资源包的组织


一般来说,你是按照资源的用途来组织资源包的,比如会把所有的页面按钮的信息放入一个名为ButtonResources的资源包中。在实际的应用过程中,以下几个原则可以帮你决定如何组织资源包:
1、要易于维护。
2、最好不要将所有的信息都放入一个资源包中,因为这样资源包载入内存时将会很耗时。
3、最好将一个大的资源包分为几个小的资源包,这样可以在使用的时候才导入必须的资源,减少内存消耗。

分享到:
评论

相关推荐

    Java课程设计——饭卡管理系统(JavaSwing、JavaFX、MySQL)

    * 项目名:Java课程设计——饭卡管理系统(JavaSwing、JavaFX、MySQL) * @author :第四维度 * 创建时间:2021-6-21 * 采用JavaSwing、JavaFX设计UI界面,结合MySQL数据库进行增删改查操作,功能较为完善 * 包含...

    java小游戏——森林冰火人单人版.zip

    java类的小游戏——森林冰火人,单人游戏, 实现人物行走,跳跃,吃水晶,具有计时功能,积分功能,倒计时结束游戏失败。

    10_Java Web——JSP案例资源

    与我的博客10_Java Web——JSP中案例配套资源,包含完整的数据增删查改的完成,采用MVC模式代发,希望有所帮助

    尚硅谷Java基础实战——Bank项目下载地址

    包含java基础项目实战,此文档包含资源下载地址,可免费下载

    java飞机大战,经典小游戏

    ———————————————————————————————————————— 功能尚不完善,但是可以作为基础参考,适合初学者。 欢迎大家下载,资源免费,若对于相关部分有问题欢迎评论区留言反馈。

    java实现游戏-飞翔的小鸟

    ———————————————————————————————————————— 功能尚不完善,但是可以作为基础参考,适合初学者。 欢迎大家下载,资源免费,若对于相关部分有问题欢迎评论区留言反馈。 ——...

    java源码包---java 源码 大量 实例

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码...

    【java项目】——ubuntu14.04系统部署java web项目-附件资源

    【java项目】——ubuntu14.04系统部署java web项目-附件资源

    java实现游戏-简易贪吃蛇

    ——————————————————————————————————————— 功能尚不完善,但是可以作为基础参考,适合初学者。 欢迎大家下载,资源免费,若对于相关部分有问题欢迎评论区留言反馈。 ——...

    java源码包4

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java...

    java源码包3

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java...

    java源码包2

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java...

    贪吃蛇小游戏的Java实现——源码+jar文件+分析报告

    1.资源概况:(报告十分详细)本资源为基于Java、由bluej开发的贪吃蛇小游戏(eclipse也可以),含源码+jar文件+分析报告。项目包括背景音乐播放功能、账号登陆功能、排行榜功能、难度调节功能,以及其他基础功能 2....

    Web 小游戏——欢乐竞技场(Cocos Creator + Java + MySQL).zip

    Java语言游戏项目实战资源包 内容概览: 这次分享为你带来了丰富的Java语言游戏项目实战资源,让你在实践中深入掌握Java语言,并开启游戏开发之旅。资源包中包括: 游戏项目代码:精心挑选了多个经典的小游戏项目...

    Java实现的人力资源管理系统,可用作毕业设计,课程设计

    此资源集包含了一套完整的Java实现的人力资源管理系统项目源代码、相关的毕业论文以及详尽的使用说明。它旨在提供一个全面、深入的学习和研究工具,适用于本科课程设计、毕业设计以及任何希望深入学习Java编程的学习...

    Java实现的公共资源管理系统(源代码+论文),可用作毕业设计,课程设计

    此资源集包含了一套完整的Java实现的公共资源管理系统项目源代码、相关的毕业论文以及详尽的使用说明。它旨在提供一个全面、深入的学习和研究工具,适用于本科课程设计、毕业设计以及任何希望深入学习Java编程的学习...

    Java实现的办公自动化系统(源代码+论文+外文翻译),可用作毕业设计,课程设计

    此资源集包含了一套完整的Java实现的办公自动化系统项目源代码、相关的毕业论文以及详尽的使用说明。它旨在提供一个全面、深入的学习和研究工具,适用于本科课程设计、毕业设计以及任何希望深入学习Java编程的学习者...

    Java实现的OA流程可视化系统(源代码+论文),可用作毕业设计,课程设计

    此资源集包含了一套完整的Java实现的OA流程可视化系统项目源代码、相关的毕业论文以及详尽的使用说明。它旨在提供一个全面、深入的学习和研究工具,适用于本科课程设计、毕业设计以及任何希望深入学习Java编程的学习...

    JAVA上百实例源码以及开源项目

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码...

    JAVA上百实例源码以及开源项目源代码

    Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来...

Global site tag (gtag.js) - Google Analytics