Java 资源本地化与国际化

资源包

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

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

ResourceBundle类

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

资源包中的每个成员共享一个被称作基名(basename)的名称,然后在此基础上根据一定的命名规范进行扩展。下面就列出了一些成员的名称:

LabelResources

LabelResources_de

LabelResources_de_CH

LabelResources_de_CH_UNIX

可见这些子类依据这样的命名规范:baseName_language_country_variant,其中language等几个变量就是你在构造Locale类时所使用的。而资源包正是通过这个符合命名规范的名称来和locale进行关联的,比如LabelResource_de_CH就对应于由德语(de)和瑞士(CH)组成的locale对象。

Locale currentLocale = new Locale("de", "CH", "UNIX");ResourceBundle myResources =ResourceBundle.getBundle("LabelResources", currentLocale);ResourceBundle.getBundle(message)//获取当前系统所使用的区域环境获得指定资源文件ResourceBundle.getBundle(message,locale)//根据指定的区域获取对应的资源文件

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

ResourceBundle.getBundle(message)//获取当前系统所使用的区域环境获得指定资源文件ResourceBundle.getBundle(message,locale)//根据指定的区域获取对应的资源文件

如果该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”))

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

创建了具体的资源包子类实例以后,就需要获得具体的信息。信息在资源包中是以键值对的方式存储的

LabelResources.properties

# This isLabelResources.properties filegreetings = 您好!farewell = 再见。inquiry = 您好吗?

漫过心际的孤独,早已蔚然成冰,而你是这个季节里最美的音符。

Java 资源本地化与国际化

相关文章:

你感兴趣的文章:

标签云: