RWUResourceBundle is a mechanism for storing and accessing locale-dependent data.
Every resource bundle contains one or more resources. An individual resource can be of type string, integer, integer vector, or binary. A collection of resources can be arranged as a table or as an array. Each element of a table has a const
char*
key; each element of an array has an integer index. Any element of a table or array may be either an individual resource or another table or array. Tables and arrays are themselves treated as RWUResourceBundle instances, so RWUResourceBundle instances nest recursively.
Each resource bundle contains data for one locale. The bundles for an application are organized in a logical hierarchy based upon the locales associated with the bundles. At the base of the hierarchy is a "root" resource bundle that contains a resource value for every aspect of the program that needs to be localized; typically, these resource values are expressed in the locale of the application developer. Below the "root" resource bundle are language-specific bundles (for example, en
, de
, and ja
bundles). Below the language-specific bundles are region-specific bundles (for example, de_DE
and de_CH
), and below the region-specific bundles are variant-specific bundles (for example, de_DE_PREEURO
). Typically, only the "root" bundle contains a resource value for every localizable aspect of the application. A fallback mechanism ensures that a child resource bundle need only contain the resources whose values differ from its ancestor bundles.
When an application needs localized data, it constructs an RWUResourceBundle, then queries the bundle for the needed resources. The constructors for RWUResourceBundle accept the name of a directory containing .res
files, and the name of a locale. The RWUResourceBundle instances created by these constructors are known as "top-level" resource bundles. These top-level resource bundles are guaranteed to be of type table, containing one or more "top-level" resources associated with string keys.
When creating a top-level RWUResourceBundle, the constructor may succeed, succeed through fallback, or fail, depending on whether an exact match to the requested locale is found, a fallback match is found, or no bundle at all is found. Constructors throw an RWUException if no bundle is found, but otherwise succeed and cache an RWUStatusCode to indicate the level of success. The getStatus() method returns the status of an RWUResourceBundle.
Similarly, when a top-level RWUResourceBundle is queried for a particular top-level resource, the query may succeed, succeed through fallback, or fail. The query throws RWUException if it fails, but otherwise returns an RWUResourceBundle holding a cached RWUStatusCode. Again, the getStatus() method returns the status code.
The fallback mechanism works in three stages. In the first stage, you create an RWUResourceBundle from a locale name and path:
- The library first looks for the exact named RWUResourceBundle.
- Failing that, the library looks for a parent locale along the named locale's branch.
- If no parent locale is found, the library looks for the locale named by RWULocale::getDefault().
- Failing that, the library looks for a parent locale along the default locale's branch.
- Failing that, the library attempts to open the RWUResourceBundle named
root
.
- Finally, if it can find no information for any of the above mentioned locales, the library throws an RWUException.
For example, suppose there are RWUResourceBundle instances available for root
, en
, en_US
, en_US_POSIX
, and es
, and that the current default RWULocale is es_ES
. If you attempt to open the RWUResourceBundle named ja_JP
, the library tries these bundle names in order:
ja_JP
– the exact match
ja
– the parent
es_ES
– the default locale
es
– the default parent: Success!
- if
es
been missing, root
would have been tried next
In the second stage, you access a resource named at the top level:
- The library first looks for the named resource in the currently open RWUResourceBundle.
- Failing that, the library looks for the named resource in a parent of the currently open RWUResourceBundle.
- Failing that, the library looks in the
root
resource bundle.
- Failing that, the library throws an RWUException.
For example, suppose that in the es
resource bundle there is a table named menu
containing entries for file
, edit
, and help
. Suppose also that the root
resource bundle has, in addition to the menu
table, a string resource named currentVersion
. If you attempt to access the menu
table resource, the library returns the one in the es
RWUResourceBundle. If you attempt to access the currentVersion
string resource, the library returns the one in root
.
In the third stage, you open a resource held within a top-level array or table:
- The library looks only in the already open top-level resource.
- If the requested datum is not there, an RWUException is thrown.
For instance, continuing from the Stage 2 example, suppose you have opened the menu
resource, and now are looking for the tools
string within the menu
table. Suppose this entry is available in the menu
resource in the root
resource bundle, but not in the menu
resource in the es
resource bundle. Your attempt does not fall back–it fails.
Data in a resource bundle are compiled into a compact form. Note that binary data, as well as keyed data, are compiled without regard to platform-specific details. As a result, table data may not be found on a platform where the character encoding (US-ASCII or EBCDIC, for instance) used for the keys is different than that where compiled. For similar reasons, binary data may be wrong if compiled on a big-endian machine and read on a little-endian machine, or vice versa.
- See also
- RWULocale