1 from django
.template
import Node
, resolve_variable
2 from django
.template
import TemplateSyntaxError
, TokenParser
, Library
3 from django
.template
import TOKEN_TEXT
, TOKEN_VAR
4 from django
.utils
import translation
8 class GetAvailableLanguagesNode(Node
):
9 def __init__(self
, variable
):
10 self
.variable
= variable
12 def render(self
, context
):
13 from django
.conf
import settings
14 context
[self
.variable
] = [(k
, translation
.ugettext(v
)) for k
, v
in settings
.LANGUAGES
]
17 class GetCurrentLanguageNode(Node
):
18 def __init__(self
, variable
):
19 self
.variable
= variable
21 def render(self
, context
):
22 context
[self
.variable
] = translation
.get_language()
25 class GetCurrentLanguageBidiNode(Node
):
26 def __init__(self
, variable
):
27 self
.variable
= variable
29 def render(self
, context
):
30 context
[self
.variable
] = translation
.get_language_bidi()
33 class TranslateNode(Node
):
34 def __init__(self
, value
, noop
):
38 def render(self
, context
):
39 value
= resolve_variable(self
.value
, context
)
43 return translation
.ugettext(value
)
45 class BlockTranslateNode(Node
):
46 def __init__(self
, extra_context
, singular
, plural
=None, countervar
=None, counter
=None):
47 self
.extra_context
= extra_context
48 self
.singular
= singular
50 self
.countervar
= countervar
51 self
.counter
= counter
53 def render_token_list(self
, tokens
):
56 if token
.token_type
== TOKEN_TEXT
:
57 result
.append(token
.contents
)
58 elif token
.token_type
== TOKEN_VAR
:
59 result
.append('%%(%s)s' % token
.contents
)
60 return ''.join(result
)
62 def render(self
, context
):
64 for var
,val
in self
.extra_context
.items():
65 context
[var
] = val
.resolve(context
)
66 singular
= self
.render_token_list(self
.singular
)
67 if self
.plural
and self
.countervar
and self
.counter
:
68 count
= self
.counter
.resolve(context
)
69 context
[self
.countervar
] = count
70 plural
= self
.render_token_list(self
.plural
)
71 result
= translation
.ungettext(singular
, plural
, count
) % context
73 result
= translation
.ugettext(singular
) % context
77 def do_get_available_languages(parser
, token
):
79 This will store a list of available languages
84 {% get_available_languages as languages %}
85 {% for language in languages %}
89 This will just pull the LANGUAGES setting from
90 your setting file (or the default settings) and
91 put it into the named variable.
93 args
= token
.contents
.split()
94 if len(args
) != 3 or args
[1] != 'as':
95 raise TemplateSyntaxError
, "'get_available_languages' requires 'as variable' (got %r)" % args
96 return GetAvailableLanguagesNode(args
[2])
98 def do_get_current_language(parser
, token
):
100 This will store the current language in the context.
104 {% get_current_language as language %}
106 This will fetch the currently active language and
107 put it's value into the ``language`` context
110 args
= token
.contents
.split()
111 if len(args
) != 3 or args
[1] != 'as':
112 raise TemplateSyntaxError
, "'get_current_language' requires 'as variable' (got %r)" % args
113 return GetCurrentLanguageNode(args
[2])
115 def do_get_current_language_bidi(parser
, token
):
117 This will store the current language layout in the context.
121 {% get_current_language_bidi as bidi %}
123 This will fetch the currently active language's layout and
124 put it's value into the ``bidi`` context variable.
125 True indicates right-to-left layout, otherwise left-to-right
127 args
= token
.contents
.split()
128 if len(args
) != 3 or args
[1] != 'as':
129 raise TemplateSyntaxError
, "'get_current_language_bidi' requires 'as variable' (got %r)" % args
130 return GetCurrentLanguageBidiNode(args
[2])
132 def do_translate(parser
, token
):
134 This will mark a string for translation and will
135 translate the string for the current language.
139 {% trans "this is a test" %}
141 This will mark the string for translation so it will
142 be pulled out by mark-messages.py into the .po files
143 and will run the string through the translation engine.
145 There is a second form::
147 {% trans "this is a test" noop %}
149 This will only mark for translation, but will return
150 the string unchanged. Use it when you need to store
151 values into forms that should be translated later on.
153 You can use variables instead of constant strings
154 to translate stuff you marked somewhere else::
158 This will just try to translate the contents of
159 the variable ``variable``. Make sure that the string
160 in there is something that is in the .po file.
162 class TranslateParser(TokenParser
):
166 if self
.tag() == 'noop':
169 raise TemplateSyntaxError
, "only option for 'trans' is 'noop'"
173 value
, noop
= TranslateParser(token
.contents
).top()
174 return TranslateNode(value
, noop
)
176 def do_block_translate(parser
, token
):
178 This will translate a block of text with parameters.
182 {% blocktrans with foo|filter as bar and baz|filter as boo %}
183 This is {{ bar }} and {{ boo }}.
186 Additionally, this supports pluralization::
188 {% blocktrans count var|length as count %}
189 There is {{ count }} object.
191 There are {{ count }} objects.
194 This is much like ngettext, only in template syntax.
196 class BlockTranslateParser(TokenParser
):
204 if tag
== 'with' or tag
== 'and':
206 if self
.tag() != 'as':
207 raise TemplateSyntaxError
, "variable bindings in 'blocktrans' must be 'with value as variable'"
208 extra_context
[self
.tag()] = parser
.compile_filter(value
)
210 counter
= parser
.compile_filter(self
.value())
211 if self
.tag() != 'as':
212 raise TemplateSyntaxError
, "counter specification in 'blocktrans' must be 'count value as variable'"
213 countervar
= self
.tag()
215 raise TemplateSyntaxError
, "unknown subtag %s for 'blocktrans' found" % tag
216 return (countervar
, counter
, extra_context
)
218 countervar
, counter
, extra_context
= BlockTranslateParser(token
.contents
).top()
223 token
= parser
.next_token()
224 if token
.token_type
in (TOKEN_VAR
, TOKEN_TEXT
):
225 singular
.append(token
)
228 if countervar
and counter
:
229 if token
.contents
.strip() != 'plural':
230 raise TemplateSyntaxError
, "'blocktrans' doesn't allow other block tags inside it"
232 token
= parser
.next_token()
233 if token
.token_type
in (TOKEN_VAR
, TOKEN_TEXT
):
237 if token
.contents
.strip() != 'endblocktrans':
238 raise TemplateSyntaxError
, "'blocktrans' doesn't allow other block tags (seen %r) inside it" % token
.contents
240 return BlockTranslateNode(extra_context
, singular
, plural
, countervar
, counter
)
242 register
.tag('get_available_languages', do_get_available_languages
)
243 register
.tag('get_current_language', do_get_current_language
)
244 register
.tag('get_current_language_bidi', do_get_current_language_bidi
)
245 register
.tag('trans', do_translate
)
246 register
.tag('blocktrans', do_block_translate
)