转:eclipse插件开发电子工业出版社
国际化程序需要满足的条件:
1.不同国家/地区,程序不许重新编译。
2.文本内容本地化,界面文字,提示信息,帮助内容,本地语言化;
3.程序中的标签,汇率,度量衡格式本地化;
基于上面对于插件来说,做国际化需要在三个方面弄清楚:
l数字、日期等界面关键信息要表示正确(主要用NumberFormat,DateFormant实现)
l界面一些提示信息、指示标签、标题等文本语言要本地化(用ResourceBundle、NLS或段来实现)
l扩展插件配置时注意要国际化(将plugin.xml中的字段国际化,plugin.properties)
1.本地化的数字/日期/时区等
Java中使用java.util.Locale类型存储与地域相关的内容。
Locale locale = new Locale(String language);//language 必须是ISO规定的,如en,zh……
Locale locale = new Locale(String language, String country);//country,ISO规定,如US,CN
在Locale内还内置了一些常用的国家地区对象,如:Locale.CHINA,Locale.TAIWAN等。
不同地区日期,数字格式化方式不同。Java提供了java.text.NumberFormat方式处理。要指定locale。如:NumberFormat chinaFormat = NumberFormat.getInstance(Locale.CHINA);
chinaFormat.format(5542.22d);//结果为5,542.22,
//转化为百分数
NumberFormat aFormat = NumberFormat.getPercentInstance(Locale.US);
aFormat.format(.22d);//结果为22%,
//打印货币符号
NumberFormat aFormat = NumberFormat.getCurrencyInstance(Locale.US);
aFormat.format(12345.67);//结果为$12345.67,
java.util.Currency还可以获得与货币相关的信息,如常规的货币小数位数。
Currency ic = Currency.getInstance(“KRW”); ic.getDefaultFractionDigits();
Java.text.DateFormat与NumberFormat相似。
DateFormat dFormat = DateFormat.getDateInstance(DateFormat.SHORT,Locale.CHINA);//格式日期
DateFormat dFormat = DateFormat.getTimeInstance(DateFormat.SHORT,Locale.CHINA);//格式时间
DateFormat dFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT,Locale.CHINA);//格式日期和时间
四种格式
DateFormat.SHORT
DateFormat.MEDIUM
DateFormat.LONG
DateFormat.FULL
标准格林尼治时间GMT + 偏移量:GMT+08:00
夏令时DST:指示某个时区是否参加DST。
TimeZone.getTimeZone(“China/Beijing”);//通过TimeZone.getAvailableIDs()获取
地区时间转GMT时间:
Calendar c = Calendar.getInstance();
c.setTimeZone(TimeZone.getTimeZone(“………”));//时区a
c.clear();
c.setYear,setDate……
DateFormat df = DateFormat.getDateTimeFormat(DateFormat.FULL,Locale.UK);
Df.setTimeZone(TimeZone.getTimeZonn(“GMT”));//GMT时区
df.format(c.getTime());
可以这样计算两个时区的时间差
Calendar a = Calendar.getInstance(TimeZone.getTimeZone(“GMT”));
Calendar b = Calendar.getInstance(Locale.CHINA);
a.setYear…..
b.setYear…
sysout(a.getTimeInMills() – b.getTimeInMills() );
基于以上工具类,个人认为在系统中设定好Locale,那么我们就可以在不同的环境中得到本地化的时间、日期、文字等。(除非指定某些格式是不变的)。
2.文本语言国际化
这个地方讲的主要是在产生视图、对话框等界面元素时,写到界面是的指示性标签、标题等的国际化问题。
采用方式为使用java.util.ResourceBundle资源束管理地域相关的资源。
ResourceBundle已知的子类有ListResourceBundle和PropertyResourceBundle。List**需要我们自己写实现getContent()方法,不常用;在这里说的bundle指的是简单的PropertyResourceBundle。因此可以认为资源束就是一些键值对文件加上对这些文件处理产生的对象,有多少个地域就有多少个资源束文件。这些文件的键key都是一样的,但值是根据地域而不同的。这些资源束文件都用同一个名字+后缀组成。如:messages_zh_CN.properties,messages_en_US.properties。
我们可以通过ResourceBundle获取一个资源束对象。一般地,我们通过ResourceBundle.getBundle(String name);获取基于本地Locale的资源束。这样,软件在不同的地域表现出不同的语言样式。
好了,下面说说具体如何用ResourceBundle实现国际化。
在某个包(aa.bb.cc)下我们新建属性文件,messages.properties,messages_zh.properteis messages_zh_CN.properties messages_en_US.properties。在每个属性文件中写入相同的键和不同的值。
新建类,处理程序中用到的界面文本信息,ResourceBundle bundle = ResourceBundle.getBundle(“aa.bb.cc.messages”);在程序中获取文本标签的方法为bundle.getString(key)。
注意:1 这里属性文件必须是同一个文件名messages+后缀的方式。后缀为语言或是语言+国家/地区。所以呢,在getBundle()时参数为aa.bb.cc.messages。
2所有的属性文件必须为ISO-8859-1编码,存储中文,日文等,需要将字符串转为unicode字符的ASCII格式。即\u4f60类似的样式。否则乱码。
(Native2ascii.exe–encoding GBKmm.propertiesmmUnicode.properties)
3 注意在使用前一定要初始化一下。即:调用getBundle(XXX)一次。
4 其中的key与messagesXXX.properties中的key一致。(可以存入一个类中)
eclipse中NLS也是负责多语言化的类(也是资源束),功能与ResourceBundle基本相同。它要求key值一定写到取值方法类XXX中,即key要在messages中出现,也要在XXX类中出现(必须相同)。在初始化时也有点细微的区别,类加载时调用一次NLS.initializeMessages(msgFileName, XXX.class);其中msgFileName既是messages的相对路径,XXX.class为类。在使用时不是get方法获取,而是直接取XXX类对象的某个属性值。
NLS对应的属性文件同样需要ISO-8859-1的Unicode编码。幸运的是我们可以在eclipse中直接编辑属性文件.propertites,文件自会以Unicode格式保存。
要注意:XXX类中的成员是public static String 类型的。
不管是resourceBundle还是NLS,它们都是自动寻找当前的Locale,当前的Locale是JVM在启动时从操作系统中提取的。
它遵循的查找本地语言properties时都是从上向下加载的。
1 msg_zh_CN.properties
2 msg_zh.properties
3 msg.properties
该功能就是查找程序中的硬编码字符串,用资源束(NLS)代替它们。功能路径是:源代码—》外部化字符串。系统自动生成NLS国际化所需要的属性文件,对应key的类,并修改程序中的字符串用key代替。
然而ResourceBundle和NLS(当然eclipse字符串外部化的本质也是这个)具有缺陷。它的资源文件必须同程序绑定到同一个插件中(工程中),随程序一起打包发布。如果已到另一个区域,则需要重新打包。
Eclipse插件解决问题的方式是使用段(Fragment)来解决。
3.Eclipse中的段
段是eclipse插件体系结构的一部分,它依赖于某个插件,作为它的可选组成部分存在,段可以和它依赖的插件分开打包发布,当eclipse平台装入某一个插件时,会在系统中查找依赖于该插件的段,并一起装入。
在段中,同样可以声明扩展点,创建扩展等,与一般的插件开发一般无二,这些内容都记在了fragment.xml文件中了,平台在装入段时,会将fragment.xml中的内容直接插入到父插件的plugin.xml中。
在段中,同样可以编写java代码。并且这个代码会和父插件中的代码被装载到同一个类空间中,如果在段中包结构和父插件包结构相同,那么类可以互访包可见成员方法。可见段和插件之间的交互比插件间通过扩展点的交互要紧密的多。
段的依赖性继承自原始插件。在段中不用再重新引入依赖插件。当然没有的插件可能需要单独添加依赖。
段它不对原始的插件做任何修改,只是单纯的添加一些内容,因此特别适合做插件国际化。我们发布了版本,然后发布一些语言包,只要将语言包复制到程序中就实现了本地化。
我们可以把程序的一个或多个语言版本用段来实现。一般地为了区分方便,段的名称与主插件相关(但不是强制)。
1 创建段的过程与创建插件的过程相同,就是多了一个选择主插件选项,并指定主插件最小和最大版本(当eclipse启动调用的插件版本不在该范围之内时,eclipse就不会装入这个段)。
2 在段项目中建立与主插件相同结构的包层次,在与主插件同样层次的语言包下创建xxx.properties文件。如messsages_en_UK.properties,messages_ja_JP.properties.
OK,现在就可以使用语言包了,在不同的locale下,界面呈现不同的语言。
Plugin.xml中语言的国际化
在插件开发时,有一些标签的内容是编写在plugin.xml中的,如actionset,menu,view等扩展,工作中这些标签也需要国际化。
国际化步骤:
1.在plugin.xml同样的目录(插件根目录)创建plugin.properties,plugin_en_US.properties等文件 (名称一定是pluginXXX.properties)。
2.类似于NLS的属性文件,用一些键值对表示plugin.xml中的标签,当然为了程序可读,建议用扩展点的id+元素的id等形式作为键。如:actionSetQQ.addressMenu.label=\u4f60。
3.在plugin.xml中将需要国际化的字符串替换为“%键”。
4.在plugin.xml的“构建”选项卡中,将这几个属性文件添加到构建路径中,否则打包时没有它们。
OK,以上就完成了plugin.xml的国际化。
值得一提的是:跟eclipse在程序中外部化java字符串功能一样,eclipse可以帮助我们做这件事。
打开plugin.xml(不打开也行,反正选中外部化字符串菜单时你还要选择),选中外部化字符串,在打开的对话框中,选中plugin.xml和MANIFEST.MF,在本地化标签中显示将在系统根目录下创建一个属性文件OSGI-INF/l10n/bundle.properties。同时修改plugin.xml, MANIFEST.MF文件,将它们的字符串用“%键”代替。一步完成。我们可以把这个bundle.properties文件剪切到根目录下,并该名称为plugin.properties.然后添加plugin_zh_CN.properties等。