Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #16516 -- Relaxed the blocktrans rendering a little by falling …

…back to the default language if resolving one of the arguments fails, raising a KeyError. Thanks, Claude Paroz and Aymeric Augustin.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16723 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 16bb9c594cf7306f4b2fc3ba915be43b05dad5d2 1 parent 2b4341d
Jannis Leidel authored September 08, 2011
7  django/templatetags/i18n.py
@@ -128,7 +128,12 @@ def render(self, context):
128 128
         result = re.sub(u'%(?!\()', u'%%', result)
129 129
         data = dict([(v, _render_value_in_context(context.get(v, ''), context)) for v in vars])
130 130
         context.pop()
131  
-        return result % data
  131
+        try:
  132
+            result = result % data
  133
+        except KeyError:
  134
+            with translation.override(None):
  135
+                result = self.render(context)
  136
+        return result
132 137
 
133 138
 
134 139
 class LanguageNode(Node):
5  django/utils/translation/__init__.py
@@ -115,7 +115,10 @@ def __init__(self, language, deactivate=False):
115 115
         self.old_language = get_language()
116 116
 
117 117
     def __enter__(self):
118  
-        activate(self.language)
  118
+        if self.language is not None:
  119
+            activate(self.language)
  120
+        else:
  121
+            deactivate_all()
119 122
 
120 123
     def __exit__(self, exc_type, exc_value, traceback):
121 124
         if self.deactivate:
9  docs/ref/utils.txt
@@ -532,15 +532,18 @@ For a complete discussion on the usage of the following see the
532 532
     useful when we want delayed translations to appear as the original string
533 533
     for some reason.
534 534
 
535  
-.. function:: override(language)
  535
+.. function:: override(language, deactivate=False)
536 536
 
537 537
     .. versionadded:: 1.4
538 538
 
539 539
     A Python context manager that uses
540 540
     :func:`django.utils.translation.activate` to fetch the translation object
541 541
     for a given language, installing it as the translation object for the
542  
-    current thread and deinstalls it again on exit with
543  
-    :func:`django.utils.translation.deactivate`.
  542
+    current thread and reinstall the previous active language on exit.
  543
+    Optionally it can simply deinstall the temporary translation on exit with
  544
+    :func:`django.utils.translation.deactivate` if the deactivate argument is
  545
+    True. If you pass None as the language argument, a NullTranslations()
  546
+    instance is installed while the context is active.
544 547
 
545 548
 .. function:: get_language()
546 549
 
7  docs/topics/i18n/internationalization.txt
@@ -512,6 +512,13 @@ You can use multiple expressions inside a single ``blocktrans`` tag::
512 512
 .. note:: The previous more verbose format is still supported:
513 513
    ``{% blocktrans with book|title as book_t and author|title as author_t %}``
514 514
 
  515
+.. versionchanged:: 1.4
  516
+
  517
+If resolving one of the block arguments fails, blocktrans will fall back to
  518
+the default language by deactivating the currently active language
  519
+temporarily with the :func:`~django.utils.translation.deactivate_all`
  520
+function.
  521
+
515 522
 This tag also provides for pluralization. To use it:
516 523
 
517 524
     * Designate and bind a counter value with the name ``count``. This value will
BIN  tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mo
Binary file not shown
21  tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.po
... ...
@@ -0,0 +1,21 @@
  1
+# SOME DESCRIPTIVE TITLE.
  2
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
  3
+# This file is distributed under the same license as the PACKAGE package.
  4
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
  5
+#
  6
+msgid ""
  7
+msgstr ""
  8
+"Project-Id-Version: django tests\n"
  9
+"Report-Msgid-Bugs-To: \n"
  10
+"POT-Creation-Date: 2010-02-14 17:33+0100\n"
  11
+"PO-Revision-Date: 2011-01-21 21:37-0300\n"
  12
+"Last-Translator: Claude\n"
  13
+"Language-Team: fr <fr@li.org>\n"
  14
