4.1.1 Translation Negotiations, Defaults, and Selection
Description
One of the key issues an application has to resolve is determining the target language for translatable product components. The method for doing this is usually platform dependent. On Solaris, for example, it can be set either by the user or system administrator using environmental variables. Also, on Solaris it is usually set globally; that is, a user's entire session is set to the chosen language and cannot change without the risk of inadvertently affecting other processes in the same session. This is usually referred to as not being multithread (MT) safe. Java applications, on the other hand, allow users to change the target language for translatable components at any time without affecting other processes. This is achieved by treating a locale as an object that can be supplied with a call to any locale-sensitive operation. It is also important that if translated components for a selected language are not available, then an appropriate default mechanism should be used.
There is not always a one-to-one relationship between language and country, for example, Canada has two national languages: French and English. Switzerland has four: German, French, Italian, and Romansch. Chinese is really a family of dialects, many of which are mutually incomprehensible as spoken. There are also two distinct and mutually incomprehensible written forms: Traditional Chinese and Simplified Chinese. It is inappropriate to fall back from one to the other if one is unavailable. This is complicated enough when applied to a single platform situation. Imagine, however, trying to deal with this issue in a distributed system where client, server, and database might all be running on different machines and in different locales. How can one platform know what language another is using? These are typical problems faced by developers when developing properly internationalized software.
Default behavior is also important with regard to translation negotiations. There are two main reasons for this. Firstly, default behavior is required if translated components are not found. Secondly, most systems have default locations for translated components which means that application programming interfaces (APIs) do not need to specify full path names when accessing message catalogs, unless such catalogs reside at proprietary locations.
Command Line Interface
Environmental variables, which can be set on the command line, play an important part in determining how your application locates translatable components. Also, the mechanism that you use to access these translatable components determines which environmental variables are used. On Solaris, you can access translated components using several different mechanisms. Two of these are gettext() and catgets(). The former is a Sun proprietary method, the latter is a standard method from XPG4.
gettext() retrieves translated text from a message catalog whose location is determined by a combination of locale name (established using environmental variables and a call to setlocale()), a call to textdomain(), and an optional call to bindtextdomain().
The location is usually of the form:
.../locale/LC_MESSAGES/domain.mo
where:
locale is the current locale.
domain is the argument passed to textdomain(), which is effectively the filename of the message catalog.
Message catalogs usually have a default location, for example, /usr/lib/locale/locale/LC_MESSAGES/domain.mo. To change this location, use bindtextdomain(). To establish the current locale, use setlocale(), which uses environmental variables. The following table details precedence rules that are used to determine the locale.
Table 4-1. Precedence Rules for Environment Variables
| Precedence |
Variable |
| Highest |
LC_ALL |
| Middle |
LC_CTYPE |
|
LC_TIME |
|
LC_MONETARY |
|
LC_NUMERIC |
|
LC_COLLATE |
|
LC_MESSAGES |
| Lowest |
LANG |
NOTE: These environment variables are recognized by most UNIX platforms.
UNIX Example
catgets() retrieves translated text from a message catalog whose location is determined by a combination of locale name (established using environmental variables and a call to setlocale()), a call to catopen(), and a special environment variable called NLSPATH . NLSPATH is a series of colon (:) separated paths which can contain wildcard characters with special meanings. The following is an example of NLSPATH usage:
/usr/lib/locale/%L/LC_MESSAGES/%N.cat:/tmp/%N.%L.cat
In this example, catopen() replaces %N with its first argument; that is, the name of the file that contains the translated messages, minus the .cat suffix. %L is the full locale name as established by setlocale(). So, if the locale were set to fr_FR.ISO8859-1, catopen() would use the following file to retrieve French messages:
/usr/lib/locale/fr_FR.ISO8859-1/LC_MESSAGES/filename.cat
If this file does not exist, catopen() tries the following path:
/tmp/filename.fr_FR.ISO8859-1.cat
If NLSPATH is not set, a default location is used. The default location is usually:
/usr/lib/locale/locale/LC_MESSAGES/filename.cat
Other wildcard characters can be used here also. These can be platform dependent so you should check the platform documentation for these. The following table summarises the environment variables used with gettext() and catgets(), the two methods for retrieving text.
Table 4-2. Relationship Between Environment Variables and APIs for Translation Negotiation
| Function |
Standard |
Locale establishment |
Catalog filename establishment |
Catalog directory name establishment |
| gettext() |
Sun |
LC_MESSAGES/setlocale() |
textdomain() |
default or bindtextdomain() |
| catgets() |
XPG4 |
LC_MESSAGES/setlocale() |
catopen() |
default or NLSPATH/catopen() |
Some toolkits also allow you to specify the locale on the command line when invoking the command. The X Toolkit (Xt) Intrinsics layer, for example, provides a resource for this called XnLanguage. Two examples of how this resource can be used include:
- Using a command line option - Type the following command:
myapplication -xnllanguage ko
- Using an X11 resource file - You can add the following line to your .Xdefaults file:
*xnlLanguage: zh_TW
Character Interface
In a user interface (UI), translation comes into play in two areas: The interface itself is presented in one or more languages. Through the interface, users request or enter data for the software to process. In both cases, the interface can supply the user with language options. For example, a product that is shipped with multiple translations can enable the user to select a default that will be displayed each time the program is executed. In addition, the interface can supply a menu that enables the user to select different languages, resulting in a dynamic change to the UI text. Sometimes, additional fields or options are offered depending on the language.
When the user enters data into the system, a method too indicate the input language is required. The program might require the data to be in the same language as the interface, or it might provide an option to set the language of the input data.
Graphical Interface
For information on text in the UI, see "Character Interface."
In some cases, graphical elements can be used to select different languages. For example, flags are often used for language selection, though this is not the best graphical element as it is country-biased and may cause offense. Sometimes the graphics are simply the text name of the language in that language. This is difficult to display in text mode because the character and font support are usually not available for all the languages on the same page. Also, graphical elements can change along with text, or additional graphics can appear in certain languages.
Application Protocols
Translation negotiation is particularly important among different applications that are running either on different platforms or on the same platform. It becomes even more complicated if those platforms are not homogeneous. Imagine, for example, a client application running on one platform requesting information from a server application on another whose database resides on yet another machine. Assume also that each application on each platform is running on a different locale. If an error message is generated from the database, what will eventually be displayed on the client end? This is the type of issue that a distributed international application needs to address.
Storage and Interchange
Files need to be stored in a way that enables desired translations to be retrieved. In the UNIX example`s "Command Line Interface" section, the catalog files accessed by catgets() can be retrieved according to their file name. Java resource bundles have a language or locale as part of the class file name. Storing a file with a language tag as part of the file name can be invaluable for files that are exchanged or moved frequently. Using standard language or locale extensions enables the programmatic building of a language-specific file name.
Application Programming Interfaces (APIs)
Environment variables and certain APIs work closely in negotiating the target language for an application. For more information, see the "Command Line Interface" section.
NOTE: If you use a toolkit, it might not be necessary to call setlocale() directly. The toolkit might do it for you. For example, the Xt toolkit must be initialized to handle international data. In Xt, this is normally done using the XtSetLanguageProc() call. This is how Motif applications, for example, set their locale. XtSetLanguageProc() actually calls setlocale().
Requirements for Compliance
Command Line Interface
If your application is written using a toolkit that supports a locale command line option or resource, for example, Xt, then that application automatically complies with the recommendations in this section.
NOTE: Not all toolkits or libraries provide this support.
Also, if your application uses the appropriate APIs for translation negotiation, the application does not need to change if environment variables change. It is also important that your application can fall back to some default behavior if it is unable to
establish a target locale.
Character Interface
The interface must provide users with a clear choice for language display and language data processing. For a monolingual application, the data coming in from the user and the data returned should be in a language expected by the user. In other words, it must be clear to the user what data they are allowed to enter and what language the program assumes it to be. The language of the data that the application returns should also be obvious to the user.
In multilingual applications, language options must be clearly presented. Users must be able to understand what happens when they select a language option. For example:
- Does the language of interface elements change immediately or after they restart the application?
- Does the application assume that the language of all subsequent input data is the selected language?
- Is all subsequent data that the application returns in the selected language?
Graphical Interface
See the "Character Interface" requirements.
Application Protocols
You need to ensure that your application properly negotiates its target locale--and hence language--in situations where application components are running on the same platform using the same locale (simple scenario) and where application components are running on heterogeneous platforms and in different locales. You have to address issues relating to character sets, language identification, and cultural requirements when dealing with these issues. Certain standards bodies are currently trying to address such issues. These include the Unicode Consortium and W3C who have an internationalization working group dealing with such issues in the World Wide Web.
Storage and Interchange
File names should correspond to the translation retrieval mechanism used. For example, if you are relying on Java to select the resource bundle according to the locale, the class name and file name of the resource bundle must have the appropriate locale extension.
Application Programming Interfaces
Ensure you use the appropriate APIs for your platform when establishing the target locale or language. Most platforms have dedicated APIs for this. For more information, see the Solaris example. Make sure that these APIs display appropriate default behavior when locale information is not available.
|
|