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
This commit is contained in:
Jannis Leidel 2011-09-08 13:24:41 +00:00
parent 2b4341d532
commit 16bb9c594c
7 changed files with 64 additions and 7 deletions

View File

@ -128,7 +128,12 @@ class BlockTranslateNode(Node):
result = re.sub(u'%(?!\()', u'%%', result) result = re.sub(u'%(?!\()', u'%%', result)
data = dict([(v, _render_value_in_context(context.get(v, ''), context)) for v in vars]) data = dict([(v, _render_value_in_context(context.get(v, ''), context)) for v in vars])
context.pop() context.pop()
return result % data try:
result = result % data
except KeyError:
with translation.override(None):
result = self.render(context)
return result
class LanguageNode(Node): class LanguageNode(Node):

View File

@ -115,7 +115,10 @@ class override(object):
self.old_language = get_language() self.old_language = get_language()
def __enter__(self): 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): def __exit__(self, exc_type, exc_value, traceback):
if self.deactivate: if self.deactivate:

View File

@ -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 useful when we want delayed translations to appear as the original string
for some reason. for some reason.
.. function:: override(language) .. function:: override(language, deactivate=False)
.. versionadded:: 1.4 .. versionadded:: 1.4
A Python context manager that uses A Python context manager that uses
:func:`django.utils.translation.activate` to fetch the translation object :func:`django.utils.translation.activate` to fetch the translation object
for a given language, installing it as the translation object for the for a given language, installing it as the translation object for the
current thread and deinstalls it again on exit with current thread and reinstall the previous active language on exit.
:func:`django.utils.translation.deactivate`. 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() .. function:: get_language()

View File

@ -512,6 +512,13 @@ You can use multiple expressions inside a single ``blocktrans`` tag::
.. note:: The previous more verbose format is still supported: .. note:: The previous more verbose format is still supported:
``{% blocktrans with book|title as book_t and author|title as author_t %}`` ``{% 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: This tag also provides for pluralization. To use it:
* Designate and bind a counter value with the name ``count``. This value will * Designate and bind a counter value with the name ``count``. This value will

View File

@ -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."

View File

@ -9,6 +9,7 @@ from threading import local
from django.conf import settings from django.conf import settings
from django.template import Template, Context from django.template import Template, Context
from django.test import TestCase, RequestFactory from django.test import TestCase, RequestFactory
from django.test.utils import override_settings
from django.utils.formats import (get_format, date_format, time_format, from django.utils.formats import (get_format, date_format, time_format,
localize, localize_input, iter_format_modules, get_format_modules) localize, localize_input, iter_format_modules, get_format_modules)
from django.utils.importlib import import_module from django.utils.importlib import import_module
@ -27,6 +28,8 @@ from commands.tests import *
from patterns.tests import * from patterns.tests import *
from test_warnings import DeprecationWarningTests from test_warnings import DeprecationWarningTests
here = os.path.dirname(os.path.abspath(__file__))
class TranslationTests(TestCase): class TranslationTests(TestCase):
def test_override(self): def test_override(self):
@ -34,6 +37,9 @@ class TranslationTests(TestCase):
with translation.override('pl'): with translation.override('pl'):
self.assertEqual(get_language(), 'pl') self.assertEqual(get_language(), 'pl')
self.assertEqual(get_language(), 'de') self.assertEqual(get_language(), 'de')
with translation.override(None):
self.assertEqual(get_language(), settings.LANGUAGE_CODE)
self.assertEqual(get_language(), 'de')
deactivate() deactivate()
def test_lazy_objects(self): def test_lazy_objects(self):
@ -67,7 +73,7 @@ class TranslationTests(TestCase):
def test_pgettext(self): def test_pgettext(self):
# Reset translation catalog to include other/locale/de # Reset translation catalog to include other/locale/de
extended_locale_paths = settings.LOCALE_PATHS + ( 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): with self.settings(LOCALE_PATHS=extended_locale_paths):
from django.utils.translation import trans_real 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('en_US'), 'en-us')
self.assertEqual(to_language('sr_Lat'), 'sr-lat') 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): class FormattingTests(TestCase):
@ -636,7 +654,7 @@ class LocalePathsResolutionOrderI18NTests(ResolutionOrderI18NTests):
def setUp(self): def setUp(self):
self.old_locale_paths = settings.LOCALE_PATHS 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() super(LocalePathsResolutionOrderI18NTests, self).setUp()
def tearDown(self): def tearDown(self):