Guideline A: User interface

A6: Variable order

Providing for flexible variable order

Messages in the UI usually employ substitution variables to contain variable information. When a message is retrieved dynamically, the current information replaces the substitution variable. However, when a message is translated into another language, the position and order of the substitution variables may have to change in order to meet the syntax requirements of the target language.


Guideline A6

Permit variables that are substituted into text strings to assume any location and order.

Substitution variables used with messages must be uniquely identifiable (a unique identifier must be assigned to each variable), so that when they are repositioned and reordered, there is no requirement to change the program logic.

Example: The following C segment retrieves a message string from an external message file and prints it to the standard output. Depending on the user's preference, the message string is retrieved from either the English or the German message file.

int iReturnCode; /* return code */
char cFunctionName[33]; /* function name */
char *pcFormat; /* printf(...) format string */
nl_catd descCat; /* message catalog descriptor */
:
:
/* Retrieve the printf(...) format string */
pcFormat = catgets( descCat, MSG_SET_ID, MSG_ID, NULL );
if ( pcFormat != NULL ) /* success */
(void)printf( pcFormat, iReturnCode, cFunctionName );

The message in the two external message files is as follows:

Language Message Text
English Return code %d was returned by the function %s.
German Die Funktion %s endete mit dem Fehlercode %d.

When the English format string is retrieved, %d formats the variable iReturnCode as a decimal number, and %s formats the variable pcFunctionName as a character string. When the German format string is retrieved, however, not only are %d and %s erroneously used to format the variables pcFunctionName and iReturnCode, but the resultant message is incorrect because you are misinterpreting the function name as the return code, and the return code as the function name.

The ISO/IEC international standard on the C programming language recognized the importance of this problem, and introduced the %n$ construct to explicitly bind a format flag to a specific argument. Using this feature, the message may be rewritten as:

Language Message Text
English Return code %1$d was returned by the function %2$s.
German Die Funktion %2$s endete mit dem Fehlercode %1$d.

Another important point to remember when dealing with variables is to avoid hard coding the strings which are to be substituted for the variables. The sample Java code below illustrates two ways of handling variables: substituting hard-coded strings and using the ResourceBundle class.

Example:

msg = MessageFormat.format(msg, myobj.getPreState());
// BAD: variables are substituted by hard-coded strings in a message
public String getPreState() {
state = "creating";
// GOOD: ResourceBundle class is used
public String getPreState() {
state = resourceBundle.getString("wsrm.dest.state.creating");

When a variable is to be substituted by a very long string (such as the full name of a specific product component), it is good practice to use a pair of double quotes around the variable to distinguish the variable from the surrounding text. This improves the readability of the message and helps translators understand the sentence.

Example:

Message = "Deleting \"{0}\" removes the business system resource and all its children from Corporate Administrative Systems. Do you want to delete this business system and all its children?"

Variable {0} = used for a specific product component name ("Business System: AY - Accounts Payable Imaging - Viewstar")

Resulting message = Deleting "Business System: AY - Accounts Payable Imaging - Viewstar" removes the business system resource and all its children from Corporate Administrative Systems. Do you want to delete this business system and all its children?

We recommend that detailed information about each of the substitution variables used in a message be provided to assist translators in determining the position and order that is most appropriate for the target language. Information about the variable, such as type (integer, string or datetime), all possible values, and actual usage examples in English for each possible value, would help ensure better translations.