forked from jdb/jdb.github.com
-
Notifications
You must be signed in to change notification settings - Fork 0
/
i18n.html
251 lines (235 loc) · 12 KB
/
i18n.html
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
<!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>One application, multiple languages — bits v0.7 documentation</title>
<link rel="stylesheet" href="static/sphinxdoc.css" type="text/css" />
<link rel="stylesheet" href="static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.7',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="static/jquery.js"></script>
<script type="text/javascript" src="static/underscore.js"></script>
<script type="text/javascript" src="static/doctools.js"></script>
<link rel="top" title="bits v0.7 documentation" href="index.html" />
<link rel="next" title="An upgrade safety net with the logical volume manager" href="lvm.html" />
<link rel="prev" title="A journey with Pi, Python, a functional algorithm and multicore" href="functional.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="lvm.html" title="An upgrade safety net with the logical volume manager"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="functional.html" title="A journey with Pi, Python, a functional algorithm and multicore"
accesskey="P">previous</a> |</li>
<li><a href="index.html">bits v0.7 documentation</a> »</li>
</ul>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">One application, multiple languages</a><ul>
<li><a class="reference internal" href="#how-does-it-work-at-runtime">How does it work at runtime?</a></li>
<li><a class="reference internal" href="#how-to-build-the-application">How to build the application?</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="functional.html"
title="previous chapter">A journey with Pi, Python, a functional algorithm and multicore</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="lvm.html"
title="next chapter">An upgrade safety net with the logical volume manager</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="sources/i18n.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="one-application-multiple-languages">
<h1>One application, multiple languages<a class="headerlink" href="#one-application-multiple-languages" title="Permalink to this headline">¶</a></h1>
<p>I have investigated the standard internationalization (i18n) tools,
because some day users may request to get messages in the language of
their choice. These first steps are recorded here, first paragraph is
to get a rough mental representation of how it works, second
paragraph: how to build such an app.</p>
<div class="section" id="how-does-it-work-at-runtime">
<h2>How does it work at runtime?<a class="headerlink" href="#how-does-it-work-at-runtime" title="Permalink to this headline">¶</a></h2>
<p>Here is a super simple internationalized application in Python, called
<em>myi18n.py</em>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">gettext</span>
<span class="n">_</span> <span class="o">=</span> <span class="n">gettext</span><span class="o">.</span><span class="n">gettext</span>
<span class="n">gettext</span><span class="o">.</span><span class="n">bindtextdomain</span><span class="p">(</span> <span class="s">"myi18n"</span><span class="p">,</span> <span class="s">"language.d"</span><span class="p">)</span>
<span class="n">gettext</span><span class="o">.</span><span class="n">textdomain</span><span class="p">(</span><span class="s">"myi18n"</span><span class="p">)</span>
<span class="n">gettext</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="s">"myi18n"</span><span class="p">)</span>
<span class="k">print</span> <span class="n">_</span><span class="p">(</span><span class="s">"Yozzaaa"</span><span class="p">)</span>
</pre></div>
</div>
<p>These sources uses the following conventional directory layout:</p>
<div class="highlight-python"><pre>|-- myi18n.py
`-- language.d
|-- fr
| `-- LC_MESSAGES
| `-- myi18n.mo
`-- it
`-- LC_MESSAGES
`-- myi18n.mo</pre>
</div>
<p>In the sample application, the <a class="reference external" href="http://docs.python.org/library/gettext.html">bindtextdomain</a> is the most
interesting function. It takes two arguments: <em>domain</em> and
<em>language_dir</em>:</p>
<ol class="arabic">
<li><p class="first">the <strong>domain</strong>, (<tt class="docutils literal"><span class="pre">myi18n</span></tt> in our example) is the name of a file
containing a compilation of the translated messages, and is located
in a directory <tt class="docutils literal"><span class="pre">$language_dir/$LOCALE/LC_MESSAGES</span></tt>. The file
always ends with .mo but do not write the suffixe in the parameter,</p>
</li>
<li><p class="first">the <strong>language directory</strong> (<tt class="docutils literal"><span class="pre">language.d</span></tt> in our example) which
defines where to find all the fr/, en/,... directories which
contains a mandatory <tt class="docutils literal"><span class="pre">LC_MESSAGES</span></tt> which contains the <em>mo</em> files
i.e like that</p>
<div class="highlight-python"><pre><language directory>
|-- <language1>
| `-- LC_MESSAGES
| `-- <domain>.mo
`-- <language2>
`-- ...</pre>
</div>
</li>
</ol>
<p>The gettext system expects:</p>
<ol class="arabic simple">
<li>to be informed at runtime of the desired langage (exporting the
environment variable <tt class="docutils literal"><span class="pre">LANGUAGE</span></tt> is a common way to do it),</li>
<li>in the source: which file to look for (a <em>domain</em>, and a langage
directory),</li>
<li>.mo file in <em>path_to_language_dir/$LANGUAGE/LC_MESSAGES/</em></li>
</ol>
</div>
<div class="section" id="how-to-build-the-application">
<h2>How to build the application?<a class="headerlink" href="#how-to-build-the-application" title="Permalink to this headline">¶</a></h2>
<p>The code presented here is meant to be copied and pasted in a
terminal, at the end, you get a working app.</p>
<ol class="arabic">
<li><p class="first">When writing code, just use the <em>_()</em> shortcut around any strings
that you later want to translate even you do not translate the
application right away: it is not harmful anyway</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">cat</span> <span class="o">></span> <span class="n">myi18n</span><span class="o">.</span><span class="n">py</span> <span class="o"><<</span> <span class="n">EOF</span>
<span class="kn">import</span> <span class="nn">gettext</span>
<span class="n">_</span> <span class="o">=</span> <span class="n">gettext</span><span class="o">.</span><span class="n">gettext</span>
<span class="n">gettext</span><span class="o">.</span><span class="n">bindtextdomain</span><span class="p">(</span> <span class="s">"myi18n"</span><span class="p">,</span> <span class="s">"language.d"</span><span class="p">)</span>
<span class="n">gettext</span><span class="o">.</span><span class="n">textdomain</span><span class="p">(</span><span class="s">"myi18n"</span><span class="p">)</span>
<span class="n">gettext</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="s">"myi18n"</span><span class="p">)</span>
<span class="k">print</span> <span class="n">_</span><span class="p">(</span> <span class="s">"Hello world"</span> <span class="p">)</span>
<span class="n">EOF</span>
</pre></div>
</div>
</li>
<li><p class="first">Use pygettext on the source file to create a <em>messages.pot</em>
template translation file, which lists every messages found in the
sources</p>
<div class="highlight-python"><pre>pygettext myi18n.py
sed -i s/CHARSET/UTF-8/ messages.pot</pre>
</div>
<p>.pot is for an empty template translation file; .po are for
translation source files; .mo are for compiled translation files</p>
</li>
<li><p class="first">Copy and rename the template file to a <language>.po file. One for
every language you want to support. Example: fr.po, en.po. Fill the
template with the message translations</p>
<div class="highlight-python"><pre>sub_below () { sed -r "h; N; s/^(.*$1.*\n).*/\1$2/; P; D" $3 ; }
sub_below Hello 'msgstr "Ciao tutti"' messages.pot > it.po
sub_below Hello 'msgstr "Héllo à tous"' messages.pot > fr.po</pre>
</div>
</li>
<li><p class="first">Create the directories where the application expects the message
translation</p>
<div class="highlight-python"><pre>mkdir -p language.d/{fr,it}/LC_MESSAGES/</pre>
</div>
</li>
<li><p class="first">Transform the .po in .mo with the <em>msgfmt</em> command, in the
lang_dir/fr/LC_MESSAGES/<domain>.mo</p>
<div class="highlight-python"><pre>msgfmt fr.po -o language.d/fr/LC_MESSAGES/myi18n.mo
msgfmt it.po -o language.d/it/LC_MESSAGES/myi18n.mo
rm {fr,it}.po messages.pot</pre>
</div>
</li>
<li><p class="first">Test the app with the different language</p>
<div class="highlight-python"><pre>for i in en fr it; do
export LANGUAGE=$i ; python myi18n.py; done
# Obviously, accents are correctly handled, it is made with python :)
unset LANGUAGE</pre>
</div>
</li>
</ol>
<p>Next time, you’ll see how to use conversion specifiers in the message
strings, as in printf. Also, there are similarities between i18n and
audience (audience as in support, dev, admin, grandma), I would like
to see how to hack i18n to address different audience.</p>
<p><em>15 November 2009</em></p>
</div>
</div>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="lvm.html" title="An upgrade safety net with the logical volume manager"
>next</a> |</li>
<li class="right" >
<a href="functional.html" title="A journey with Pi, Python, a functional algorithm and multicore"
>previous</a> |</li>
<li><a href="index.html">bits v0.7 documentation</a> »</li>
</ul>
</div>
<div class="footer">
© Copyright 2009, Jean Daniel Browne.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.
</div>
</body>
</html>