diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py
index c7202e2..cd7a3a7 100644
a
|
b
|
class BlockTranslateNode(Node):
|
122 | 122 | result = re.sub(u'%(?!\()', u'%%', result) |
123 | 123 | data = dict([(v, _render_value_in_context(context.get(v, ''), context)) for v in vars]) |
124 | 124 | context.pop() |
125 | | return result % data |
| 125 | try: |
| 126 | result = result % data |
| 127 | except KeyError: |
| 128 | with translation.override(None): |
| 129 | result = self.render(context) |
| 130 | return result |
126 | 131 | |
127 | 132 | |
128 | 133 | class LanguageNode(Node): |
diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py
index acf4d8d..8ad9c5d 100644
a
|
b
|
class override(object):
|
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: |
diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt
index 0849a21..299d026 100644
a
|
b
|
For a complete discussion on the usage of the following see the
|
537 | 537 | useful when we want delayed translations to appear as the original string |
538 | 538 | for some reason. |
539 | 539 | |
540 | | .. function:: override(language) |
| 540 | .. function:: override(language, deactivate=False) |
541 | 541 | |
542 | 542 | .. versionadded:: 1.4 |
543 | 543 | |
544 | 544 | A Python context manager that uses |
545 | 545 | :func:`django.utils.translation.activate` to fetch the translation object |
546 | 546 | for a given language, installing it as the translation object for the |
547 | | current thread and deinstalls it again on exit with |
548 | | :func:`django.utils.translation.deactivate`. |
| 547 | current thread and reinstall the previous active language on exit. |
| 548 | Optionally it can simply deinstall the temporary translation on exit with |
| 549 | :func:`django.utils.translation.deactivate` if the deactivate argument is |
| 550 | True. |
| 551 | If you pass None as the language argument, a NullTranslations() instance is |
| 552 | installed while the context is active. |
549 | 553 | |
550 | 554 | .. function:: get_language() |
551 | 555 | |
diff --git a/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mo b/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mo
new file mode 100644
index 0000000..f0a2179
Binary files /dev/null and b/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mo differ
diff --git a/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.po b/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.po
new file mode 100644
index 0000000..8e9b9e1
-
|
+
|
|
| 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." |
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index 0b955ad..e5a08da 100644
a
|
b
|
from threading import local
|
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 |
… |
… |
class TranslationTests(TestCase):
|
34 | 35 | with translation.override('pl'): |
35 | 36 | self.assertEqual(get_language(), 'pl') |
36 | 37 | self.assertEqual(get_language(), 'de') |
| 38 | with translation.override(None): |
| 39 | self.assertEqual(get_language(), settings.LANGUAGE_CODE) |
| 40 | self.assertEqual(get_language(), 'de') |
37 | 41 | deactivate() |
38 | 42 | |
39 | 43 | def test_lazy_objects(self): |
… |
… |
class TranslationTests(TestCase):
|
129 | 133 | self.assertEqual(to_language('en_US'), 'en-us') |
130 | 134 | self.assertEqual(to_language('sr_Lat'), 'sr-lat') |
131 | 135 | |
| 136 | @override_settings( |
| 137 | LOCALE_PATHS = ( |
| 138 | os.path.join(os.path.dirname(os.path.abspath(__file__)), 'other', 'locale'), |
| 139 | ), |
| 140 | ) |
| 141 | def test_bad_placeholder(self): |
| 142 | """ |
| 143 | Error in translation file should not crash template rendering |
| 144 | (%(person)s is translated as %(personne)s in fr.po) |
| 145 | """ |
| 146 | from django.template import Template, Context |
| 147 | with translation.override('fr'): |
| 148 | t = Template('{% load i18n %}{% blocktrans %}My name is {{ person }}.{% endblocktrans %}') |
| 149 | c = Context({'person': u"James"}) |
| 150 | rendered = t.render(c) |
| 151 | self.assertEqual(rendered, u"My name is James.") |
| 152 | |
132 | 153 | |
133 | 154 | class FormattingTests(TestCase): |
134 | 155 | |