+"MIME-Version: 1.0\n"
  15
+"Content-Type: text/plain; charset=UTF-8\n"
  16
+"Content-Transfer-Encoding: 8bit\n"
  17
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
  18
+
  19
+#: template.html:3
  20
+msgid "My name is %(person)s."
  21
+msgstr "Mon nom est %(personne)s."
22  tests/regressiontests/i18n/tests.py
@@ -9,6 +9,7 @@
9 9
 from django.conf import settings
10 10
 from django.template import Template, Context
11 11
 from django.test import TestCase, RequestFactory
  12
+from django.test.utils import override_settings
12 13
 from django.utils.formats import (get_format, date_format, time_format,
13 14
     localize, localize_input, iter_format_modules, get_format_modules)
14 15
 from django.utils.importlib import import_module
@@ -27,6 +28,8 @@
27 28
 from patterns.tests import *
28 29
 from test_warnings import DeprecationWarningTests
29 30
 
  31
+here = os.path.dirname(os.path.abspath(__file__))
  32
+
30 33
 class TranslationTests(TestCase):
31 34
 
32 35
     def test_override(self):
@@ -34,6 +37,9 @@ def test_override(self):
34 37
         with translation.override('pl'):
35 38
             self.assertEqual(get_language(), 'pl')
36 39
         self.assertEqual(get_language(), 'de')
  40
+        with translation.override(None):
  41
+            self.assertEqual(get_language(), settings.LANGUAGE_CODE)
  42
+        self.assertEqual(get_language(), 'de')
37 43
         deactivate()
38 44
 
39 45
     def test_lazy_objects(self):
@@ -67,7 +73,7 @@ def test_lazy_pickle(self):
67 73
     def test_pgettext(self):
68 74
         # Reset translation catalog to include other/locale/de
69 75
         extended_locale_paths = settings.LOCALE_PATHS + (
70  
-            os.path.join(os.path.dirname(os.path.abspath(__file__)), 'other', 'locale'),
  76
+            os.path.join(here, 'other', 'locale'),
71 77
         )
72 78
         with self.settings(LOCALE_PATHS=extended_locale_paths):
73 79
             from django.utils.translation import trans_real
@@ -129,6 +135,18 @@ def test_to_language(self):
129 135
         self.assertEqual(to_language('en_US'), 'en-us')
130 136
         self.assertEqual(to_language('sr_Lat'), 'sr-lat')
131 137
 
  138
+    @override_settings(LOCALE_PATHS=(os.path.join(here, 'other', 'locale'),))
  139
+    def test_bad_placeholder(self):
  140
+        """
  141
+        Error in translation file should not crash template rendering
  142
+        (%(person)s is translated as %(personne)s in fr.po)
  143
+        """
  144
+        from django.template import Template, Context
  145
+        with translation.override('fr'):
  146
+            t = Template('{% load i18n %}{% blocktrans %}My name is {{ person }}.{% endblocktrans %}')
  147
+            rendered = t.render(Context({'person': 'James'}))
  148
+            self.assertEqual(rendered, 'My name is James.')
  149
+
132 150
 
133 151
 class FormattingTests(TestCase):
134 152
 
@@ -636,7 +654,7 @@ class LocalePathsResolutionOrderI18NTests(ResolutionOrderI18NTests):
636 654
 
637 655
     def setUp(self):
638 656
         self.old_locale_paths = settings.LOCALE_PATHS
639  
-        settings.LOCALE_PATHS += (os.path.join(os.path.dirname(os.path.abspath(__file__)), 'other', 'locale'),)
  657
+        settings.LOCALE_PATHS += (os.path.join(here, 'other', 'locale'),)
640 658
         super(LocalePathsResolutionOrderI18NTests, self).setUp()
641 659
 
642 660
     def tearDown(self):

0 notes on commit 16bb9c5

Please sign in to comment.
Something went wrong with that request. Please try again.