summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJannis Leidel <jannis@leidel.info>2011-09-08 13:24:41 +0000
committerJannis Leidel <jannis@leidel.info>2011-09-08 13:24:41 +0000
commit16bb9c594cf7306f4b2fc3ba915be43b05dad5d2 (patch)
tree447587001df5ccf70e094b6e89d796c80c54ae7a
parent2b4341d532b376702a17212a9ff9f8710ca4c14a (diff)
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
-rw-r--r--django/templatetags/i18n.py7
-rw-r--r--django/utils/translation/__init__.py5
-rw-r--r--docs/ref/utils.txt9
-rw-r--r--docs/topics/i18n/internationalization.txt7
-rw-r--r--tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mobin0 -> 454 bytes
-rw-r--r--tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.po21
-rw-r--r--tests/regressiontests/i18n/tests.py22
7 files changed, 64 insertions, 7 deletions
diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py
index 8fc312c066..519354985f 100644
--- a/django/templatetags/i18n.py
+++ b/django/templatetags/i18n.py
@@ -128,7 +128,12 @@ class BlockTranslateNode(Node):
result = re.sub(u'%(?!\()', u'%%', result)
data = dict([(v, _render_value_in_context(context.get(v, ''), context)) for v in vars])
context.pop()
- return result % data
+ try:
+ result = result % data
+ except KeyError:
+ with translation.override(None):
+ result = self.render(context)
+ return result
class LanguageNode(Node):
diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py
index acf4d8dead..8ad9c5d59a 100644
--- a/django/utils/translation/__init__.py
+++ b/django/utils/translation/__init__.py
@@ -115,7 +115,10 @@ class override(object):
self.old_language = get_language()
def __enter__(self):
- activate(self.language)
+ if self.language is not None:
+ activate(self.language)
+ else:
+ deactivate_all()
def __exit__(self, exc_type, exc_value, traceback):
if self.deactivate:
diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt
index 0b2e386268..1755ee77b3 100644
--- a/docs/ref/utils.txt
+++ b/docs/ref/utils.txt
@@ -532,15 +532,18 @@ For a complete discussion on the usage of the following see the
useful when we want delayed translations to appear as the original string
for some reason.
-.. function:: override(language)
+.. function:: override(language, deactivate=False)
.. versionadded:: 1.4
A Python context manager that uses
:func:`django.utils.translation.activate` to fetch the translation object
for a given language, installing it as the translation object for the
- current thread and deinstalls it again on exit with
- :func:`django.utils.translation.deactivate`.
+ current thread and reinstall the previous active language on exit.
+ Optionally it can simply deinstall the temporary translation on exit with
+ :func:`django.utils.translation.deactivate` if the deactivate argument is
+ True. If you pass None as the language argument, a NullTranslations()
+ instance is installed while the context is active.
.. function:: get_language()
diff --git a/docs/topics/i18n/internationalization.txt b/docs/topics/i18n/internationalization.txt
index 176ad7fb43..dbeb77c879 100644
--- a/docs/topics/i18n/internationalization.txt
+++ b/docs/topics/i18n/internationalization.txt
@@ -512,6 +512,13 @@ You can use multiple expressions inside a single ``blocktrans`` tag::
.. note:: The previous more verbose format is still supported:
``{% blocktrans with book|title as book_t and author|title as author_t %}``
+.. versionchanged:: 1.4
+
+If resolving one of the block arguments fails, blocktrans will fall back to
+the default language by deactivating the currently active language
+temporarily with the :func:`~django.utils.translation.deactivate_all`
+function.
+
This tag also provides for pluralization. To use it:
* Designate and bind a counter value with the name ``count``. This value will
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 0000000000..f0a2179767
--- /dev/null
+++ b/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mo
Binary files 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 0000000000..8e9b9e1034
--- /dev/null
+++ b/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.po
@@ -0,0 +1,21 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: django tests\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-02-14 17:33+0100\n"
+"PO-Revision-Date: 2011-01-21 21:37-0300\n"
+"Last-Translator: Claude\n"
+"Language-Team: fr <fr@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: template.html:3
+msgid "My name is %(person)s."
+msgstr "Mon nom est %(personne)s."
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index 0b955ad3da..f230e59556 100644
--- a/tests/regressiontests/i18n/tests.py
+++ b/tests/regressiontests/i18n/tests.py
@@ -9,6 +9,7 @@ from threading import local
from django.conf import settings
from django.template import Template, Context
from django.test import TestCase, RequestFactory
+from django.test.utils import override_settings
from django.utils.formats import (get_format, date_format, time_format,
localize, localize_input, iter_format_modules, get_format_modules)
from django.utils.importlib import import_module
@@ -27,6 +28,8 @@ from commands.tests import *
from patterns.tests import *
from test_warnings import DeprecationWarningTests
+here = os.path.dirname(os.path.abspath(__file__))
+
class TranslationTests(TestCase):
def test_override(self):
@@ -34,6 +37,9 @@ class TranslationTests(TestCase):
with translation.override('pl'):
self.assertEqual(get_language(), 'pl')
self.assertEqual(get_language(), 'de')
+ with translation.override(None):
+ self.assertEqual(get_language(), settings.LANGUAGE_CODE)
+ self.assertEqual(get_language(), 'de')
deactivate()
def test_lazy_objects(self):
@@ -67,7 +73,7 @@ class TranslationTests(TestCase):
def test_pgettext(self):
# Reset translation catalog to include other/locale/de
extended_locale_paths = settings.LOCALE_PATHS + (
- os.path.join(os.path.dirname(os.path.abspath(__file__)), 'other', 'locale'),
+ os.path.join(here, 'other', 'locale'),
)
with self.settings(LOCALE_PATHS=extended_locale_paths):
from django.utils.translation import trans_real
@@ -129,6 +135,18 @@ class TranslationTests(TestCase):
self.assertEqual(to_language('en_US'), 'en-us')
self.assertEqual(to_language('sr_Lat'), 'sr-lat')
+ @override_settings(LOCALE_PATHS=(os.path.join(here, 'other', 'locale'),))
+ def test_bad_placeholder(self):
+ """
+ Error in translation file should not crash template rendering
+ (%(person)s is translated as %(personne)s in fr.po)
+ """
+ from django.template import Template, Context
+ with translation.override('fr'):
+ t = Template('{% load i18n %}{% blocktrans %}My name is {{ person }}.{% endblocktrans %}')
+ rendered = t.render(Context({'person': 'James'}))
+ self.assertEqual(rendered, 'My name is James.')
+
class FormattingTests(TestCase):
@@ -636,7 +654,7 @@ class LocalePathsResolutionOrderI18NTests(ResolutionOrderI18NTests):
def setUp(self):
self.old_locale_paths = settings.LOCALE_PATHS
- settings.LOCALE_PATHS += (os.path.join(os.path.dirname(os.path.abspath(__file__)), 'other', 'locale'),)
+ settings.LOCALE_PATHS += (os.path.join(here, 'other', 'locale'),)
super(LocalePathsResolutionOrderI18NTests, self).setUp()
def tearDown(self):