diff --git a/django/core/template/defaulttags.py b/django/core/template/defaulttags.py index f1ed28d4da..bea4857dec 100644 --- a/django/core/template/defaulttags.py +++ b/django/core/template/defaulttags.py @@ -290,63 +290,6 @@ class WidthRatioNode(Node): return '' return str(int(round(ratio))) -class GetAvailableLanguagesNode(Node): - - def __init__(self, variable): - self.variable = variable - - def render(self, context): - from django.conf.settings import LANGUAGES - context[self.variable] = LANGUAGES - return '' - -class I18NNode(Node): - - def __init__(self, cmd): - self.cmd = cmd - self.i18n_re = re.compile(r'^\s*(_|gettext|gettext_noop)\((.*)\)\s*$') - self.ngettext_re = re.compile(r'''^\s*ngettext\(((?:".+")|(?:'.+')|(?:""".+"""))\s*,\s*((?:".+")|(?:'.+')|(?:""".+"""))\s*,\s*(.*)\)\s*$''') - - def _resolve_var(self, s, context): - if s.startswith("'") and s.endswith("'"): - s = s[1:-1] - elif s.startswith('"""') and s.endswith('"""'): - s = s[3:-3] - elif s.startswith('"') and s.endswith('"'): - s = s[1:-1] - else: - s = resolve_variable_with_filters(s, context) - return s - - def render(self, context): - m = self.i18n_re.match(self.cmd) - if m: - f = m.group(1) - s = self._resolve_var(m.group(2), context) - if f in ('_', 'gettext'): - return translation.gettext(s) % context - elif f == 'gettext_noop': - return translation.gettext_noop(s) % context - else: - raise TemplateSyntaxError("i18n only supports _, gettext, gettext_noop and ngettext as functions, not %s" % f) - m = self.ngettext_re.match(self.cmd) - if m: - singular = self._resolve_var(m.group(1), context) - plural = self._resolve_var(m.group(2), context) - var = resolve_variable_with_filters(m.group(3), context) - return translation.ngettext(singular, plural, var) % context - raise TemplateSyntaxError("i18n must be called as {% i18n _('some message') %} or {% i18n ngettext('singular', 'plural', var) %}") - - cyclevars = [v for v in args[1].split(",") if v] # split and kill blanks - name = args[3] - node = CycleNode(cyclevars) - - if not hasattr(parser, '_namedCycleNodes'): - parser._namedCycleNodes = {} - - parser._namedCycleNodes[name] = node - return node - def do_comment(parser, token): """ Ignore everything between ``{% comment %}`` and ``{% endcomment %}`` @@ -813,45 +756,6 @@ def do_widthratio(parser, token): raise TemplateSyntaxError("widthratio final argument must be an integer") return WidthRatioNode(this_value_var, max_value_var, max_width) -def do_get_available_languages(parser, token): - """ - This will store a list of available languages - in the context. - - Usage is as follows:: - - {% get_available_languages as languages %} - {% for language in languages %} - ... - {% endfor %} - - This will just pull the LANGUAGES setting from - your setting file (or the default settings) and - put it into the named variable. - """ - - args = token.contents.split() - if len(args) != 3 or args[1] != 'as': - raise template.TemplateSyntaxError("'get_available_languages' requires 'as variable' (got %r)" % args) - return GetAvailableLanguagesNode(args[2]) - -def do_i18n(parser, token): - """ - translate a given string with the current - translation object. - - For example:: - - {% i18n _('test') %} - {% i18n ngettext('singular', 'plural', counter) %} - - """ - args = token.contents.split(' ', 1) - if len(args) != 2: - raise template.TemplateSyntaxError("'i18n' requires one argument (got %r)" % args) - - return I18NNode(args[1].strip()) - register_tag('comment', do_comment) register_tag('cycle', do_cycle) register_tag('debug', do_debug) @@ -868,5 +772,3 @@ register_tag('load', do_load) register_tag('now', do_now) register_tag('templatetag', do_templatetag) register_tag('widthratio', do_widthratio) -register_tag('i18n', do_i18n) -register_tag('get_available_languages', do_get_available_languages) diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py index 37f7175593..e9702f2dc3 100644 --- a/django/templatetags/i18n.py +++ b/django/templatetags/i18n.py @@ -18,7 +18,7 @@ class GetAvailableLanguagesNode(Node): context[self.variable] = LANGUAGES return '' -class GetCurrentLanguage(Node): +class GetCurrentLanguageNode(Node): def __init__(self, variable): self.variable = variable @@ -112,7 +112,7 @@ def do_get_current_language(parser, token): args = token.contents.split() if len(args) != 3 or args[1] != 'as': raise TemplateSyntaxError, "'get_available_languages' requires 'as variable' (got %r)" % args - return GetAvailableLanguagesNode(args[2]) + return GetCurrentLanguageNode(args[2]) def do_translate(parser, token): """ @@ -144,14 +144,21 @@ def do_translate(parser, token): the variable ``variable``. Make sure that the string in there is something that is in the .po file. """ - args = token.contents.split(None, 1) - p = args[1].rfind(' ') - noop = False - value = '' - if p >= 0 and args[1][p:].strip() == 'noop': - value = args[1][:p].strip() - else: - value = args[1] + + class TranslateParser(TokenParser): + + def top(self): + value = self.value() + if self.more(): + if self.tag() == 'noop': + noop = True + else: + raise TemplateSyntaxError, "only option for 'trans' is 'noop'" + else: + noop = False + return (value, noop) + + (value, noop) = TranslateParser(token.contents).top() return TranslateNode(value, noop) def do_block_translate(parser, token): @@ -189,7 +196,7 @@ def do_block_translate(parser, token): singular.append(token) else: break - if countervar and counter: + if countervar and counter: if token.contents.strip() != 'plural': raise TemplateSyntaxError, "'blocktrans' doesn't allow other block tags inside it" % tag while parser.tokens: @@ -200,11 +207,11 @@ def do_block_translate(parser, token): break if token.contents.strip() != 'endblocktrans': raise TemplateSyntaxError, "'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents - + return BlockTranslateNode(extra_context, singular, plural, countervar, counter) register_tag('get_available_languages', do_get_available_languages) -register_tag('get_curent_language', do_get_current_language) +register_tag('get_current_language', do_get_current_language) register_tag('trans', do_translate) register_tag('blocktrans', do_block_translate) diff --git a/tests/othertests/templates.py b/tests/othertests/templates.py index e2afad5777..c889f2c7cb 100644 --- a/tests/othertests/templates.py +++ b/tests/othertests/templates.py @@ -218,49 +218,40 @@ TEMPLATE_TESTS = { 'exception04': ("{% extends 'inheritance17' %}{% block first %}{% echo 400 %}5678{% endblock %}", {}, template.TemplateSyntaxError), # simple translation of a string delimited by ' - 'i18n01': ("{% i18n _('xxxyyyxxx') %}", {}, "xxxyyyxxx"), + 'i18n01': ("{% load i18n %}{% trans 'xxxyyyxxx' %}", {}, "xxxyyyxxx"), # simple translation of a string delimited by " - 'i18n02': ('{% i18n _("xxxyyyxxx") %}', {}, "xxxyyyxxx"), - - # simple translation of a string delimited by """ - 'i18n03': ('{% i18n _("""xxxyyyxxx""") %}', {}, "xxxyyyxxx"), + 'i18n02': ('{% load i18n %}{% trans "xxxyyyxxx" %}', {}, "xxxyyyxxx"), # simple translation of a variable - 'i18n04': ('{% i18n _(anton) %}', {'anton': 'xxxyyyxxx'}, "xxxyyyxxx"), + 'i18n03': ('{% load i18n %}{% blocktrans %}{{ anton }}{% endblocktrans %}', {'anton': 'xxxyyyxxx'}, "xxxyyyxxx"), - # simple translation of a variable - 'i18n05': ('{% i18n _(anton|lower) %}', {'anton': 'XXXYYYXXX'}, "xxxyyyxxx"), + # simple translation of a variable and filter + 'i18n04': ('{% load i18n %}{% blocktrans with anton|lower as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'XXXYYYXXX'}, "xxxyyyxxx"), # simple translation of a string with interpolation - 'i18n05': ('{% i18n _("xxx%(anton)sxxx") %}', {'anton': 'yyy'}, "xxxyyyxxx"), + 'i18n05': ('{% load i18n %}{% blocktrans %}xxx{{ anton }}xxx{% endblocktrans %}', {'anton': 'yyy'}, "xxxyyyxxx"), # simple translation of a string to german - 'i18n07': ('{% i18n _("Page not found") %}', {'LANGUAGE_CODE': 'de'}, "Seite nicht gefunden"), + 'i18n06': ('{% load i18n %}{% trans "Page not found" %}', {'LANGUAGE_CODE': 'de'}, "Seite nicht gefunden"), # translation of singular form - 'i18n08': ('{% i18n ngettext("singular", "plural", count) %}', {'count': 1}, "singular"), + 'i18n07': ('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}plural{% endblocktrans %}', {'number': 1}, "singular"), # translation of plural form - 'i18n09': ('{% i18n ngettext("singular", "plural", count) %}', {'count': 2}, "plural"), + 'i18n08': ('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}plural{% endblocktrans %}', {'number': 2}, "plural"), # simple non-translation (only marking) of a string to german - 'i18n10': ('{% i18n gettext_noop("Page not found") %}', {'LANGUAGE_CODE': 'de'}, "Page not found"), - - # translation of string without i18n tag - 'i18n11': ('{{ _("blah") }}', {}, "blah"), - - # translation of string without i18n tag but with interpolation - 'i18n12': ('{{ _("blah%(anton)s") }}', {'anton': 'blubb'}, "blahblubb"), + 'i18n09': ('{% load i18n %}{% trans "Page not found" noop %}', {'LANGUAGE_CODE': 'de'}, "Page not found"), # translation of a variable with a translated filter - 'i18n13': ('{{ bool|yesno:_("ja,nein") }}', {'bool': True}, 'ja'), + 'i18n10': ('{{ bool|yesno:_("ja,nein") }}', {'bool': True}, 'ja'), # translation of a variable with a non-translated filter - 'i18n14': ('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'), + 'i18n11': ('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'), # usage of the get_available_languages tag - 'i18n15': ('{% get_available_languages as langs %}{% for lang in langs %}{% ifequal lang.0 "de" %}{{ lang.0 }}{% endifequal %}{% endfor %}', {}, 'de'), + 'i18n12': ('{% load i18n %}{% get_available_languages as langs %}{% for lang in langs %}{% ifequal lang.0 "de" %}{{ lang.0 }}{% endifequal %}{% endfor %}', {}, 'de'), } def test_template_loader(template_name, template_dirs=None):