|
创建过Java多语言本地化应用的朋友应该都很熟悉Java的本地化资源访问的功能,现在好了,Flex2诸多激动人心更新中的一个就是本地化特性(localization feature),这倒是Adobe加强推广Flex2的一个强助力了(这一特性可以本地化Flex组件,这样估计以后会有中文版的Flex2了...),使用Flex2的本地化特性我们可以很容易创建多语言本地化的Flex应用,为我们的Flex应用打入国际市场添威助力,不过不像Java的本地化资源动态获取的方式,目前Flex2的本地化特性只支持静态的本地化资源嵌入,还不支持运行时动态获取本地化资源。 要本地化Flex2应用,我们需要将本地化资源文件编译为SWC库文件,然后在Flex应用中使用ActionScript或者MXML访问资源集(resource bundles )中的本地化值。 Flex2的本地化特性面向以以下人员:
Web应用开发人员 Web应用翻译人员 Flex框架开发人员 Flex框架翻译人员(中文版?!嘿嘿...) 本地化应用流程:
要本地化Flex代码,我们需要改变我们MXML和ActionScript代码,创建本地化属性文件和类,运行compc工具创建SWC库文件,最后使用mxmlc工具将我们的应用编译成SWF文件。
使用ResourceBundle API
要本地化Flex代码第一步是使用 mx.resource.ResourceBundle API替换期待本地化的硬编码内容。我们可以在ActionScript和MXML代码中使用ResourceBundle API。
ResourceBundle是ActionScript 3.0语言规范的一部分,其包含如下与本地化资源交互的方法:
static getBundle(name:String):ResourceBundle,这里name指的是属性文件名或ResourceBundle子类名。 getString(key:String):String, 这里key指的是属性文件或ResourceBundle子类中明值对名称 getObject(clsName:String):Object 使用本地化字符串
在下面的例子的ActionScript代码中,ResourceBundle API被用来设置某一按钮的label值,ResourceBundle.getBundle()方法获取某一资源集,然后使用 ResourceBundle.getString() 方法资源集中某一键值。
... var myBundle:ResourceBundle = ResourceBundle.getBundle(getSystemManager(), ’MyBundle’); myButton1.label = myBundle.getString(’myButton1_label’); ...
在MXML中,我们指定资源集名称和键名给@Resource指令来获取特点资源集中的特定值。如果,我们只标明键名,默认资源集名称为当前类名称。资源集名称为包含特定键的属性文件或ResourceBundle子类名称。@Resource有以下两种形式以下例子使用@Resource指令设置Button控件的label属性:
<mx:Button id="myButton1" label="@Resource(bundle=’MyButtonResources’, key=’myButton1_label’)" click="ti1.text=’myButton1.label=’+myButton1.label;"/>
在本地化字符串中使用绑定(Using binding with localized strings)
我们可以使用绑定表达式将@Resource指令的键参数绑定到相应属性文件的键值中,以下MXML代码使用绑定表达式作为@Resource指令的键参数: <mx:Label id=”lab” text="@Resource('lab.text', {product.name})"/>
以下示例是相应属性文件中键值对,{0}将会被product.name替代:
lab.text = We do not have {0} in stock.
我们也可以使用多个参数,例如在@Resource指令有多个参数时的:{0}和{1}。
如果需要的话,我们必须确保product.name是本地化的。
掉换本地化字符串顺序
我们可以基于区域使用某一本地化字符串或其他,例如,默认的英语属性文件可能包含如下键:
MYTEXT = {0} and {1}
而另外一个English属性文件可能包含如下值:
MYTEXT = {1} and {0}
某一MXML文件可能包含如下@Resource指令:
@Resource('MYTEXT', "My name is Bill.", "I am a developer.");
以上两个字符串在第二个区域中被掉换了。
以下是与以上@Resource指令等价的ActionScript代码:
var r:ResourceBundle; r = ResourceBundle.getBundle(sm, "MyComponent1"); StringUtil.substitute(r.MYTEXT, "My name is Anant", "I am in the Flex team");
使用本地化对象和嵌入资源
在应用中,如果要使用ActionScript类或嵌入资源,如图像,我们可以调用ResourceBundle.getObject()方法,当我们获取一个ResourceBundle子类后,可以使用该ResourceBundle子类的getObject()方法从资源集中获取特定的类:
var bundle:ResourceBundle = ResourceBundle.getBundle(sm, "LocaleClasses"); var obj:Object = bundle.getObject("FormattingClass");
因为这里并没有到类的直接引用,我们必须使用ActionScript增加任意的可视子对象,例如:
var bundle:ResourceBundle = ResourceBundle.getBundle(sm, "LocaleClasses"); var obj:DisplayObject = DisplayObject(bundle.getObject("FormattingClass")); myLocaleParent.add(obj);
以上示例中,LocaleClasses是某一我们创建的用来存放嵌入类的ResourceBundle子类, 该类引用了被ResourceBundle的getContent()方法返回的对象的类(这句有些拗口:This class references the classes that are needed in the ResourceBundle in an Object returned from its getContent() method. )。以下LocaleClasses示例:
public class LocaleClasses extends ResourceBundle { public function LocaleClasses() { super(); } override protected static function getContent():Object { var contentObj:Object = new Object(); contentObj.push("FormattingClass", FormattingClass); contentObj.push("Class2", Class2); // More classes can by added here. return contentObj; } }
处理的过程类似嵌入资源,一共有三个步骤,首先我们必须使用基于类版本的嵌入,这就意味着我们必须为每个需要嵌入的资源创建一个类,例如,如果我们有一个JPG图片需要本地化,我们可以将以下RedJpg类添加到本地化目录中:
package { import mx.core.SkinSprite; [Embed(source=’red_jpg.jpg’)] public class RedJpg extends SkinSprite { } }
第二步,将RedJpg类添加到某一扩展ResourceBundle的类中,这样是为了让编译器就有个需要处理的资源集了 。通常我们将所有需要的类放置在同一个资源集类中。
以下是一个包含RedJpg类的ResourceBundle子类:
package { import mx.reso
|