|
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>54.2. For the Programmer</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets V1.79.1" /><link rel="prev" href="nls-translator.html" title="54.1. For the Translator" /><link rel="next" href="plhandler.html" title="Chapter 55. Writing a Procedural Language Handler" /></head><body><div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">54.2. For the Programmer</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="nls-translator.html" title="54.1. For the Translator">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="nls.html" title="Chapter 54. Native Language Support">Up</a></td><th width="60%" align="center">Chapter 54. Native Language Support</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 12.4 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="plhandler.html" title="Chapter 55. Writing a Procedural Language Handler">Next</a></td></tr></table><hr></hr></div><div class="sect1" id="NLS-PROGRAMMER"><div class="titlepage"><div><div><h2 class="title" style="clear: both">54.2. For the Programmer</h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="nls-programmer.html#NLS-MECHANICS">54.2.1. Mechanics</a></span></dt><dt><span class="sect2"><a href="nls-programmer.html#NLS-GUIDELINES">54.2.2. Message-Writing Guidelines</a></span></dt></dl></div><div class="sect2" id="NLS-MECHANICS"><div class="titlepage"><div><div><h3 class="title">54.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" id="id-1.10.7.3.2.3"><p class="title"><strong>Adding NLS Support to a Program</strong></p><ol class="procedure" type="1"><li class="step"><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 class="step"><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 NLS support is
- not configured.)
- </p><p>
- This tends 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 class="step"><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 class="variablelist"><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 — 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">“<span class="quote">file</span>”</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).
- If you have a function that supports pluralized messages,
- the item should look like <code class="literal">func:1,2</code>
- (identifying the singular and plural message arguments).
- </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" id="NLS-GUIDELINES"><div class="titlepage"><div><div><h3 class="title">54.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 class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><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 might be different in other
- languages. Also, even if you remember to call <code class="function">gettext()</code> on
- each fragment, the fragments might 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 class="listitem"><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. It's often best to design the message
- to avoid the issue altogether, for instance like this:
- </p><pre class="programlisting">
- printf("number of copied files: %d", n);
- </pre><p>
- </p><p>
- If you really want to construct a properly pluralized message,
- there is support for this, but it's a bit awkward. When generating
- a primary or detail error message in <code class="function">ereport()</code>, you can
- write something like this:
- </p><pre class="programlisting">
- errmsg_plural("copied %d file",
- "copied %d files",
- n,
- n)
- </pre><p>
- The first argument is the format string appropriate for English
- singular form, the second is the format string appropriate for
- English plural form, and the third is the integer control value
- that determines which plural form to use. Subsequent arguments
- are formatted per the format string as usual. (Normally, the
- pluralization control value will also be one of the values to be
- formatted, so it has to be written twice.) In English it only
- matters whether <em class="replaceable"><code>n</code></em> is 1 or not 1, but in other
- languages there can be many different plural forms. The translator
- sees the two English forms as a group and has the opportunity to
- supply multiple substitute strings, with the appropriate one being
- selected based on the run-time value of <em class="replaceable"><code>n</code></em>.
- </p><p>
- If you need to pluralize a message that isn't going directly to an
- <code class="function">errmsg</code> or <code class="function">errdetail</code> report, you have to use
- the underlying function <code class="function">ngettext</code>. See the gettext
- documentation.
- </p></li><li class="listitem"><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><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="nls-translator.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="nls.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="plhandler.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">54.1. For the Translator </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 55. Writing a Procedural Language Handler</td></tr></table></div></body></html>
|