annotate doc/i18n.txt @ 889:963ffe1ce667 trunk

Minor fix for i18n doc.
author cmlenz
date Mon, 19 Apr 2010 11:47:42 +0000
parents 7e85b17cc317
children d30ceea3eadd
rev   line source
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
1 .. -*- mode: rst; encoding: utf-8 -*-
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
2
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
3 =====================================
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
4 Internationalization and Localization
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
5 =====================================
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
6
886
13017f59f5ea Set reST MIME type on new loader doc page.
cmlenz
parents: 885
diff changeset
7 Genshi provides comprehensive supporting infrastructure for internationalizing
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
8 and localizing templates. That includes functionality for extracting
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
9 localizable strings from templates, as well as a template filter that can
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
10 apply translations to templates as they get rendered.
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
11
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
12 This support is based on `gettext`_ message catalogs and the `gettext Python
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
13 module`_. The extraction process can be used from the API level, or through
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
14 the front-ends implemented by the `Babel`_ project, for which Genshi provides
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
15 a plugin.
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
16
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
17 .. _`gettext`: http://www.gnu.org/software/gettext/
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
18 .. _`gettext python module`: http://docs.python.org/lib/module-gettext.html
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
19 .. _`babel`: http://babel.edgewall.org/
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
20
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
21
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
22 .. contents:: Contents
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
23 :depth: 2
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
24 .. sectnum::
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
25
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
26
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
27 Basics
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
28 ======
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
29
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
30 The simplest way to internationalize and translate templates would be to wrap
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
31 all localizable strings in a ``gettext()`` function call (which is often
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
32 aliased to ``_()`` for brevity). In that case, no extra template filter is
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
33 required.
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
34
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
35 .. code-block:: genshi
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
36
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
37 <p>${_("Hello, world!")}</p>
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
38
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
39 However, this approach results in significant “character noise” in templates,
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
40 making them harder to read and preview.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
41
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
42 The ``genshi.filters.Translator`` filter allows you to get rid of the
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
43 explicit `gettext`_ function calls, so you can continue to just write:
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
44
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
45 .. code-block:: genshi
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
46
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
47 <p>Hello, world!</p>
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
48
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
49 This text will still be extracted and translated as if you had wrapped it in a
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
50 ``_()`` call.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
51
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
52 .. note:: For parameterized or pluralizable messages, you need to use the
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
53 special `template directives`_ described below, or use the
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
54 corresponding ``gettext`` function in embedded Python expressions.
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
55
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
56 You can control which tags should be ignored by this process; for example, it
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
57 doesn't really make sense to translate the content of the HTML
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
58 ``<script></script>`` element. Both ``<script>`` and ``<style>`` are excluded
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
59 by default.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
60
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
61 Attribute values can also be automatically translated. The default is to
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
62 consider the attributes ``abbr``, ``alt``, ``label``, ``prompt``, ``standby``,
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
63 ``summary``, and ``title``, which is a list that makes sense for HTML
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
64 documents. Of course, you can tell the translator to use a different set of
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
65 attribute names, or none at all.
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
66
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
67 ----------------
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
68 Language Tagging
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
69 ----------------
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
70
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
71 You can control automatic translation in your templates using the ``xml:lang``
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
72 attribute. If the value of that attribute is a literal string, the contents and
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
73 attributes of the element will be ignored:
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
74
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
75 .. code-block:: genshi
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
76
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
77 <p xml:lang="en">Hello, world!</p>
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
78
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
79 On the other hand, if the value of the ``xml:lang`` attribute contains a Python
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
80 expression, the element contents and attributes are still considered for
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
81 automatic translation:
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
82
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
83 .. code-block:: genshi
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
84
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
85 <html xml:lang="$locale">
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
86 ...
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
87 </html>
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
88
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
89
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
90 .. _`template directives`:
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
91
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
92 Template Directives
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
93 ===================
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
94
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
95 Sometimes localizable strings in templates may contain dynamic parameters, or
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
96 they may depend on the numeric value of some variable to choose a proper
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
97 plural form. Sometimes the strings contain embedded markup, such as tags for
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
98 emphasis or hyperlinks, and you don't want to rely on the people doing the
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
99 translations to know the syntax and escaping rules of HTML and XML.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
100
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
101 In those cases the simple text extraction and translation process described
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
102 above is not sufficient. You could just use ``gettext`` API functions in
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
103 embedded Python expressions for parameters and pluralization, but Genshi also
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
104 provides special template directives for internationalization that attempt to
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
105 provide a comprehensive solution for this problem space.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
106
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
107 To enable these directives, you'll need to register them with the templates
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
108 they are used in. You can do this by adding them manually via the
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
109 ``Template.add_directives(namespace, factory)`` (where ``namespace`` would be
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
110 “http://genshi.edgewall.org/i18n” and ``factory`` would be an instance of the
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
111 ``Translator`` class). Or you can just call the ``Translator.setup(template)``
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
112 class method, which both registers the directives and adds the translation
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
113 filter.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
114
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
115 .. note:: The internationalization directives are still somewhat experimental
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
116 and have some known issues. However, the attribute language they
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
117 implement should be stable and is not subject to change
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
118 substantially in future versions.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
119
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
120
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
121 --------
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
122 Messages
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
123 --------
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
124
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
125 ``i18n:msg``
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
126 ------------
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
127
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
128 This is the basic directive for defining localizable text passages that
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
129 contain parameters and/or markup.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
130
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
131 For example, consider the following template snippet:
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
132
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
133 .. code-block:: genshi
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
134
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
135 <p>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
136 Please visit <a href="${site.url}">${site.name}</a> for help.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
137 </p>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
138
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
139 Without further annotation, the translation filter would treat this sentence
887
93c683af039b More doc improvements.
cmlenz
parents: 886
diff changeset
140 as two separate messages (“Please visit” and “for help”), and the translator
93c683af039b More doc improvements.
cmlenz
parents: 886
diff changeset
141 would have no control over the position of the link in the sentence.
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
142
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
143 However, when you use the Genshi internationalization directives, you simply
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
144 add an ``i18n:msg`` attribute to the enclosing ``<p>`` element:
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
145
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
146 .. code-block:: genshi
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
147
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
148 <p i18n:msg="name">
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
149 Please visit <a href="${site.url}">${site.name}</a> for help.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
150 </p>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
151
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
152 Genshi is then able to identify the text in the ``<p>`` element as a single
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
153 message for translation purposes. You'll see the following string in your
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
154 message catalog::
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
155
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
156 Please visit [1:%(name)s] for help.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
157
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
158 The `<a>` element with its attribute has been replaced by a part in square
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
159 brackets, which does not include the tag name or the attributes of the element.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
160
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
161 The value of the ``i18n:msg`` attribute is a comma-separated list of parameter
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
162 names, which serve as simplified aliases for the actual Python expressions the
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
163 message contains. The order of the paramer names in the list must correspond
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
164 to the order of the expressions in the text. In this example, there is only
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
165 one parameter: its alias for translation is “name”, while the corresponding
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
166 expression is ``${site.name}``.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
167
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
168 The translator now has complete control over the structure of the sentence. He
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
169 or she certainly does need to make sure that any bracketed parts are not
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
170 removed, and that the ``name`` parameter is preserved correctly. But those are
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
171 things that can be easily checked by validating the message catalogs. The
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
172 important thing is that the translator can change the sentence structure, and
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
173 has no way to break the application by forgetting to close a tag, for example.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
174
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
175 So if the German translator of this snippet decided to translate it to::
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
176
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
177 Um Hilfe zu erhalten, besuchen Sie bitte [1:%(name)s]
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
178
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
179 The resulting output might be:
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
180
889
963ffe1ce667 Minor fix for i18n doc.
cmlenz
parents: 888
diff changeset
181 .. code-block:: xml
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
182
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
183 <p>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
184 Um Hilfe zu erhalten, besuchen Sie bitte
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
185 <a href="http://example.com/">Example</a>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
186 </p>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
187
887
93c683af039b More doc improvements.
cmlenz
parents: 886
diff changeset
188 Messages may contain multiple tags, and they may also be nested. For example:
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
189
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
190 .. code-block:: genshi
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
191
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
192 <p i18n:msg="name">
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
193 <i>Please</i> visit <b>the site <a href="${site.url}">${site.name}</a></b>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
194 for help.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
195 </p>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
196
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
197 This would result in the following message ID::
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
198
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
199 [1:Please] visit [2:the site [3:%(name)s]] for help.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
200
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
201 Again, the translator has full control over the structure of the sentence. So
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
202 the German translation could actually look like this::
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
203
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
204 Um Hilfe zu erhalten besuchen Sie [1:bitte]
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
205 [3:%(name)s], [2:das ist eine Web-Site]
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
206
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
207 Which Genshi would recompose into the following outout:
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
208
889
963ffe1ce667 Minor fix for i18n doc.
cmlenz
parents: 888
diff changeset
209 .. code-block:: xml
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
210
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
211 <p>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
212 Um Hilfe zu erhalten besuchen Sie <i>bitte</i>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
213 <a href="http://example.com/">Example</a>, <b>das ist eine Web-Site</b>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
214 </p>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
215
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
216 Note how the translation has changed the order and even the nesting of the
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
217 tags.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
218
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
219 .. warning:: Please note that ``i18n:msg`` directives do not support other
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
220 nested directives. Directives commonly change the structure of
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
221 the generated markup dynamically, which often would result in the
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
222 structure of the text changing, thus making translation as a
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
223 single message ineffective.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
224
888
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
225 ``i18n:choose``, ``i18n:singular``, ``i18n:plural``
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
226 ---------------------------------------------------
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
227
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
228 Translatable strings that vary based on some number of objects, such as “You
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
229 have 1 new message” or “You have 3 new messages”, present their own challenge,
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
230 in particular when you consider that different languages have different rules
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
231 for pluralization. For example, while English and most western languages have
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
232 two plural forms (one for ``n=1`` and an other for ``n<>1``), Welsh has five
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
233 different plural forms, while Hungarian only has one.
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
234
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
235 The ``gettext`` framework has long supported this via the ``ngettext()``
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
236 family of functions. You specify two default messages, one singular and one
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
237 plural, and the number of items. The translations however may contain any
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
238 number of plural forms for the message, depending on how many are commonly
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
239 used in the language. ``ngettext`` will choose the correct plural form of the
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
240 translated message based on the specified number of items.
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
241
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
242 Genshi provides a variant of the ``i18n:msg`` directive described above that
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
243 allows choosing the proper plural form based on the numeric value of a given
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
244 variable. The pluralization support is implemented in a set of three
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
245 directives that must be used together: ``i18n:choose``, ``i18n:singular``, and
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
246 ``i18n:plural``.
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
247
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
248 The ``i18n:choose`` directive is used to set up the context of the message: it
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
249 simply wraps the singular and plural variants.
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
250
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
251 The value of this directive is split into two parts: the first is the
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
252 *numeral*, a Python expression that evaluates to a number to determine which
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
253 plural form should be chosen. The second part, separated by a semicolon, lists
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
254 the parameter names. This part is equivalent to the value of the ``i18n:msg``
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
255 directive.
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
256
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
257 For example:
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
258
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
259 .. code-block:: genshi
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
260
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
261 <p i18n:choose="len(messages); num">
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
262 <i18n:singular>You have <b>${len(messages)}</b> new message.</i18n:singular>
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
263 <i18n:plural>You have <b>${len(messages)}</b> new messages.</i18n:plural>
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
264 </p>
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
265
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
266 All three directives can be used either as elements or attribute. So the above
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
267 example could also be written as follows:
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
268
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
269 .. code-block:: genshi
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
270
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
271 <i18n:choose numeral="len(messages)" params="num">
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
272 <p i18n:singular="">You have <b>${len(messages)}</b> new message.</p>
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
273 <p i18n:plural="">You have <b>${len(messages)}</b> new messages.</p>
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
274 </i18n:choose>
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
275
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
276 When used as an element, the two parts of the ``i18n:choose`` value are split
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
277 into two different attributes: ``numeral`` and ``params``. The
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
278 ``i18n:singular`` and ``i18n:plural`` directives do not require or support any
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
279 value (or any extra attributes).
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
280
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
281 --------------------
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
282 Comments and Domains
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
283 --------------------
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
284
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
285 ``i18n:comment``
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
286 ----------------
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
287
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
288 The ``i18n:comment`` directive can be used to supply a comment for the
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
289 translator. For example, if a template snippet is not easily understood
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
290 outside of its context, you can add a translator comment to help the
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
291 translator understand in what context the message will be used:
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
292
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
293 .. code-block:: genshi
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
294
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
295 <p i18n:msg="name" i18n:comment="Link to the relevant support site">
887
93c683af039b More doc improvements.
cmlenz
parents: 886
diff changeset
296 Please visit <a href="${site.url}">${site.name}</a> for help.
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
297 </p>
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
298
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
299 This comment will be extracted together with the message itself, and will
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
300 commonly be placed along the message in the message catalog, so that it is
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
301 easily visible to the person doing the translation.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
302
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
303 This directive has no impact on how the template is rendered, and is ignored
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
304 outside of the extraction process.
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
305
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
306 ``i18n:domain``
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
307 ---------------
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
308
888
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
309 In larger projects, message catalogs are commonly split up into different
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
310 *domains*. For example, you might have a core application domain, and then
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
311 separate domains for extensions or libraries.
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
312
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
313 Genshi provides a directive called ``i18n:domain`` that lets you choose the
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
314 translation domain for a particular scope. For example:
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
315
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
316 .. code-block:: genshi
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
317
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
318 <div i18n:domain="examples">
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
319 <p>Hello, world!</p>
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
320 </div>
7e85b17cc317 More i18n doc improvements.
cmlenz
parents: 887
diff changeset
321
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
322
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
323 Extraction
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
324 ==========
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
325
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
326 The ``Translator`` class provides a class method called ``extract``, which is
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
327 a generator yielding all localizable strings found in a template or markup
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
328 stream. This includes both literal strings in text nodes and attribute values,
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
329 as well as strings in ``gettext()`` calls in embedded Python code. See the API
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
330 documentation for details on how to use this method directly.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
331
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
332 -----------------
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
333 Babel Integration
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
334 -----------------
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
335
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
336 This functionality is integrated with the message extraction framework provided
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
337 by the `Babel`_ project. Babel provides a command-line interface as well as
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
338 commands that can be used from ``setup.py`` scripts using `Setuptools`_ or
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
339 `Distutils`_.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
340
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
341 .. _`setuptools`: http://peak.telecommunity.com/DevCenter/setuptools
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
342 .. _`distutils`: http://docs.python.org/dist/dist.html
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
343
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
344 The first thing you need to do to make Babel extract messages from Genshi
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
345 templates is to let Babel know which files are Genshi templates. This is done
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
346 using a “mapping configuration”, which can be stored in a configuration file,
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
347 or specified directly in your ``setup.py``.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
348
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
349 In a configuration file, the mapping may look like this:
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
350
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
351 .. code-block:: ini
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
352
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
353 # Python souce
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
354 [python:**.py]
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
355
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
356 # Genshi templates
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
357 [genshi:**/templates/**.html]
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
358 include_attrs = title
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
359
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
360 [genshi:**/templates/**.txt]
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
361 template_class = genshi.template.TextTemplate
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
362 encoding = latin-1
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
363
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
364 Please consult the Babel documentation for details on configuration.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
365
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
366 If all goes well, running the extraction with Babel should create a POT file
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
367 containing the strings from your Genshi templates and your Python source files.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
368
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
369
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
370 ---------------------
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
371 Configuration Options
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
372 ---------------------
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
373
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
374 The Genshi extraction plugin for Babel supports the following options:
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
375
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
376 ``template_class``
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
377 ------------------
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
378 The concrete ``Template`` class that the file should be loaded with. Specify
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
379 the package/module name and the class name, separated by a colon.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
380
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
381 The default is to use ``genshi.template:MarkupTemplate``, and you'll want to
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
382 set it to ``genshi.template:TextTemplate`` for `text templates`_.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
383
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
384 .. _`text templates`: text-templates.html
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
385
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
386 ``encoding``
594
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
387 ------------
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
388 The encoding of the template file. This is only used for text templates. The
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
389 default is to assume “utf-8”.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
390
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
391 ``include_attrs``
594
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
392 -----------------
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
393 Comma-separated list of attribute names that should be considered to have
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
394 localizable values. Only used for markup templates.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
395
594
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
396 ``ignore_tags``
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
397 ---------------
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
398 Comma-separated list of tag names that should be ignored. Only used for markup
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
399 templates.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
400
594
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
401 ``extract_text``
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
402 ----------------
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
403 Whether text outside explicit ``gettext`` function calls should be extracted.
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
404 By default, any text nodes not inside ignored tags, and values of attribute in
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
405 the ``include_attrs`` list are extracted. If this option is disabled, only
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
406 strings in ``gettext`` function calls are extracted.
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
407
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
408 .. note:: If you disable this option, it's not necessary to add the translation
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
409 filter as described above. You only need to make sure that the
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
410 template has access to the ``gettext`` functions it uses.
2bbaa61b328f Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 558
diff changeset
411
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
412
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
413 Translation
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
414 ===========
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
415
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
416 If you have prepared MO files for use with Genshi using the appropriate tools,
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
417 you can access the message catalogs with the `gettext Python module`_. You'll
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
418 probably want to create a ``gettext.GNUTranslations`` instance, and make the
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
419 translation functions it provides available to your templates by putting them
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
420 in the template context.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
421
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
422 The ``Translator`` filter needs to be added to the filters of the template
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
423 (applying it as a stream filter will likely not have the desired effect).
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
424 Furthermore it needs to be the first filter in the list, including the internal
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
425 filters that Genshi adds itself:
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
426
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
427 .. code-block:: python
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
428
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
429 from genshi.filters import Translator
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
430 from genshi.template import MarkupTemplate
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
431
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
432 template = MarkupTemplate("...")
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
433 template.filters.insert(0, Translator(translations.ugettext))
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
434
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
435 If you're using `TemplateLoader`, you should specify a callback function in
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
436 which you add the filter:
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
437
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
438 .. code-block:: python
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
439
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
440 from genshi.filters import Translator
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
441 from genshi.template import TemplateLoader
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
442
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
443 def template_loaded(template):
885
b7e8b971d90a Started extending the i18n docs.
cmlenz
parents: 884
diff changeset
444 Translator(translations.ugettext).setup(template)
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
445
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
446 loader = TemplateLoader('templates', callback=template_loaded)
884
e97cdbf09a18 Improve the template loader docs.
cmlenz
parents: 594
diff changeset
447 template = loader.load('test.html')
528
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
448
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
449 This approach ensures that the filter is not added everytime the template is
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
450 loaded, and thus being applied multiple times.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
451
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
452
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
453 Related Considerations
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
454 ======================
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
455
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
456 If you intend to produce an application that is fully prepared for an
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
457 international audience, there are a couple of other things to keep in mind:
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
458
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
459 -------
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
460 Unicode
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
461 -------
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
462
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
463 Use ``unicode`` internally, not encoded bytestrings. Only encode/decode where
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
464 data enters or exits the system. This means that your code works with characters
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
465 and not just with bytes, which is an important distinction for example when
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
466 calculating the length of a piece of text. When you need to decode/encode, it's
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
467 probably a good idea to use UTF-8.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
468
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
469 -------------
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
470 Date and Time
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
471 -------------
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
472
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
473 If your application uses datetime information that should be displayed to users
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
474 in different timezones, you should try to work with UTC (universal time)
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
475 internally. Do the conversion from and to "local time" when the data enters or
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
476 exits the system. Make use the Python `datetime`_ module and the third-party
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
477 `pytz`_ package.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
478
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
479 --------------------------
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
480 Formatting and Locale Data
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
481 --------------------------
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
482
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
483 Make sure you check out the functionality provided by the `Babel`_ project for
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
484 things like number and date formatting, locale display strings, etc.
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
485
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
486 .. _`datetime`: http://docs.python.org/lib/module-datetime.html
24df908da22d Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents:
diff changeset
487 .. _`pytz`: http://pytz.sourceforge.net/
Copyright (C) 2012-2017 Edgewall Software