Ticket #14181: localize-template-tag.diff

File localize-template-tag.diff, 11.3 KB (added by piquadrat, 5 years ago)

Implementation of {% localization %} template tag

  • django/contrib/gis/templates/gis/google/google-map.js

    diff --git a/django/contrib/gis/templates/gis/google/google-map.js b/django/contrib/gis/templates/gis/google/google-map.js
    index 06f11e3..a8bcba5 100644
    a b  
    11{% autoescape off %}
     2{% localize off %}
    23{% block vars %}var geodjango = {};{% for icon in icons %}
    34var {{ icon.varname }} = new GIcon(G_DEFAULT_ICON);
    45{% if icon.image %}{{ icon.varname }}.image = "{{ icon.image }}";{% endif %}
    var {{ icon.varname }} = new GIcon(G_DEFAULT_ICON); 
    3233    alert("Sorry, the Google Maps API is not compatible with this browser.");
    3334  }
    3435}
    35 {% endblock load %}{% endblock functions %}{% endautoescape %}
     36{% endblock load %}{% endblock functions %}{% endlocalize %}{% endautoescape %}
  • django/template/__init__.py

    diff --git a/django/template/__init__.py b/django/template/__init__.py
    index c316786..0edcbe2 100644
    a b from django.utils.itercompat import is_iterable 
    5959from django.utils.functional import curry, Promise
    6060from django.utils.text import smart_split, unescape_string_literal, get_text_list
    6161from django.utils.encoding import smart_unicode, force_unicode, smart_str
    62 from django.utils.translation import ugettext as _
     62from django.utils.translation import ugettext as _, get_language, activate
    6363from django.utils.safestring import SafeData, EscapeData, mark_safe, mark_for_escaping
    6464from django.utils.formats import localize
    6565from django.utils.html import escape
    class TextNode(Node): 
    819819    def render(self, context):
    820820        return self.s
    821821
     822def _localize_from_context(value, context):
     823    """
     824    Checks if context requires special localization and applies localization
     825    if necessary
     826    """
     827    locale = context.get('_locale', None)
     828    if locale is not None:
     829        if not isinstance(locale, bool):
     830            old_lang = get_language()
     831            activate(locale)
     832            value = localize(value, force=True)
     833        elif locale:
     834            value = localize(value, force=locale)
     835    else:
     836        value = localize(value)
     837    return value
     838
    822839def _render_value_in_context(value, context):
    823840    """
    824841    Converts any value to a string to become part of a rendered template. This
    825842    means escaping, if required, and conversion to a unicode object. If value
    826843    is a string, it is expected to have already been translated.
    827844    """
    828     value = localize(value)
     845    value = _localize_from_context(value, context)
    829846    value = force_unicode(value)
    830847    if (context.autoescape and not isinstance(value, SafeData)) or isinstance(value, EscapeData):
    831848        return escape(value)
  • django/template/debug.py

    diff --git a/django/template/debug.py b/django/template/debug.py
    index c21fb50..0ba4e02 100644
    a b  
    1 from django.template import Lexer, Parser, tag_re, NodeList, VariableNode, TemplateSyntaxError
     1from django.template import Lexer, Parser, tag_re, NodeList, VariableNode, TemplateSyntaxError, _localize_from_context
    22from django.utils.encoding import force_unicode
    33from django.utils.html import escape
    44from django.utils.safestring import SafeData, EscapeData
    class DebugVariableNode(VariableNode): 
    8787    def render(self, context):
    8888        try:
    8989            output = self.filter_expression.resolve(context)
    90             output = localize(output)
     90            output = _localize_from_context(value, context)
    9191            output = force_unicode(output)
    9292        except TemplateSyntaxError, e:
    9393            if not hasattr(e, 'source'):
  • django/template/defaulttags.py

    diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
    index 1b07413..c4c347a 100644
    a b class WithNode(Node): 
    433433        context.pop()
    434434        return output
    435435
     436class LocalizeNode(Node):
     437    def __init__(self, nodelist, locale):
     438        self.nodelist = nodelist
     439        self.locale = locale
     440
     441    def __repr__(self):
     442        return "<LocalizeNode>"
     443
     444    def render(self, context):
     445        if isinstance(self.locale, bool):
     446            context['_locale'] = self.locale
     447        else:
     448            context['_locale'] = self.locale.resolve(context)
     449        output = self.nodelist.render(context)
     450        del context['_locale']
     451        return output
     452
    436453#@register.tag
    437454def autoescape(parser, token):
    438455    """
    def do_with(parser, token): 
    12161233    parser.delete_first_token()
    12171234    return WithNode(var, name, nodelist)
    12181235do_with = register.tag('with', do_with)
     1236
     1237@register.tag
     1238def localize(parser, token):
     1239    """
     1240    Temporarely deactivates localization inside of this block, e.g.
     1241    to avoid rendering syntactically incorrect JavaScript code.
     1242    """
     1243    locale = None
     1244    bits = list(token.split_contents())
     1245    if len(bits) == 1:
     1246        locale = True
     1247    elif len(bits) > 2:
     1248        raise TemplateSyntaxError("%r expected argument is on/off or a single locale like de or en-us" % bits[0])
     1249    else:
     1250        if bits[1] == 'off':
     1251            print "off"
     1252            locale = False
     1253        elif bits[1] == 'on':
     1254            print "on"
     1255            locale = True
     1256        else:
     1257            locale = parser.compile_filter(bits[1])
     1258    nodelist = parser.parse(('endlocalize',))
     1259    parser.delete_first_token()
     1260    return LocalizeNode(nodelist, locale)
  • django/utils/formats.py

    diff --git a/django/utils/formats.py b/django/utils/formats.py
    index e64cc4e..6f8087d 100644
    a b def get_format_modules(reverse=False): 
    4141        modules.reverse()
    4242    return modules
    4343
    44 def get_format(format_type, lang=None):
     44def get_format(format_type, lang=None, force=False):
    4545    """
    4646    For a specific format type, returns the format for the current
    4747    language (locale), defaults to the format in the settings.
    48     format_type is the name of the format, e.g. 'DATE_FORMAT'
     48    format_type is the name of the format, e.g. 'DATE_FORMAT'.
    4949    """
    5050    format_type = smart_str(format_type)
    51     if settings.USE_L10N:
     51    if settings.USE_L10N or force:
    5252        if lang is None:
    5353            lang = get_language()
    5454        cache_key = (format_type, lang)
    def get_format(format_type, lang=None): 
    6565            _format_cache[cache_key] = None
    6666    return getattr(settings, format_type)
    6767
    68 def date_format(value, format=None):
     68def date_format(value, format=None, force=False):
    6969    """
    7070    Formats a datetime.date or datetime.datetime object using a
    7171    localizable format
    7272    """
    73     return dateformat.format(value, get_format(format or 'DATE_FORMAT'))
     73    return dateformat.format(value, get_format(format or 'DATE_FORMAT', force=force))
    7474
    75 def time_format(value, format=None):
     75def time_format(value, format=None, force=False):
    7676    """
    7777    Formats a datetime.time object using a localizable format
    7878    """
    79     return dateformat.time_format(value, get_format(format or 'TIME_FORMAT'))
     79    return dateformat.time_format(value, get_format(format or 'TIME_FORMAT', force=force))
    8080
    81 def number_format(value, decimal_pos=None):
     81def number_format(value, decimal_pos=None, force=False):
    8282    """
    8383    Formats a numeric value using localization settings
    8484    """
    85     if settings.USE_L10N:
     85    if settings.USE_L10N or force:
    8686        lang = get_language()
    8787    else:
    8888        lang = None
    8989    return numberformat.format(
    9090        value,
    91         get_format('DECIMAL_SEPARATOR', lang),
     91        get_format('DECIMAL_SEPARATOR', lang, force=force),
    9292        decimal_pos,
    93         get_format('NUMBER_GROUPING', lang),
    94         get_format('THOUSAND_SEPARATOR', lang),
     93        get_format('NUMBER_GROUPING', lang, force=force),
     94        get_format('THOUSAND_SEPARATOR', lang, force=force),
    9595    )
    9696
    97 def localize(value):
     97def localize(value, force=False):
    9898    """
    9999    Checks if value is a localizable type (date, number...) and returns it
    100100    formatted as a string using current locale format
     101    If force is True, localization is enabled without respecting settings.USE_L10N.
    101102    """
    102103    if isinstance(value, (decimal.Decimal, float, int, long)):
    103         return number_format(value)
     104        return number_format(value, force=force)
    104105    elif isinstance(value, datetime.datetime):
    105         return date_format(value, 'DATETIME_FORMAT')
     106        return date_format(value, 'DATETIME_FORMAT', force=force)
    106107    elif isinstance(value, datetime.date):
    107         return date_format(value)
     108        return date_format(value, force=force)
    108109    elif isinstance(value, datetime.time):
    109         return time_format(value, 'TIME_FORMAT')
     110        return time_format(value, 'TIME_FORMAT', force=force)
    110111    else:
    111112        return value
    112113
  • docs/ref/templates/builtins.txt

    diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
    index 70f0ffd..b846b58 100644
    a b Load a custom template tag set. 
    639639
    640640See :doc:`Custom tag and filter libraries </howto/custom-template-tags>` for more information.
    641641
     642.. templatetag:: localize
     643
     644localize
     645~~~~~
     646
     647.. versionadded:: 1.3
     648
     649Adjusts localization behavior for contained block.
     650
     651This tag allows a more fine grained control of localization than
     652:setting:`USE_L10N`.
     653
     654To activate or deactivate localization for a template block, use::
     655
     656    {% localize on %}
     657        {{ value }}
     658    {% endlocalize %}
     659   
     660    {% localize off %}
     661        {{ value }}
     662    {% endlocalize %}
     663
     664You can use a different locale than the current one for a template block::
     665
     666    {% localize "de" %}
     667        {{ value }}
     668    {% endlocalize %}
     669
     670.. note::
     671
     672    The value of :setting:`USE_L10N` is not respected inside of a
     673    `{% localize %}` block.   
     674
    642675.. templatetag:: now
    643676
    644677now
  • tests/regressiontests/i18n/tests.py

    diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
    index 4aa52b6..19e4b6c 100644
    a b class FormattingTests(TestCase): 
    453453            settings.FORMAT_MODULE_PATH = old_format_module_path
    454454            deactivate()
    455455
     456    def test_localize_templatetag(self):
     457        """
     458        Tests the {% noloc %} templatetag
     459        """
     460        context = Context({'value': 3.14 })
     461        template1 = Template("{{ value }};{% localize off %}{{ value }};{% endlocalize %}{{ value }}")
     462        template2 = Template("{% localize %}{{ value }}{% endlocalize %};{% localize on %}{{ value }}{% endlocalize %}")
     463        template3 = Template('{{ value }};{% localize "de" %}{{ value }}{% endlocalize %}')
     464        output1 = '3,14;3.14;3,14'
     465        output2 = '3,14;3,14'
     466        output3 = '3.14;3,14'
     467        old_debug = settings.TEMPLATE_DEBUG
     468        old_localize = settings.USE_L10N
     469        try:
     470            for debug in (True, False):
     471                settings.TEMPLATE_DEBUG = debug
     472                settings.USE_L10N = False
     473                self.assertEqual(template3.render(context), output3)
     474                activate('de')
     475                self.assertEqual(template2.render(context), output2)
     476                settings.USE_L10N = True
     477                self.assertEqual(template1.render(context), output1)
     478                deactivate()
     479        finally:
     480            deactivate()
     481            settings.TEMPLATE_DEBUG = old_debug
     482            settings.USE_L10N = old_localize
     483
    456484class MiscTests(TestCase):
    457485
    458486    def test_parse_spec_http_header(self):
Back to Top