~ubuntu-branches/ubuntu/oneiric/python-django/oneiric-201108291626

« back to all changes in this revision

Viewing changes to django/templatetags/i18n.py

  • Committer: Bazaar Package Importer
  • Author(s): Piotr Ożarowski, Chris Lamb, Piotr Ożarowski
  • Date: 2011-05-02 22:23:37 UTC
  • mfrom: (1.1.14 upstream) (4.4.14 sid)
  • Revision ID: james.westby@ubuntu.com-20110502222337-bhlfr6gr1l1cj7dn
Tags: 1.3-2
* Team upload.

[ Chris Lamb ]
* Don't remove "backup~" test file - upstream did ship it; we were just
  removing it with dh_clean.

[ Piotr Ożarowski ]
* Fix builds with non-default Python versions installed
* Bump Standards-Version to 3.9.2 (no changes needed)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import re
2
2
 
3
 
from django.template import Node, Variable, VariableNode, _render_value_in_context
 
3
from django.template import Node, Variable, VariableNode
4
4
from django.template import TemplateSyntaxError, TokenParser, Library
5
5
from django.template import TOKEN_TEXT, TOKEN_VAR
 
6
from django.template.base import _render_value_in_context
6
7
from django.utils import translation
7
8
from django.utils.encoding import force_unicode
 
9
from django.template.defaulttags import token_kwargs
8
10
 
9
11
register = Library()
10
12
 
17
19
        context[self.variable] = [(k, translation.ugettext(v)) for k, v in settings.LANGUAGES]
18
20
        return ''
19
21
 
 
22
class GetLanguageInfoNode(Node):
 
23
    def __init__(self, lang_code, variable):
 
24
        self.lang_code = Variable(lang_code)
 
25
        self.variable = variable
 
26
 
 
27
    def render(self, context):
 
28
        lang_code = self.lang_code.resolve(context)
 
29
        context[self.variable] = translation.get_language_info(lang_code)
 
30
        return ''
 
31
 
 
32
class GetLanguageInfoListNode(Node):
 
33
    def __init__(self, languages, variable):
 
34
        self.languages = Variable(languages)
 
35
        self.variable = variable
 
36
 
 
37
    def get_language_info(self, language):
 
38
        # ``language`` is either a language code string or a sequence
 
39
        # with the language code as its first item
 
40
        if len(language[0]) > 1:
 
41
            return translation.get_language_info(language[0])
 
42
        else:
 
43
            return translation.get_language_info(str(language))
 
44
 
 
45
    def render(self, context):
 
46
        langs = self.languages.resolve(context)
 
47
        context[self.variable] = [self.get_language_info(lang) for lang in langs]
 
48
        return ''
 
49
 
20
50
class GetCurrentLanguageNode(Node):
21
51
    def __init__(self, variable):
22
52
        self.variable = variable
68
98
    def render(self, context):
69
99
        tmp_context = {}
70
100
        for var, val in self.extra_context.items():
71
 
            tmp_context[var] = val.render(context)
 
101
            tmp_context[var] = val.resolve(context)
72
102
        # Update() works like a push(), so corresponding context.pop() is at
73
103
        # the end of function
74
104
        context.update(tmp_context)
83
113
            result = translation.ugettext(singular)
84
114
        # Escape all isolated '%' before substituting in the context.
85
115
        result = re.sub(u'%(?!\()', u'%%', result)
86
 
        data = dict([(v, _render_value_in_context(context[v], context)) for v in vars])
 
116
        data = dict([(v, _render_value_in_context(context.get(v, ''), context)) for v in vars])
87
117
        context.pop()
88
118
        return result % data
89
119
 
108
138
        raise TemplateSyntaxError("'get_available_languages' requires 'as variable' (got %r)" % args)
109
139
    return GetAvailableLanguagesNode(args[2])
110
140
 
 
141
def do_get_language_info(parser, token):
 
142
    """
 
143
    This will store the language information dictionary for the given language
 
144
    code in a context variable.
 
145
 
 
146
    Usage::
 
147
 
 
148
        {% get_language_info for LANGUAGE_CODE as l %}
 
149
        {{ l.code }}
 
150
        {{ l.name }}
 
151
        {{ l.name_local }}
 
152
        {{ l.bidi|yesno:"bi-directional,uni-directional" }}
 
153
    """
 
154
    args = token.contents.split()
 
155
    if len(args) != 5 or args[1] != 'for' or args[3] != 'as':
 
156
        raise TemplateSyntaxError("'%s' requires 'for string as variable' (got %r)" % (args[0], args[1:]))
 
157
    return GetLanguageInfoNode(args[2], args[4])
 
158
 
 
159
def do_get_language_info_list(parser, token):
 
160
    """
 
161
    This will store a list of language information dictionaries for the given
 
162
    language codes in a context variable. The language codes can be specified
 
163
    either as a list of strings or a settings.LANGUAGES style tuple (or any
 
164
    sequence of sequences whose first items are language codes).
 
165
 
 
166
    Usage::
 
167
 
 
168
        {% get_language_info_list for LANGUAGES as langs %}
 
169
        {% for l in langs %}
 
170
          {{ l.code }}
 
171
          {{ l.name }}
 
172
          {{ l.name_local }}
 
173
          {{ l.bidi|yesno:"bi-directional,uni-directional" }}
 
174
        {% endfor %}
 
175
    """
 
