1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>45.2.For the Programmer</title>
<link rel="stylesheet" href="stylesheet.css" type="text/css">
<link rev="made" href="pgsql-docs@postgresql.org">
<meta name="generator" content="DocBook XSL Stylesheets V1.70.0">
<link rel="start" href="index.html" title="PostgreSQL 8.1.4 Documentation">
<link rel="up" href="nls.html" title="Chapter45.Native Language Support">
<link rel="prev" href="nls.html" title="Chapter45.Native Language Support">
<link rel="next" href="plhandler.html" title="Chapter46.Writing A Procedural Language Handler">
<link rel="copyright" href="ln-legalnotice.html" title="Legal Notice">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="sect1" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="nls-programmer"></a>45.2.For the Programmer</h2></div></div></div>
<div class="sect2" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="nls-mechanics"></a>45.2.1.Mechanics</h3></div></div></div>
<p> This section describes how to implement native language support in a
program or library that is part of the
<span class="productname">PostgreSQL</span> distribution.
Currently, it only applies to C programs.
</p>
<div class="procedure">
<a name="id840784"></a><p class="title"><b>Adding NLS support to a program</b></p>
<ol type="1">
<li>
<p> Insert this code into the start-up sequence of the program:
</p>
<pre class="programlisting">#ifdef ENABLE_NLS
#include <locale.h>
#endif
...
#ifdef ENABLE_NLS
setlocale(LC_ALL, "");
bindtextdomain("<em class="replaceable"><code>progname</code></em>", LOCALEDIR);
textdomain("<em class="replaceable"><code>progname</code></em>");
#endif</pre>
<p>
(The <em class="replaceable"><code>progname</code></em> can actually be chosen
freely.)
</p>
</li>
<li>
<p> Wherever a message that is a candidate for translation is found,
a call to <code class="function">gettext()</code> needs to be inserted. E.g.,
</p>
<pre class="programlisting">fprintf(stderr, "panic level %d\n", lvl);</pre>
<p>
would be changed to
</p>
<pre class="programlisting">fprintf(stderr, gettext("panic level %d\n"), lvl);</pre>
<p>
(<code class="symbol">gettext</code> is defined as a no-op if no NLS is
configured.)
</p>
<p> This may tend to add a lot of clutter. One common shortcut is to use
</p>
<pre class="programlisting">#define _(x) gettext(x)</pre>
<p>
Another solution is feasible if the program does much of its
communication through one or a few functions, such as
<code class="function">ereport()</code> in the backend. Then you make this
function call <code class="function">gettext</code> internally on all
input strings.
</p>
</li>
<li>
<p> Add a file <code class="filename">nls.mk</code> in the directory with the
program sources. This file will be read as a makefile. The
following variable assignments need to be made here:
</p>
<div class="variablelist"><dl>
<dt><span class="term"><code class="varname">CATALOG_NAME</code></span></dt>
<dd><p> The program name, as provided in the
<code class="function">textdomain()</code> call.
</p></dd>
<dt><span class="term"><code class="varname">AVAIL_LANGUAGES</code></span></dt>
<dd><p> List of provided translations [mdash ] initially empty.
</p></dd>
<dt><span class="term"><code class="varname">GETTEXT_FILES</code></span></dt>
<dd><p> List of files that contain translatable strings, i.e., those
marked with <code class="function">gettext</code> 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 “<span class="quote">file</span>” be a <code class="literal">+</code>
and the second word be a file that contains one file name per
line.
</p></dd>
<dt><span class="term"><code class="varname">GETTEXT_TRIGGERS</code></span></dt>
<dd><p> The tools that generate message catalogs for the translators
to work on need to know what function calls contain
translatable strings. By default, only
<code class="function">gettext()</code> calls are known. If you used
<code class="function">_</code> 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
<code class="literal">func:2</code> (for the second argument).
</p></dd>
</dl></div>
<p>
</p>
</li>
</ol>
</div>
<p> The build system will automatically take care of building and
installing the message catalogs.
</p>
</div>
<div class="sect2" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="nls-guidelines"></a>45.2.2.Message-writing guidelines</h3></div></div></div>
<p> Here are some guidelines for writing messages that are easily
translatable.
</p>
<div class="itemizedlist"><ul type="disc">
<li>
<p> Do not construct sentences at run-time, like
</p>
<pre class="programlisting">printf("Files were %s.\n", flag ? "copied" : "removed");</pre>
<p>
The word order within the sentence may be different in other
languages. Also, even if you remember to call gettext() on each
fragment, the fragments may not translate well separately. It's
better to duplicate a little code so that each message to be
translated is a coherent whole. Only numbers, file names, and
such-like run-time variables should be inserted at run time into
a message text.
</p>
</li>
<li>
<p> For similar reasons, this won't work:
</p>
<pre class="programlisting">printf("copied %d file%s", n, n!=1 ? "s" : "");</pre>
<p>
because it assumes how the plural is formed. If you figured you
could solve it like this
</p>
<pre class="programlisting">if (n==1)
printf("copied 1 file");
else
printf("copied %d files", n):</pre>
<p>
then be disappointed. Some languages have more than two forms,
with some peculiar rules. We may have a solution for this in
the future, but for now the matter is best avoided altogether.
You could write:
</p>
<pre class="programlisting">printf("number of copied files: %d", n);</pre>
<p>
</p>
</li>
<li>
<p> If you want to communicate something to the translator, such as
about how a message is intended to line up with other output,
precede the occurrence of the string with a comment that starts
with <code class="literal">translator</code>, e.g.,
</p>
<pre class="programlisting">/* translator: This message is not what it seems to be. */</pre>
<p>
These comments are copied to the message catalog files so that
the translators can see them.
</p>
</li>
</ul></div>
<p>
</p>
</div>
</div></body>
</html>
|