[ Next Article | Previous Article | Book Contents | Library Home | Legal | Search ]
General Programming Concepts: Writing and Debugging Programs

Message Facility Overview for Programming

To facilitate translations of messages into various languages and make them available to a program based on a user's locale, it is necessary to keep messages separate from the program by providing them in the form of message catalogs that the program can access at run time. To aid in this task, commands and subroutines are provided by the Message Facility.

Message source files containing application messages are created by the programmer and converted to message catalogs. The application uses these catalogs to retrieve and display messages, as needed. Translating message source files into other languages and then converting the files to message catalogs does not require changing and recompiling a program.

The following information is provided for understanding the Message Facility:

Creating a Message Source File

The Message Facility provides commands and subroutines to retrieve and display program messages located in externalized message catalogs. A programmer creates a message source file containing application messages and converts it to a message catalog with the gencat command.

To create a message-text source file, open a file using any text editor. Enter a message identification number or symbolic identifier. Then enter the message text as shown in the following example:

1 message-text   $       (This message is numbered)
2 message-text   $       (This message is numbered)
OUTMSG message-text  $   (This message has a symbolic identifier \
                          called OUTMSG)
4 message-text   $       (This message is numbered)

Usage Considerations

Consider the following:

Adding Comments to the Message Source File

You can include a comment anywhere in a message source file except within message text. Leave at least one space or tab (blank) after the $ (dollar sign). The following is an example of a comment:

$ This is a comment.

Comments do not appear in the message catalog generated from the message source file.

Comments can help developers in the process of maintaining message source files, translators in the process of translation, and writers in the process of editing and documenting messages. Use comments to identify what variables, such as %s, %c, and %d, represent. For example, create a note that states whether the variable refers to a user, file, directory, or flag. Comments also should be used to identify obsolete messages.

For clarity, you should place a comment line directly beneath the message to which it refers, rather than at the bottom of the message catalog. Global comments for an entire set can be placed directly below the $set directive.

Continuing Messages on the Next Line

All text following the blank after the message number is included as message text, up to the end of the line. Use the escape character \ (backslash) to continue message text on the following line. The \ (backslash) must be the last character on the line as in the following example:

5 This is the text associated with \
message number 5.

These two physical lines define the single-line message:

This is the text associated with message number 5.
Note: The use of more than one blank character after the message number or symbolic identifier is specific to the Message Facility. Portability of message source files can be affected by the use of more than one blank.

Including Special Characters in the Message Text

The \ (backslash) can be used to insert special characters into the message text. These special characters are:

\n Inserts a new-line character.
\t Inserts a horizontal tab character.
\v Inserts a vertical tab character.
\b Inserts a backspace character.
\r Inserts a carriage-return character.
\f Inserts a form-feed character.
\\ Inserts a \ (backslash) character.
\ddd Inserts a single-byte character associated with the octal value represented by the valid octal digits ddd.
Note: One, two, or three octal digits can be specified. However, you must include a leading zero if the characters following the octal digits are also valid octal digits. For example, the octal value for $ (dollar sign) is 44. To display $5.00, use \0445.00, not \445.00, or the 5 will be parsed as part of the octal value.
\xdd Inserts a single-byte character associated with the hexadecimal value represented by the two valid hexadecimal digits dd. You must include a leading zero to avoid parsing errors (see the note about \ddd).
\xdddd Inserts a double-byte character associated with the hexadecimal value represented by the four valid hexadecimal digits dddd. You must include a leading zero to avoid parsing errors (see the note about \ddd).

Defining a Character to Delimit Message Text

You can use the $quote directive in a message source file to define a character for delimiting message text. This character should be an ASCII character. The format is:

$quote [character] [comment]

Use the specified character before and after the message text. In the following example, the $quote directive sets the quote character to _ (underscore), and then disables it before the last message, which contains quotation marks:

$quote _   Use an underscore to delimit message text
$set MSFAC         Message Facility - symbolic identifiers
SYM_FORM   _Symbolic identifiers can contain alphanumeric \
characters or the \_ (underscore character)\n_
SYM_LEN    _Symbolic identifiers can be up to 65 \
characters long \n_
5              _You can mix symbolic identifiers and numbers \n_
$quote
MSG_H     Remember to include the _msg_h_ file in your program\n

The last $quote directive in the previous example disables the underscore character.

In the following example, the $quote directive defines " (double quotation marks) as the quote character. The quote character must be the first non-blank character following the message number. Any text following the next occurrence of the quote character is ignored.

