Java基础之国际化

国际化程序实现

原理

  • 国际化程序:同一个程序代码可以根据不同语言描述,但核心业务是相同的

  • 实现国际化程序开发

    • 定义保存文字的文本信息

    • 根据不同区域语言的编码读取指定的资源信息

在这里插入图片描述

前期准备

编码问题
  • 解决不同国家用户的区域和语言的编码问题

    • java.uilt.Locale 类专门描述区域和语言编码
  • Locale 类主要构造方法

    • public Locale(String language)

    • public Locale(String language, String country)

      • 需要国家和语言的代码
        • 中文的代码:zh_CN
        • 美国英语的代码: en_US
    • 区域和语言的编码最佳获得方式就是通过 IE 浏览器

  • 利用 Locale 类自动获取当前运行环境

    • 默认方式实例化
      • 读取本地默认环境 Locale loc = Locale.getDefault();
      • loc 输出 zh_CN
  • 在实际开发中大多并不关心国家和语言的编码,将一些著名国家编码设置了常量简化开发

    • 常量实例化 Locale 对象 Locale loc = Locale.CHINA;
      • loc 输出 zh_CN
    • 避免一些区域编码信息的繁琐
读取资源文件
  • 主要依靠 ResourceBundle 类进行

    • public abstrach class ResourceBundle{}
  • 该类为抽象类,使用其子类完成资源读取

    • 或其中的一个静态方法获取 ResourceBundle 对象
      • public static final ResourceBundle getBundle(String baseName)
        • baseName:资源文件名称,不含后缀;即资源文件路径
    • 根据 key 读取资源内容
      • public final String getString(String key)
      • 资源读取时要确保路径下有文件,且文件中存在相应的 key
ResourceBundle
  • 包含特定于语言环境的对象

    • 当程序需要特定于语言环境的资源(例如 String )时可以从适合当前用户语言环境的资源包中加载
  • 程序可以

    • 一次处理多个语言环境
    • 轻松修改以支持更多语言环境
  • 如果不同国家有不同的资源,可以进行专门化

    • 例如:MyResources_de_CH 包含瑞士( CH ) 的德语 ( de ) 对象
    • 如果只想修改专精中的部分资源,可以这样做
  • 程序需要特定于语言环境的对象时,使用 getBundle 方法加载 ResourceBundle

    • ResourceBundle myResources = ResourceBundle.getBundle("MyResources", currentLocale);
    • 资源包包含键/值对
      • 键唯一地标识包中特定于语言环境的对象
      • 键必须是 String
      • 值可以是任何类型的对象
  • ListResourceBundle示例

    • public class MyResources extends ListResourceBundle {
          protected Object[][] getContents() {
              return new Object[][] {
                  // LOCALIZE THE SECOND STRING OF EACH ARRAY (e.g., "OK")
                  {"OkKey", "OK"},
                  {"CancelKey", "Cancel"},
                  // END OF MATERIAL TO LOCALIZE
              };
          }
      }
      
  • 使用 getter 方法从资源包中检索对象

    • getter 方法需要键作为参数
      • 找到则返回对象
      • 如果找不到对象 getter 方法会抛出 MissingResourceException
    • ResourceBundle 提供了一种获取字符串数组的方法 getStringArray
    • 用于任何其他类型对象的通用 getObject 方法
      • 使用 getObject 时,必须将结果转换为适当的类型
      • 例如:int[] myIntegers = (int[]) myResources.getObject("intList");
  • Java 提供 ResourceBundle 两个子类 ListResourceBundlePropertyResourceBundle

    • 提供一种相当简单的方法来创建资源
      • ListResourceBundle 将资源作为键/值对列表进行管理
      • PropertyResourceBundle 使用属性文件来管理资源
      • 可以编写自定义的 ResourceBundle 子类
        • 子类必须覆盖两个方法:handleGetObjectgetKeys()
  • ResourceBundle 子类同时被多个线程使用,其实现必须是线程安全的

    • 该类中非抽象方法的默认实现,以及直接已知的具体子类 ListResourceBundlePropertyResourceBundle 中的方法都是线程安全的
  • 缓存管理:getBundle 工厂方法创建的资源包实例默认会被缓存

    • 如果已经缓存,工厂方法会多次返回同一个资源包实例
    • getBundle 客户端可以清除缓存,使用生存时间值管理缓存的资源包实例的生命周期
      • 或者指定不缓存资源包实例
  • 不必限制使用单一的 ResourceBundle 系列、

    • 例如:可以有一组用于异常消息的包 ExceptionResources
      • ExceptionResources_frExceptionResources_de
    • 用于小部件的 WidgetResource 等
      • WidgetResources_frWidgetResources_de

实现

步骤

核心关键:读取资源信息

  1. CLASSPATH 下建立:项目源文件路径下 cn.mldn.message.Messages_zh_CN.properties;

    • info="欢迎访问":资源内容

    • zh_CN:表示中文资源

      • CLASSPATH:文件路径;
  2. CLASSPATH 下建立 cn.mldn.message.Messages_en_US.properties;

    • info=Welcome:资源内容

    • en_US:表示英文资源

  3. 没有设置的默认区域资源文件

    • 共有三个资源
  4. 使用 ResourceBundle 类读取资源

    • ResourceBundle.getBundle("").getString();
    • 未指定明确的 Locale 对象,使用默认的本地 Locale 对象
  5. 有需要可以修改 Locale 环境

    • public static final ResourceBundle getBundle(String baseName, Locale loc)
      • 获取指定区域的资源文件
    • 指定区域的资源文件存在,未设置区域的资源文件信息不会被读取
    • 指定的的区域没有资源文件存在,读取默认本地资源文件
    • 都不存在则读取没有区域的公共资源
  6. 读取顺序

    • 指定区域的资源文件 > 默认的本地资源 > 公共的资源(没有区域)
消息格式化显示

登陆成功时显示的 “Xxx,欢迎登录”

  • 这些东西若保存在资源文件中则需要占位符
  • 取出时需要进行格式化处理
  • 例如:info="欢迎{0}登录,今日日期:{1}"
    • 占位符:{0}、{1}…
    • 直接读取资源文件会将占位符{0}{1}同时读取出来
  • 使用 MessageFormat 类 进行格式化文本
    • public static String format(String pattern, Object...arguments)
      • pattermn:资源文件中的文本语句
      • arguments:替换占位符的参数(可变参数)
  • 在资源文件中{0}、{1}…等都表示占位符,读取资源时必须使用 MessageFormat 格式化处理