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