5
5
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/">
6
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/">
7
7
<title>Genshi: Internationalization and Localization</title>
8
8
<link rel="stylesheet" href="common/style/edgewall.css" type="text/css">
11
11
<div class="document" id="internationalization-and-localization">
12
12
<div id="navigation">
13
<span class="projinfo">Genshi 0.5.1</span>
13
<span class="projinfo">Genshi 0.6</span>
14
14
<a href="index.html">Documentation Index</a>
16
16
<h1 class="title">Internationalization and Localization</h1>
17
<p>Genshi provides basic supporting infrastructure for internationalizing
18
and localizing templates. That includes functionality for extracting localizable
19
strings from templates, as well as a template filter that can apply translations
20
to templates as they get rendered.</p>
21
<p>This support is based on <a class="reference" href="http://www.gnu.org/software/gettext/">gettext</a> message catalogs and the <a class="reference" href="http://docs.python.org/lib/module-gettext.html">gettext Python
22
module</a>. The extraction process can be used from the API level, or through the
23
front-ends implemented by the <a class="reference" href="http://babel.edgewall.org/">Babel</a> project, for which Genshi provides a
25
<div class="contents topic">
26
<p class="topic-title first"><a id="contents" name="contents">Contents</a></p>
17
<p>Genshi provides comprehensive supporting infrastructure for internationalizing
18
and localizing templates. That includes functionality for extracting
19
localizable strings from templates, as well as a template filter and special
20
directives that can apply translations to templates as they get rendered.</p>
21
<p>This support is based on <a class="reference external" href="http://www.gnu.org/software/gettext/">gettext</a> message catalogs and the <a class="reference external" href="http://docs.python.org/lib/module-gettext.html">gettext Python
22
module</a>. The extraction process can be used from the API level, or through
23
the front-ends implemented by the <a class="reference external" href="http://babel.edgewall.org/">Babel</a> project, for which Genshi provides
25
<div class="contents topic" id="contents">
26
<p class="topic-title first">Contents</p>
27
27
<ul class="auto-toc simple">
28
<li><a class="reference" href="#basics" id="id1" name="id1">1 Basics</a></li>
29
<li><a class="reference" href="#extraction" id="id2" name="id2">2 Extraction</a><ul class="auto-toc">
30
<li><a class="reference" href="#configuration-options" id="id3" name="id3">2.1 Configuration Options</a></li>
33
<li><a class="reference" href="#translation" id="id4" name="id4">3 Translation</a></li>
34
<li><a class="reference" href="#related-considerations" id="id5" name="id5">4 Related Considerations</a><ul class="auto-toc">
35
<li><a class="reference" href="#unicode" id="id6" name="id6">4.1 Unicode</a></li>
36
<li><a class="reference" href="#date-and-time" id="id7" name="id7">4.2 Date and Time</a></li>
37
<li><a class="reference" href="#formatting-and-locale-data" id="id8" name="id8">4.3 Formatting and Locale Data</a></li>
28
<li><a class="reference internal" href="#basics" id="id3">1 Basics</a><ul class="auto-toc">
29
<li><a class="reference internal" href="#language-tagging" id="id4">1.1 Language Tagging</a></li>
32
<li><a class="reference internal" href="#id1" id="id5">2 Template Directives</a><ul class="auto-toc">
33
<li><a class="reference internal" href="#messages" id="id6">2.1 Messages</a></li>
34
<li><a class="reference internal" href="#comments-and-domains" id="id7">2.2 Comments and Domains</a></li>
37
<li><a class="reference internal" href="#extraction" id="id8">3 Extraction</a><ul class="auto-toc">
38
<li><a class="reference internal" href="#babel-integration" id="id9">3.1 Babel Integration</a></li>
39
<li><a class="reference internal" href="#configuration-options" id="id10">3.2 Configuration Options</a></li>
42
<li><a class="reference internal" href="#translation" id="id11">4 Translation</a></li>
43
<li><a class="reference internal" href="#related-considerations" id="id12">5 Related Considerations</a><ul class="auto-toc">
44
<li><a class="reference internal" href="#unicode" id="id13">5.1 Unicode</a></li>
45
<li><a class="reference internal" href="#date-and-time" id="id14">5.2 Date and Time</a></li>
46
<li><a class="reference internal" href="#formatting-and-locale-data" id="id15">5.3 Formatting and Locale Data</a></li>
43
<h1><a id="basics" name="basics">1 Basics</a></h1>
51
<div class="section" id="basics">
44
53
<p>The simplest way to internationalize and translate templates would be to wrap
45
all localizable strings in a <tt class="docutils literal"><span class="pre">gettext()</span></tt> function call (which is often aliased
46
to <tt class="docutils literal"><span class="pre">_()</span></tt> for brevity). In that case, no extra template filter is required.</p>
54
all localizable strings in a <tt class="docutils literal"><span class="pre">gettext()</span></tt> function call (which is often
55
aliased to <tt class="docutils literal"><span class="pre">_()</span></tt> for brevity). In that case, no extra template filter is
47
57
<div class="highlight"><pre><span class="nt"><p></span><span class="cp">${</span><span class="n">_</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">)</span><span class="cp">}</span><span class="nt"></p></span>
49
59
<p>However, this approach results in significant “character noise” in templates,
50
60
making them harder to read and preview.</p>
51
61
<p>The <tt class="docutils literal"><span class="pre">genshi.filters.Translator</span></tt> filter allows you to get rid of the
52
explicit <a class="reference" href="http://www.gnu.org/software/gettext/">gettext</a> function calls, so you can continue to just write:</p>
62
explicit <a class="reference external" href="http://www.gnu.org/software/gettext/">gettext</a> function calls, so you can (often) just continue to write:</p>
53
63
<div class="highlight"><pre><span class="nt"><p></span>Hello, world!<span class="nt"></p></span>
55
65
<p>This text will still be extracted and translated as if you had wrapped it in a
56
66
<tt class="docutils literal"><span class="pre">_()</span></tt> call.</p>
58
68
<p class="first admonition-title">Note</p>
59
<p class="last">For parameterized or pluralizable messages, you need to continue using
60
the appropriate <tt class="docutils literal"><span class="pre">gettext</span></tt> functions.</p>
69
<p class="last">For parameterized or pluralizable messages, you need to use the
70
special <a class="reference internal" href="#template-directives">template directives</a> described below, or use the
71
corresponding <tt class="docutils literal"><span class="pre">gettext</span></tt> function in embedded Python expressions.</p>
62
73
<p>You can control which tags should be ignored by this process; for example, it
63
74
doesn't really make sense to translate the content of the HTML
81
94
<span class="nt"></html></span>
85
<h1><a id="extraction" name="extraction">2 Extraction</a></h1>
98
<div class="section" id="id1">
99
<span id="template-directives"></span><h1>2 Template Directives</h1>
100
<p>Sometimes localizable strings in templates may contain dynamic parameters, or
101
they may depend on the numeric value of some variable to choose a proper
102
plural form. Sometimes the strings contain embedded markup, such as tags for
103
emphasis or hyperlinks, and you don't want to rely on the people doing the
104
translations to know the syntax and escaping rules of HTML and XML.</p>
105
<p>In those cases the simple text extraction and translation process described
106
above is not sufficient. You could just use <tt class="docutils literal"><span class="pre">gettext</span></tt> API functions in
107
embedded Python expressions for parameters and pluralization, but that does
108
not help when messages contain embedded markup. Genshi provides special
109
template directives for internationalization that attempt to provide a
110
comprehensive solution for this problem space.</p>
111
<p>To enable these directives, you'll need to register them with the templates
112
they are used in. You can do this by adding them manually via the
113
<tt class="docutils literal"><span class="pre">Template.add_directives(namespace,</span> <span class="pre">factory)</span></tt> (where <tt class="docutils literal"><span class="pre">namespace</span></tt> would be
114
“http://genshi.edgewall.org/i18n” and <tt class="docutils literal"><span class="pre">factory</span></tt> would be an instance of the
115
<tt class="docutils literal"><span class="pre">Translator</span></tt> class). Or you can just call the <tt class="docutils literal"><span class="pre">Translator.setup(template)</span></tt>
116
class method, which both registers the directives and adds the translation
118
<p>After the directives have been registered with the template engine on the
119
Python side of your application, you need to declare the corresponding
120
directive namespace in all markup templates that use them. For example:</p>
121
<div class="highlight"><pre><span class="nt"><html</span> <span class="na">xmlns:py=</span><span class="s">"http://genshi.edgewall.org/"</span>
122
<span class="na">xmlns:i18n=</span><span class="s">"http://genshi.edgewall.org/i18n/"</span><span class="nt">></span>
124
<span class="nt"></html></span>
126
<p>These directives only make sense in the context of <a class="reference external" href="xml-templates.html">markup templates</a>. For
127
<a class="reference external" href="text-templates.html">text templates</a>, you can just use the corresponding <tt class="docutils literal"><span class="pre">gettext</span></tt> API calls as needed.</p>
129
<p class="first admonition-title">Note</p>
130
<p class="last">The internationalization directives are still somewhat experimental
131
and have some known issues. However, the attribute language they
132
implement should be stable and is not subject to change
133
substantially in future versions.</p>
135
<div class="section" id="messages">
136
<h2>2.1 Messages</h2>
137
<div class="section" id="i18n-msg">
138
<h3>2.1.1 <tt class="docutils literal"><span class="pre">i18n:msg</span></tt></h3>
139
<p>This is the basic directive for defining localizable text passages that
140
contain parameters and/or markup.</p>
141
<p>For example, consider the following template snippet:</p>
142
<div class="highlight"><pre><span class="nt"><p></span>
143
Please visit <span class="nt"><a</span> <span class="na">href=</span><span class="s">"</span><span class="cp">${</span><span class="n">site</span><span class="o">.</span><span class="n">url</span><span class="cp">}</span><span class="s">"</span><span class="nt">></span><span class="cp">${</span><span class="n">site</span><span class="o">.</span><span class="n">name</span><span class="cp">}</span><span class="nt"></a></span> for help.
144
<span class="nt"></p></span>
146
<p>Without further annotation, the translation filter would treat this sentence
147
as two separate messages (“Please visit” and “for help”), and the translator
148
would have no control over the position of the link in the sentence.</p>
149
<p>However, when you use the Genshi internationalization directives, you simply
150
add an <tt class="docutils literal"><span class="pre">i18n:msg</span></tt> attribute to the enclosing <tt class="docutils literal"><span class="pre"><p></span></tt> element:</p>
151
<div class="highlight"><pre><span class="nt"><p</span> <span class="na">i18n:msg=</span><span class="s">"name"</span><span class="nt">></span>
152
Please visit <span class="nt"><a</span> <span class="na">href=</span><span class="s">"</span><span class="cp">${</span><span class="n">site</span><span class="o">.</span><span class="n">url</span><span class="cp">}</span><span class="s">"</span><span class="nt">></span><span class="cp">${</span><span class="n">site</span><span class="o">.</span><span class="n">name</span><span class="cp">}</span><span class="nt"></a></span> for help.
153
<span class="nt"></p></span>
155
<p>Genshi is then able to identify the text in the <tt class="docutils literal"><span class="pre"><p></span></tt> element as a single
156
message for translation purposes. You'll see the following string in your
158
<pre class="literal-block">
159
Please visit [1:%(name)s] for help.
161
<p>The <cite><a></cite> element with its attribute has been replaced by a part in square
162
brackets, which does not include the tag name or the attributes of the element.</p>
163
<p>The value of the <tt class="docutils literal"><span class="pre">i18n:msg</span></tt> attribute is a comma-separated list of parameter
164
names, which serve as simplified aliases for the actual Python expressions the
165
message contains. The order of the paramer names in the list must correspond
166
to the order of the expressions in the text. In this example, there is only
167
one parameter: its alias for translation is “name”, while the corresponding
168
expression is <tt class="docutils literal"><span class="pre">${site.name}</span></tt>.</p>
169
<p>The translator now has complete control over the structure of the sentence. He
170
or she certainly does need to make sure that any bracketed parts are not
171
removed, and that the <tt class="docutils literal"><span class="pre">name</span></tt> parameter is preserved correctly. But those are
172
things that can be easily checked by validating the message catalogs. The
173
important thing is that the translator can change the sentence structure, and
174
has no way to break the application by forgetting to close a tag, for example.</p>
175
<p>So if the German translator of this snippet decided to translate it to:</p>
176
<pre class="literal-block">
177
Um Hilfe zu erhalten, besuchen Sie bitte [1:%(name)s]
179
<p>The resulting output might be:</p>
180
<div class="highlight"><pre><span class="nt"><p></span>
181
Um Hilfe zu erhalten, besuchen Sie bitte
182
<span class="nt"><a</span> <span class="na">href=</span><span class="s">"http://example.com/"</span><span class="nt">></span>Example<span class="nt"></a></span>
183
<span class="nt"></p></span>
185
<p>Messages may contain multiple tags, and they may also be nested. For example:</p>
186
<div class="highlight"><pre><span class="nt"><p</span> <span class="na">i18n:msg=</span><span class="s">"name"</span><span class="nt">></span>
187
<span class="nt"><i></span>Please<span class="nt"></i></span> visit <span class="nt"><b></span>the site <span class="nt"><a</span> <span class="na">href=</span><span class="s">"</span><span class="cp">${</span><span class="n">site</span><span class="o">.</span><span class="n">url</span><span class="cp">}</span><span class="s">"</span><span class="nt">></span><span class="cp">${</span><span class="n">site</span><span class="o">.</span><span class="n">name</span><span class="cp">}</span><span class="nt"></a></b></span>
189
<span class="nt"></p></span>
191
<p>This would result in the following message ID:</p>
192
<pre class="literal-block">
193
[1:Please] visit [2:the site [3:%(name)s]] for help.
195
<p>Again, the translator has full control over the structure of the sentence. So
196
the German translation could actually look like this:</p>
197
<pre class="literal-block">
198
Um Hilfe zu erhalten besuchen Sie [1:bitte]
199
[3:%(name)s], [2:das ist eine Web-Site]
201
<p>Which Genshi would recompose into the following outout:</p>
202
<div class="highlight"><pre><span class="nt"><p></span>
203
Um Hilfe zu erhalten besuchen Sie <span class="nt"><i></span>bitte<span class="nt"></i></span>
204
<span class="nt"><a</span> <span class="na">href=</span><span class="s">"http://example.com/"</span><span class="nt">></span>Example<span class="nt"></a></span>, <span class="nt"><b></span>das ist eine Web-Site<span class="nt"></b></span>
205
<span class="nt"></p></span>
207
<p>Note how the translation has changed the order and even the nesting of the
209
<div class="warning">
210
<p class="first admonition-title">Warning</p>
211
<p class="last">Please note that <tt class="docutils literal"><span class="pre">i18n:msg</span></tt> directives do not support other
212
nested directives. Directives commonly change the structure of
213
the generated markup dynamically, which often would result in the
214
structure of the text changing, thus making translation as a
215
single message ineffective.</p>
218
<div class="section" id="i18n-choose-i18n-singular-i18n-plural">
219
<h3>2.1.2 <tt class="docutils literal"><span class="pre">i18n:choose</span></tt>, <tt class="docutils literal"><span class="pre">i18n:singular</span></tt>, <tt class="docutils literal"><span class="pre">i18n:plural</span></tt></h3>
220
<p>Translatable strings that vary based on some number of objects, such as “You
221
have 1 new message” or “You have 3 new messages”, present their own challenge,
222
in particular when you consider that different languages have different rules
223
for pluralization. For example, while English and most western languages have
224
two plural forms (one for <tt class="docutils literal"><span class="pre">n=1</span></tt> and an other for <tt class="docutils literal"><span class="pre">n<>1</span></tt>), Welsh has five
225
different plural forms, while Hungarian only has one.</p>
226
<p>The <tt class="docutils literal"><span class="pre">gettext</span></tt> framework has long supported this via the <tt class="docutils literal"><span class="pre">ngettext()</span></tt>
227
family of functions. You specify two default messages, one singular and one
228
plural, and the number of items. The translations however may contain any
229
number of plural forms for the message, depending on how many are commonly
230
used in the language. <tt class="docutils literal"><span class="pre">ngettext</span></tt> will choose the correct plural form of the
231
translated message based on the specified number of items.</p>
232
<p>Genshi provides a variant of the <tt class="docutils literal"><span class="pre">i18n:msg</span></tt> directive described above that
233
allows choosing the proper plural form based on the numeric value of a given
234
variable. The pluralization support is implemented in a set of three
235
directives that must be used together: <tt class="docutils literal"><span class="pre">i18n:choose</span></tt>, <tt class="docutils literal"><span class="pre">i18n:singular</span></tt>, and
236
<tt class="docutils literal"><span class="pre">i18n:plural</span></tt>.</p>
237
<p>The <tt class="docutils literal"><span class="pre">i18n:choose</span></tt> directive is used to set up the context of the message: it
238
simply wraps the singular and plural variants.</p>
239
<p>The value of this directive is split into two parts: the first is the
240
<em>numeral</em>, a Python expression that evaluates to a number to determine which
241
plural form should be chosen. The second part, separated by a semicolon, lists
242
the parameter names. This part is equivalent to the value of the <tt class="docutils literal"><span class="pre">i18n:msg</span></tt>
245
<div class="highlight"><pre><span class="nt"><p</span> <span class="na">i18n:choose=</span><span class="s">"len(messages); num"</span><span class="nt">></span>
246
<span class="nt"><i18n:singular></span>You have <span class="nt"><b></span><span class="cp">${</span><span class="nb">len</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span><span class="cp">}</span><span class="nt"></b></span> new message.<span class="nt"></i18n:singular></span>
247
<span class="nt"><i18n:plural></span>You have <span class="nt"><b></span><span class="cp">${</span><span class="nb">len</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span><span class="cp">}</span><span class="nt"></b></span> new messages.<span class="nt"></i18n:plural></span>
248
<span class="nt"></p></span>
250
<p>All three directives can be used either as elements or attribute. So the above
251
example could also be written as follows:</p>
252
<div class="highlight"><pre><span class="nt"><i18n:choose</span> <span class="na">numeral=</span><span class="s">"len(messages)"</span> <span class="na">params=</span><span class="s">"num"</span><span class="nt">></span>
253
<span class="nt"><p</span> <span class="na">i18n:singular=</span><span class="s">""</span><span class="nt">></span>You have <span class="nt"><b></span><span class="cp">${</span><span class="nb">len</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span><span class="cp">}</span><span class="nt"></b></span> new message.<span class="nt"></p></span>
254
<span class="nt"><p</span> <span class="na">i18n:plural=</span><span class="s">""</span><span class="nt">></span>You have <span class="nt"><b></span><span class="cp">${</span><span class="nb">len</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span><span class="cp">}</span><span class="nt"></b></span> new messages.<span class="nt"></p></span>
255
<span class="nt"></i18n:choose></span>
257
<p>When used as an element, the two parts of the <tt class="docutils literal"><span class="pre">i18n:choose</span></tt> value are split
258
into two different attributes: <tt class="docutils literal"><span class="pre">numeral</span></tt> and <tt class="docutils literal"><span class="pre">params</span></tt>. The
259
<tt class="docutils literal"><span class="pre">i18n:singular</span></tt> and <tt class="docutils literal"><span class="pre">i18n:plural</span></tt> directives do not require or support any
260
value (or any extra attributes).</p>
263
<div class="section" id="comments-and-domains">
264
<h2>2.2 Comments and Domains</h2>
265
<div class="section" id="i18n-comment">
266
<h3>2.2.1 <tt class="docutils literal"><span class="pre">i18n:comment</span></tt></h3>
267
<p>The <tt class="docutils literal"><span class="pre">i18n:comment</span></tt> directive can be used to supply a comment for the
268
translator. For example, if a template snippet is not easily understood
269
outside of its context, you can add a translator comment to help the
270
translator understand in what context the message will be used:</p>
271
<div class="highlight"><pre><span class="nt"><p</span> <span class="na">i18n:msg=</span><span class="s">"name"</span> <span class="na">i18n:comment=</span><span class="s">"Link to the relevant support site"</span><span class="nt">></span>
272
Please visit <span class="nt"><a</span> <span class="na">href=</span><span class="s">"</span><span class="cp">${</span><span class="n">site</span><span class="o">.</span><span class="n">url</span><span class="cp">}</span><span class="s">"</span><span class="nt">></span><span class="cp">${</span><span class="n">site</span><span class="o">.</span><span class="n">name</span><span class="cp">}</span><span class="nt"></a></span> for help.
273
<span class="nt"></p></span>
275
<p>This comment will be extracted together with the message itself, and will
276
commonly be placed along the message in the message catalog, so that it is
277
easily visible to the person doing the translation.</p>
278
<p>This directive has no impact on how the template is rendered, and is ignored
279
outside of the extraction process.</p>
281
<div class="section" id="i18n-domain">
282
<h3>2.2.2 <tt class="docutils literal"><span class="pre">i18n:domain</span></tt></h3>
283
<p>In larger projects, message catalogs are commonly split up into different
284
<em>domains</em>. For example, you might have a core application domain, and then
285
separate domains for extensions or libraries.</p>
286
<p>Genshi provides a directive called <tt class="docutils literal"><span class="pre">i18n:domain</span></tt> that lets you choose the
287
translation domain for a particular scope. For example:</p>
288
<div class="highlight"><pre><span class="nt"><div</span> <span class="na">i18n:domain=</span><span class="s">"examples"</span><span class="nt">></span>
289
<span class="nt"><p></span>Hello, world!<span class="nt"></p></span>
290
<span class="nt"></div></span>
295
<div class="section" id="extraction">
296
<h1>3 Extraction</h1>
86
297
<p>The <tt class="docutils literal"><span class="pre">Translator</span></tt> class provides a class method called <tt class="docutils literal"><span class="pre">extract</span></tt>, which is
87
298
a generator yielding all localizable strings found in a template or markup
88
299
stream. This includes both literal strings in text nodes and attribute values,
89
300
as well as strings in <tt class="docutils literal"><span class="pre">gettext()</span></tt> calls in embedded Python code. See the API
90
301
documentation for details on how to use this method directly.</p>
91
<p>This functionality is integrated into the message extraction framework provided
92
by the <a class="reference" href="http://babel.edgewall.org/">Babel</a> project. Babel provides a command-line interface as well as
93
commands that can be used from <tt class="docutils literal"><span class="pre">setup.py</span></tt> scripts using <a class="reference" href="http://peak.telecommunity.com/DevCenter/setuptools">Setuptools</a> or
94
<a class="reference" href="http://docs.python.org/dist/dist.html">Distutils</a>.</p>
302
<div class="section" id="babel-integration">
303
<h2>3.1 Babel Integration</h2>
304
<p>This functionality is integrated with the message extraction framework provided
305
by the <a class="reference external" href="http://babel.edgewall.org/">Babel</a> project. Babel provides a command-line interface as well as
306
commands that can be used from <tt class="docutils literal"><span class="pre">setup.py</span></tt> scripts using <a class="reference external" href="http://peak.telecommunity.com/DevCenter/setuptools">Setuptools</a> or
307
<a class="reference external" href="http://docs.python.org/dist/dist.html">Distutils</a>.</p>
95
308
<p>The first thing you need to do to make Babel extract messages from Genshi
96
309
templates is to let Babel know which files are Genshi templates. This is done
97
310
using a “mapping configuration”, which can be stored in a configuration file,
111
324
<p>Please consult the Babel documentation for details on configuration.</p>
112
325
<p>If all goes well, running the extraction with Babel should create a POT file
113
326
containing the strings from your Genshi templates and your Python source files.</p>
115
<p class="first admonition-title">Note</p>
116
<p class="last">Genshi currently does not support “translator comments”, i.e. text in
117
template comments that would get added to the POT file. This support
118
may or may not be added in future versions.</p>
120
<div class="section">
121
<h2><a id="configuration-options" name="configuration-options">2.1 Configuration Options</a></h2>
328
<div class="section" id="configuration-options">
329
<h2>3.2 Configuration Options</h2>
122
330
<p>The Genshi extraction plugin for Babel supports the following options:</p>
123
<div class="section">
124
<h3><a id="template-class" name="template-class">2.1.1 <tt class="docutils literal"><span class="pre">template_class</span></tt></a></h3>
331
<div class="section" id="template-class">
332
<h3>3.2.1 <tt class="docutils literal"><span class="pre">template_class</span></tt></h3>
125
333
<p>The concrete <tt class="docutils literal"><span class="pre">Template</span></tt> class that the file should be loaded with. Specify
126
334
the package/module name and the class name, separated by a colon.</p>
127
335
<p>The default is to use <tt class="docutils literal"><span class="pre">genshi.template:MarkupTemplate</span></tt>, and you'll want to
128
set it to <tt class="docutils literal"><span class="pre">genshi.template:TextTemplate</span></tt> for <a class="reference" href="text-templates.html">text templates</a>.</p>
336
set it to <tt class="docutils literal"><span class="pre">genshi.template:TextTemplate</span></tt> for <a class="reference external" href="text-templates.html">text templates</a>.</p>
130
<div class="section">
131
<h3><a id="encoding" name="encoding">2.1.2 <tt class="docutils literal"><span class="pre">encoding</span></tt></a></h3>
338
<div class="section" id="encoding">
339
<h3>3.2.2 <tt class="docutils literal"><span class="pre">encoding</span></tt></h3>
132
340
<p>The encoding of the template file. This is only used for text templates. The
133
341
default is to assume “utf-8”.</p>
135
<div class="section">
136
<h3><a id="include-attrs" name="include-attrs">2.1.3 <tt class="docutils literal"><span class="pre">include_attrs</span></tt></a></h3>
343
<div class="section" id="include-attrs">
344
<h3>3.2.3 <tt class="docutils literal"><span class="pre">include_attrs</span></tt></h3>
137
345
<p>Comma-separated list of attribute names that should be considered to have
138
346
localizable values. Only used for markup templates.</p>
140
<div class="section">
141
<h3><a id="ignore-tags" name="ignore-tags">2.1.4 <tt class="docutils literal"><span class="pre">ignore_tags</span></tt></a></h3>
348
<div class="section" id="ignore-tags">
349
<h3>3.2.4 <tt class="docutils literal"><span class="pre">ignore_tags</span></tt></h3>
142
350
<p>Comma-separated list of tag names that should be ignored. Only used for markup
145
<div class="section">
146
<h3><a id="extract-text" name="extract-text">2.1.5 <tt class="docutils literal"><span class="pre">extract_text</span></tt></a></h3>
353
<div class="section" id="extract-text">
354
<h3>3.2.5 <tt class="docutils literal"><span class="pre">extract_text</span></tt></h3>
147
355
<p>Whether text outside explicit <tt class="docutils literal"><span class="pre">gettext</span></tt> function calls should be extracted.
148
356
By default, any text nodes not inside ignored tags, and values of attribute in
149
357
the <tt class="docutils literal"><span class="pre">include_attrs</span></tt> list are extracted. If this option is disabled, only
150
358
strings in <tt class="docutils literal"><span class="pre">gettext</span></tt> function calls are extracted.</p>
151
359
<div class="note">
152
360
<p class="first admonition-title">Note</p>
153
<p class="last">If you disable this option, it's not necessary to add the translation
154
filter as described above. You only need to make sure that the
155
template has access to the <tt class="docutils literal"><span class="pre">gettext</span></tt> functions it uses.</p>
160
<div class="section">
161
<h1><a id="translation" name="translation">3 Translation</a></h1>
361
<p class="last">If you disable this option, and do not make use of the
362
internationalization directives, it's not necessary to add the
363
translation filter as described above. You only need to make sure
364
that the template has access to the <tt class="docutils literal"><span class="pre">gettext</span></tt> functions it uses.</p>
369
<div class="section" id="translation">
370
<h1>4 Translation</h1>
162
371
<p>If you have prepared MO files for use with Genshi using the appropriate tools,
163
you can access the message catalogs with the <a class="reference" href="http://docs.python.org/lib/module-gettext.html">gettext Python module</a>. You'll
372
you can access the message catalogs with the <a class="reference external" href="http://docs.python.org/lib/module-gettext.html">gettext Python module</a>. You'll
164
373
probably want to create a <tt class="docutils literal"><span class="pre">gettext.GNUTranslations</span></tt> instance, and make the
165
374
translation functions it provides available to your templates by putting them
166
375
in the template context.</p>
168
377
(applying it as a stream filter will likely not have the desired effect).
169
378
Furthermore it needs to be the first filter in the list, including the internal
170
379
filters that Genshi adds itself:</p>
171
<div class="highlight"><pre><span class="k">from</span> <span class="nn">genshi.filters</span> <span class="k">import</span> <span class="n">Translator</span>
172
<span class="k">from</span> <span class="nn">genshi.template</span> <span class="k">import</span> <span class="n">MarkupTemplate</span>
380
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">genshi.filters</span> <span class="kn">import</span> <span class="n">Translator</span>
381
<span class="kn">from</span> <span class="nn">genshi.template</span> <span class="kn">import</span> <span class="n">MarkupTemplate</span>
174
383
<span class="n">template</span> <span class="o">=</span> <span class="n">MarkupTemplate</span><span class="p">(</span><span class="s">"..."</span><span class="p">)</span>
175
384
<span class="n">template</span><span class="o">.</span><span class="n">filters</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span> <span class="n">Translator</span><span class="p">(</span><span class="n">translations</span><span class="o">.</span><span class="n">ugettext</span><span class="p">))</span>
177
<p>If you're using <cite>TemplateLoader</cite>, you should specify a callback function in
178
which you add the filter:</p>
179
<div class="highlight"><pre><span class="k">from</span> <span class="nn">genshi.filters</span> <span class="k">import</span> <span class="n">Translator</span>
180
<span class="k">from</span> <span class="nn">genshi.template</span> <span class="k">import</span> <span class="n">TemplateLoader</span>
182
<span class="k">def</span> <span class="nf">template_loaded</span><span class="p">(</span><span class="n">template</span><span class="p">):</span>
183
<span class="n">template</span><span class="o">.</span><span class="n">filters</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span> <span class="n">Translator</span><span class="p">(</span><span class="n">translations</span><span class="o">.</span><span class="n">ugettext</span><span class="p">))</span>
185
<span class="n">loader</span> <span class="o">=</span> <span class="n">TemplateLoader</span><span class="p">(</span><span class="s">'templates'</span><span class="p">,</span> <span class="n">callback</span><span class="o">=</span><span class="n">template_loaded</span><span class="p">)</span>
186
<span class="n">template</span> <span class="o">=</span> <span class="n">loader</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s">"..."</span><span class="p">)</span>
386
<p>The <tt class="docutils literal"><span class="pre">Translator</span></tt> class also provides the convenience method <tt class="docutils literal"><span class="pre">setup()</span></tt>,
387
which will both add the filter and register the i18n directives:</p>
388
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">genshi.filters</span> <span class="kn">import</span> <span class="n">Translator</span>
389
<span class="kn">from</span> <span class="nn">genshi.template</span> <span class="kn">import</span> <span class="n">MarkupTemplate</span>
391
<span class="n">template</span> <span class="o">=</span> <span class="n">MarkupTemplate</span><span class="p">(</span><span class="s">"..."</span><span class="p">)</span>
392
<span class="n">translator</span> <span class="o">=</span> <span class="n">Translator</span><span class="p">(</span><span class="n">translations</span><span class="o">.</span><span class="n">ugettext</span><span class="p">)</span>
393
<span class="n">translator</span><span class="o">.</span><span class="n">setup</span><span class="p">(</span><span class="n">template</span><span class="p">)</span>
188
<p>This approach ensures that the filter is not added everytime the template is
189
loaded, and thus being applied multiple times.</p>
191
<div class="section">
192
<h1><a id="related-considerations" name="related-considerations">4 Related Considerations</a></h1>
395
<div class="warning">
396
<p class="first admonition-title">Warning</p>
397
<p class="last">If you're using <tt class="docutils literal"><span class="pre">TemplateLoader</span></tt>, you should specify a
398
<a class="reference external" href="loader.html#callback-interface">callback function</a> in which you add the filter. That ensures
399
that the filter is not added everytime the template is rendered,
400
thereby being applied multiple times.</p>
403
<div class="section" id="related-considerations">
404
<h1>5 Related Considerations</h1>
193
405
<p>If you intend to produce an application that is fully prepared for an
194
406
international audience, there are a couple of other things to keep in mind:</p>
195
<div class="section">
196
<h2><a id="unicode" name="unicode">4.1 Unicode</a></h2>
407
<div class="section" id="unicode">
197
409
<p>Use <tt class="docutils literal"><span class="pre">unicode</span></tt> internally, not encoded bytestrings. Only encode/decode where
198
410
data enters or exits the system. This means that your code works with characters
199
411
and not just with bytes, which is an important distinction for example when
200
412
calculating the length of a piece of text. When you need to decode/encode, it's
201
413
probably a good idea to use UTF-8.</p>
203
<div class="section">
204
<h2><a id="date-and-time" name="date-and-time">4.2 Date and Time</a></h2>
415
<div class="section" id="date-and-time">
416
<h2>5.2 Date and Time</h2>
205
417
<p>If your application uses datetime information that should be displayed to users
206
418
in different timezones, you should try to work with UTC (universal time)
207
419
internally. Do the conversion from and to "local time" when the data enters or
208
exits the system. Make use the Python <a class="reference" href="http://docs.python.org/lib/module-datetime.html">datetime</a> module and the third-party
209
<a class="reference" href="http://pytz.sourceforge.net/">pytz</a> package.</p>
420
exits the system. Make use the Python <a class="reference external" href="http://docs.python.org/lib/module-datetime.html">datetime</a> module and the third-party
421
<a class="reference external" href="http://pytz.sourceforge.net/">pytz</a> package.</p>
211
<div class="section">
212
<h2><a id="formatting-and-locale-data" name="formatting-and-locale-data">4.3 Formatting and Locale Data</a></h2>
213
<p>Make sure you check out the functionality provided by the <a class="reference" href="http://babel.edgewall.org/">Babel</a> project for
423
<div class="section" id="formatting-and-locale-data">
424
<h2>5.3 Formatting and Locale Data</h2>
425
<p>Make sure you check out the functionality provided by the <a class="reference external" href="http://babel.edgewall.org/">Babel</a> project for
214
426
things like number and date formatting, locale display strings, etc.</p>