From 61fd00d4fd65f44d0a05be4c7e95124e4102ec27 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Fri, 2 May 2014 19:31:22 +0200 Subject: [PATCH] [1.7.x] Fixed #22565 -- Prevented pgettext_lazy crash with bytestring input Thanks ygbo for the report. Backport of 142c27218 from master. --- django/utils/translation/trans_real.py | 3 ++- docs/releases/1.6.5.txt | 3 +++ tests/i18n/tests.py | 20 ++++++++++++++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index 6bbdbe5f20..4f07012149 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -322,7 +322,8 @@ def pgettext(context, message): result = ugettext(msg_with_ctxt) if CONTEXT_SEPARATOR in result: # Translation not found - result = message + # force unicode, because lazy version expects unicode + result = force_text(message) return result diff --git a/docs/releases/1.6.5.txt b/docs/releases/1.6.5.txt index 9abe6702cc..3c46b953b7 100644 --- a/docs/releases/1.6.5.txt +++ b/docs/releases/1.6.5.txt @@ -11,3 +11,6 @@ Bugfixes * Made the ``year_lookup_bounds_for_datetime_field`` Oracle backend method Python 3 compatible (`#22551 `_). + +* Fixed ``pgettext_lazy`` crash when receiving bytestring content on Python 2 + (`#22565 `_). diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index 9501849e09..9edcec4774 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -8,6 +8,7 @@ from importlib import import_module import os import pickle from threading import local +from unittest import skipUnless from django.conf import settings from django.template import Template, Context @@ -29,7 +30,7 @@ from django.utils.translation import (activate, deactivate, ugettext, ugettext_lazy, ngettext_lazy, ungettext_lazy, - pgettext, + pgettext, pgettext_lazy, npgettext, npgettext_lazy, check_for_language, string_concat, LANGUAGE_SESSION_KEY) @@ -93,9 +94,20 @@ class TranslationTests(TestCase): s4 = ugettext_lazy('Some other string') self.assertEqual(False, s == s4) - if six.PY2: - # On Python 2, gettext_lazy should not transform a bytestring to unicode - self.assertEqual(gettext_lazy(b"test").upper(), b"TEST") + @skipUnless(six.PY2, "No more bytestring translations on PY3") + def test_lazy_and_bytestrings(self): + # On Python 2, (n)gettext_lazy should not transform a bytestring to unicode + self.assertEqual(gettext_lazy(b"test").upper(), b"TEST") + self.assertEqual((ngettext_lazy(b"%d test", b"%d tests") % 1).upper(), b"1 TEST") + + # Other versions of lazy functions always return unicode + self.assertEqual(ugettext_lazy(b"test").upper(), "TEST") + self.assertEqual((ungettext_lazy(b"%d test", b"%d tests") % 1).upper(), "1 TEST") + self.assertEqual(pgettext_lazy(b"context", b"test").upper(), "TEST") + self.assertEqual( + (npgettext_lazy(b"context", b"%d test", b"%d tests") % 1).upper(), + "1 TEST" + ) def test_lazy_pickle(self): s1 = ugettext_lazy("test")