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