11.3. String Bundles

String bundles are flat text files that contain text for the UI that is accessed in JavaScript, C++, and theoretically any language that fits within the Mozilla framework. These bundles are strings that can be presented visually to the user via some functionality in the application at any time. This may be anything from a dynamically changing menu item to an alert box, or from a URL to a placeholder that is filled depending on the context in which it is accessed. The bundle files are given an extension of .properties and they commonly reside in the locale directory with the DTD files.

A user interface can use one or more string bundles, each of which is defined in a <stringbundle> element and surrounded by a <stringbundleset> element. Example 11-3 contains the bundles used by the Mozilla browser.

Example 11-3. String bundles used by the Mozilla browser

<stringbundleset id="stringbundleset">
    <stringbundle id="bundle_navigator"
        src="chrome://navigator/locale/navigator.properties"/>
    <stringbundle id="bundle_brand" 
        src="chrome://global/locale/brand.properties"/>
    <stringbundle id="bundle_navigator_region" 
        src="chrome://navigator-region/locale/region.properties"/>
    <stringbundle id="bundle_brand_region" 
        src="chrome://global-region/locale/region.properties"/>
    <stringbundle id="findBundle" 
        src="chrome://global/locale/finddialog.properties"/>
</stringbundleset>

As you can see from their names and their locations in the chrome, each bundle serves a different purpose. They include a file that contains the bulk of the strings for the browser (navigator.properties), a file that includes branding strings, and a couple of files for regional information. This model is useful if you need to output many strings to the UI from your source code and would like to organize them into meaningful groups.

11.3.1. Inside a Bundle

A string bundle (.properties) file has a very simple format. It contains one or more lines that have the identifier associated with the localizable string. The format of a string bundle string with an identifier is:

Identifier=String

The format for comments in a bundle file requires the hash notation (#). Comments are useful for notifying translators of the context of strings, or flagging a string that should be left as is and not localized. Comments in properties files are formatted in the following manner.

# DO NOT TRANSLATE
applicationTitle=xFly

Spaces in bundles are treated literally -- spaces between words are observed, with the exception of the start and the end of the string.

The next section shows the methods and properties specific to the <stringbundle> element that are available to you when you use it. The implementations are contained in the binding for the element.

11.3.2. String Bundle Methods and Properties

Defining your bundle in XUL and then creating the file with the values is only half the story. This section shows how to extract the values from the bundle and place them in UI. The language of choice in these examples is JavaScript. This process is necessary when you have to change values in the UI because DTD entities can not be updated dynamically.

11.3.2.1. Methods

Our bundle is defined in XUL like this:

<stringbundle id="bundle_xfly" 
    src="chrome://xfly/locale/xfly.properties"/>

To access the methods of the bundle object in your script, you have to get a handle on the XUL element by using its id. First declare the variable globally that will be holding the bundle:

var xFlyBundle;

Then assign the variable to the bundle. A good place to do this is in the load handler function of your XUL window, or in the constructor for your binding if you are using it from there:

xFlyBundle = document.getElementById("bundle_xfly");

Now that you have access to the bundle, you can use the available methods to retrieve the strings. The two main functions are getString and getFormattedString.

11.3.3. Creating Your Own Bundle

The implementation for setting up your string bundle just described is hidden from the XUL author. You only need to point at the bundle you want to use by using the source attribute. There is however, an alternative way to do this if you do not favor using <stringbundle> or would like to extend that binding.

The alternative is to use utility routines that come bundled with Mozilla and are contained in a string resources JavaScript file: strres.js. With this file, creating a bundle is a three-step process.

  1. Include the JavaScript file:

    <script type="application/x-javascript"
       src="chrome://global/content/strres.js"/>

  1. Set up your bundle:

    var bundle =
       srGetStrBundle("chrome://mypackage/locale/mypackage.properties");

  1. Access the strings:

    var greeting = bundle.GetStringFromName( "hello" );

The result retrieves the string corresponding to "hello" in your bundle file and is the equivalent of the getString call when using the XUL bundle method.

If your chrome is independent of Mozilla's chrome and you do not want to use their UI files, you can create the bundle directly by using the nsIStringBundleService XPCOM interface, as seen in Example 11-4.

The first step is to get the application locale -- the language that is currently registered with the chrome service. This is done via the nsILocalService component. The nsIStringBundleService is then initialized and the CreateBundle method is called, returning an instance of nsIStringBundle that provides access to the methods for querying strings.