January 02nd 2009 - Entry Posted to:
ActionScript 3, tutorial
How best to approach setting up a Flash based website to handle multiple languages is often a topic of discussion at the various Flash forums I frequent.
Adobe have a few pointers for creating multi language Flash projects, using the Strings Panel. This looks OK, but I’ve never actually used it, so cant really comment beyond reading over the documentation.
My approach to mulitlanguage files consists of creating a seperate XML file for each language I want to use in the application, and then loading that file at load time where a user can select it before the site loads and allowing for the user to change the language file at runtime, after the site has loaded and all content is displayed. If a user selects a language file then that selection is stored as a SharedObject, so that with subsequent site loads, the language file is automatically selected and loaded.
Setting up a Flash project for multiple language selection is fairly painless. I’ll run through a general approach to setting up your projects, and then a couple of ActionScript implementations that explore different means of achieving the same result; namely load and runtime selection of language files. One note, is that these example files are pure ActionScript projects, all content is dynamically created. However, if you have static content, the general principles will still apply.
The first thing you will want to set up is your XML language files. I’ve created two, an English and a French version. (The French version is just some google translated English text, so excuse the probably massive translation errors
). The english.xml file is below.
<?xml version="1.0" encoding="UTF-8" ?>
<!-- English XML File - 2008 -->
<website lang="english">
<ui>
<lang id="changelang" title="Change Language" />
<noponies id="blog" title="View Blog Entry" url="http://www.blog.noponies.com/feed" />
<noponies id="illustrations" title="View Illustrations" url="http://www.noponies.com/" />
<noponies id="about" title="About" url="http://www.blog.noponies.com/about" />
</ui>
<!-- DUMMY -->
<people>
<person id="people/director" title="Dale Sattler" >
<text><![CDATA[<p><strong>About</strong>
I’m a New Zealand based Designer and Illustrator. Apart from what you see here I like to surf, draw and enjoy the outdoors.
This site is little blog to place the Flash and other technical stuff that does not fit into my main http://www.noponies.com site, which is more focused on my illustration and design.
Drop me a line if you find the files useful and maybe even send me a link to the site in which it was used. Feel free to make a donation to my paypal account if you want to reward me for the effort I put into making this resource. Its not a requirement, but is nice. </p>]]>
</text>
</person>
</people>
</website>
As you can see, the XML is wrapped in an website tag with an attribute for the language, called “lang”. We then have a ui and a people tag, with various children. The ui tag, will provide our sites interface with its text labels, and the people tag will simply provide us with some dummy text content.
The most important element to pick up from the XML file, is the use of the id attribute for each XML fragment that corresponds to some actual content in our Flash website. This id attribute must be unique for each element and is used by Flash a key when we search through each XML file, matching the id attribute against each of our Flash sites elements own id tags. This key based approach is also the means by which I create Flash sites that use SWFAddress. Each XML element also has either a title or a text tag which corresponds to the Flash elements actual content. If you contrast the english.xml against the french.xml, you will see that the id attributes are unchanged, it is only the title or text elements that change.
So, that is the XML part of the project explained. Now, onto the Flash implementations. As I mentioned earlier, there are various different approaches to using multiple language files in Flash. As a Flash developer, you have a few options to consider. The first is when do you want a user select their language file. Generally, you would want a user to make this selection before the site has loaded, a sort of “Choose your language” splash page. This is the most simple approach, as it negates the need to allow for users changing language settings once the website has loaded and its content has displayed. The second is to allow for runtime language changes, although hardly any users would want to change their language after the site has loaded, but there may be a small subset that perhaps make a mistake etc. This approach is a little more complicated, because you need to build into your project the means to let all the elements that can change their language, that they have to change their language, and then also a means for passing around the relevant language data to each of these elements.
Which ever way you approach your language swapping, your interface will need to be flexible enough to accommodate the various different amounts of text it takes to express something like “About Us” in different languages.
For this demo I have allowed for runtime language changing, with a default language “english” loading. I have not added in any functionality to storing a language selection, but this is simple to add.
Ok, onto the ActionScript.
As I mentioned earlier, the main problem to overcome with runtime language swapping is how to notify all the interested parties in Flash that they need to update their language and dimensions when a user chooses to change language settings. There are various means to approach this, but what it boils down to, is a means to store the language XML in a way that allows for all elements to access it, and a means for notifying all elements that they must change their language file and probably their dimensions.
I’ve implemented 3 different approaches to changing language files in Flash. Each example is a different means for solving the problem of passing the language files XML to each element and notifying them that they need to change their language settings, along with the means to actually change language files. The different approaches are; Singleton Pattern, Custom Event with params and Observer Pattern. Universal to each example is the use of a simple interface that each ui element implements to guarantee the presence of a setLanguage method in all ui elements that need to change their language. I probably didn’t really need an interface for this one method, but with a complicated site, with many ui elements, it can be easy to forget a particular method.
1 – Singleton Using a Singleton to store language file in a globally accessible point. Singleton classes, allow for what many consider a bit of a hack, and that is global access to one class instance. In this implementation, the Singleton is used as an XML loading class, with each class that requires access to the language file importing a reference to this Singletons one and only instance. When a user chooses to change language, an event is dispatched, that all elements are listening for. When this notification event is received, each subscribing item then queries the Singleton for the sites language file, parses this XML data matching its id against the XML elements id code, if a match is found, then that XML fragment is used by the element for its language setting, and the ui updates. This approach works fine, but I don’t like the long …. lookups on the Singleton instance and the main deal breaker for me with this implementation is that it locks the site as a whole into accessing this one point for its data. So, if we wanted to provide the language file by some means other than via an external xml file, then we would have some issues.
2 – Custom Event Using a custom event with a parameter that allows for us to pass the XML data around the site is the obvious choice I think for sites that need to change language files. The implementation is simple, write a custom event class that allows for us to pass around the XML data from the language file. Have each element that needs to change its language listen for this event, and when a user changes language, simply dispatch the event. When this notification event is received, each subscribing item then queries the events parameter for the sites language file, parses this XML data matching its id against the XML elements id code, if a match is found, then that XML fragment is used by the element for its language setting, and the ui updates. I like this approach, as it decouples the sites ui elements from one particular source for that XML data, it could come from a database, or an external xml file. Either way, the ui elements have no idea where the data comes from, they just listen for an event.
3 – Observer Design Pattern Using an Observer pattern works fairly well in this situation. Again, the implementation is fairly straightforward, we create an Observer class, which has the usual addSubscriber, removeSubscriber and update methods. Each ui element then subscribes to the observer pattern instance, and when a user changes language files, the observer then loops through its subscribed children, calling each child’s setLanguage method, passing the sites new XML language data through to each child as a argument of the setLanguage method. This approach works well I think. It still maintains a loose relationship between the ui elements and the language data. The only thing I don’t really like about this approach, and this design pattern is that it feels like I’m replicating the basic event dispatcher model in Flash, and so feels redundant. Maybe I’m missing something. One thing to note, is that I changed the interface for this approach to allow for the setLanguage method to accept XML as an argument.
So, whats the best approach? I tend to prefer using custom events, mostly out of force of habit. I’m curious to see how other people approach swapping language files in Flash website projects?
View Example
You can view a pretty simple demo of the event based approach here: http://www.noponies.com/dev/as3_lang/
Source Files
Files for each of the 3 approaches are here: Language Swapping Source Files (733) – 2.3 MB
Each example is well commented, and the comments should explain most of the functionality.