annotate genshi/filters/i18n.py @ 888:18dee397f8e1

More i18n doc improvements.
author cmlenz
date Mon, 19 Apr 2010 11:45:40 +0000
parents 6f49c23045b1
children b40dbfee9ba6
rev   line source
531
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
1 # -*- coding: utf-8 -*-
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
2 #
850
47297fd93363 Update copyright years on files changed due to advanced-i18n merge.
cmlenz
parents: 849
diff changeset
3 # Copyright (C) 2007-2009 Edgewall Software
531
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
4 # All rights reserved.
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
5 #
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
6 # This software is licensed as described in the file COPYING, which
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
7 # you should have received as part of this distribution. The terms
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
8 # are also available at http://genshi.edgewall.org/wiki/License.
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
9 #
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
10 # This software consists of voluntary contributions made by many
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
11 # individuals. For the exact contribution history, see the revision
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
12 # history and logs, available at http://genshi.edgewall.org/log/.
6bb05c0480fe Add missing copyright header to i18n.py.
cmlenz
parents: 528
diff changeset
13
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
14 """Directives and utilities for internationalization and localization of
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
15 templates.
576
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 565
diff changeset
16
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 565
diff changeset
17 :since: version 0.4
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
18 :note: Directives support added since version 0.6
576
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 565
diff changeset
19 """
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
20
856
1e2be9fb3348 Add a couple of fallback imports for Python 3.0.
cmlenz
parents: 854
diff changeset
21 try:
1e2be9fb3348 Add a couple of fallback imports for Python 3.0.
cmlenz
parents: 854
diff changeset
22 any
1e2be9fb3348 Add a couple of fallback imports for Python 3.0.
cmlenz
parents: 854
diff changeset
23 except NameError:
1e2be9fb3348 Add a couple of fallback imports for Python 3.0.
cmlenz
parents: 854
diff changeset
24 from genshi.util import any
788
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
25 from gettext import NullTranslations
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
26 import os
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
27 import re
788
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
28 from types import FunctionType
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
29
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
30 from genshi.core import Attrs, Namespace, QName, START, END, TEXT, START_NS, \
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
31 END_NS, XML_NAMESPACE, _ensure, StreamEventKind
794
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
32 from genshi.template.eval import _ast
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
33 from genshi.template.base import DirectiveFactory, EXPR, SUB, _apply_directives
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
34 from genshi.template.directives import Directive, StripDirective
528
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
35 from genshi.template.markup import MarkupTemplate, EXEC
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
36
528
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
37 __all__ = ['Translator', 'extract']
501
3073ac688651 Added new markup transformation filter contributed by Alec Thomas (#122). This provides gorgeous jQuery-inspired stream transformation capabilities based on XPath expressions.
cmlenz
parents: 493
diff changeset
38 __docformat__ = 'restructuredtext en'
3073ac688651 Added new markup transformation filter contributed by Alec Thomas (#122). This provides gorgeous jQuery-inspired stream transformation capabilities based on XPath expressions.
cmlenz
parents: 493
diff changeset
39
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
40
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
41 I18N_NAMESPACE = Namespace('http://genshi.edgewall.org/i18n')
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
42
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
43 MSGBUF = StreamEventKind('MSGBUF')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
44 SUB_START = StreamEventKind('SUB_START')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
45 SUB_END = StreamEventKind('SUB_END')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
46
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
47
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
48 class I18NDirective(Directive):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
49 """Simple interface for i18n directives to support messages extraction."""
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
50
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
51 def __call__(self, stream, directives, ctxt, **vars):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
52 return _apply_directives(stream, directives, ctxt, vars)
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
53
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
54
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
55 class ExtractableI18NDirective(I18NDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
56 """Simple interface for directives to support messages extraction."""
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
57
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
58 def extract(self, stream, comment_stack):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
59 raise NotImplementedError
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
60
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
61
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
62 class CommentDirective(I18NDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
63 """Implementation of the ``i18n:comment`` template directive which adds
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
64 translation comments.
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
65
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
66 >>> tmpl = MarkupTemplate('''<html xmlns:i18n="http://genshi.edgewall.org/i18n">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
67 ... <p i18n:comment="As in Foo Bar">Foo</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
68 ... </html>''')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
69 >>> translator = Translator()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
70 >>> translator.setup(tmpl)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
71 >>> list(translator.extract(tmpl.stream))
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
72 [(2, None, u'Foo', [u'As in Foo Bar'])]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
73 """
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
74 __slots__ = ['comment']
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
75
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
76 def __init__(self, value, template, hints=None, namespaces=None,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
77 lineno=-1, offset=-1):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
78 Directive.__init__(self, None, template, namespaces, lineno, offset)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
79 self.comment = value
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
80
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
81
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
82 class MsgDirective(ExtractableI18NDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
83 r"""Implementation of the ``i18n:msg`` directive which marks inner content
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
84 as translatable. Consider the following examples:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
85
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
86 >>> tmpl = MarkupTemplate('''<html xmlns:i18n="http://genshi.edgewall.org/i18n">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
87 ... <div i18n:msg="">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
88 ... <p>Foo</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
89 ... <p>Bar</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
90 ... </div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
91 ... <p i18n:msg="">Foo <em>bar</em>!</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
92 ... </html>''')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
93
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
94 >>> translator = Translator()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
95 >>> translator.setup(tmpl)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
96 >>> list(translator.extract(tmpl.stream))
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
97 [(2, None, u'[1:Foo]\n [2:Bar]', []), (6, None, u'Foo [1:bar]!', [])]
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 850
diff changeset
98 >>> print(tmpl.generate().render())
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
99 <html>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
100 <div><p>Foo</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
101 <p>Bar</p></div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
102 <p>Foo <em>bar</em>!</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
103 </html>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
104
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
105 >>> tmpl = MarkupTemplate('''<html xmlns:i18n="http://genshi.edgewall.org/i18n">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
106 ... <div i18n:msg="fname, lname">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
107 ... <p>First Name: ${fname}</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
108 ... <p>Last Name: ${lname}</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
109 ... </div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
110 ... <p i18n:msg="">Foo <em>bar</em>!</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
111 ... </html>''')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
112 >>> translator.setup(tmpl)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
113 >>> list(translator.extract(tmpl.stream)) #doctest: +NORMALIZE_WHITESPACE
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
114 [(2, None, u'[1:First Name: %(fname)s]\n [2:Last Name: %(lname)s]', []),
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
115 (6, None, u'Foo [1:bar]!', [])]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
116
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
117 >>> tmpl = MarkupTemplate('''<html xmlns:i18n="http://genshi.edgewall.org/i18n">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
118 ... <div i18n:msg="fname, lname">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
119 ... <p>First Name: ${fname}</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
120 ... <p>Last Name: ${lname}</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
121 ... </div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
122 ... <p i18n:msg="">Foo <em>bar</em>!</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
123 ... </html>''')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
124 >>> translator.setup(tmpl)
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 850
diff changeset
125 >>> print(tmpl.generate(fname='John', lname='Doe').render())
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
126 <html>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
127 <div><p>First Name: John</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
128 <p>Last Name: Doe</p></div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
129 <p>Foo <em>bar</em>!</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
130 </html>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
131
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
132 Starting and ending white-space is stripped of to make it simpler for
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
133 translators. Stripping it is not that important since it's on the html
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
134 source, the rendered output will remain the same.
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
135 """
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
136 __slots__ = ['params']
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
137
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
138 def __init__(self, value, template, hints=None, namespaces=None,
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
139 lineno=-1, offset=-1):
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
140 Directive.__init__(self, None, template, namespaces, lineno, offset)
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
141 self.params = [param.strip() for param in value.split(',') if param]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
142
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
143 @classmethod
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
144 def attach(cls, template, stream, value, namespaces, pos):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
145 if type(value) is dict:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
146 value = value.get('params', '').strip()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
147 return super(MsgDirective, cls).attach(template, stream, value.strip(),
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
148 namespaces, pos)
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
149
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
150 def __call__(self, stream, directives, ctxt, **vars):
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
151 gettext = ctxt.get('_i18n.gettext')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
152 dgettext = ctxt.get('_i18n.dgettext')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
153 if ctxt.get('_i18n.domain'):
854
0d9e87c6cf6e More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
154 assert hasattr(dgettext, '__call__'), \
0d9e87c6cf6e More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
155 'No domain gettext function passed'
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
156 gettext = lambda msg: dgettext(ctxt.get('_i18n.domain'), msg)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
157
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
158 def _generate():
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
159 msgbuf = MessageBuffer(self)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
160 previous = stream.next()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
161 if previous[0] is START:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
162 yield previous
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
163 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
164 msgbuf.append(*previous)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
165 previous = stream.next()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
166 for kind, data, pos in stream:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
167 msgbuf.append(*previous)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
168 previous = kind, data, pos
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
169 if previous[0] is not END:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
170 msgbuf.append(*previous)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
171 previous = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
172 for event in msgbuf.translate(gettext(msgbuf.format())):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
173 yield event
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
174 if previous:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
175 yield previous
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
176
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
177 return _apply_directives(_generate(), directives, ctxt, vars)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
178
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
179 def extract(self, stream, comment_stack):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
180 msgbuf = MessageBuffer(self)
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
181
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
182 stream = iter(stream)
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
183 previous = stream.next()
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
184 if previous[0] is START:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
185 previous = stream.next()
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
186 for event in stream:
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
187 msgbuf.append(*previous)
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
188 previous = event
869
38c44e2f4232 Apply patch for I18n message extraction bug as reported in #358. Thanks to cboos for the patch, again.
cmlenz
parents: 856
diff changeset
189 msgbuf.append(*previous)
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
190
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
191 yield None, msgbuf.format(), comment_stack[-1:]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
192
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
193
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
194 class ChooseBranchDirective(I18NDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
195 __slots__ = ['params']
871
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
196
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
197 def __call__(self, stream, directives, ctxt, **vars):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
198 self.params = ctxt.get('_i18n.choose.params', [])[:]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
199 msgbuf = MessageBuffer(self)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
200
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
201 stream = iter(_apply_directives(stream, directives, ctxt, vars))
871
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
202
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
203 previous = stream.next()
871
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
204 if previous[0] is START:
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
205 yield previous
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
206 else:
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
207 msgbuf.append(*previous)
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
208
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
209 try:
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
210 previous = stream.next()
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
211 except StopIteration:
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
212 # For example <i18n:singular> or <i18n:plural> directives
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
213 yield MSGBUF, (), -1 # the place holder for msgbuf output
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
214 ctxt['_i18n.choose.%s' % type(self).__name__] = msgbuf
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
215 return
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
216
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
217 for kind, data, pos in stream:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
218 msgbuf.append(*previous)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
219 previous = kind, data, pos
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
220 yield MSGBUF, (), -1 # the place holder for msgbuf output
871
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
221
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
222 if previous[0] is END:
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
223 yield previous # the outer end tag
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
224 else:
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
225 msgbuf.append(*previous)
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
226 ctxt['_i18n.choose.%s' % type(self).__name__] = msgbuf
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
227
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
228
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
229 def extract(self, stream, comment_stack, msgbuf):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
230 stream = iter(stream)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
231 previous = stream.next()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
232 if previous[0] is START:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
233 previous = stream.next()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
234 for event in stream:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
235 msgbuf.append(*previous)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
236 previous = event
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
237 if previous[0] is not END:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
238 msgbuf.append(*previous)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
239 return msgbuf
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
240
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
241
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
242 class SingularDirective(ChooseBranchDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
243 """Implementation of the ``i18n:singular`` directive to be used with the
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
244 ``i18n:choose`` directive."""
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
245
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
246
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
247 class PluralDirective(ChooseBranchDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
248 """Implementation of the ``i18n:plural`` directive to be used with the
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
249 ``i18n:choose`` directive."""
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
250
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
251
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
252 class ChooseDirective(ExtractableI18NDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
253 """Implementation of the ``i18n:choose`` directive which provides plural
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
254 internationalisation of strings.
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
255
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
256 This directive requires at least one parameter, the one which evaluates to
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
257 an integer which will allow to choose the plural/singular form. If you also
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
258 have expressions inside the singular and plural version of the string you
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
259 also need to pass a name for those parameters. Consider the following
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
260 examples:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
261
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
262 >>> tmpl = MarkupTemplate('''\
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
263 <html xmlns:i18n="http://genshi.edgewall.org/i18n">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
264 ... <div i18n:choose="num; num">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
265 ... <p i18n:singular="">There is $num coin</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
266 ... <p i18n:plural="">There are $num coins</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
267 ... </div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
268 ... </html>''')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
269 >>> translator = Translator()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
270 >>> translator.setup(tmpl)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
271 >>> list(translator.extract(tmpl.stream)) #doctest: +NORMALIZE_WHITESPACE
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
272 [(2, 'ngettext', (u'There is %(num)s coin',
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
273 u'There are %(num)s coins'), [])]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
274
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
275 >>> tmpl = MarkupTemplate('''\
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
276 <html xmlns:i18n="http://genshi.edgewall.org/i18n">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
277 ... <div i18n:choose="num; num">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
278 ... <p i18n:singular="">There is $num coin</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
279 ... <p i18n:plural="">There are $num coins</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
280 ... </div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
281 ... </html>''')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
282 >>> translator.setup(tmpl)
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 850
diff changeset
283 >>> print(tmpl.generate(num=1).render())
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
284 <html>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
285 <div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
286 <p>There is 1 coin</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
287 </div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
288 </html>
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 850
diff changeset
289 >>> print(tmpl.generate(num=2).render())
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
290 <html>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
291 <div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
292 <p>There are 2 coins</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
293 </div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
294 </html>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
295
888
18dee397f8e1 More i18n doc improvements.
cmlenz
parents: 882
diff changeset
296 When used as a element and not as an attribute:
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
297
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
298 >>> tmpl = MarkupTemplate('''\
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
299 <html xmlns:i18n="http://genshi.edgewall.org/i18n">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
300 ... <i18n:choose numeral="num" params="num">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
301 ... <p i18n:singular="">There is $num coin</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
302 ... <p i18n:plural="">There are $num coins</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
303 ... </i18n:choose>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
304 ... </html>''')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
305 >>> translator.setup(tmpl)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
306 >>> list(translator.extract(tmpl.stream)) #doctest: +NORMALIZE_WHITESPACE
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
307 [(2, 'ngettext', (u'There is %(num)s coin',
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
308 u'There are %(num)s coins'), [])]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
309 """
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
310 __slots__ = ['numeral', 'params']
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
311
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
312 def __init__(self, value, template, hints=None, namespaces=None,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
313 lineno=-1, offset=-1):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
314 Directive.__init__(self, None, template, namespaces, lineno, offset)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
315 params = [v.strip() for v in value.split(';')]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
316 self.numeral = self._parse_expr(params.pop(0), template, lineno, offset)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
317 self.params = params and [name.strip() for name in
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
318 params[0].split(',') if name] or []
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
319
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
320 @classmethod
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
321 def attach(cls, template, stream, value, namespaces, pos):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
322 if type(value) is dict:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
323 numeral = value.get('numeral', '').strip()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
324 assert numeral is not '', "at least pass the numeral param"
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
325 params = [v.strip() for v in value.get('params', '').split(',')]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
326 value = '%s; ' % numeral + ', '.join(params)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
327 return super(ChooseDirective, cls).attach(template, stream, value,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
328 namespaces, pos)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
329
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
330 def __call__(self, stream, directives, ctxt, **vars):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
331 ctxt.push({'_i18n.choose.params': self.params,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
332 '_i18n.choose.SingularDirective': None,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
333 '_i18n.choose.PluralDirective': None})
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
334
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
335 new_stream = []
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
336 singular_stream = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
337 singular_msgbuf = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
338 plural_stream = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
339 plural_msgbuf = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
340
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
341 ngettext = ctxt.get('_i18n.ungettext')
854
0d9e87c6cf6e More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
342 assert hasattr(ngettext, '__call__'), 'No ngettext function available'
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
343 dngettext = ctxt.get('_i18n.dngettext')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
344 if not dngettext:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
345 dngettext = lambda d, s, p, n: ngettext(s, p, n)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
346 for kind, event, pos in stream:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
347 if kind is SUB:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
348 subdirectives, substream = event
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
349 if isinstance(subdirectives[0],
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
350 SingularDirective) and not singular_stream:
873
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
351 strip_directive_present = []
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
352 for idx, subdirective in enumerate(subdirectives):
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
353 if isinstance(subdirective, StripDirective):
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
354 # Any strip directive should be applied AFTER
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
355 # the event's have been translated.
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
356 strip_directive_present.append(
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
357 subdirectives.pop(idx)
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
358 )
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
359 # Apply directives to update context
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
360 singular_stream = list(_apply_directives(substream,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
361 subdirectives,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
362 ctxt, vars))
871
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
363 if strip_directive_present:
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
364 singular_stream = list(
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
365 _apply_directives(singular_stream,
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
366 strip_directive_present,
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
367 ctxt, vars)
7eb6f506bb54 Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes.
palgarvio
parents: 869
diff changeset
368 )
873
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
369 del strip_directive_present
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
370 new_stream.append((MSGBUF, (), ('', -1))) # msgbuf place holder
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
371 singular_msgbuf = ctxt.get('_i18n.choose.SingularDirective')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
372 elif isinstance(subdirectives[0],
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
373 PluralDirective) and not plural_stream:
873
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
374 strip_directive_present = []
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
375 for idx, subdirective in enumerate(subdirectives):
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
376 if isinstance(subdirective, StripDirective):
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
377 # Any strip directive should be applied AFTER
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
378 # the event's have been translated.
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
379 strip_directive_present.append(
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
380 subdirectives.pop(idx)
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
381 )
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
382 # Apply directives to update context
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
383 plural_stream = list(_apply_directives(substream,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
384 subdirectives,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
385 ctxt, vars))
873
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
386 if strip_directive_present:
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
387 plural_stream = list(
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
388 _apply_directives(plural_stream,
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
389 strip_directive_present,
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
390 ctxt, vars)
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
391 )
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
392 del strip_directive_present
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
393 plural_msgbuf = ctxt.get('_i18n.choose.PluralDirective')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
394 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
395 new_stream.append((kind, event, pos))
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
396 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
397 new_stream.append((kind, event, pos))
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
398
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
399 if ctxt.get('_i18n.domain'):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
400 ngettext = lambda s, p, n: dngettext(ctxt.get('_i18n.domain'),
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
401 s, p, n)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
402
873
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
403 # XXX: should we test which form was chosen like this!?!?!?
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
404 # There should be no match in any catalogue for these singular and
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
405 # plural test strings
882
6f49c23045b1 Fix regression in [1099]: templates must not have an implicit loader during message extraction.
cmlenz
parents: 873
diff changeset
406 singular_test = u'O\x85\xbe\xa9\xa8az\xc3?\xe6\xa1\x02n\x84\x93'
6f49c23045b1 Fix regression in [1099]: templates must not have an implicit loader during message extraction.
cmlenz
parents: 873
diff changeset
407 plural_test = u'\xcc\xfb+\xd3Pn\x9d\tT\xec\x1d\xda\x1a\x88\x00'
873
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
408 translation = ngettext(singular_test, plural_test,
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
409 self.numeral.evaluate(ctxt))
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
410 if translation==singular_test:
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
411 chosen_msgbuf = singular_msgbuf
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
412 chosen_stream = singular_stream
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
413 else:
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
414 chosen_msgbuf = plural_msgbuf
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
415 chosen_stream = plural_stream
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
416 del singular_test, plural_test, translation
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
417
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
418 for kind, data, pos in new_stream:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
419 if kind is MSGBUF:
873
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
420 for skind, sdata, spos in chosen_stream:
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
421 if skind is MSGBUF:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
422 translation = ngettext(singular_msgbuf.format(),
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
423 plural_msgbuf.format(),
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
424 self.numeral.evaluate(ctxt))
873
9786aa263217 Any `py:strip` involved on `i18n:singular` or `i18n:plural` is now handled separately, ie, if one has `py:strip` on a `i18n:singular` element or directive and the plural form is the one chosen, no stripping will be performed. Refs #371.
palgarvio
parents: 872
diff changeset
425 for event in chosen_msgbuf.translate(translation):
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
426 yield event
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
427 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
428 yield skind, sdata, spos
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
429 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
430 yield kind, data, pos
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
431
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
432 ctxt.pop()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
433
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
434 def extract(self, stream, comment_stack):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
435 stream = iter(stream)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
436 previous = stream.next()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
437 if previous is START:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
438 stream.next()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
439
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
440 singular_msgbuf = MessageBuffer(self)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
441 plural_msgbuf = MessageBuffer(self)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
442
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
443 for kind, event, pos in stream:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
444 if kind is SUB:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
445 subdirectives, substream = event
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
446 for subdirective in subdirectives:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
447 if isinstance(subdirective, SingularDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
448 singular_msgbuf = subdirective.extract(substream, comment_stack,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
449 singular_msgbuf)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
450 elif isinstance(subdirective, PluralDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
451 plural_msgbuf = subdirective.extract(substream, comment_stack,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
452 plural_msgbuf)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
453 elif not isinstance(subdirective, StripDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
454 singular_msgbuf.append(kind, event, pos)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
455 plural_msgbuf.append(kind, event, pos)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
456 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
457 singular_msgbuf.append(kind, event, pos)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
458 plural_msgbuf.append(kind, event, pos)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
459
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
460 yield 'ngettext', \
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
461 (singular_msgbuf.format(), plural_msgbuf.format()), \
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
462 comment_stack[-1:]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
463
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
464
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
465 class DomainDirective(I18NDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
466 """Implementation of the ``i18n:domain`` directive which allows choosing
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
467 another i18n domain(catalog) to translate from.
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
468
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
469 >>> from genshi.filters.tests.i18n import DummyTranslations
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
470 >>> tmpl = MarkupTemplate('''\
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
471 <html xmlns:i18n="http://genshi.edgewall.org/i18n">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
472 ... <p i18n:msg="">Bar</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
473 ... <div i18n:domain="foo">
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
474 ... <p i18n:msg="">FooBar</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
475 ... <p>Bar</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
476 ... <p i18n:domain="bar" i18n:msg="">Bar</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
477 ... <p i18n:domain="">Bar</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
478 ... </div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
479 ... <p>Bar</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
480 ... </html>''')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
481
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
482 >>> translations = DummyTranslations({'Bar': 'Voh'})
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
483 >>> translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'foo_Bar'})
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
484 >>> translations.add_domain('bar', {'Bar': 'bar_Bar'})
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
485 >>> translator = Translator(translations)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
486 >>> translator.setup(tmpl)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
487
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 850
diff changeset
488 >>> print(tmpl.generate().render())
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
489 <html>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
490 <p>Voh</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
491 <div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
492 <p>BarFoo</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
493 <p>foo_Bar</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
494 <p>bar_Bar</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
495 <p>Voh</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
496 </div>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
497 <p>Voh</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
498 </html>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
499 """
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
500 __slots__ = ['domain']
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
501
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
502 def __init__(self, value, template, hints=None, namespaces=None,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
503 lineno=-1, offset=-1):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
504 Directive.__init__(self, None, template, namespaces, lineno, offset)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
505 self.domain = value and value.strip() or '__DEFAULT__'
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
506
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
507 @classmethod
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
508 def attach(cls, template, stream, value, namespaces, pos):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
509 if type(value) is dict:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
510 value = value.get('name')
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
511 return super(DomainDirective, cls).attach(template, stream, value,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
512 namespaces, pos)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
513
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
514 def __call__(self, stream, directives, ctxt, **vars):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
515 ctxt.push({'_i18n.domain': self.domain})
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
516 for event in _apply_directives(stream, directives, ctxt, vars):
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
517 yield event
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
518 ctxt.pop()
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
519
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
520
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
521 class Translator(DirectiveFactory):
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
522 """Can extract and translate localizable strings from markup streams and
450
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
523 templates.
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
524
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
525 For example, assume the following template:
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
526
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
527 >>> tmpl = MarkupTemplate('''<html xmlns:py="http://genshi.edgewall.org/">
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
528 ... <head>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
529 ... <title>Example</title>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
530 ... </head>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
531 ... <body>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
532 ... <h1>Example</h1>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
533 ... <p>${_("Hello, %(name)s") % dict(name=username)}</p>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
534 ... </body>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
535 ... </html>''', filename='example.html')
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
536
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
537 For demonstration, we define a dummy ``gettext``-style function with a
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
538 hard-coded translation table, and pass that to the `Translator` initializer:
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
539
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
540 >>> def pseudo_gettext(string):
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
541 ... return {
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
542 ... 'Example': 'Beispiel',
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
543 ... 'Hello, %(name)s': 'Hallo, %(name)s'
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
544 ... }[string]
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
545 >>> translator = Translator(pseudo_gettext)
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
546
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
547 Next, the translator needs to be prepended to any already defined filters
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
548 on the template:
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
549
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
550 >>> tmpl.filters.insert(0, translator)
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
551
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
552 When generating the template output, our hard-coded translations should be
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
553 applied as expected:
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
554
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 850
diff changeset
555 >>> print(tmpl.generate(username='Hans', _=pseudo_gettext))
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
556 <html>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
557 <head>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
558 <title>Beispiel</title>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
559 </head>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
560 <body>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
561 <h1>Beispiel</h1>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
562 <p>Hallo, Hans</p>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
563 </body>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
564 </html>
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
565
522
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
566 Note that elements defining ``xml:lang`` attributes that do not contain
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
567 variable expressions are ignored by this filter. That can be used to
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
568 exclude specific parts of a template from being extracted and translated.
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
569 """
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
570
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
571 directives = [
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
572 ('domain', DomainDirective),
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
573 ('comment', CommentDirective),
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
574 ('msg', MsgDirective),
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
575 ('choose', ChooseDirective),
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
576 ('singular', SingularDirective),
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
577 ('plural', PluralDirective)
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
578 ]
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
579
450
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
580 IGNORE_TAGS = frozenset([
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
581 QName('script'), QName('http://www.w3.org/1999/xhtml}script'),
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
582 QName('style'), QName('http://www.w3.org/1999/xhtml}style')
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
583 ])
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
584 INCLUDE_ATTRS = frozenset([
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
585 'abbr', 'alt', 'label', 'prompt', 'standby', 'summary', 'title'
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
586 ])
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
587 NAMESPACE = I18N_NAMESPACE
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
588
788
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
589 def __init__(self, translate=NullTranslations(), ignore_tags=IGNORE_TAGS,
594
0fb43dc2e165 Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 576
diff changeset
590 include_attrs=INCLUDE_ATTRS, extract_text=True):
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
591 """Initialize the translator.
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
592
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
593 :param translate: the translation function, for example ``gettext`` or
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
594 ``ugettext``.
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
595 :param ignore_tags: a set of tag names that should not be localized
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
596 :param include_attrs: a set of attribute names should be localized
594
0fb43dc2e165 Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 576
diff changeset
597 :param extract_text: whether the content of text nodes should be
0fb43dc2e165 Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 576
diff changeset
598 extracted, or only text in explicit ``gettext``
0fb43dc2e165 Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 576
diff changeset
599 function calls
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
600
788
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
601 :note: Changed in 0.6: the `translate` parameter can now be either
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
602 a ``gettext``-style function, or an object compatible with the
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
603 ``NullTransalations`` or ``GNUTranslations`` interface
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
604 """
450
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
605 self.translate = translate
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
606 self.ignore_tags = ignore_tags
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
607 self.include_attrs = include_attrs
594
0fb43dc2e165 Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 576
diff changeset
608 self.extract_text = extract_text
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
609
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
610 def __call__(self, stream, ctxt=None, search_text=True):
448
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
611 """Translate any localizable strings in the given stream.
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
612
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
613 This function shouldn't be called directly. Instead, an instance of
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
614 the `Translator` class should be registered as a filter with the
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
615 `Template` or the `TemplateLoader`, or applied as a regular stream
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
616 filter. If used as a template filter, it should be inserted in front of
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
617 all the default filters.
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
618
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
619 :param stream: the markup event stream
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
620 :param ctxt: the template context (not used)
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
621 :param search_text: whether text nodes should be translated (used
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
622 internally)
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
623 :return: the localized stream
0407937b2853 Add support for HTML5 doctype.
cmlenz
parents: 446
diff changeset
624 """
450
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
625 ignore_tags = self.ignore_tags
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
626 include_attrs = self.include_attrs
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
627 skip = 0
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
628 xml_lang = XML_NAMESPACE['lang']
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
629
788
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
630 if type(self.translate) is FunctionType:
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
631 gettext = self.translate
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
632 if ctxt:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
633 ctxt['_i18n.gettext'] = gettext
788
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
634 else:
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
635 gettext = self.translate.ugettext
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
636 try:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
637 dgettext = self.translate.dugettext
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
638 except AttributeError:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
639 dgettext = lambda x, y: gettext(y)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
640 ngettext = self.translate.ungettext
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
641 try:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
642 dngettext = self.translate.dungettext
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
643 except AttributeError:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
644 dngettext = lambda d, s, p, n: ngettext(s, p, n)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
645
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
646 if ctxt:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
647 ctxt['_i18n.gettext'] = gettext
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
648 ctxt['_i18n.ugettext'] = gettext
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
649 ctxt['_i18n.dgettext'] = dgettext
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
650 ctxt['_i18n.ngettext'] = ngettext
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
651 ctxt['_i18n.ungettext'] = ngettext
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
652 ctxt['_i18n.dngettext'] = dngettext
787
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
653
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
654 extract_text = self.extract_text
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
655 if not extract_text:
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
656 search_text = False
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
657
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
658 if ctxt and ctxt.get('_i18n.domain'):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
659 old_gettext = gettext
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
660 gettext = lambda msg: dgettext(ctxt.get('_i18n.domain'), msg)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
661
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
662 for kind, data, pos in stream:
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
663
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
664 # skip chunks that should not be localized
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
665 if skip:
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
666 if kind is START:
522
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
667 skip += 1
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
668 elif kind is END:
522
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
669 skip -= 1
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
670 yield kind, data, pos
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
671 continue
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
672
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
673 # handle different events that can be localized
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
674 if kind is START:
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
675 tag, attrs = data
522
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
676 if tag in self.ignore_tags or \
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
677 isinstance(attrs.get(xml_lang), basestring):
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
678 skip += 1
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
679 yield kind, data, pos
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
680 continue
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
681
493
abe6e4ab7ecf Fix another bug in the translation filter: translated attributes were getting added instead of replaced.
cmlenz
parents: 485
diff changeset
682 new_attrs = []
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
683 changed = False
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
684
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
685 for name, value in attrs:
483
dabb9e1e2ba1 Fix for handling of interpolated attribute values in translation filter.
cmlenz
parents: 481
diff changeset
686 newval = value
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
687 if extract_text and isinstance(value, basestring):
483
dabb9e1e2ba1 Fix for handling of interpolated attribute values in translation filter.
cmlenz
parents: 481
diff changeset
688 if name in include_attrs:
788
09531799bac2 Change `Translator` class to accept either a `gettext`-style function, or an object compatible with the `NullTranslations` / `GNUTranslations` interface.
cmlenz
parents: 787
diff changeset
689 newval = gettext(value)
483
dabb9e1e2ba1 Fix for handling of interpolated attribute values in translation filter.
cmlenz
parents: 481
diff changeset
690 else:
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
691 newval = list(
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
692 self(_ensure(value), ctxt, search_text=False)
483
dabb9e1e2ba1 Fix for handling of interpolated attribute values in translation filter.
cmlenz
parents: 481
diff changeset
693 )
dabb9e1e2ba1 Fix for handling of interpolated attribute values in translation filter.
cmlenz
parents: 481
diff changeset
694 if newval != value:
dabb9e1e2ba1 Fix for handling of interpolated attribute values in translation filter.
cmlenz
parents: 481
diff changeset
695 value = newval
dabb9e1e2ba1 Fix for handling of interpolated attribute values in translation filter.
cmlenz
parents: 481
diff changeset
696 changed = True
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
697 new_attrs.append((name, value))
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
698 if changed:
667
077c9142dca0 Fix case where attributes weren't properly wrapped in an `Attrs` instance if one or more of them were translated by the I18n filter, potentially breaking things further down the chain. Closes #162.
cmlenz
parents: 600
diff changeset
699 attrs = Attrs(new_attrs)
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
700
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
701 yield kind, (tag, attrs), pos
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
702
485
770ba8556940 Follow-up to [583]: Don't extract strings from interpolated attribute values for attributes that shouldn't be included.
cmlenz
parents: 483
diff changeset
703 elif search_text and kind is TEXT:
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
704 text = data.strip()
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
705 if text:
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
706 data = data.replace(text, unicode(gettext(text)))
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
707 yield kind, data, pos
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
708
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
709 elif kind is SUB:
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
710 directives, substream = data
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
711 current_domain = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
712 for idx, directive in enumerate(directives):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
713 # Organize directives to make everything work
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
714 if isinstance(directive, DomainDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
715 # Grab current domain and update context
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
716 current_domain = directive.domain
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
717 ctxt.push({'_i18n.domain': current_domain})
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
718 # Put domain directive as the first one in order to
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
719 # update context before any other directives evaluation
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
720 directives.insert(0, directives.pop(idx))
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
721
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
722 # If this is an i18n directive, no need to translate text
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
723 # nodes here
856
1e2be9fb3348 Add a couple of fallback imports for Python 3.0.
cmlenz
parents: 854
diff changeset
724 is_i18n_directive = any([
1e2be9fb3348 Add a couple of fallback imports for Python 3.0.
cmlenz
parents: 854
diff changeset
725 isinstance(d, ExtractableI18NDirective)
1e2be9fb3348 Add a couple of fallback imports for Python 3.0.
cmlenz
parents: 854
diff changeset
726 for d in directives
1e2be9fb3348 Add a couple of fallback imports for Python 3.0.
cmlenz
parents: 854
diff changeset
727 ])
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
728 substream = list(self(substream, ctxt,
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
729 search_text=not is_i18n_directive))
790
1b6968d31089 Merged the custom-directives branch back into trunk.
cmlenz
parents: 788
diff changeset
730 yield kind, (directives, substream), pos
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
731
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
732 if current_domain:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
733 ctxt.pop()
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
734 else:
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
735 yield kind, data, pos
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
736
450
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
737 GETTEXT_FUNCTIONS = ('_', 'gettext', 'ngettext', 'dgettext', 'dngettext',
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
738 'ugettext', 'ungettext')
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
739
485
770ba8556940 Follow-up to [583]: Don't extract strings from interpolated attribute values for attributes that shouldn't be included.
cmlenz
parents: 483
diff changeset
740 def extract(self, stream, gettext_functions=GETTEXT_FUNCTIONS,
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
741 search_text=True, msgbuf=None, comment_stack=None):
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
742 """Extract localizable strings from the given template stream.
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
743
450
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
744 For every string found, this function yields a ``(lineno, function,
787
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
745 message, comments)`` tuple, where:
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
746
450
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
747 * ``lineno`` is the number of the line on which the string was found,
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
748 * ``function`` is the name of the ``gettext`` function used (if the
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
749 string was extracted from embedded Python code), and
469
5eae4a5c42ac The I18n extraction now returns a tuple of strings for `ngettext` and similar functions.
cmlenz
parents: 467
diff changeset
750 * ``message`` is the string itself (a ``unicode`` object, or a tuple
787
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
751 of ``unicode`` objects for functions with multiple string
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
752 arguments).
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
753 * ``comments`` is a list of comments related to the message, extracted
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
754 from ``i18n:comment`` attributes found in the markup
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
755
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
756 >>> tmpl = MarkupTemplate('''<html xmlns:py="http://genshi.edgewall.org/">
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
757 ... <head>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
758 ... <title>Example</title>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
759 ... </head>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
760 ... <body>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
761 ... <h1>Example</h1>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
762 ... <p>${_("Hello, %(name)s") % dict(name=username)}</p>
469
5eae4a5c42ac The I18n extraction now returns a tuple of strings for `ngettext` and similar functions.
cmlenz
parents: 467
diff changeset
763 ... <p>${ngettext("You have %d item", "You have %d items", num)}</p>
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
764 ... </body>
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
765 ... </html>''', filename='example.html')
787
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
766 >>> for line, func, msg, comments in Translator().extract(tmpl.stream):
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 850
diff changeset
767 ... print('%d, %r, %r' % (line, func, msg))
450
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
768 3, None, u'Example'
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
769 6, None, u'Example'
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
770 7, '_', u'Hello, %(name)s'
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
771 8, 'ngettext', (u'You have %d item', u'You have %d items', None)
469
5eae4a5c42ac The I18n extraction now returns a tuple of strings for `ngettext` and similar functions.
cmlenz
parents: 467
diff changeset
772
450
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
773 :param stream: the event stream to extract strings from; can be a
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
774 regular stream or a template stream
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
775 :param gettext_functions: a sequence of function names that should be
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
776 treated as gettext-style localization
d2fdcd320743 Extend the I18n extraction to also yield function names if applicable.
cmlenz
parents: 448
diff changeset
777 functions
485
770ba8556940 Follow-up to [583]: Don't extract strings from interpolated attribute values for attributes that shouldn't be included.
cmlenz
parents: 483
diff changeset
778 :param search_text: whether the content of text nodes should be
770ba8556940 Follow-up to [583]: Don't extract strings from interpolated attribute values for attributes that shouldn't be included.
cmlenz
parents: 483
diff changeset
779 extracted (used internally)
469
5eae4a5c42ac The I18n extraction now returns a tuple of strings for `ngettext` and similar functions.
cmlenz
parents: 467
diff changeset
780
5eae4a5c42ac The I18n extraction now returns a tuple of strings for `ngettext` and similar functions.
cmlenz
parents: 467
diff changeset
781 :note: Changed in 0.4.1: For a function with multiple string arguments
5eae4a5c42ac The I18n extraction now returns a tuple of strings for `ngettext` and similar functions.
cmlenz
parents: 467
diff changeset
782 (such as ``ngettext``), a single item with a tuple of strings is
5eae4a5c42ac The I18n extraction now returns a tuple of strings for `ngettext` and similar functions.
cmlenz
parents: 467
diff changeset
783 yielded, instead an item for each string argument.
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
784 :note: Changed in 0.6: The returned tuples now include a fourth
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
785 element, which is a list of comments for the translator.
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
786 """
594
0fb43dc2e165 Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 576
diff changeset
787 if not self.extract_text:
0fb43dc2e165 Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 576
diff changeset
788 search_text = False
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
789 if comment_stack is None:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
790 comment_stack = []
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
791 skip = 0
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
792
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
793 # Un-comment bellow to extract messages without adding directives
522
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
794 xml_lang = XML_NAMESPACE['lang']
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
795
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
796 for kind, data, pos in stream:
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
797 if skip:
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
798 if kind is START:
522
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
799 skip += 1
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
800 if kind is END:
522
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
801 skip -= 1
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
802
549
da5cbf6d134d The I18n filter now extracts text from translation functions in ignored tags. Fixes #132.
cmlenz
parents: 535
diff changeset
803 if kind is START and not skip:
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
804 tag, attrs = data
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
805
522
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
806 if tag in self.ignore_tags or \
c1738dec04d9 The I18n filter now skips the content of elements that have an `xml:lang` attribute with a fixed string value. Basically, `xml:lang` can now be used as a flag to mark specific sections as not needing localization.
cmlenz
parents: 501
diff changeset
807 isinstance(attrs.get(xml_lang), basestring):
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
808 skip += 1
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
809 continue
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
810
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
811 for name, value in attrs:
594
0fb43dc2e165 Add option to I18n filter to only extract strings in gettext function calls.
cmlenz
parents: 576
diff changeset
812 if search_text and isinstance(value, basestring):
483
dabb9e1e2ba1 Fix for handling of interpolated attribute values in translation filter.
cmlenz
parents: 481
diff changeset
813 if name in self.include_attrs:
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
814 text = value.strip()
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
815 if text:
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
816 # XXX: Do we need to grab i18n:comment from comment_stack ???
787
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
817 yield pos[1], None, text, []
483
dabb9e1e2ba1 Fix for handling of interpolated attribute values in translation filter.
cmlenz
parents: 481
diff changeset
818 else:
787
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
819 for lineno, funcname, text, comments in self.extract(
485
770ba8556940 Follow-up to [583]: Don't extract strings from interpolated attribute values for attributes that shouldn't be included.
cmlenz
parents: 483
diff changeset
820 _ensure(value), gettext_functions,
535
c8806216aec4 The I18n filter no longer extracts or translates literal strings in attribute values that also contain expressions.
cmlenz
parents: 531
diff changeset
821 search_text=False):
787
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
822 yield lineno, funcname, text, comments
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
823
561
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
824 if msgbuf:
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
825 msgbuf.append(kind, data, pos)
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
826
549
da5cbf6d134d The I18n filter now extracts text from translation functions in ignored tags. Fixes #132.
cmlenz
parents: 535
diff changeset
827 elif not skip and search_text and kind is TEXT:
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
828 if not msgbuf:
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
829 text = data.strip()
854
0d9e87c6cf6e More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
830 if text and [ch for ch in text if ch.isalpha()]:
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
831 yield pos[1], None, text, comment_stack[-1:]
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
832 else:
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
833 msgbuf.append(kind, data, pos)
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
834
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
835 elif not skip and msgbuf and kind is END:
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
836 msgbuf.append(kind, data, pos)
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
837 if not msgbuf.depth:
854
0d9e87c6cf6e More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
838 yield msgbuf.lineno, None, msgbuf.format(), [
0d9e87c6cf6e More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
839 c for c in msgbuf.comment if c
0d9e87c6cf6e More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
840 ]
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
841 msgbuf = None
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
842
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
843 elif kind is EXPR or kind is EXEC:
775
f0f1416a814f Support for parameters in internationalized `i18n:msg` content. See #129.
cmlenz
parents: 762
diff changeset
844 if msgbuf:
f0f1416a814f Support for parameters in internationalized `i18n:msg` content. See #129.
cmlenz
parents: 762
diff changeset
845 msgbuf.append(kind, data, pos)
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
846 for funcname, strings in extract_from_code(data,
561
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
847 gettext_functions):
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
848 # XXX: Do we need to grab i18n:comment from comment_stack ???
787
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
849 yield pos[1], funcname, strings, []
446
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
850
90f5908cd10a Add basic I18n/L10n functionality, based on GenshiRecipes/Localization.
cmlenz
parents:
diff changeset
851 elif kind is SUB:
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
852 directives, substream = data
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
853 in_comment = False
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
854
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
855 for idx, directive in enumerate(directives):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
856 # Do a first loop to see if there's a comment directive
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
857 # If there is update context and pop it from directives
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
858 if isinstance(directive, CommentDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
859 in_comment = True
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
860 comment_stack.append(directive.comment)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
861 if len(directives) == 1:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
862 # in case we're in the presence of something like:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
863 # <p i18n:comment="foo">Foo</p>
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
864 messages = self.extract(
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
865 substream, gettext_functions,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
866 search_text=search_text and not skip,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
867 msgbuf=msgbuf, comment_stack=comment_stack)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
868 for lineno, funcname, text, comments in messages:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
869 yield lineno, funcname, text, comments
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
870 directives.pop(idx)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
871 elif not isinstance(directive, I18NDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
872 # Remove all other non i18n directives from the process
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
873 directives.pop(idx)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
874
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
875 if not directives and not in_comment:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
876 # Extract content if there's no directives because
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
877 # strip was pop'ed and not because comment was pop'ed.
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
878 # Extraction in this case has been taken care of.
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
879 messages = self.extract(
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
880 substream, gettext_functions,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
881 search_text=search_text and not skip, msgbuf=msgbuf)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
882 for lineno, funcname, text, comments in messages:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
883 yield lineno, funcname, text, comments
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
884
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
885 for directive in directives:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
886 if isinstance(directive, ExtractableI18NDirective):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
887 messages = directive.extract(substream, comment_stack)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
888 for funcname, text, comments in messages:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
889 yield pos[1], funcname, text, comments
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
890 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
891 messages = self.extract(
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
892 substream, gettext_functions,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
893 search_text=search_text and not skip, msgbuf=msgbuf)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
894 for lineno, funcname, text, comments in messages:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
895 yield lineno, funcname, text, comments
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
896
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
897 if in_comment:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
898 comment_stack.pop()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
899
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
900 def get_directive_index(self, dir_cls):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
901 total = len(self._dir_order)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
902 if dir_cls in self._dir_order:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
903 return self._dir_order.index(dir_cls) - total
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
904 return total
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
905
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
906 def setup(self, template):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
907 """Convenience function to register the `Translator` filter and the
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
908 related directives with the given template.
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
909
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
910 :param template: a `Template` instance
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
911 """
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
912 template.filters.insert(0, self)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
913 if hasattr(template, 'add_directives'):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
914 template.add_directives(Translator.NAMESPACE, self)
528
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
915
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
916
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
917 class MessageBuffer(object):
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
918 """Helper class for managing internationalized mixed content.
576
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 565
diff changeset
919
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 565
diff changeset
920 :since: version 0.5
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 565
diff changeset
921 """
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
922
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
923 def __init__(self, directive=None):
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
924 """Initialize the message buffer.
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
925
882
6f49c23045b1 Fix regression in [1099]: templates must not have an implicit loader during message extraction.
cmlenz
parents: 873
diff changeset
926 :param directive: the directive owning the buffer
6f49c23045b1 Fix regression in [1099]: templates must not have an implicit loader during message extraction.
cmlenz
parents: 873
diff changeset
927 :type directive: I18NDirective
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
928 """
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
929 # params list needs to be copied so that directives can be evaluated
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
930 # more than once
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
931 self.orig_params = self.params = directive.params[:]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
932 self.directive = directive
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
933 self.string = []
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
934 self.events = {}
775
f0f1416a814f Support for parameters in internationalized `i18n:msg` content. See #129.
cmlenz
parents: 762
diff changeset
935 self.values = {}
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
936 self.depth = 1
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
937 self.order = 1
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
938 self.stack = [0]
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
939 self.subdirectives = {}
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
940
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
941 def append(self, kind, data, pos):
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
942 """Append a stream event to the buffer.
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
943
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
944 :param kind: the stream event kind
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
945 :param data: the event data
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
946 :param pos: the position of the event in the source
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
947 """
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
948 if kind is SUB:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
949 # The order needs to be +1 because a new START kind event will
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
950 # happen and we we need to wrap those events into our custom kind(s)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
951 order = self.stack[-1] + 1
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
952 subdirectives, substream = data
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
953 # Store the directives that should be applied after translation
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
954 self.subdirectives.setdefault(order, []).extend(subdirectives)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
955 self.events.setdefault(order, []).append((SUB_START, None, pos))
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
956 for skind, sdata, spos in substream:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
957 self.append(skind, sdata, spos)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
958 self.events.setdefault(order, []).append((SUB_END, None, pos))
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
959 elif kind is TEXT:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
960 if '[' in data or ']' in data:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
961 # Quote [ and ] if it ain't us adding it, ie, if the user is
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
962 # using those chars in his templates, escape them
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
963 data = data.replace('[', '\[').replace(']', '\]')
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
964 self.string.append(data)
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
965 self.events.setdefault(self.stack[-1], []).append((kind, data, pos))
775
f0f1416a814f Support for parameters in internationalized `i18n:msg` content. See #129.
cmlenz
parents: 762
diff changeset
966 elif kind is EXPR:
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
967 if self.params:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
968 param = self.params.pop(0)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
969 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
970 params = ', '.join(['"%s"' % p for p in self.orig_params if p])
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
971 if params:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
972 params = "(%s)" % params
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
973 raise IndexError("%d parameters%s given to 'i18n:%s' but "
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
974 "%d or more expressions used in '%s', line %s"
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
975 % (len(self.orig_params), params,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
976 self.directive.tagname,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
977 len(self.orig_params)+1,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
978 os.path.basename(pos[0] or
872
e966d7a20d48 Typo correction.
palgarvio
parents: 871
diff changeset
979 'In-memory Template'),
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
980 pos[1]))
775
f0f1416a814f Support for parameters in internationalized `i18n:msg` content. See #129.
cmlenz
parents: 762
diff changeset
981 self.string.append('%%(%s)s' % param)
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
982 self.events.setdefault(self.stack[-1], []).append((kind, data, pos))
775
f0f1416a814f Support for parameters in internationalized `i18n:msg` content. See #129.
cmlenz
parents: 762
diff changeset
983 self.values[param] = (kind, data, pos)
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
984 else:
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
985 if kind is START:
854
0d9e87c6cf6e More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
986 self.string.append('[%d:' % self.order)
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
987 self.stack.append(self.order)
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
988 self.events.setdefault(self.stack[-1],
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
989 []).append((kind, data, pos))
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
990 self.depth += 1
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
991 self.order += 1
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
992 elif kind is END:
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
993 self.depth -= 1
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
994 if self.depth:
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
995 self.events[self.stack[-1]].append((kind, data, pos))
854
0d9e87c6cf6e More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
996 self.string.append(']')
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
997 self.stack.pop()
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
998
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
999 def format(self):
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1000 """Return a message identifier representing the content in the
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1001 buffer.
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1002 """
854
0d9e87c6cf6e More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
1003 return ''.join(self.string).strip()
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
1004
775
f0f1416a814f Support for parameters in internationalized `i18n:msg` content. See #129.
cmlenz
parents: 762
diff changeset
1005 def translate(self, string, regex=re.compile(r'%\((\w+)\)s')):
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1006 """Interpolate the given message translation with the events in the
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1007 buffer and return the translated stream.
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1008
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1009 :param string: the translated message string
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1010 """
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1011 substream = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1012
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1013 def yield_parts(string):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1014 for idx, part in enumerate(regex.split(string)):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1015 if idx % 2:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1016 yield self.values[part]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1017 elif part:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1018 yield (TEXT,
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1019 part.replace('\[', '[').replace('\]', ']'),
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1020 (None, -1, -1)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1021 )
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1022
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
1023 parts = parse_msg(string)
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1024 parts_counter = {}
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
1025 for order, string in parts:
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1026 parts_counter.setdefault(order, []).append(None)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1027
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1028 while parts:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1029 order, string = parts.pop(0)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1030 if len(parts_counter[order]) == 1:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1031 events = self.events[order]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1032 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1033 events = [self.events[order].pop(0)]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1034 parts_counter[order].pop()
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1035
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1036 for event in events:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1037 if event[0] is SUB_START:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1038 substream = []
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1039 elif event[0] is SUB_END:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1040 # Yield a substream which might have directives to be
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1041 # applied to it (after translation events)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1042 yield SUB, (self.subdirectives[order], substream), event[2]
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1043 substream = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1044 elif event[0] is TEXT:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1045 if string:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1046 for part in yield_parts(string):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1047 if substream is not None:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1048 substream.append(part)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1049 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1050 yield part
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1051 # String handled, reset it
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1052 string = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1053 elif event[0] is START:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1054 if substream is not None:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1055 substream.append(event)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1056 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1057 yield event
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1058 if string:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1059 for part in yield_parts(string):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1060 if substream is not None:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1061 substream.append(part)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1062 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1063 yield part
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1064 # String handled, reset it
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1065 string = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1066 elif event[0] is END:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1067 if string:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1068 for part in yield_parts(string):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1069 if substream is not None:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1070 substream.append(part)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1071 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1072 yield part
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1073 # String handled, reset it
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1074 string = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1075 if substream is not None:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1076 substream.append(event)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1077 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1078 yield event
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1079 elif event[0] is EXPR:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1080 # These are handled on the strings itself
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1081 continue
775
f0f1416a814f Support for parameters in internationalized `i18n:msg` content. See #129.
cmlenz
parents: 762
diff changeset
1082 else:
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1083 if string:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1084 for part in yield_parts(string):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1085 if substream is not None:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1086 substream.append(part)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1087 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1088 yield part
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1089 # String handled, reset it
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1090 string = None
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1091 if substream is not None:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1092 substream.append(event)
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1093 else:
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1094 yield event
560
f227a2f12e5f Start implementation of advanced I18n as dicussed in #129 and the MailingList. This is not complete yet, but many simple cases work okay.
cmlenz
parents: 549
diff changeset
1095
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1096 def parse_msg(string, regex=re.compile(r'(?:\[(\d+)\:)|(?<!\\)\]')):
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1097 """Parse a translated message using Genshi mixed content message
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1098 formatting.
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1099
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1100 >>> parse_msg("See [1:Help].")
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1101 [(0, 'See '), (1, 'Help'), (0, '.')]
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1102
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1103 >>> parse_msg("See [1:our [2:Help] page] for details.")
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1104 [(0, 'See '), (1, 'our '), (2, 'Help'), (1, ' page'), (0, ' for details.')]
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1105
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1106 >>> parse_msg("[2:Details] finden Sie in [1:Hilfe].")
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1107 [(2, 'Details'), (0, ' finden Sie in '), (1, 'Hilfe'), (0, '.')]
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1108
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1109 >>> parse_msg("[1:] Bilder pro Seite anzeigen.")
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1110 [(1, ''), (0, ' Bilder pro Seite anzeigen.')]
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1111
738
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1112 :param string: the translated message string
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1113 :return: a list of ``(order, string)`` tuples
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1114 :rtype: `list`
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1115 """
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1116 parts = []
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1117 stack = [0]
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1118 while True:
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1119 mo = regex.search(string)
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1120 if not mo:
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1121 break
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1122
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1123 if mo.start() or stack[-1]:
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1124 parts.append((stack[-1], string[:mo.start()]))
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1125 string = string[mo.end():]
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1126
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1127 orderno = mo.group(1)
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1128 if orderno is not None:
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1129 stack.append(int(orderno))
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1130 else:
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1131 stack.pop()
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1132 if not stack:
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1133 break
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1134
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1135 if string:
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1136 parts.append((stack[-1], string))
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1137
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1138 return parts
4b7e2aa518af Minor cleanup in the i18n module.
cmlenz
parents: 667
diff changeset
1139
776
9e0ba5b9693c Added tests for the parameter support added to advanced internationalization in [901]. See #129.
cmlenz
parents: 775
diff changeset
1140
561
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1141 def extract_from_code(code, gettext_functions):
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1142 """Extract strings from Python bytecode.
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1143
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1144 >>> from genshi.template.eval import Expression
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1145 >>> expr = Expression('_("Hello")')
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1146 >>> list(extract_from_code(expr, Translator.GETTEXT_FUNCTIONS))
561
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1147 [('_', u'Hello')]
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1148
561
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1149 >>> expr = Expression('ngettext("You have %(num)s item", '
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1150 ... '"You have %(num)s items", num)')
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1151 >>> list(extract_from_code(expr, Translator.GETTEXT_FUNCTIONS))
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1152 [('ngettext', (u'You have %(num)s item', u'You have %(num)s items', None))]
561
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1153
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1154 :param code: the `Code` object
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1155 :type code: `genshi.template.eval.Code`
561
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1156 :param gettext_functions: a sequence of function names
576
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 565
diff changeset
1157 :since: version 0.5
561
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1158 """
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1159 def _walk(node):
794
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1160 if isinstance(node, _ast.Call) and isinstance(node.func, _ast.Name) \
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1161 and node.func.id in gettext_functions:
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1162 strings = []
600
0d802a7e3630 Handle starargs and dstarargs in the I18n extraction code.
cmlenz
parents: 596
diff changeset
1163 def _add(arg):
794
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1164 if isinstance(arg, _ast.Str) and isinstance(arg.s, basestring):
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1165 strings.append(unicode(arg.s, 'utf-8'))
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1166 elif arg:
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1167 strings.append(None)
600
0d802a7e3630 Handle starargs and dstarargs in the I18n extraction code.
cmlenz
parents: 596
diff changeset
1168 [_add(arg) for arg in node.args]
794
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1169 _add(node.starargs)
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1170 _add(node.kwargs)
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1171 if len(strings) == 1:
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1172 strings = strings[0]
561
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1173 else:
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1174 strings = tuple(strings)
794
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1175 yield node.func.id, strings
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1176 elif node._fields:
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1177 children = []
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1178 for field in node._fields:
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1179 child = getattr(node, field, None)
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1180 if isinstance(child, list):
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1181 for elem in child:
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1182 children.append(elem)
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1183 elif isinstance(child, _ast.AST):
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1184 children.append(child)
ada9d53ea751 Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 790
diff changeset
1185 for child in children:
565
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1186 for funcname, strings in _walk(child):
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1187 yield funcname, strings
aa8e85a4085e * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 561
diff changeset
1188 return _walk(code.ast)
561
3225bb74c672 Move code for extracting messages from bytecode into a separate function.
cmlenz
parents: 560
diff changeset
1189
776
9e0ba5b9693c Added tests for the parameter support added to advanced internationalization in [901]. See #129.
cmlenz
parents: 775
diff changeset
1190
528
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1191 def extract(fileobj, keywords, comment_tags, options):
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1192 """Babel extraction method for Genshi templates.
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1193
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1194 :param fileobj: the file-like object the messages should be extracted from
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1195 :param keywords: a list of keywords (i.e. function names) that should be
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1196 recognized as translation functions
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1197 :param comment_tags: a list of translator tags to search for and include
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1198 in the results
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1199 :param options: a dictionary of additional options (optional)
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1200 :return: an iterator over ``(lineno, funcname, message, comments)`` tuples
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1201 :rtype: ``iterator``
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1202 """
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1203 template_class = options.get('template_class', MarkupTemplate)
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1204 if isinstance(template_class, basestring):
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1205 module, clsname = template_class.split(':', 1)
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1206 template_class = getattr(__import__(module, {}, {}, [clsname]), clsname)
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1207 encoding = options.get('encoding', None)
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1208
596
f436c7db99f5 Follow-up to [708]. The added `extract_text` option wasn't actually being handled by the Babel extraction plugin.
cmlenz
parents: 594
diff changeset
1209 extract_text = options.get('extract_text', True)
f436c7db99f5 Follow-up to [708]. The added `extract_text` option wasn't actually being handled by the Babel extraction plugin.
cmlenz
parents: 594
diff changeset
1210 if isinstance(extract_text, basestring):
f436c7db99f5 Follow-up to [708]. The added `extract_text` option wasn't actually being handled by the Babel extraction plugin.
cmlenz
parents: 594
diff changeset
1211 extract_text = extract_text.lower() in ('1', 'on', 'yes', 'true')
f436c7db99f5 Follow-up to [708]. The added `extract_text` option wasn't actually being handled by the Babel extraction plugin.
cmlenz
parents: 594
diff changeset
1212
528
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1213 ignore_tags = options.get('ignore_tags', Translator.IGNORE_TAGS)
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1214 if isinstance(ignore_tags, basestring):
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1215 ignore_tags = ignore_tags.split()
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1216 ignore_tags = [QName(tag) for tag in ignore_tags]
596
f436c7db99f5 Follow-up to [708]. The added `extract_text` option wasn't actually being handled by the Babel extraction plugin.
cmlenz
parents: 594
diff changeset
1217
528
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1218 include_attrs = options.get('include_attrs', Translator.INCLUDE_ATTRS)
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1219 if isinstance(include_attrs, basestring):
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1220 include_attrs = include_attrs.split()
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1221 include_attrs = [QName(attr) for attr in include_attrs]
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1222
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1223 tmpl = template_class(fileobj, filename=getattr(fileobj, 'name', None),
f38ce008ab0a Integrated [http://babel.edgewall.org/ Babel] message extraction plugin, and added I18n doc page.
cmlenz
parents: 522
diff changeset
1224 encoding=encoding)
882
6f49c23045b1 Fix regression in [1099]: templates must not have an implicit loader during message extraction.
cmlenz
parents: 873
diff changeset
1225 tmpl.loader = None
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1226
596
f436c7db99f5 Follow-up to [708]. The added `extract_text` option wasn't actually being handled by the Babel extraction plugin.
cmlenz
parents: 594
diff changeset
1227 translator = Translator(None, ignore_tags, include_attrs, extract_text)
849
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1228 if hasattr(tmpl, 'add_directives'):
e43633b320db Merged advanced-i18n branch back into trunk.
cmlenz
parents: 794
diff changeset
1229 tmpl.add_directives(Translator.NAMESPACE, translator)
787
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
1230 for message in translator.extract(tmpl.stream, gettext_functions=keywords):
422a9dd01e9f Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
cmlenz
parents: 785
diff changeset
1231 yield message
Copyright (C) 2012-2017 Edgewall Software