- 浏览: 255112 次
- 性别:
- 来自: 大连
文章分类
最新评论
-
红小豆:
Criteria和Detachedcriteria的区别及应用 -
fjjiaboming:
那就稍微翻译一下 啊....
Mysql autoReconnect 的问题 -
woyaowenzi:
非常感谢,我正想做一个画线的控件,就和windows的画图板一 ...
一个简单的FLEX画图demo -
guzen:
可以用一下flash builder 4,现在支持绝对定位了, ...
how to use flex layouts -
suifeng:
好!
一个简单的FLEX画图demo
Runtime Localization
Gordon Smith
September 25. 2007
Table of contents <noscript type="text/javascript">showTocToggle("show","hide")</noscript> [show hide ] |
Introduction
In Flex 2, the localized resources for an application had to be linked into the application SWF. Also, the resources could only be for a single locale, so if you wanted to localize for multiple locales you had to build multiple application SWFs.
With Flex 3, localization support will become much more Flexible! Here’s how:
-
You can put your resources into resource modules -- similar to style modules -- rather than into the application itself. You can preload the module for an appropriate locale when the application starts, and you can load modules for additional locales later.
-
You can compile resources for multiple locales into a single application or module.
-
You access all resources through a new ResourceManager, which can manage resources for multiple locales. You can change at runtime which locales get searched for resources.
-
Binding expressions that reference resources via the new ResourceManager will automatically update if the locale changes. Components are notified when the locale changes so that they can update themselves appropriately.
-
You can also use images, sounds, etc. as resources rather than just strings.
-
You can programatically create your own resources at runtime and use them just like ones that were compiled from .properties files. So you can create resources at runtime from downloaded XML files, database results, etc.
Sounds cool. Can I see a demo?
To see what you’ll be able to do with runtime localization, take a
look at the FlightReservation1 and FlightReservation2 demo
applications. They accomplish the same thing, but they use two
different localization strategies. Both versions have been localized
for U.S. English (the en_US
locale) and for Japanese (the ja_JP
locale). They are provided as Flex Builder 3 projects which you can
import into a Flex Builder workspace. Choose File > Import, select
General > Existing Projects into Workspace, and browse for each
project. Please read each project's README.txt
file for
more information. If you simply copy files into a new Flex Builder
project rather than importing the projects, be sure to follow the
instructions in these files or you may get compilation or runtime
errors.
In FlightReservation1, both the en_US
and the ja_JP
resources are compiled into the application SWF. The first time that the application is launched, the en_US
resources will be used by default. A Language combobox allows the user
to select Japanese, at which point the application tells the
ResourceManager to use the ja_JP
resources instead of the en_US
ones. As a result, the user interface switches — on the fly! — to
Japanese. The application also saves the user’s locale choice in a
local SharedObject. The next time the application starts, it reads this
saved locale and uses its resources by default. So if you switch to
Japanese and quit, this application will restart in Japanese.
In FlightReservation2, the application has no resources inside it.
Instead they are compiled into two separate resource module SWFs, Resources_en_US.swf
and Resources_ja_JP.swf
. (Note: You cannot create resource modules in Flex Builder 3; you must use command-line tools to do so.) The HTML template (html-template/index.template.html
) has been customized to preload the English resource module by specifying properties named resourceModuleURLs
and localeChain
in the FlashVars
.
Make sure that you use this template rather than Flex Builder’s default
one. (In general, server-side logic could decide which locale to
initially load, and generate the appropriate HTML wrapper.) When the
user switches the locale at runtime, the application determines whether
the new locale has already been loaded, and, if not, loads the
appropriate resource module. So, the first time that the user chooses
Japanese, the Japanese module will get loaded. But then the user can
continue to switch back and forth between English and Japanese with no
further module loading.
The on-the-fly locale switching in both versions is accomplished primarily by simple binding expressions which automatically update when the locale is changed. However, these applications use some other interesting localization techniques:
-
The XML data — which simulates back-end data that in the real world would come from a database — is locale-independent. For example, the “from” and “to” locations for a route are expressed as airport codes. But the user interface localizes this info into locale-dependent city names using
labelFunction
s, and it sorts the lists based on the localized names. -
Dates are displayed with locale-dependent formatting.
-
The flight distance is displayed in locale-dependent units — miles for U.S. English, kilometers for Japanese — with locale-dependent formatting.
- Prices are displayed in locale-dependent units — U.S. dollars for U.S. English, Yen for Japanese — with locale-dependent formatting (i.e., currency symbol and precision).
How about a simpler tutorial?
Sure. There is quite a bit going on in the FlightReservation demo, so I’ll let you dig into that by yourself when you’re ready. For now, lets go step-by-step through a really simple “Hello” app that we’ll localize for English and French. It will give you a good introduction to various aspects of localization in Flex 3.
Create a new Flex Project called RunLoc in Flex Builder. Enter the following code for RunLoc.mxml
:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Label text="@Resource(bundle='myResources', key='GREETING')" fontSize="48"/> </mx:Application>
Just as in Flex 2, you can use the @Resource()
MXML compiler directive to specify that the Label’s text
property is to be set to a localized value from a resource bundle, rather than simply writing
<mx:Label text="Hello!" fontSize="48"/>
with the hard-coded English word “Hello!”. The bundle
and key
attributes inside the @Resource() directive tell the compiler that we want to use the resource named GREETING
inside a resource bundle named myResources
.
The simplest way to create a resource bundle is to provide a
.properties file defining the keys and values in the bundle. The MXML
compiler will compile a .properties file into a subclass of the
mx.resources.ResourceBundle class. So, create a folder named locale
inside the project (as a sibling of the src
folder) and, inside locale
, create a folder named en_US
for our U.S. English resources. Inside the en_US
folder, create a file called myResources.properties.
Open the Properties dialog for the myResources.properties
file and set its "Text file encoding" to UTF-8. (If this causes a
warning, ignore it.) The MXML compiler expects all .properties files to
have UTF-8 encoding. Now edit the file and put one English resource in
it:
GREETING=Hello!
Now open the project’s Properties dialog, select the Flex Compiler pane, and enter the following as “Additional compiler arguments”:
-locale=en_US -source-path=../locale/{locale}
If you now compile and run the application, you should see “Hello!” displayed.
What are all those compilation options?
I knew you’d ask.
From the @Resource()
directive, the compiler knows that the application uses a resource bundle named myResources
. The -source-path
option tells the compiler where to look for additional source files such myResources.properties
. The locale, en_US
, specified by the -locale
option is automatically subsituted for the special {locale}
token in -source-path
.
When we change the locale, we won’t have to also change the source
path. You need the .. in the source path because, in Flex Builder 3
Beta 2, a relative source path is resolved relative to the src
directory, not relative to the project directory. This may change before we ship.
The -locale=en_US
option also tells the compiler to use the en_US
version of the framework resources. What are framework resources? Well,
framework components such as Label use resources, just like your
application and your custom components can use resources. Label and
other framework classes have been precompiled into component libraries
in the frameworks/libs
folder of the Flex SDK. The resources required by these classes are located in separate resource bundle libraries in the frameworks/locale
folder. For example, the English resources for the frameworks/libs/framework.swc
library are in the resource bundle library frameworks/locale/en_US/framework_rb.swc
.
Now we’d like to localize our RunLoc app for French — by providing resources for the fr_FR
locale. But first we need to deal with the fact that the Flex SDK doesn't provide French framework resources.
Huh? French framework resources?
In the past, the MXML compiler was happy as long as you provided application resources for the locale you specified with the -locale
option; it would fall back and use the en_US
framework resources if it didn’t find those for the locale you specified. But the Flex 3 compiler is pickier: if you specify -locale=fr_FR
then it will expect to find French framework resources.
Don’t worry, though... it’s not hard to make an fr_FR
framework resource library. You can just use a command-line script which will compile the en_US
.properties files for the fr_FR
locale!
Set the current directory to the Flex SDK that your Flex Builder project is using. By default, this will be the directory sdks/3.0.0
inside your Flex Builder installation. Now execute
bin\copylocale.exe en_US fr_FR
on Windows or
bin/copylocale.sh en_US fr_FR
on Macintosh. Check to make sure that you now have a framework_rb.swc
file inside frameworks\locale\fr_FR
.
Now that we’ve made a French framework resource library, it’s really easy to localize our app for French.
Note that for some reason the data visualization src folder is missing from build 3.0.183654. So if you try to run copylocale you will get this message: C:\Program Files\Adobe\Flex Builder 3\sdks\3.0.0\bin>copylocale en_US fr_FR Error: Directory "C:\Program Files\Adobe\Flex Builder 3\sdks\3.0.0\frameworks\projects\datavisualization\bundles\en_US\src" does not exist I simply created an empty src folder at that location and then copylocale works. C:\Program Files\Adobe\Flex Builder 3\sdks\3.0.0\bin>copylocale en_US fr_FR In Flex SDK at C:\Program Files\Adobe\Flex Builder 3\sdks\3.0.0 ...
Hello? Non... Bonjour!
Inside the locale
folder of the RunLoc project, create a folder called fr_FR
. Inside the fr_FR
folder, create a file called myResources.properties
and sets its encoding to UTF-8. Enter the French version of the GREETING
resource in it:
GREETING=Bonjour!
Open the project’s Properties dialog, select the Flex Compiler pane, and in the “Additional compiler arguments” simply change
-locale=en_US
to
-locale=fr_FR
Now run the application... you should see “Bonjour!” instead of “Hello!”.
OK, OK. How do I switch locales on the fly?
You’re right to be bored so far... up to this point we haven’t done anything that wasn’t possible in previous versions of Flex. But now we’re ready to talk about Flex 3’s improvements. To start, let's compile our RunLoc demo for both English and French, and add some code to switch between them.
Change RunLoc.mxml
to look like this:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Metadata> [ResourceBundle("myResources")] </mx:Metadata> <mx:Script> <![CDATA[
[Bindable] private var locales:Array = [ "en_US" , "fr_FR" ];
private function localeComboBox_initializeHandler(event:Event):void { localeComboBox.selectedIndex = locales.indexOf(resourceManager.localeChain[0]); } private function localeComboBox_changeHandler(event:Event):void { // Set the localeChain to either the one-element Array // [ "en_US" ] or the one-element Array [ "fr_FR" ]. resourceManager.localeChain = [ localeComboBox.selectedItem ]; }
]]> </mx:Script> <mx:Label text="{resourceManager.getString('myResources', 'GREETING')}" fontSize="48"/>
<mx:ComboBox id="localeComboBox" dataProvider="{locales}" initialize="localeComboBox_initializeHandler(event)" change="localeComboBox_changeHandler(event)"/> </mx:Application>
Change the -locale
option to be
-locale=en_US,fr_FR
Note from Jason: For Flex Builder 3.0.183654 I had to use space instead of column. i.e. "-locale=en_US fr_FR". Also take away the <br> in the source code shown above. Great Tutorial. Thank you.
When you compile and run, the application will start in English (because en_US
is specified as the first locale). But when you choose fr_FR
in the combobox, the “Hello!” changes on the fly to “Bonjour!”. Next we’ll explain how this happens.
What’s this resourceManager thing?
A new manager in the Flex framework — the ResourceManager — now
handles access to all localized resources in an application. Any
components that extend UIComponent, Formatter, or Validator now have a
new resourceManager
property, which lets you easily
access the singleton instance of this manager. If you’re writing some
other kind of class that needs to use the ResourceManager, you can call
ResourceManager.getInstance()
to get a reference to it.
We compiled the RunLoc application in such a way that various resource bundles — our own myResources
bundle, but also framework bundles such as core
, controls,
formatters
,
etc. — were linked into the application SWF. When the application
started, instances of these resource bundles were automatically added
to the ResourceManager. After they’ve been added, we can look up
resources in them using ResourceManager methods such as getString()
.
Note that in the binding expression
text="{resourceManager.getString('myResources', 'GREETING')}"
we specify a bundle name and a resource key, but not a particular
locale. Instead, the locales that get searched for resources are
determined by the localeChain
property of the ResourceManager. The handler for the locale combobox’s "change"
event sets resourceManager.localeChain
. The setter for this property dispatches a "change"
event from the ResourceManager, which is a signal that the
application’s resources have changed in some way. This event causes two
things to happen:
-
Binding expressions involving resource-access methods of ResourceManager such as
getString()
are updated. This is why “Hello!” changed to “Bonjour!”. -
Components that extend UIComponent, Formatter, or Validator execute their
resourcesChanged()
method. This is how components such as CurrencyFormatter can update their default value for resource-backed properties such ascurrencySymbol
. If you are writing another kind of class that needs to respond to resource changes, you can simply listen for"change"
events from the ResourceManager.
Why do I need to write a binding expression instead of @Resource()?
We could have made the @Resource()
directive generate a binding expression that would update when the localeChain
changes, but we decided not to. Binding expressions have some overhead
associated with them and we don’t want to penalize developers who need
localization but not on-the-fly locale changes.
Although switching locales on the fly is cool, it’s not something
that every localized application will need. For many or even most apps,
it will be good enough to start up in an appropriate locale, and
perhaps allow the user to select a different locale for the next time
that the application starts. In that case, @Resource()
will work just fine.
Our thinking is that developers who want to support on-the-fly locale changes should “opt in” to that by writing explicit binding expressions.
What’s up with [ResourceBundle]?
I was wondering when you were going to ask why I put the tag
<mx:Metadata> [ResourceBundle("myResources")] </mx:Metadata>
in the RunLoc app. The answer is that when you use an expression like resourceManager.getString(bundleName, key)
instead of the directive @Resource(bundle='myResources', key='GREETING')
to access resources, the compiler isn’t clever enough to figure out
what resource bundles your application (or component, or AS class)
needs. You might be determining bundleName
in some very convoluted way. So when you don’t use @Resource()
, you have to tell the compiler in another, very explicit, way which bundles you’re accessing.
The way to do that now is to put [ResourceBundle()]
metadata with the name of the bundle into your application’s (or component’s) <mx:Metadata>
tag. If you’re writing an ActionScript class instead, put this metadata on the class declaration, like this:
[ResourceBundle("myResources")] public class MyComponent extends UIComponent { ... }
If you’ve localized Flex applications in the past, you may have used [ResourceBundle()]
metadata on static or instance variables:
[ResourceBundle("myResources")]
static var rb:ResourceBundle;
This would initialize rb
to be a reference to the myResources
ResourceBundle instance, and you could then write expressions such as rb.getString("GREETING")
. Although this should still work if you compile for one and only one locale, it is very strongly discouraged.
The new localization scheme relies on all resource bundles being owned by the ResourceManager, and all resource access going through the ResourceManager. You should revise any old code which access resources directly from resource bundles.
Why is the localeChain an Array?
Ah, you noticed that too! For example, if you want to search only the French resources you have to write
resourceManager.localeChain = [ "fr_FR" ];
not
resourceManager.localeChain = "fr_FR";
The reason that the localeChain
is an Array is so that the ResourceManager can support incomplete locales.
Suppose that you’re localizing an application for English as spoken in India (i.e., the en_IN
locale). Most — but not all — of the resources will be the same as for
U.S. English, so there’s no reason to duplicate them all in the en_IN
resources — this just bloats your application’s size. The en_IN
.properties files need only to have the resources that differ between en_US
and en_IN
. Then, if the ResourceManager has bundles for both en_US
and en_IN
and you set
resourceManager.localeChain = [ "en_IN", "en_US" ];
the ResourceManager will search for a resource first in the en_IN
bundle and, if it isn’t found there, then in the en_US
bundle. You can “fall back” from one locale to another until you find a resource. If getString()
doesn’t find the resource you specify in any locale, it returns null
.
Can resource values only be Strings?
The short answer to this is No, but it’s a little complicated so I’ll give a fuller explanation.
When you compile a .properties file with resources such as
COUNTRY=United States PRICE=19.99 AGE=21 SENIOR=true
the MXML compiler autogenerates a subclass of ResourceBundle with a content
Object containing the key/value pairs for those resources. The generated code is equivalent to
content["COUNTRY"] = "United States"; content["PRICE"] = "19.99"; content["AGE"] = "21"; content["SENIOR"] = "true"
Note that all of these resource values are Strings. The compiler doesn’t look at SENIOR=true
and decide that the value should be the Boolean true
rather than the String "true"
. So if you call resourceManager.getString("myBundle", "SENIOR")
you’ll get the String "true"
.
However, the ResourceManager has other resource-access methods besides getString()
. For example:
resourceManager.getNumber("myResources", "PRICE"); // returns the Number 19.99, not the String "19.99" resourceManager.getInt("myResources", "AGE"); // returns the int 21, not the String "21" resourceManager.getBoolean("myResources", "SENIOR") // returns the Boolean true, not the String "true"
These methods, like getString(
), are actually all wrappers around the fundamental resource-access method getObject()
, which returns the resource value with no conversion.
Beginning with Flex 3, you can now use Embed()
and ClassReference()
directives in .properties files, as in
LOGO=Embed("logo.png") SORTER=ClassReference("sorters.Urdu")
These directives work just the same as in CSS files or <mx:Style>
tags. When you use these directives, the resource value is of type Class. This is obvious for ClassReference()
; for Embed()
,
it’s because the MXML compiler autogenerates a class to represent
embedded data such as a PNG graphics file. You can use the
ResourceManager’s getClass()
method to access these resource values..
If you create your own resource bundles at runtime rather than having the MXML compiler compile them from .properties files, you can put any key/value pairs you want into their content Object. You’re not limited to Strings. This is discussed in a later section.
Determining the initial locale
When an application is compiled for multiple locales, such as with the compilation option
-locale=en_US,fr_FR
the ResourceManager's localeChain
property is initialized to this sequence of locales. For example, in this case it would find the English resources because en_US
is listed first. However, you can override this default initial value by specifying the localeChain
as an application parameter in the FlashVars in the HTML template.
In the html-template
folder of the RunLoc project, open the index.template.html
file and insert the line
"FlashVars", "localeChain=fr_FR",
after the line
"src", "${swf}",
in the second call to the JavaScript function AC_FL_RunContent()
.
Save the file. Now clean the project (with Project > Clean in the menubar) to force the RunLoc.html
file in the bin
folder (which is simply a renamed copy of the index.template.html
file) to be regenerated. It should automatically update when the index.template.html
file is saved, but due to a bug in Beta 3 this doesn't happen.
When you run, the application should start up in French. If you change fr_FR
to en_US
and regenerate RunLoc.html
, the app should start up in English.
You can specify multiple locales in the FlashVars, as in
"FlashVars", "localeChain=en_IN,en_US",
which would initialize the localeChain property to [ "en_IN", "en_US" ]
.
To support browsers that have JavaScript disabled, you need to also specify the FlashVars in two other places (in the <object>
and <embed>
tags). See the index.template.html
file for the FlightReservation2 application for an example of doing this.
Tell me about resource modules!
I’ve shown you how to compile your application for multiple locales, such as English and French, but if you’re localizing for twenty locales it might not be reasonable to bloat your application’s size by linking in resources for all of them. This is where resource modules can be useful. You can go to the other extreme, such as compiling no resources into your application and instead loading them as needed from resource modules. (Or you can link some into your application and load others. It’s all up to you.)
Resource modules are SWFs, separate from your application SWF, which contain resources bundles for one or more locales. Your application can preload one or more resource modules as it starts up, before it displays its user interface. It can also load resource modules later, such as in response to the user selecting a new locale. The ResourceManager doesn’t care whether the resource bundles it manages were originally compiled into the application or loaded from resource modules.
Before you can compile a resource module, you need to know which
resource bundles to put into it. In other words, you need to know which
resource bundles your application — and all of its framework classes —
actually needs. The MXML compiler can tell you that, if you specify the
-resource-bundle-list
option; when it compiles an application, it determines which bundles it needs by looking at the [ResourceBundle]
metadata on all the classes in your application.
Open the RunLoc project’s Properties dialog, select the Flex
Compiler pane, and in the “Additional compiler arguments” field, change
the -locale
option to
-locale=
to tell the application not to compile any resources into itself, and add the option
-resource-bundle-list=bundles.txt
This option tells the MXML compiler to write out a file named bundles.txt
containing a list of the resource bundle names used by RunLoc. In Beta 2, this file will appear in the project's bin
folder, although this may change before we ship. If you open this file you’ll see the list
bundles = collections containers controls core effects myResources skins styles
Notice that only the myResources
bundle contains application resources; the others are bundles containing framework resources.
If you run the application now, you won't see either “Hello!” or “Bonjour!” because both the English and the French resources are missing.
How do I compile a resource module?
Unfortunately, due to the fact that resource modules require a different set of compilation options from other kinds of modules, you can’t compile them with Flex Builder. You have to use command-line compilation.
We’ll use the bundle names we obtained to compile two resource modules as follows. First change the current directory to the RunLoc project directory. Then execute these two commands:
mxmlc -locale=en_US -source-path=locale/{locale} -include-resource-bundles=collections,containers,controls,core,effects,myResources,skins,styles -output=src/Resources_en_US.swf
mxmlc -locale=fr_FR -source-path=locale/{locale} -include-resource-bundles=collections,containers,controls,core,effects,myResources,skins,styles -output=src/Resources_fr_FR.swf
If you haven’t placed the SDK’s bin
directory on your PATH, you’ll need to specify an absolute path for mxmlc.
Windows commandline: If -source-path
does not work, and return unable to open 'en_US'
: specify the absolute path to your project locale folder instead.
Windows commandline: -output
also expect an absolute
path to your project src folder, otherwise it will create the swf in
c:\src\ There is maybe a better solution, but I could not make it work
otherwise: ps: great tutorials! thanks.
The project's src
directory should now contain two resource modules named Resources_en_US.swf
and Resources_fr_FR.swf
.
How do I preload a resource module?
The Flex framework can handle preloading one or more resource modules for you automatically. All you have to do is set the resourceModuleURLs
application parameter in the FlashVars of the HTML wrapper. You should also set the localeChain
parameter to tell the application what locale to initially use. For example, if you change the FlashVars in index.template.html
to
"FlashVars", "resourceModuleURLs=Resources_en_US.swf&localeChain=en_US",
(and save the file and clean the project) then the resource module Resources_en_US.swf
will be preloaded (this URL is relative to the application SWF) and the ResourceManager's localeChain
will be initialized to [ "en_US" ]
.
When you run the application, it should load the English resource module and you should see “Hello!”. If you change this line to
"FlashVars", "resourceModuleURLs=Resources_fr_FR.swf&localeChain=fr_FR",
(and save the file and clean the project) it should load the French resource module and you should see “Bonjour!”.
You can specify a comma-spearated list of resource module URLs to preload more than one resource module.
How do I load a resource module programmatically?
You use the ResourceManager’s loadResourceModule()
to start asynchronously loading a resource module. It works similarly to the loadStyleDeclarations()
of the StyleManager, which loads style modules.
The loadResourceModule()
method returns an event-dispatching object. You can listen for "progress"
, "complete"
, and "error"
events — of type ResourceEvent — which it dispatches. Primarily, you’ll
be interested in knowing when the load is complete, because that’s when
you’ll probably want to set the localeChain
to use the resources that you just loaded. You’ll generally want to do something like this:
private function someMethod():void { ... var url:String = "Resources_fr_FR.swf"; var eventDispatcher:IEventDispatcher = loadResourceModule(url); eventDispatcher.addEventListener(ResourceEvent.COMPLETE, completeHandler); ... } private function completeHandler(event:ResourceEvent):void { resourceManager.localeChain = [ "fr_FR" ]; }
Can I see a complete example?
Sure. Change RunLoc.mxml
to have the following code
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Metadata> [ResourceBundle("myResources")] </mx:Metadata> <mx:Script> <![CDATA[ import mx.events.ResourceEvent; [Bindable] private var locales:Array = [ "en_US" , "fr_FR" ]; private function localeComboBox_initializeHandler(event:Event):void { localeComboBox.selectedIndex = locales.indexOf(resourceManager.localeChain[0]); } private function localeComboBox_changeHandler(event:Event):void { var newLocale:String = String(localeComboBox.selectedItem); if (resourceManager.getLocales().indexOf(newLocale) != -1) { completeHandler(null); } else { var resourceModuleURL:String = "Resources_" + newLocale + ".swf"; var eventDispatcher:IEventDispatcher = resourceManager.loadResourceModule(resourceModuleURL); eventDispatcher.addEventListener( ResourceEvent.COMPLETE, completeHandler); } } private function completeHandler(event:ResourceEvent):void { resourceManager.localeChain = [ localeComboBox.selectedItem ]; } ]]> </mx:Script> <mx:Label text="{resourceManager.getString('myResources', 'GREETING')}" fontSize="48"/>
<mx:ComboBox id="localeComboBox" dataProvider="{locales}" initialize="localeComboBox_initializeHandler(event)" change="localeComboBox_changeHandler(event)"/> </mx:Application>
Set the FlashVars in index.template.html
back to preload the English resources (and save the file and clean the project).
When you run the application, it loads Resources_en_US.swf
and displays “Hello!”. When you choose fr_FR
in the combobox, it loads Resources_fr_FR.swf
and displays “Bonjour!”.
Note that the logic
if (resourceManager.getLocales().indexOf(newLocale) != -1)
determines whether we’ve already loaded the locale that the user wants to switch to.
I’m tired! Anything else?
There are just a few more things you should know.
I’ve already mentioned that the ResourceManager manages ResourceBundles, but it doesn’t care where the ResourceBundles come from. They can be compiled into the application. Or they can be loaded from a resource module. Or you can create them yourself at runtime, rather than compiling them from .properties files at compile time. For example, this code creates a new bundle, populates it with two resources, and adds it to the ResourceManager.
var moreResources:ResourceBundle = new ResourceBundle("fr_FR", "moreResources"); moreResources.content["OPEN"] = "Ouvrez"; moreResources.content["CLOSE"] = "Fermez"; resourceManager.addResourceBundle(moreResources);
Once a resource bundle is in the ResourceManager, methods like getString()
can be used to find its resources:
resourceManager.localeChain = [ "fr_FR" ]; trace(resourceManager.getString("moreResources", "OPEN")); // outputs "Ouvrez"
The ability to create resource bundles yourself means that you can “roll your own” ways of loading resources at runtime. We’ve chosen to support doing it via compiled resource modules, because this makes it possible to localize images, sounds, classes, etc. rather than just strings. But if you want, you can download XML files or fetch resource data from a database, put it into ResourceBundles, and access it through the ResourceManager.
You can use the removeResourceBundle()
method to remove a resource bundle from the ResourceManager, so that its resources can no longer be found.
You can find out which resource bundles exist in the ResourceManager by calling getLocales()
and getBundlesNamesForLocale()
and you can get a reference to a particular bundle by calling getResourceBundle()
. These methods make it possible to enumerate all the resources in the ResourceManager. (Once you have a ResourceBundle, use a for-in
loop to iterate over it’s content
Object.)
When you set the localeChain
, the ResourceManager automatically dispatches a "change"
event. (Remember, this event causes your application’s user interface
to update with the new resource values.) This event is also dispatched
after a module completes loading, if you passed true
as the second parameter to loadResourceModule()
.
If you want to tell the ResourceManager to dispatch this event in other
circumstances, such as after you have added a bundle yourself, you can
call the ResourceManager’s update()
method.
I hope you find Flex 3’s Runtime Localization feature to be useful in your applications!
发表评论
-
flex lcds 的日志配置
2009-06-16 17:26 1750Server-side logging <!-- ... -
PopUpManager--createPopUp与addPopUp区别
2009-06-07 00:38 2062Java代码 <?xml vers ... -
how to use flex layouts
2009-06-06 21:27 2008当 我们新建一个flex应 ... -
flex 装载多个module出现的问题
2009-02-02 23:24 3388TypeError: Error #1034: 强制转换类型失 ... -
Flash trace panel
2009-01-15 22:50 1557今天晚上下载了flash trace panel,调试flas ... -
一个简单的FLEX画图demo
2009-01-14 08:42 7502虽然只能画简单的矩形和线段,不过还是很有意思的。 http ... -
Top 10 Mistakes when building Flex Applications
2009-01-14 08:37 1009zz from http://www.infoq.com/ne ... -
43 Hot Flex and ActionScript 3.0 APIs, tips
2009-01-14 08:21 2351Autumn is here again and it’s t ... -
flex与java集成开发及遇到问题的解决办法
2009-01-14 08:07 2770一、开发环境:eclipse3 ... -
Flex与Spring集成中遇到的问题
2009-01-11 21:36 8821.前几天的项目都搭在公司的机器上, flex build p ... -
一些Flex开源项目的整理
2009-01-06 09:03 926Adobe APIs 主要包含corelib, mappr, ... -
FLEX HTTPService vs RemoteObject
2009-01-06 08:38 4168zz from xxxx 仅供参考!!! 1.Remot ... -
使用Flash,Flex Builder和AS3创建自适应的用户界
2009-01-04 20:24 3082一、概述 1.1 关于作者 J ... -
Stop using mx.transitions.Tween
2009-01-04 20:07 1484zz from:http://www.psyked.co.uk ... -
FLEX 点点滴滴
2008-12-28 12:01 941ViewStack: A ViewStack naviga ... -
flex urls
2008-12-28 00:32 1185http://blog.csdn.net/Baijinwen ... -
初试FLEX Store中遇到的问题
2008-12-28 00:22 1451剛開始研究了一下Flex,看到FlexStore,感覺不錯 ...
相关推荐
《ShaderX2: Introductions and Tutorials with DirectX 9.0》是一本专注于ShaderX编程技术的图书,其首次出版于2003年8月25日。这本书的内容着重于游戏开发中的一种重要技能——着色器编程。着色器是图形处理单元...
《ShaderX2 - Introductions and Tutorials with DirectX9》是一部深入探讨DirectX9着色器技术的专业文献,旨在引导读者理解和掌握DirectX9中的着色语言和编程技巧。本书结合了理论与实践,通过一系列的教程,为读者...
### ShaderX2: Introductions & Tutorials with DirectX 9 #### 一、书籍概述 《ShaderX2: Introductions & Tutorials with DirectX 9》是一本专注于介绍和教授DirectX 9环境下着色器编程的基础教程。本书由...
This book is an essential guide to the implementation of image processing and computer vision techniques, with tutorial introductions and sample code in Matlab. Algorithms are presented and fully ...
Essentially three books in one: provides thorough introductions to the PHP language and the MySQL database, and shows you how these two technologies can be effectively integrated to build powerful ...
### DirectX 9 Introductions and Tutorials #### 概述 《ShaderX2:DirectX 9 的介绍与教程》是一本由 Wolfgang F. Engel 编辑的专业书籍,主要聚焦于 DirectX 9 的使用与高级图形编程技术。本书不仅为初学者提供...
这个“Introductions_and_Tutorials_with_DirectX_9_code”源代码集合可能是由一系列教程或示例程序组成的,旨在帮助初学者和有经验的开发者更好地理解和应用DirectX 9技术。 在这些压缩包的子文件中,我们看到了以...
Shader X1 和 Shader X2的pdf文件,压缩包 Direct3D ShaderX: Vertex and Pixel Shader Tips and Tricks ShaderX2: Introductions and Tutorials with DirectX 9.0
Unit 3:Good Manners和Family * Good Manners:thank you、please * Family:mom、dad、brother、sister、grandma、grandpa Unit 4:Questions和Useful Phrases * Questions:what、where、how * Useful ...
#### Lesson 3: CMOS Logic Circuit - **CMOS逻辑电路介绍**:互补金属氧化物半导体(CMOS)逻辑电路是现代数字电子系统的核心组成部分。它利用了CMOS技术的低功耗特性。 - **基本单元**:CMOS逻辑门由P型和N型...
Chapter 3: Common Concepts Chapter 4: RxJava Chapter 5: Reactor Chapter 6: Akka Streams Chapter 7: Android and RxJava Chapter 8: Spring Boot and Reactor Chapter 9: Akka HTTP and Akka Streams Chapter ...
Chapter 3: PHP Basics Chapter 4: Functions Chapter 5: Arrays Chapter 6: Object-Oriented PHP Chapter 7: Advanced OOP Features Chapter 8: Error and Exception Handling Chapter 9: Strings and Regular ...
This idea led to two books: ShaderX2: Introductions & Tutorials with DirectX 9 ShaderX2: Shader Programming Tips & Tricks with DirectX 9 The first book helps the reader get started with ...
This idea led to two books: ShaderX2: Introductions & Tutorials with DirectX 9 ShaderX2: Shader Programming Tips & Tricks with DirectX 9 The first book helps the reader get started with ...
【标题】"ws-spring-jaxb-introductions-demo:VA 的访问后总结"涉及到的是一个基于Spring框架的Web服务示例项目,其中可能包含了使用Java进行Web服务开发的相关技术。这个项目可能用来演示如何在Spring环境中集成和...
该资料库是为第3周的作业而设计的,我们将在其中介绍您自己的课程。 这也是我们收集您的GitHub并将其添加到此存储库的方式。 我们将为您自己的名为.md的文件(即mlh4xc.md)创建一个拉取请求(PR),该文件具有以下...
三年级上册英语单元达标测评卷-Module 2 Introductions_13-14外研版(三起)扫描版.doc