26.4.使用本地化资源模块

26.4.1. 问题
我的应用程序需要支持多种区域设置。
26.4.2. 解决办法
在运行时根据需要使用资源模块载入特定本地化资源。
26.4.3. 讨论
根据程序需要支持的语言,将每个本地化资源包都编译进应用程序将使得SWF文件大小倍增,而绝大多数用户其实只需要一种区域语言,这将浪费大量的时间用在SWF文件的下载上。还好Flex 3添加一种功能可以编译资源包,这被称作资源模块,它可以在运行时动态加载到应用程序中。你可以先检测用户的区域设置,然后载入相应的资源模块。

要想根据本地化属性文件构建资源模块,首先要检测应用程序需要什么资源,这不仅包括你定义的资源,而且也包括Flex框架所需的资源。你可以使用mxmlc编译器分析应用程序,输出所需资源列表。这可以修改Flex Builder 3的项目属性对话框中的额外编译器参数达到目的。不过命令行模式下也照样可做到,而且更方便快捷。当调用编译器时,没有指定区域,一个编译器分析结果输出的保存文件和MXML文件名称:
mxmlc -locale= -resource-bundle-list=resources.txt ResourceModules.mxml

当命令完成后,resources.txt的内容类似这样:
bundles = containers controls core effects localizedContent skins styles

这个输出内容告诉编译器哪些资源包将被构建到资源模块中。如果使用资源模块编译应用程序,必须使用命令行编译。指定source path为本地化属性文件,资源包列表和上面一样。例如为26.4的ResourceModules.mxml 例子编译:
mxmlc -locale=en_US -source-path=.,locale/{locale}
-include-resource-bundles=containers,controls,core,effects,localizedContent,skins,styles
-output en_US_resources.swf


编译为法语模块:
mxmlc -locale=fr_FR -source-path=.,locale/{locale}
-include-resource-bundles=containers,controls,core,effects,localizedContent,skins,styles
-output fr_FR_resources.swf


这个命令有几项内容。起先,使用-locale参数定义区域,其二,source path参数可能已经很熟悉了,这个例子中包括当前目录(.) 。这个例子中localizedContent属性文件包含一个嵌入类引用,如果source path中没有应用程序根目录,编译器可能就找不到类引用。注意假定你在工程源文件目录下调用了mxmlc,接着include-resource-bundles 参数设置为之前例子生成的列表内容,这个列表有逗号分割符和未含空格的包名组成。最后,这个例子告诉编译器输出文件名称为en_US_resources.swf。你可以命名为其他的。但最好是根据区域标识取名称,这样你就可以根据文件名编程实现载入合适的资源模块了。

当你使用mxmlc编译资源模块后,嵌入资源如图片的引用路径将是相对于本地化属性文件的位置。也就是说,如果应用程序使用编译的资源包资源路径是相对于工程源文件目录的。

程序代码中,使用资源管理器的loadResourceModule方法载入资源模块。给此方法传递一个标识你要使用的资源模块URL,这个方法和其他ActionScript载入方法机理类似,比如SWFLoader或传统模块。一个需要SWF文件的请求发送到服务器,然后SWF被浏览器下载。

如果所需资源模块来自其他域这需要cross-domain策略文件。你必须等资源模块下载完成后才可使用,当子模块可以使用时,ResourceEvent事件会被触发。你可以监听这些事件如ResourceEvent.COMPLETE。

loadResourceModule方法返回一个实现IEventDispatcher接口的对象引用。下面摘录自ResourceModules.mxml例子代码演示如何载入和使用资源模块:
+展开
-ActionScript
import mx.events.ResourceEvent;
import mx.resources.ResourceManager;
private var selectedLocale:String;
private function setAppLocale(locale:String):void
{
this.selectedLocale = locale;
if (resourceManager.getLocales().indexOf(locale) == -1)
{
var dispatcher:IEventDispatcher = resourceManager.loadResourceModule(locale + "_resources.swf");
dispatcher.addEventListener(ResourceEvent.COMPLETE, onResourceLoaded);
}
else
{
onResourceLoaded(null);
}
}
private function onResourceLoaded(e:ResourceEvent):void
{
resourceManager.localeChain = [this.selectedLocale];
views.selectedIndex = 1;
contentBackground.setStyle("borderSkin",
resourceManager.getClass('localizedContent''borderSkin'));
contentBackground.invalidateDisplayList();
contentBackground.validateNow();
}

在这个例子中,用户可在美国英语和法语中做出选择。当用户选择一个语言后,setAppLocale方法被调用,载入所需资源模块。这个方法首先通过资源管理器的getLocales方法输出结果检测所需资源是否已经被载入。这样做很有好处,如果资源没有被载入过,再调用loadResourceModule方法载入资源模块,并且监听complete事件以便可以知道资源模块是否已经准备好。

在complete事件的响应中,应用程序设置localeChain属性为最近使用的资源模块。接着调用了contentBackgroud对象的三个方法。使用资源模块更新样式。

loadResourceModule方法还可接收一些可选的参数。如果程序需要载入多个资源模块,将会载入所以模块,但最后个update参数需设置为false。这样就不会多次重复调用资源管理器的update而节省开销。

加支付宝好友偷能量挖...


评论(0)网络
阅读(128)喜欢(0)flash/flex/fcs/AIR