Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Detect string formatting issues

- Fallback to original string
- Mail managers

fix bug 775557
  • Loading branch information...
commit e55dabf0cfd7ca06f30085037b3471791ae0decf 1 parent a759b55
Anthony Ricaud Rik authored
2  .gitignore
View
@@ -18,4 +18,4 @@ tmp/*
.#*
*.less.css
db.sql
-locale
+/locale
3  bin/jenkins.sh
View
@@ -36,6 +36,9 @@ from settings.base import *
ROOT_URLCONF = 'workspace.urls'
LOG_LEVEL = logging.ERROR
+ADMINS = ('foo@bar.com',)
+MANAGERS = ADMINS
+
SETTINGS
echo "Update product_details"
20 lib/l10n_utils/dotlang.py
View
@@ -9,12 +9,17 @@
import codecs
import os
+import re
from django.conf import settings
from django.core.cache import cache
from django.utils import translation
from django.utils.functional import lazy
+FORMAT_IDENTIFIER_RE = re.compile(r"""(%
+ (?:\((\w+)\))? # Mapping key
+ s)""", re.VERBOSE)
+
def parse(path):
"""Parse a dotlang file and return a dict of translations."""
@@ -28,7 +33,7 @@ def parse(path):
for line in lines:
if u'' in line:
- mail_error(line, path)
+ mail_error(path, line)
line = line.strip()
if line == '' or line[0] == '#':
@@ -45,12 +50,11 @@ def parse(path):
return trans
-def mail_error(line, path):
- """Email admins when a decoding error happened"""
+def mail_error(path, message):
+ """Email managers when an error is detected"""
from django.core import mail
subject = '%s is corrupted' % path
- message = line
- mail.mail_admins(subject, message)
+ mail.mail_managers(subject, message)
def fix_case(locale):
@@ -77,6 +81,12 @@ def translate(text, files):
cache.set(key, trans, settings.DOTLANG_CACHE)
if text in trans:
+ original = FORMAT_IDENTIFIER_RE.findall(text)
+ translated = FORMAT_IDENTIFIER_RE.findall(trans[text])
+ if original != translated:
+ message = '%s\n%s' % (text, trans[text])
+ mail_error(file_, message)
+ return text
return trans[text]
return text
2  lib/l10n_utils/tests/locale/en-US/format_identifier_mismatch.lang
View
@@ -0,0 +1,2 @@
+;%(foo)s is the new %s
+%(foo)s is the new bar
31 lib/l10n_utils/tests/test_dotlang.py
View
@@ -3,18 +3,19 @@
import os
import unittest
+from mock import patch
from nose.tools import eq_
+from django.conf import settings
from django.core import mail
-from l10n_utils.dotlang import parse
+from l10n_utils.dotlang import FORMAT_IDENTIFIER_RE, parse, translate
+ROOT = os.path.dirname(os.path.abspath(__file__))
-class TestDotlang(unittest.TestCase):
- def setUp(self):
- self.path = os.path.dirname(os.path.abspath(__file__))
+class TestDotlang(unittest.TestCase):
def test_parse(self):
- path = os.path.join(self.path, 'test.lang')
+ path = os.path.join(ROOT, 'test.lang')
parsed = parse(path)
expected = {
u'Hooray! Your Firefox is up to date.':
@@ -23,11 +24,10 @@ def test_parse(self):
u'Your Firefox is out of date.':
u'Votre Firefox ne semble pas \xe0 jour.'
}
-
eq_(parsed, expected)
def test_parse_utf8_error(self):
- path = os.path.join(self.path, 'test_utf8_error.lang')
+ path = os.path.join(ROOT, 'test_utf8_error.lang')
parsed = parse(path)
eq_(len(mail.outbox), 1)
eq_(mail.outbox[0].subject, '[Django] %s is corrupted' % path)
@@ -37,3 +37,20 @@ def test_parse_utf8_error(self):
}
eq_(parsed, expected)
mail.outbox = []
+
+ def test_format_identifier_re(self):
+ eq_(FORMAT_IDENTIFIER_RE.findall('%s %s'),
+ [('%s', ''), ('%s', '')])
+
+ eq_(FORMAT_IDENTIFIER_RE.findall('%(foo_bar)s %s'),
+ [('%(foo_bar)s', 'foo_bar'), ('%s', '')])
+
+ @patch.object(settings, 'ROOT', ROOT)
+ def test_format_identifier_mismatch(self):
+ path = 'format_identifier_mismatch'
+ expected = '%(foo)s is the new %s'
+ result = translate(expected, [path])
+ eq_(expected, result)
+ eq_(len(mail.outbox), 1)
+ eq_(mail.outbox[0].subject, '[Django] %s is corrupted' % path)
+ mail.outbox = []
Please sign in to comment.
Something went wrong with that request. Please try again.