Coming from a country with two official languages, one request I get a lot is for a website to be multi-lingual, a.k.a. support i18n (a fancy abbreviation for "internationalization"). This is easy if you are using Mura, since its supports multi-lingual content and locales right out of the box (it even has a translations plugin that will allow you to coordinate multiple-language websites). But what about your own development work?
As is often the case, Mura's framework makes this quite easy.
Mura makes i18n happen through the Java ResourceBundle, a very efficient method of matching content strings and placeholders. For those who like to explore, the three classes in /requirements/mura/resourceBundle are the ones that implement and manage this functionality.
Introduction to Resource Bundles
As part of the application initiation, a resource bundle "factory" is created that loads the core resource files. These files are named with the convention "language abbreviation[_country code].properties", like "en.properties" or "fr.properties". For finer grain control over locales, you can use two-letter ISO 3166-1 country codes like "en_US" "en_CA" to further narrow which resource you wish to implement. If a resource for a specific locale, say "fr_CA.properties" isn't found, the resource manager will automatically swim upstream, looking first for "fr.properties" and continuing until it finds the parent resource to use. Mura's resources are found in two main locations the first located at /requirements/mura/resourceBundle/resources/ and the second at /[siteid]/includes/resourceBundles/. For more detail on these files, see the Wikipedia entry.
The format for a resource property is a simple one, and it allows you to add a straight-forward methodology to managing them. For instance, here are a couple example drawn from Mura.
In these, you will see a common pattern of "application.word key", which helps you sort out specifics of where and when the resource should be applied. This is important because in many cases you will use the same word key but in different contexts. For instance, "cancel" might be "Delete", "Cancel", "Go Back" in various points within your application. Keep in mind too that others will be using your base resource file to create alternate language versions, using these resource descriptions almost entirely to determine where they are located.
To create an alternate-language version of the above, you simply replace the default values with one appropriate to the language.
Adding Your Own
Adding your own resource bundles in Mura is very easy. Take the example code below:
...that's it! One line. The above example is from a plugin, and I'll break it down for you a bit.
The first step is creating a local "rbFactory" object. We then init() this new object with several values. The function is expecting, in order, the parent (i.e. Mura's) resource bundle factory, the path to your resource bundles, and finally the active locale. Simply put you are using init( "Mura Resource Bundle Factory", "path to my X.properties files", "locale I'm using in Mura i.e. en").
You'll be calling this a lot in our application, so make sure you store your rbFactory in a persistent scope. In the case of a plugin, this can be done by storing it in the plugin's application scope (best accomplished in your "onApplicationLoad" event.
Now that that is done, you will need to replace your static labels, hints etc. in your code with resource references. For instance, in my "Cormorant" plugin (heh, more about that later ;), I have replaced the static word "Back" in my plugin menu with the following code:
In this case, I have embedded my "rbfactory" in a FuseBox event (hence event.getValue("rbFactory")). I then use the getKeyValue() method to retrieve the specific key in my resource bundle. The magic in ths is I can use keys identified in Mura's resource bundles without changing a thing!!!
Now, it does take a bit of practice to get used to using resource keys instead of text, but the effort is well worth it. The usable base for your application will become global, and updating or changing your own labels is now a single-stop effort.

Recent Comments