annotate genshi/filters/i18n.py @ 1037:744a33f78ccc trunk

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