1 from django
.core
.template
import Node
, NodeList
, Template
, Context
, resolve_variable
2 from django
.core
.template
import TemplateSyntaxError
, TokenParser
, Library
3 from django
.core
.template
import TOKEN_BLOCK
, TOKEN_TEXT
, TOKEN_VAR
4 from django
.utils
import translation
9 class GetAvailableLanguagesNode(Node
):
10 def __init__(self
, variable
):
11 self
.variable
= variable
13 def render(self
, context
):
14 from django
.conf
.settings
import LANGUAGES
15 context
[self
.variable
] = LANGUAGES
18 class GetCurrentLanguageNode(Node
):
19 def __init__(self
, variable
):
20 self
.variable
= variable
22 def render(self
, context
):
23 context
[self
.variable
] = translation
.get_language()
26 class TranslateNode(Node
):
27 def __init__(self
, value
, noop
):
31 def render(self
, context
):
32 value
= resolve_variable(self
.value
, context
)
36 return translation
.gettext(value
)
38 class BlockTranslateNode(Node
):
39 def __init__(self
, extra_context
, singular
, plural
=None, countervar
=None, counter
=None):
40 self
.extra_context
= extra_context
41 self
.singular
= singular
43 self
.countervar
= countervar
44 self
.counter
= counter
46 def render_token_list(self
, tokens
):
49 if token
.token_type
== TOKEN_TEXT
:
50 result
.append(token
.contents
)
51 elif token
.token_type
== TOKEN_VAR
:
52 result
.append('%%(%s)s' % token
.contents
)
53 return ''.join(result
)
55 def render(self
, context
):
57 for var
,val
in self
.extra_context
.items():
58 context
[var
] = val
.resolve(context
)
59 singular
= self
.render_token_list(self
.singular
)
60 if self
.plural
and self
.countervar
and self
.counter
:
61 count
= self
.counter
.resolve(context
)
62 context
[self
.countervar
] = count
63 plural
= self
.render_token_list(self
.plural
)
64 result
= translation
.ngettext(singular
, plural
, count
) % context
66 result
= translation
.gettext(singular
) % context
70 def do_get_available_languages(parser
, token
):
72 This will store a list of available languages
77 {% get_available_languages as languages %}
78 {% for language in languages %}
82 This will just pull the LANGUAGES setting from
83 your setting file (or the default settings) and
84 put it into the named variable.
86 args
= token
.contents
.split()
87 if len(args
) != 3 or args
[1] != 'as':
88 raise TemplateSyntaxError
, "'get_available_languages' requires 'as variable' (got %r)" % args
89 return GetAvailableLanguagesNode(args
[2])
91 def do_get_current_language(parser
, token
):
93 This will store the current language in the context.
97 {% get_current_language as language %}
99 This will fetch the currently active language and
100 put it's value into the ``language`` context
103 args
= token
.contents
.split()
104 if len(args
) != 3 or args
[1] != 'as':
105 raise TemplateSyntaxError
, "'get_available_languages' requires 'as variable' (got %r)" % args
106 return GetCurrentLanguageNode(args
[2])
108 def do_translate(parser
, token
):
110 This will mark a string for translation and will
111 translate the string for the current language.
115 {% trans "this is a test" %}
117 This will mark the string for translation so it will
118 be pulled out by mark-messages.py into the .po files
119 and will run the string through the translation engine.
121 There is a second form::
123 {% trans "this is a test" noop %}
125 This will only mark for translation, but will return
126 the string unchanged. Use it when you need to store
127 values into forms that should be translated later on.
129 You can use variables instead of constant strings
130 to translate stuff you marked somewhere else::
134 This will just try to translate the contents of
135 the variable ``variable``. Make sure that the string
136 in there is something that is in the .po file.
138 class TranslateParser(TokenParser
):
142 if self
.tag() == 'noop':
145 raise TemplateSyntaxError
, "only option for 'trans' is 'noop'"
149 (value
, noop
) = TranslateParser(token
.contents
).top()
150 return TranslateNode(value
, noop
)
152 def do_block_translate(parser
, token
):
154 This will translate a block of text with parameters.
158 {% blocktrans with foo|filter as bar and baz|filter as boo %}
159 This is {{ bar }} and {{ boo }}.
162 Additionally, this supports pluralization::
164 {% blocktrans count var|length as count %}
165 There is {{ count }} object.
167 There are {{ count }} objects.
170 This is much like ngettext, only in template syntax.
172 class BlockTranslateParser(TokenParser
):
180 if tag
== 'with' or tag
== 'and':
182 if self
.tag() != 'as':
183 raise TemplateSyntaxError
, "variable bindings in 'blocktrans' must be 'with value as variable'"
184 extra_context
[self
.tag()] = parser
.compile_filter(value
)
186 counter
= parser
.compile_filter(self
.value())
187 if self
.tag() != 'as':
188 raise TemplateSyntaxError
, "counter specification in 'blocktrans' must be 'count value as variable'"
189 countervar
= self
.tag()
191 raise TemplateSyntaxError
, "unknown subtag %s for 'blocktrans' found" % tag
192 return (countervar
, counter
, extra_context
)
194 (countervar
, counter
, extra_context
) = BlockTranslateParser(token
.contents
).top()
199 token
= parser
.next_token()
200 if token
.token_type
in (TOKEN_VAR
, TOKEN_TEXT
):
201 singular
.append(token
)
204 if countervar
and counter
:
205 if token
.contents
.strip() != 'plural':
206 raise TemplateSyntaxError
, "'blocktrans' doesn't allow other block tags inside it" % tag
208 token
= parser
.next_token()
209 if token
.token_type
in (TOKEN_VAR
, TOKEN_TEXT
):
213 if token
.contents
.strip() != 'endblocktrans':
214 raise TemplateSyntaxError
, "'blocktrans' doesn't allow other block tags (seen %r) inside it" % token
.contents
216 return BlockTranslateNode(extra_context
, singular
, plural
, countervar
, counter
)
218 register
.tag('get_available_languages', do_get_available_languages
)
219 register
.tag('get_current_language', do_get_current_language
)
220 register
.tag('trans', do_translate
)
221 register
.tag('blocktrans', do_block_translate
)