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两个子类ListResourceBundle和PropertyResourceBundle- 提供一种相当简单的方法来创建资源
ListResourceBundle将资源作为键/值对列表进行管理PropertyResourceBundle使用属性文件来管理资源- 可以编写自定义的
ResourceBundle子类- 子类必须覆盖两个方法:
handleGetObject和getKeys()
- 子类必须覆盖两个方法:
- 提供一种相当简单的方法来创建资源
-
ResourceBundle子类同时被多个线程使用,其实现必须是线程安全的- 该类中非抽象方法的默认实现,以及直接已知的具体子类
ListResourceBundle和PropertyResourceBundle中的方法都是线程安全的
- 该类中非抽象方法的默认实现,以及直接已知的具体子类
-
缓存管理:
getBundle工厂方法创建的资源包实例默认会被缓存- 如果已经缓存,工厂方法会多次返回同一个资源包实例
getBundle客户端可以清除缓存,使用生存时间值管理缓存的资源包实例的生命周期- 或者指定不缓存资源包实例
-
不必限制使用单一的
ResourceBundle系列、- 例如:可以有一组用于异常消息的包
ExceptionResourcesExceptionResources_fr、ExceptionResources_de…
- 用于小部件的
WidgetResource 等WidgetResources_fr、WidgetResources_de…
- 例如:可以有一组用于异常消息的包
实现
步骤
核心关键:读取资源信息
-
CLASSPATH下建立:项目源文件路径下cn.mldn.message.Messages_zh_CN.properties;-
info="欢迎访问":资源内容 -
zh_CN:表示中文资源CLASSPATH:文件路径;
-
-
CLASSPATH下建立cn.mldn.message.Messages_en_US.properties;-
info=Welcome:资源内容 -
en_US:表示英文资源
-
-
没有设置的默认区域资源文件
- 共有三个资源
-
使用
ResourceBundle类读取资源ResourceBundle.getBundle("").getString();- 未指定明确的
Locale对象,使用默认的本地Locale对象
-
有需要可以修改 Locale 环境
public static final ResourceBundle getBundle(String baseName, Locale loc)- 获取指定区域的资源文件
- 指定区域的资源文件存在,未设置区域的资源文件信息不会被读取
- 指定的的区域没有资源文件存在,读取默认本地资源文件
- 都不存在则读取没有区域的公共资源
-
读取顺序
- 指定区域的资源文件 > 默认的本地资源 > 公共的资源(没有区域)
消息格式化显示
登陆成功时显示的 “Xxx,欢迎登录”
- 这些东西若保存在资源文件中则需要占位符
- 取出时需要进行格式化处理
- 例如:
info="欢迎{0}登录,今日日期:{1}"- 占位符:{0}、{1}…
- 直接读取资源文件会将占位符
{0}、{1}同时读取出来
- 使用
MessageFormat类 进行格式化文本public static String format(String pattern, Object...arguments)pattermn:资源文件中的文本语句arguments:替换占位符的参数(可变参数)
- 在资源文件中{0}、{1}…等都表示占位符,读取资源时必须使用 MessageFormat 格式化处理