176
    args = token.contents.split()
 
177
    if len(args) != 5 or args[1] != 'for' or args[3] != 'as':
 
178
        raise TemplateSyntaxError("'%s' requires 'for sequence as variable' (got %r)" % (args[0], args[1:]))
 
179
    return GetLanguageInfoListNode(args[2], args[4])
 
180
 
 
181
def language_name(lang_code):
 
182
    return translation.get_language_info(lang_code)['name']
 
183
 
 
184
def language_name_local(lang_code):
 
185
    return translation.get_language_info(lang_code)['name_local']
 
186
 
 
187
def language_bidi(lang_code):
 
188
    return translation.get_language_info(lang_code)['bidi']
 
189
 
111
190
def do_get_current_language(parser, token):
112
191
    """
113
192
    This will store the current language in the context.
206
285
 
207
286
    Usage::
208
287
 
209
 
        {% blocktrans with foo|filter as bar and baz|filter as boo %}
 
288
        {% blocktrans with bar=foo|filter boo=baz|filter %}
210
289
        This is {{ bar }} and {{ boo }}.
211
290
        {% endblocktrans %}
212
291
 
213
292
    Additionally, this supports pluralization::
214
293
 
215
 
        {% blocktrans count var|length as count %}
 
294
        {% blocktrans count count=var|length %}
216
295
        There is {{ count }} object.
217
296
        {% plural %}
218
297
        There are {{ count }} objects.
219
298
        {% endblocktrans %}
220
299
 
221
300
    This is much like ngettext, only in template syntax.
 
301
 
 
302
    The "var as value" legacy format is still supported::
 
303
 
 
304
        {% blocktrans with foo|filter as bar and baz|filter as boo %}
 
305
        {% blocktrans count var|length as count %}
222
306
    """
223
 
    class BlockTranslateParser(TokenParser):
224
 
        def top(self):
225
 
            countervar = None
226
 
            counter = None
227
 
            extra_context = {}
228
 
            while self.more():
229
 
                tag = self.tag()
230
 
                if tag == 'with' or tag == 'and':
231
 
                    value = self.value()
232
 
                    if self.tag() != 'as':
233
 
                        raise TemplateSyntaxError("variable bindings in 'blocktrans' must be 'with value as variable'")
234
 
                    extra_context[self.tag()] = VariableNode(
235
 
                            parser.compile_filter(value))
236
 
                elif tag == 'count':
237
 
                    counter = parser.compile_filter(self.value())
238
 
                    if self.tag() != 'as':
239
 
                        raise TemplateSyntaxError("counter specification in 'blocktrans' must be 'count value as variable'")
240
 
                    countervar = self.tag()
241
 
                else:
242
 
                    raise TemplateSyntaxError("unknown subtag %s for 'blocktrans' found" % tag)
243
 
            return (countervar, counter, extra_context)
244
 
 
245
 
    countervar, counter, extra_context = BlockTranslateParser(token.contents).top()
 
307
    bits = token.split_contents()
 
308
 
 
309
    options = {}
 
310
    remaining_bits = bits[1:]
 
311
    while remaining_bits:
 
312
        option = remaining_bits.pop(0)
 
313
        if option in options:
 
314
            raise TemplateSyntaxError('The %r option was specified more '
 
315
                                      'than once.' % option)
 
316
        if option == 'with':
 
317
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
 
318
            if not value:
 
319
                raise TemplateSyntaxError('"with" in %r tag needs at least '
 
320
                                          'one keyword argument.' % bits[0])
 
321
        elif option == 'count':
 
322
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
 
323
            if len(value) != 1:
 
324
                raise TemplateSyntaxError('"count" in %r tag expected exactly '
 
325
                                          'one keyword argument.' % bits[0])
 
326
        else:
 
327
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
 
328
                                      (bits[0], option))
 
329
        options[option] = value
 
330
 
 
331
    if 'count' in options:
 
332
        countervar, counter = options['count'].items()[0]
 
333
    else:
 
334
        countervar, counter = None, None
 
335
    extra_context = options.get('with', {}) 
246
336
 
247
337
    singular = []
248
338
    plural = []
268
358
            counter)
269
359
 
270
360
register.tag('get_available_languages', do_get_available_languages)
 
361
register.tag('get_language_info', do_get_language_info)
 
362
register.tag('get_language_info_list', do_get_language_info_list)
271
363
register.tag('get_current_language', do_get_current_language)
272
364
register.tag('get_current_language_bidi', do_get_current_language_bidi)
273
365
register.tag('trans', do_translate)
274
366
register.tag('blocktrans', do_block_translate)
 
367
 
 
368
register.filter(language_name)
 
369
register.filter(language_name_local)
 
370
register.filter(language_bidi)