国际化程序实现
原理
-
国际化程序:同一个程序代码可以根据不同语言描述,但核心业务是相同的
-
实现国际化程序开发
-
定义保存文字的文本信息
-
根据不同区域语言的编码读取指定的资源信息
-
前期准备
编码问题
-
解决不同国家用户的区域和语言的编码问题
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
系列、- 例如:可以有一组用于异常消息的包
ExceptionResources
ExceptionResources_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 格式化处理