are that English
speaking end users might also not understand it or find it
ambiguous, so it's best to improve the message.
</para>
</listitem>
</itemizedlist>
</para>
</sect2>
</sect1>
<sect1 id="nls-programmer">
<title>For the Programmer</title>
<sect2 id="nls-mechanics">
<title>Mechanics</title>
<para>
This section describes how to implement native language support in a
program or library that is part of the
<productname>PostgreSQL</productname> distribution.
Currently, it only applies to C programs.
</para>
<procedure>
<title>Adding NLS Support to a Program</title>
<step>
<para>
Insert this code into the start-up sequence of the program:
<programlisting>
#ifdef ENABLE_NLS
#include <locale.h>
#endif
...
#ifdef ENABLE_NLS
setlocale(LC_ALL, "");
bindtextdomain("<replaceable>progname</replaceable>", LOCALEDIR);
textdomain("<replaceable>progname</replaceable>");
#endif
</programlisting>
(The <replaceable>progname</replaceable> can actually be chosen
freely.)
</para>
</step>
<step>
<para>
Wherever a message that is a candidate for translation is found,
a call to <function>gettext()</function> needs to be inserted. E.g.:
<programlisting>
fprintf(stderr, "panic level %d\n", lvl);
</programlisting>
would be changed to:
<programlisting>
fprintf(stderr, gettext("panic level %d\n"), lvl);
</programlisting>
(<symbol>gettext</symbol> is defined as a no-op if NLS support is
not configured.)
</para>
<para>
This tends to add a lot of clutter. One common shortcut is to use:
<programlisting>
#define _(x) gettext(x)
</programlisting>
Another solution is feasible if the program does much of its
communication through one or a few functions, such as
<function>ereport()</function> in the backend. Then you make this
function call <function>gettext</function> internally on all
input strings.
</para>
</step>
<step>
<para>
Add a file <filename>nls.mk</filename> in the directory with the
program sources. This file will be read as a makefile. The
following variable assignments need to be made here:
<variablelist>
<varlistentry>
<term><varname>CATALOG_NAME</varname></term>
<listitem>
<para>
The program name, as provided in the
<function>textdomain()</function> call.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>GETTEXT_FILES</varname></term>
<listitem>
<para>
List of files that contain translatable strings, i.e., those
marked with <function>gettext</function> or an alternative
solution. Eventually, this will include nearly all source
files of the program. If this list gets too long you can
make the first <quote>file</quote> be a <literal>+</literal>
and the second word be a file that contains one file name per
line.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>GETTEXT_TRIGGERS</varname></term>
<listitem>
<para>
The tools that generate message catalogs for the translators
to work on need to know what function calls contain
translatable strings. By default, only
<function>gettext()</function> calls are known. If you used
<function>_</function> or other identifiers you need to list
them here. If the translatable string is not the first
argument, the item needs to be of the form
<literal>func:2</literal> (for the second argument).
If you have a function that supports pluralized messages,
the item should look like <literal>func:1,2</literal>
(identifying the singular and plural message arguments).
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</step>