$quote "   Use a double quote to delimit message text
$set 10            Message Facility - Quote command messages
1   "Use the $quote directive to define a character \
\n for delimiting message text"
2   "You can include the \"quote\" character in a message \n \
by placing a \\ in front of it"
3   You can include the "quote" character in a message \n \
by having another character as the first nonblank \
\n character after the message ID number
$quote
4   You can disable the quote mechanism by \n \
using the $quote directive without a character \n\
after it

This example illustrates two ways the quote character can be included in message text:

The example also shows the following:

Assigning Message Set Numbers and Message ID Numbers

All message sets require a set number or symbolic identifier. Use the $set directive in a source file to give a group of messages a number or identifier:

$set n [ comment ]

The message set number is specified by the value of n, a number between 1 and NL_SETMAX . Instead of a number, you can use a symbolic identifier. All messages following the $set directive are assigned to that set number until the next occurrence of a $set directive. The default set number is 1. Set numbers must be assigned in ascending order, but need not be in series. Empty sets are created for skipped numbers. However, large gaps in the number sequence decrease efficiency and performance. Moreover, performance is not enhanced by using more than one set number in a catalog.

You can also include a comment in the $set directive, as follows:

$set 10  Communication Error Messages
$set OUTMSGS  Output Error Messages

Many AIX message sets have a symbolic identifier of the form MS_PROG, where MS represents Message Set and PROG is the name of the program or utility related to the message set. For example:

$set MS_WC  Message Set for the wc Utility
$set MS_XLC1  Message Set 1 for the C For AIX compiler
$set MS_XLC2  Message Set 2 for the C For AIX compiler

Removing Messages from a Catalog

The $delset directive removes all of the messages belonging to a specified set from an existing catalog:

$delset n [ comment ]

The message set is specified by n. The $delset directive must be placed in the proper set-number order with respect to any $set directives in the same source file. You can also include a comment in the $delset directive.

Length of Message Text

The $len directive establishes the maximum display length of message text:

$len [ n [ comment ] ]

If n is not specified or if the $len directive is not included, the message text display is set to the NL_TEXTMAX value. The message-text display length is the maximum number of bytes allowed for a message. Any subsequent specification of a $len directive overrides a previous specification. The value of n cannot exceed the NL_TEXTMAX value.

Content of Message Text

Cause and Recovery Information

Whenever possible, tell users exactly what has happened and what they can do to remedy the situation. The following example shows how cause and recovery information can improve a message:

Original  Message:   Bad arg
Revised Message:   Specify year as a value between 1 and 9999.

The message Bad arg does not help users much; whereas the message Do not specify more than 2 files on the command line tells users exactly what they must do to make the command work. Similarly, the message Line too long does not give users recovery information. The message Line cannot exceed 20 characters provides the missing information.

Examples of Message Source Files

  1. The following example message source file uses numbers for message ID numbers and for message set numbers:
    $ This is a message source file sample.
    $ Define the Quote Character.
    $quote "
    $set 1 This is the set 1 of messages.
    1 "The specified file does not have read permission on/n"
    2 "The %1$s file and the %2$s file are same/n"
    3 "Hello world!/n"
    $Define the quote character
    $quote '
    $set 2 This is the set 2 of messages
    1       'fieldef: Cannot open %1$s /n'
    2       'Hello world/n'
  2. The following example message source file uses symbolic identifiers for message ID numbers and for message set numbers:
    $ This is a message source file sample.
    $ Define the Quote Character.
    $quote "
    $set MS_SET1 This is the set 1 of messages.
    MSG_1   "The specified file does not have read permission on/n"
    MSG_2   "The %1$s file and the %2$s file are same/n"
    MSG_3   "Hello world/n"
    $Define the quote character
    $quote
    $set 2 This is the set 2 of messages.
    $EMSG_1 'fieldef: Cannot open %1$s/n'
    $EMSG_2 'Hello world!/n'
  3. The following examples show how symbolic identifiers can make the specification of a message more understandable:
    catgets(cd, 1, 1, "default message")
    catgets(cd, MS_SET1, MSG_1, "default message")

Creating a Message Catalog

The Message Facility provides commands and subroutines to retrieve and display program messages located in externalized message catalogs. A programmer creates a message source file containing application messages and converts it to a message catalog. Translating message source files into other languages and then converting the files to message catalogs does not require changing or recompiling a program.

To create a message catalog, process your completed message source file with the message facility's gencat command. This command can be used three ways:

The preceding example is equivalent to the following example:

