diff options
Diffstat (limited to 'doc/user/gettext.in')
-rw-r--r-- | doc/user/gettext.in | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/doc/user/gettext.in b/doc/user/gettext.in new file mode 100644 index 0000000..da5126d --- /dev/null +++ b/doc/user/gettext.in @@ -0,0 +1,351 @@ +<!-- + + 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 + <scons_example name="ex1"> + <file name="hello.c" printme="1"> + /* hello.c */ + #include <stdio.h> + int main(int argc, char* argv[]) + { + printf("Hello world\n"); + return 0; + } + </file> + </scons_example> + + Prepare a <filename>SConstruct</filename> to compile the program + as usual. + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + # SConstruct + env = Environment() + hello = Program(["hello.c"]) + </file> + </scons_example> + </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: + <scons_example name="ex3"> + <file name="hello.c" printme="1"> + /* hello.c */ + #include <stdio.h> + #include <libintl.h> + #include <locale.h> + int main(int argc, char* argv[]) + { + bindtextdomain("hello", "locale"); + setlocale(LC_ALL, ""); + textdomain("hello"); + printf(gettext("Hello world\n")); + return 0; + } + </file> + </scons_example> + 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: + <scons_example name="ex4"> + <file name="SConstruct" printme="1"> + # 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"]) + </file> + </scons_example> + </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. + <scons_example name="ex5"> + <file name="hello.c" printme="1"> + /* hello.c */ + #include <stdio.h> + #include <libintl.h> + #include <locale.h> + 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; + } + </file> + </scons_example> + </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: + <scons_example name="ex6"> + <file name="hello.c" printme="1"> + /* hello.c */ + #include <stdio.h> + #include <libintl.h> + #include <locale.h> + 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; + } + </file> + </scons_example> + 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> |