summaryrefslogtreecommitdiff
path: root/doc/user/gettext.xml
diff options
context:
space:
mode:
Diffstat (limited to 'doc/user/gettext.xml')
-rw-r--r--doc/user/gettext.xml334
1 files changed, 334 insertions, 0 deletions
diff --git a/doc/user/gettext.xml b/doc/user/gettext.xml
new file mode 100644
index 0000000..ebaf3c0
--- /dev/null
+++ b/doc/user/gettext.xml
@@ -0,0 +1,334 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+ The &t-link-gettext; toolset supports internationalization and localization
+ of SCons-based projects. Builders provided by &t-link-gettext; automatize
+ generation and updates of translation files. You can manage translations and
+ translation templates similarly to how it's done with autotools.
+ </para>
+
+ <section>
+ <title>Prerequisites</title>
+ <para>
+ To follow examples provided in this chapter set up your operating system to
+ support two or more languages. In following examples we use locales
+ <literal>en_US</literal>, <literal>de_DE</literal>, and
+ <literal>pl_PL</literal>.
+ </para>
+
+ <para>
+ Ensure, that you have <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext
+ utilities</ulink> installed on your system.
+ </para>
+
+ <para>
+ To edit translation files you may wish to install <ulink url="http://www.poedit.net/">poedit</ulink> editor.
+ </para>
+ </section>
+
+ <section>
+ <title>Simple project</title>
+ <para>
+ Let's start with a very simple project, the "Hello world" program
+ for example
+ <programlisting>
+ /* hello.c */
+ #include &lt;stdio.h&gt;
+ int main(int argc, char* argv[])
+ {
+ printf("Hello world\n");
+ return 0;
+ }
+ </programlisting>
+
+ Prepare a <filename>SConstruct</filename> to compile the program
+ as usual.
+ <programlisting>
+ # SConstruct
+ env = Environment()
+ hello = Program(["hello.c"])
+ </programlisting>
+ </para>
+
+ <para>
+ Now we'll convert the project to a multi-lingual one. If you don't
+ already have <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext
+ utilities</ulink> installed, install them from your preffered
+ package repository, or download from <ulink url="http://ftp.gnu.org/gnu/gettext/">
+ http://ftp.gnu.org/gnu/gettext/</ulink>. For the purpose of this example,
+ you should have following three locales installed on your system:
+ <literal>en_US</literal>, <literal>de_DE</literal> and
+ <literal>pl_PL</literal>. On debian, for example, you may enable certain
+ locales through <command>dpkg-reconfigure locales</command>.
+ </para>
+
+ <para>
+ First prepare the <filename>hello.c</filename> program for
+ internationalization. Change the previous code so it reads as follows:
+ <programlisting>
+ /* hello.c */
+ #include &lt;stdio.h&gt;
+ #include &lt;libintl.h&gt;
+ #include &lt;locale.h&gt;
+ int main(int argc, char* argv[])
+ {
+ bindtextdomain("hello", "locale");
+ setlocale(LC_ALL, "");
+ textdomain("hello");
+ printf(gettext("Hello world\n"));
+ return 0;
+ }
+ </programlisting>
+ Detailed recipes for such conversion can
+ be found at <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html#Sources">
+ http://www.gnu.org/software/gettext/manual/gettext.html#Sources</ulink>.
+ The <function>gettext("...")</function> has two purposes.
+ First, it marks messages for the <command>xgettext(1)</command> program, which
+ we will use to extract from the sources the messages for localization.
+ Second, it calls the <literal>gettext</literal> library internals to
+ translate the message at runtime.
+ </para>
+
+ <para>
+ Now we shall instruct SCons how to generate and maintain translation files.
+ For that, use the &b-link-Translate; builder and &b-link-MOFiles; builder.
+ The first one takes source files, extracts internationalized
+ messages from them, creates so-called <literal>POT</literal> file
+ (translation template), and then creates <literal>PO</literal> translation
+ files, one for each requested language. Later, during the development
+ lifecycle, the builder keeps all these files up-to date. The
+ &b-link-MOFiles; builder compiles the <literal>PO</literal> files to binary
+ form. Then install the <literal>MO</literal> files under directory
+ called <filename>locale</filename>.
+ </para>
+
+ <para> The completed
+ <filename>SConstruct</filename> is as follows:
+ <programlisting>
+ # SConstruct
+ env = Environment( tools = ['default', 'gettext'] )
+ hello = env.Program(["hello.c"])
+ env['XGETTEXTFLAGS'] = [
+ '--package-name=%s' % 'hello',
+ '--package-version=%s' % '1.0',
+ ]
+ po = env.Translate(["pl","en", "de"], ["hello.c"], POAUTOINIT = 1)
+ mo = env.MOFiles(po)
+ InstallAs(["locale/en/LC_MESSAGES/hello.mo"], ["en.mo"])
+ InstallAs(["locale/pl/LC_MESSAGES/hello.mo"], ["pl.mo"])
+ InstallAs(["locale/de/LC_MESSAGES/hello.mo"], ["de.mo"])
+ </programlisting>
+ </para>
+ <para>
+ Generate the translation files with <command>scons po-update</command>.
+ You should see the output from SCons simillar to this:
+ <screen>
+ user@host:$ scons po-update
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ Entering '/home/ptomulik/projects/tmp'
+ xgettext --package-name=hello --package-version=1.0 -o - hello.c
+ Leaving '/home/ptomulik/projects/tmp'
+ Writting 'messages.pot' (new file)
+ msginit --no-translator -l pl -i messages.pot -o pl.po
+ Created pl.po.
+ msginit --no-translator -l en -i messages.pot -o en.po
+ Created en.po.
+ msginit --no-translator -l de -i messages.pot -o de.po
+ Created de.po.
+ scons: done building targets.
+ </screen>
+ </para>
+
+ <para>
+ If everything is right, you should see following new files.
+ <screen>
+ user@host:$ ls *.po*
+ de.po en.po messages.pot pl.po
+ </screen>
+ </para>
+
+ <para>
+ Open <filename>en.po</filename> in <command>poedit</command> and provide
+ the English translation to message <literal>"Hello world\n"</literal>. Do the
+ same for <filename>de.po</filename> (deutsch) and
+ <filename>pl.po</filename> (polish). Let the translations be, for example:
+ <itemizedlist>
+ <listitem><para>
+ <literal>en: "Welcome to beautiful world!\n"</literal>
+ </para></listitem>
+ <listitem><para>
+ <literal>de: "Hallo Welt!\n"</literal>
+ </para></listitem>
+ <listitem><para>
+ <literal>pl: "Witaj swiecie!\n"</literal>
+ </para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Now compile the project by executing <command>scons</command>. The
+ output should be similar to this:
+ <screen>
+ user@host:$ scons
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ msgfmt -c -o de.mo de.po
+ msgfmt -c -o en.mo en.po
+ gcc -o hello.o -c hello.c
+ gcc -o hello hello.o
+ Install file: "de.mo" as "locale/de/LC_MESSAGES/hello.mo"
+ Install file: "en.mo" as "locale/en/LC_MESSAGES/hello.mo"
+ msgfmt -c -o pl.mo pl.po
+ Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo"
+ scons: done building targets.
+ </screen>
+ SCons automatically compiled the <literal>PO</literal> files to binary format
+ <literal>MO</literal>, and the <literal>InstallAs</literal> lines installed
+ these files under <filename>locale</filename> folder.
+ </para>
+ <para>
+ Your program should be now ready. You may try it as follows (linux):
+ <screen>
+ user@host:$ LANG=en_US.UTF-8 ./hello
+ Welcome to beautiful world
+ </screen>
+ <screen>
+ user@host:$ LANG=de_DE.UTF-8 ./hello
+ Hallo Welt
+ </screen>
+ <screen>
+ user@host:$ LANG=pl_PL.UTF-8 ./hello
+ Witaj swiecie
+ </screen>
+ </para>
+ <para>
+ To demonstrate the further life of translation files, let's change Polish
+ translation (<command>poedit pl.po</command>) to <literal>"Witaj drogi
+ swiecie\n"</literal>. Run <command>scons</command> to see how scons
+ reacts to this
+ <screen>
+ user@host:$scons
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ msgfmt -c -o pl.mo pl.po
+ Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo"
+ scons: done building targets.
+ </screen>
+ </para>
+ <para>
+ Now, open <filename>hello.c</filename> and add another one
+ <literal>printf</literal> line with new message.
+ <programlisting>
+ /* hello.c */
+ #include &lt;stdio.h&gt;
+ #include &lt;libintl.h&gt;
+ #include &lt;locale.h&gt;
+ int main(int argc, char* argv[])
+ {
+ bindtextdomain("hello", "locale");
+ setlocale(LC_ALL, "");
+ textdomain("hello");
+ printf(gettext("Hello world\n"));
+ printf(gettext("and good bye\n"));
+ return 0;
+ }
+ </programlisting>
+ </para>
+ <para>
+ Compile project with <command>scons</command>. This time, the
+ <command>msgmerge(1)</command> program is used by SCons to update
+ <literal>PO</literal> file. The output from compilation is like:
+ <screen>
+ user@host:$scons
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ Entering '/home/ptomulik/projects/tmp'
+ xgettext --package-name=hello --package-version=1.0 -o - hello.c
+ Leaving '/home/ptomulik/projects/tmp'
+ Writting 'messages.pot' (messages in file were outdated)
+ msgmerge --update de.po messages.pot
+ ... done.
+ msgfmt -c -o de.mo de.po
+ msgmerge --update en.po messages.pot
+ ... done.
+ msgfmt -c -o en.mo en.po
+ gcc -o hello.o -c hello.c
+ gcc -o hello hello.o
+ Install file: "de.mo" as "locale/de/LC_MESSAGES/hello.mo"
+ Install file: "en.mo" as "locale/en/LC_MESSAGES/hello.mo"
+ msgmerge --update pl.po messages.pot
+ ... done.
+ msgfmt -c -o pl.mo pl.po
+ Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo"
+ scons: done building targets.
+ </screen>
+ </para>
+ <para>
+ The next example demonstrates what happens if we change the source code
+ in such way that the internationalized messages do not change. The answer
+ is that none of translation files (<literal>POT</literal>,
+ <literal>PO</literal>) are touched (i.e. no content changes, no
+ creation/modification time changed and so on). Let's append another
+ line to the program (after the last printf), so its code becomes:
+ <programlisting>
+ /* hello.c */
+ #include &lt;stdio.h&gt;
+ #include &lt;libintl.h&gt;
+ #include &lt;locale.h&gt;
+ int main(int argc, char* argv[])
+ {
+ bindtextdomain("hello", "locale");
+ setlocale(LC_ALL, "");
+ textdomain("hello");
+ printf(gettext("Hello world\n"));
+ printf(gettext("and good bye\n"));
+ printf("----------------\n");
+ return a;
+ }
+ </programlisting>
+ Compile the project. You'll see on your screen
+ <screen>
+ user@host:$scons
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ Entering '/home/ptomulik/projects/tmp'
+ xgettext --package-name=hello --package-version=1.0 -o - hello.c
+ Leaving '/home/ptomulik/projects/tmp'
+ Not writting 'messages.pot' (messages in file found to be up-to-date)
+ gcc -o hello.o -c hello.c
+ gcc -o hello hello.o
+ scons: done building targets.
+ </screen>
+ As you see, the internationalized messages ditn't change, so the
+ <literal>POT</literal> and the rest of translation files have not
+ even been touched.
+ </para>
+ </section>