Updated ez_setup.py from 0.6a7 to 0.6a9
[fdr-django.git] / django / templatetags / i18n.py
blob7c2019cac0eb5eb5f4774fb0a17d2379f65bd849
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
5 import re, sys
7 register = Library()
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
16 return ''
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()
24 return ''
26 class TranslateNode(Node):
27 def __init__(self, value, noop):
28 self.value = value
29 self.noop = noop
31 def render(self, context):
32 value = resolve_variable(self.value, context)
33 if self.noop:
34 return value
35 else:
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
42 self.plural = plural
43 self.countervar = countervar
44 self.counter = counter
46 def render_token_list(self, tokens):
47 result = []
48 for token in 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):
56 context.push()
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
65 else:
66 result = translation.gettext(singular) % context
67 context.pop()
68 return result
70 def do_get_available_languages(parser, token):
71 """
72 This will store a list of available languages
73 in the context.
75 Usage::
77 {% get_available_languages as languages %}
78 {% for language in languages %}
79 ...
80 {% endfor %}
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.
85 """
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):
92 """
93 This will store the current language in the context.
95 Usage::
97 {% get_current_language as language %}
99 This will fetch the currently active language and
100 put it's value into the ``language`` context
101 variable.
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.
113 Usage::
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::
132 {% trans variable %}
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):
139 def top(self):
140 value = self.value()
141 if self.more():
142 if self.tag() == 'noop':
143 noop = True
144 else:
145 raise TemplateSyntaxError, "only option for 'trans' is 'noop'"
146 else:
147 noop = False
148 return (value, 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.
156 Usage::
158 {% blocktrans with foo|filter as bar and baz|filter as boo %}
159 This is {{ bar }} and {{ boo }}.
160 {% endblocktrans %}
162 Additionally, this supports pluralization::
164 {% blocktrans count var|length as count %}
165 There is {{ count }} object.
166 {% plural %}
167 There are {{ count }} objects.
168 {% endblocktrans %}
170 This is much like ngettext, only in template syntax.
172 class BlockTranslateParser(TokenParser):
174 def top(self):
175 countervar = None
176 counter = None
177 extra_context = {}
178 while self.more():
179 tag = self.tag()
180 if tag == 'with' or tag == 'and':
181 value = self.value()
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)
185 elif tag == 'count':
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()
190 else:
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()
196 singular = []
197 plural = []
198 while parser.tokens:
199 token = parser.next_token()
200 if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
201 singular.append(token)
202 else:
203 break
204 if countervar and counter:
205 if token.contents.strip() != 'plural':
206 raise TemplateSyntaxError, "'blocktrans' doesn't allow other block tags inside it" % tag
207 while parser.tokens:
208 token = parser.next_token()
209 if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
210 plural.append(token)
211 else:
212 break
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)