- Add a section about using POSIX NLS to internationalize programs
Reviewed by: rene, rwatson
This commit is contained in:
parent
3352ee7db1
commit
ac9abd3ad2
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=33987
1 changed files with 212 additions and 1 deletions
|
@ -58,4 +58,215 @@
|
|||
libraries. Please use them for I18N compliance.</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<sect1 id="posix-nls">
|
||||
<sect1info>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Gábor</firstname>
|
||||
<surname>Kövesdán</surname>
|
||||
<contrib>Contributed by </contrib>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</sect1info>
|
||||
|
||||
<title>Localized Messages with POSIX.1 Native Language Support (NLS)</title>
|
||||
|
||||
<para>Beyond the basic I18N functions, like supporting various input
|
||||
encodings or supporting national conventions, such as the different
|
||||
decimal separators, at a higher level of I18N, it is possible to localize the
|
||||
messages written to the output by the various programs. A common way of doing
|
||||
this is using the POSIX.1 NLS functions, which are provided as a part
|
||||
of the &os; base system.</para>
|
||||
|
||||
<sect2 id="nls-catalogs">
|
||||
<title>Organizing Localized Messages into Catalog Files</title>
|
||||
|
||||
<para>POSIX.1 NLS is based on catalog files, which contain the
|
||||
localized messages in the desired encoding. The messages are
|
||||
organized into sets and each message is identified by an integer
|
||||
number in the containing set. The catalog files are conventionally
|
||||
named after the locale they contain localized messages for, followed
|
||||
by the <literal>.msg</literal> extension. For instance, the
|
||||
Hungarian messages for ISO8859-2 encoding should be stored in a file
|
||||
called <filename>hu_HU.ISO8859-2</filename>.</para>
|
||||
|
||||
<para>These catalog files are common text files that contain the
|
||||
numbered messages. It is possible to write comments by starting
|
||||
the line with a <literal>$</literal> sign. Set boundaries are also separated by
|
||||
special comments, where the keyword <literal>set</literal> must
|
||||
directly follow the <literal>$</literal> sign. The <literal>set</literal> keyword
|
||||
is then followed by the set number. For example:</para>
|
||||
|
||||
<programlisting>$set 1</programlisting>
|
||||
|
||||
<para>The actual message entries start with the message number and
|
||||
followed by the localized message. The well-known
|
||||
modifiers from &man.printf.3; are accepted:</para>
|
||||
|
||||
<programlisting>15 "File not found: %s\n"</programlisting>
|
||||
|
||||
<para>The language catalog files have to be compiled into a binary
|
||||
form before they can be opened from the program. This conversion
|
||||
is done with the &man.gencat.1; utility. Its first argument is the
|
||||
filename of the compiled catalog and its further arguments are the
|
||||
input catalogs. The localized messages can also be organized into
|
||||
more catalog files and then all of them can be processed with
|
||||
&man.gencat.1;.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="nls-using">
|
||||
<title>Using the Catalog Files from the Source Code</title>
|
||||
|
||||
<para>Using the catalog files is simple. To use
|
||||
the related functions, <filename
|
||||
class="headerfile">nl_types.h</filename> must be included. Before
|
||||
using a catalog, it has to be opened with &man.catopen.3;.
|
||||
The function takes two arguments. The first parameter is the name of the
|
||||
installed and compiled catalog. Usually, the name of the
|
||||
program is used, such as <application>grep</application>.
|
||||
This name will be used when looking for the compiled
|
||||
catalog file. The &man.catopen.3; call looks for this file
|
||||
in <filename
|
||||
class="directory">/usr/share/nls/<replaceable>locale</replaceable>/<replaceable>catname</replaceable></filename>
|
||||
and in <filename
|
||||
class="directory">/usr/local/share/nls/<replaceable>locale</replaceable>/<replaceable>catname</replaceable></filename>,
|
||||
where <literal>locale</literal> is the locale set and
|
||||
<literal>catname</literal> is the catalog name being
|
||||
discussed. The second parameter is a constant, which can have
|
||||
two values:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><literal>NL_CAT_LOCALE</literal>, which means that
|
||||
the used catalog file will be based on
|
||||
<envar>LC_MESSAGES</envar>.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><literal>0</literal>, which means that
|
||||
<envar>LANG</envar> has to be used to open
|
||||
the proper catalog.</para>
|
||||
</itemizedlist>
|
||||
|
||||
<para>The &man.catopen.3; call returns a catalog identifier of
|
||||
type <literal>nl_catd</literal>. Please refer to the manual page for a list of possible returned error
|
||||
codes.</para>
|
||||
|
||||
<para>After opening a catalog &man.catgets.3; can be used to retrieve
|
||||
a message. The first parameter is the catalog identifier returned
|
||||
by &man.catopen.3;, the second one is the number of the set, the
|
||||
third one is the number of the messages, and the fourth one is a
|
||||
fallback message, which will be returned if the requested message
|
||||
cannot be retrieved from the catalog file.</para>
|
||||
|
||||
<para>After using the catalog file, it must be closed by calling
|
||||
&man.catclose.3;, which has one argument, the catalog id.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="nls-example">
|
||||
<title>A Practical Example</title>
|
||||
|
||||
<para>The following example will demonstrate an easy solution on how to
|
||||
use NLS catalogs in a flexible way.</para>
|
||||
|
||||
<para>The below lines need to be put into a common header file of
|
||||
the program, which is included into all source files where
|
||||
localized messages are necessary:</para>
|
||||
|
||||
<programlisting>
|
||||
#ifdef WITHOUT_NLS
|
||||
#define getstr(n) nlsstr[n]
|
||||
#else
|
||||
#include <nl_types.h>
|
||||
|
||||
extern nl_catd catalog;
|
||||
#define getstr(n) catgets(catalog, 1, n, nlsstr[n])
|
||||
#endif
|
||||
|
||||
extern char *nlsstr[];</programlisting>
|
||||
|
||||
<para>Next, put these lines into the global declaration part of the
|
||||
main source file:</para>
|
||||
|
||||
<programlisting>
|
||||
#ifndef WITHOUT_NLS
|
||||
#include <nl_types.h>
|
||||
nl_catd catalog;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Default messages to use when NLS is disabled or no catalog
|
||||
* is found.
|
||||
*/
|
||||
char *nlsstr[] = {
|
||||
"",
|
||||
/* 1*/ "some random message",
|
||||
/* 2*/ "some other message"
|
||||
};</programlisting>
|
||||
|
||||
<para>Next come the real code snippets, which open, read, and
|
||||
close the catalog:</para>
|
||||
|
||||
<programlisting>
|
||||
#ifndef WITHOUT_NLS
|
||||
catalog = catopen("myapp", NL_CAT_LOCALE);
|
||||
#endif
|
||||
|
||||
...
|
||||
|
||||
printf(getstr(1));
|
||||
|
||||
...
|
||||
|
||||
#ifndef WITHOUT_NLS
|
||||
catclose(catalog);
|
||||
#endif</programlisting>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="nls-mk">
|
||||
<title>Making use of <filename>bsd.nls.mk</filename></title>
|
||||
|
||||
<para>Using the catalog files requires few repeatable steps,
|
||||
such as compiling the catalogs and installing them to the
|
||||
proper location. In order to simplify this process even
|
||||
more, <filename>bsd.nls.mk</filename> introduces some macros.
|
||||
It is not necessary to include <filename>bsd.nls.mk</filename>
|
||||
explicitly, it is pulled in from the common Makefiles,
|
||||
such as <filename>bsd.prog.mk</filename> or
|
||||
<filename>bsd.lib.mk</filename>.</para>
|
||||
|
||||
<para>Usually it is enough to define <makevar>NLSNAME</makevar>,
|
||||
which should have the catalog name mentioned as the first
|
||||
argument of &man.catopen.3; and list the catalog files in
|
||||
<makevar>NLS</makevar> without their <literal>.msg</literal>
|
||||
extension. Here is an example, which makes it possible to
|
||||
to disable NLS when used with the code examples before.
|
||||
The <makevar>WITHOUT_NLS</makevar> &man.make.1; variable has
|
||||
to be defined in order to build the program without NLS
|
||||
support.</para>
|
||||
|
||||
<programlisting>
|
||||
.if !defined(WITHOUT_NLS)
|
||||
NLS= es_ES.ISO8859-1
|
||||
NLS+= hu_HU.ISO8859-2
|
||||
NLS+= pt_BR.ISO8859-1
|
||||
.else
|
||||
CFLAGS+= -DWITHOUT_NLS
|
||||
.endif</programlisting>
|
||||
|
||||
<para>Conventionally, the catalog files are placed under the
|
||||
<filename class="directory">nls</filename> subdirectory and
|
||||
this is the default behaviour of <filename>bsd.nls.mk</filename>.
|
||||
It is possible, though to override the location of the
|
||||
catalogs with the <makevar>NLSSRCDIR</makevar> &man.make.1;
|
||||
variable. The default name of the precompiled catalog files
|
||||
also follow the naming convention mentioned before. It can be
|
||||
overriden by setting the <makevar>NLSNAME</makevar> variable.
|
||||
There are other options to fine tune the processing of the catalog
|
||||
files but usually it is not needed, thus they are not described
|
||||
here. For further information on <filename>bsd.nls.mk</filename>,
|
||||
please refer to the file itself, it is short and easy to
|
||||
understand.</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
|
Loading…
Reference in a new issue