mkcatdefs x x.msg | gencat x.cat

If a message catalog with the name specified by the CatalogFile parameter exists, the gencat command modifies the catalog according to the statements in the message source files. If a message catalog does not exist, the gencat command creates a catalog file with the name specified by the CatalogFile parameter.

You can specify any number of message text source files. Multiple files are processed in the sequence you specify. Each successive source file modifies the catalog. If you do not specify a source file, the gencat command accepts message source data from standard input.

Catalog Sizing

A message catalog can be virtually any size. The maximum numbers of sets in a catalog, messages in a catalog, and bytes in a message are defined in the /usr/include/limits.h file by the following macros:

NL_SETMAX Specifies the maximum number of set numbers that can be specified by the $set directive. If the NL_SETMAX limit is exceeded, the gencat command issues an error message and does not create or update the message catalog.
NL_MSGMAX Specifies the maximum number of message ID numbers allowed by the system. If the NL_MSGMAX limit is exceeded, the gencat command issues an error message and does not create or update the message catalog.
NL_TEXTMAX Specifies the maximum number of bytes a message can contain. If the NL_TEXTMAX limit is exceeded, the gencat command issues an error message and does not create or update the message catalog.

Examples

  1. This example shows how to create a message catalog from a source file containing message identification numbers. The following is the text of the hello.msg message source file:
    $ file: hello.msg
    $set 1    prompts
    1 Please, enter your name.
    2 Hello, %s \n
    $ end of file: hello.msg
    To create the hello.cat message catalog from the hello.msg source file, enter:
    gencat hello.cat hello.msg
  2. This example shows how to create a message catalog from a source file with symbolic references. The following is the text of the hello.msg message source file that contains symbolic references to the message set and the messages:
    $ file: hello.msg
    $quote "
    $set PROMPTS
    PLEASE  "Please, enter your name."
    HELLO   "Hello, %s \n"
    $ end of file: hello.msg
    The following is the text of the msgerrs.msg message source file that contains error messages that can be referenced by their symbolic IDs:
    $ file: msgerrs.msg
    $quote "
    $set CAT_ERRORS
    MAXOPEN  "Cannot open message catalog %s \n \
    Maximum number of catalogs already open "
    NOT_EX "File %s not executable \n "
    $set MSG_ERRORS
    NOT_FOUND "Message %1$d, Set %2$d not found \n "
    $ end of file: msgerrs.msg
    To process the hello.msg and msgerrs message source files, enter:
    runcat hello hello.msg
    runcat msgerrs msgerrs.msg /usr/lib/nls/msg/$LANG/msgerrs.cat
    The runcat command invokes the mkcatdefs and gencat commands . The first call to the runcat command takes the hello.msg source file and uses the second parameter, hello, to produce the hello.cat message catalog and the hello_msg.h definition file.

    The hello_msg.h definition file contains symbolic names for the message catalog and symbolic IDs for the messages and sets. The symbolic name for the hello.cat message catalog is MF_HELLO. This name is produced automatically by the mkcatdefs command.

    The second call to the runcat command takes the msgerrs.msg source file and uses the first parameter, msgerrs, to produce the msgerrs_msg.h definition file.

    Since the third parameter, /usr/lib/nls/msg/$LANG/msgerrs.cat, is present, the runcat command uses this parameter for the catalog file name. This parameter is an absolute path name that specifies exactly where the runcat command must put the file. The symbolic name for the msgerrs.cat catalog is MF_MSGERRS.

Displaying Messages outside of an Application Program

The following commands allow you to display messages outside of an application program. These commands are specific to AIX.

dspcat Displays the messages contained in the specified message catalog. The following example displays the messages located in the x.cat message source file:
dspcat x.cat
dspmsg Displays a single message from a message catalog. The following example displays the message located in the x.cat message source file that has the ID number of 1 and the set number of 2:
dspmsg x.cat -s 2 1

You can use the dspmsg command in shell scripts when a message must be obtained from a message catalog.

Displaying Messages with an Application Program

When programming with the Message Facility, you must include the following items in your application program:

The following subroutines provide the services necessary for displaying program messages with the message facility:

setlocale Sets the locale. Specify the LC_ALL or LC_MESSAGES environment variable in the call to the setlocale subroutine for the preferred message catalog language.
catopen Opens a specified message catalog and returns a catalog descriptor, which you use to retrieve messages from the catalog.
catgets Retrieves a message from a catalog after a successful call to the catopen subroutine.
printf Converts, formats, and writes to the stdout (standard output) stream.
catclose Closes a specified message catalog.

The following C program , hello, illustrates opening the hello.cat catalog with the catopen subroutine, retrieving messages from the catalog with the catgets subroutine, displaying the messages with the printf subroutine, and closing the catalog with the catclose subroutine.

/* program: hello */
#include <nl_types.h>
#include <locale.h>
nl_catd catd;
main()
{
/*  initialize the locale  */
setlocale (LC_ALL, "");
/* open the catalog */
catd=catopen("hello.cat",NL_CAT_LOCALE);
printf(catgets(catd,1,1,"Hello World!"));
catclose(catd);                     /* close the catalog */
exit(0);
}

In the previous example, the catopen subroutine refers to the hello.cat message catalog only by file name. Therefore, you must make sure that the NLSPATH environment variable is set correctly. If the message catalog is successfully opened by the catopen subroutine, the catgets subroutine returns a pointer to the specified message in the hello.cat catalog. If the message catalog is not found or the message does not exist in the catalog, the catgets subroutine returns the Hello World! default string.

Understanding the NLSPATH Environment Variable

The NLSPATH environment variable specifies the directories to search for message catalogs. The catopen subroutine searches these directories in the order specified when called to locate and open a message catalog. If the message catalog is not found, the message-retrieving routine returns the program-supplied default message. See the /etc/environment file for the NLSPATH default path.

Retrieving Program-Supplied Default Messages

All message-retrieving routines return the program-supplied default message text if the desired message cannot be retrieved for any reason. Program-supplied default messages are generally brief one-line messages that contain no message numbers in the text. Users who prefer these default messages can set the LC_MESSAGES category to the C locale or unset the NLSPATH environment variable. When none of the LC_ALL , LC_MESSAGES , or LANG environment variables are set, the LC_MESSAGES category defaults to the C locale.

Setting the Language Hierarchy

Multilingual users may specify a language hierarchy for message text. To set the language hierarchy for the system default or for an individual user, see the chlang command, "Changing the Language Environment" in AIX Version 4.3 System Management Guide: Operating System and Devices or use the System Management Interface Tool (SMIT). To use SMIT to set the language hierarchy, enter the SMIT fast path

smit mlang 

at the command line.

Select Change / Show Language Hierarchy

OR

At the command line, enter:

smit

Select System Environments

Select Manage Language Environment

Select Change / Show Language Hierarchy

Example of Retrieving a Message from a Catalog

This example has three parts: the message source file, the command used to generate the message catalog file, and an example program using the message catalog.

  1. The following example shows the example.msg message source file:
    $quote "
    $ every message catalog should have a beginning set number.
    $set MS_SET1
    MSG1 "Hello world\n"
    MSG2 "Good Morning\n"
    ERRMSG1 "example: 1000.220 Read permission is denied for the file
    %s.\n"
    $set MS_SET2
    MSG3 "Howdy\n"
  2. The following command uses the example.msg message source file to generate the example.h header file and the example.cat catalog file in the current directory:
    runcat example example.msg
  3. The following example program uses the example.h header file and accesses the example.cat catalog file:
    #include <locale.h>
    #include <nl_types.h>
    #include "example_msg.h" /*contains definitions for symbolic
                               identifiers*/
    main()
    {
            nl_catd catd;
            int error;
      
            (void)setlocale(LC_ALL, "");
      
            catd = catopen(MF_EXAMPLE, NL_CAT_LOCALE);
            /*
            ** Get the message number 1 from the first set.
            */
            printf( catgets(catd,MS_SET1,MSG1,"Hello world\n") );
      
            /*
            ** Get the message number 1 from the second set.
            */
            printf( catgets(catd, MS_SET2, MSG3,"Howdy\n") );
            /*
            ** Display an error message.
            */
            printf( catgets(catd, MS_SET1, ERRMSG1,"example: 100.220
                    Permission is denied to read the file %s.\n") ,
                    filename);
            catclose(catd);
    }

Related Information

National Language Support Overview for Programming, Message Facility Overview for Programming, Creating a Message Source File, Creating a Message Catalog, List of National Language Support Subroutines.

Changing the Language Environment in AIX Version 4.3 System Management Guide: Operating System and Devices.

The chlang command, dspcat command, dspmsg command, gencat command, lslpp command, mkcatdefs command, runcat command.

The environment file.

The catclose subroutine, catgets subroutine, catopen subroutine, printf subroutine.


[ Next Article | Previous Article | Book Contents | Library Home | Legal | Search ]