Skip to content

Commit

Permalink
Merge pull request #535 from pmclanahan/bug-821330-contribute-form-no…
Browse files Browse the repository at this point in the history
…t-translating

Bug 821330: Fix translations on contribute page.
  • Loading branch information
pmac committed Dec 17, 2012
2 parents 92b1e85 + d1b9805 commit b843560
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 24 deletions.
3 changes: 2 additions & 1 deletion apps/mozorg/email_contribute.py
Expand Up @@ -12,8 +12,9 @@

from l10n_utils.dotlang import _lazy as _

fa = namedtuple('FunctionalArea', ['id', 'name', 'subject', 'contacts'])

fa = namedtuple('FunctionalArea', ['id', 'name', 'subject', 'contacts'])
LANG_FILES = 'mozorg/contribute'
FUNCTIONAL_AREAS = (
fa('support',
_('Helping Users'),
Expand Down
1 change: 1 addition & 0 deletions apps/mozorg/forms.py
Expand Up @@ -23,6 +23,7 @@
LANGS = settings.NEWSLETTER_LANGUAGES
LANGS_TO_STRIP = ['en-US', 'es']
PARENTHETIC_RE = re.compile(r' \([^)]+\)$')
LANG_FILES = 'mozorg/contribute'


def strip_parenthetical(lang_name):
Expand Down
62 changes: 43 additions & 19 deletions lib/l10n_utils/dotlang.py
Expand Up @@ -10,17 +10,18 @@
It caches them using the django caching library, but it could
potentially just use thread-local variables. Caching seems safer at
the expense of another caching layer."""

import codecs
import inspect
import os
import re
from functools import partial

from django.conf import settings
from django.core.cache import cache
from django.utils import translation
from django.utils.functional import lazy

from jinja2 import Markup
from tower.management.commands.extract import tweak_message


Expand Down Expand Up @@ -99,22 +100,12 @@ def translate(text, files):
message = '%s\n\n%s\n%s' % (explanation, text,
trans[tweaked_text])
mail_error(rel_path, message)
return text
return trans[tweaked_text]
return text
return Markup(text)
return Markup(trans[tweaked_text])
return Markup(text)


def _(text, *args):
"""
Translate a piece of text from the global files. If `LANG_FILES` is defined
in the module from which this function is called, those files (or file)
will be searched first for the translation, followed by the default files.
:param text: string to translate
:param args: items for interpolation into `text`
:return: translated string
"""
lang_files = settings.DOTLANG_FILES
def _get_extra_lang_files():
frame = inspect.currentframe()
if frame is None:
if settings.DEBUG:
Expand All @@ -124,22 +115,55 @@ def _(text, *args):
'source files will not work.', RuntimeWarning)
else:
try:
# gets value of LANG_FILE constant in calling module if specified
new_lang_files = frame.f_back.f_globals.get('LANG_FILES')
# gets value of LANG_FILE constant in calling module if specified.
# have to go back 2x to compensate for this function.
new_lang_files = frame.f_back.f_back.f_globals.get('LANG_FILES', [])
finally:
del frame
if new_lang_files:
if isinstance(new_lang_files, basestring):
new_lang_files = [new_lang_files]
lang_files = new_lang_files + lang_files
return new_lang_files


def _(text, *args, **kwargs):
"""
Translate a piece of text from the global files. If `LANG_FILES` is defined
in the module from which this function is called, those files (or file)
will be searched first for the translation, followed by the default files.
:param text: string to translate
:param args: items for interpolation into `text`
:param lang_files: extra lang file names to search for a translation.
NOTE: DO NOT USE THIS for string extraction. It will NOT respect
the values in this kwarg when extracting strings. This is only useful
if you know the string is in a different file but you don't want to
add that file for the whole module via the `LANG_FILES` constant.
:return: translated string
"""
lang_files = kwargs.pop('lang_files', [])
if isinstance(lang_files, list):
lang_files = lang_files[:]
else:
lang_files = [lang_files]
if not lang_files:
lang_files += _get_extra_lang_files()
lang_files += settings.DOTLANG_FILES

text = translate(text, lang_files)
if args:
text = text % args
return text


_lazy = lazy(_, unicode)
_lazy_proxy = lazy(_, unicode)


def _lazy(*args, **kwargs):
lang_files = _get_extra_lang_files()
if lang_files:
return partial(_lazy_proxy, lang_files=lang_files)(*args, **kwargs)
return _lazy_proxy(*args, **kwargs)


def get_lang_path(path):
Expand Down
4 changes: 1 addition & 3 deletions lib/l10n_utils/helpers.py
Expand Up @@ -36,9 +36,7 @@ def gettext(ctx, text):
"""Translate a string, loading the translations for the locale if
necessary."""
install_lang_files(ctx)

trans = translate(text, ctx['request'].langfiles)
return jinja2.Markup(trans)
return translate(text, ctx['request'].langfiles)


@jingo.register.function
Expand Down
62 changes: 61 additions & 1 deletion lib/l10n_utils/tests/test_dotlang.py
Expand Up @@ -20,7 +20,7 @@
from tower.management.commands.extract import extract_tower_python

from l10n_utils.dotlang import (_, FORMAT_IDENTIFIER_RE, lang_file_is_active,
parse, translate)
parse, translate, _lazy)
from mozorg.tests import TestCase


Expand Down Expand Up @@ -200,6 +200,66 @@ def test_gettext_searches_specified_lang_files(self, trans_patch):
# restore original value to avoid test leakage
LANG_FILES = old_lang_files

@patch('l10n_utils.dotlang.translate')
def test_gettext_searches_kwarg_specified_lang_files(self, trans_patch):
"""
The `l10n_utils.dotlang._` function should search .lang files
specified in the `lang_files` keyword arg, and not the ones from the
module.
"""
# test the case when LANG_FILES is a string
trans_str = 'Translate me'
_(trans_str, lang_files='maude')
call_lang_files = ['maude'] + settings.DOTLANG_FILES
trans_patch.assert_called_with(trans_str, call_lang_files)

# test the case when LANG_FILES is a list
lang_files_list = ['maude', 'bunny', 'uli']
_(trans_str, lang_files=lang_files_list)
print lang_files_list
call_lang_files = lang_files_list + settings.DOTLANG_FILES
trans_patch.assert_called_with(trans_str, call_lang_files)

@patch('l10n_utils.dotlang.translate')
def test_gettext_lazy_searches_kwarg_specified_lang_files(self, trans_patch):
"""
The `l10n_utils.dotlang._lazy` function should search .lang files
specified in the `lang_files` keyword arg, and not the ones from the
module.
"""
# test the case when LANG_FILES is a string
trans_str = 'Translate me'
# have to call __unicode__ directly because the value is a Mock
# object, and the `unicode()` function throws an exception.
_lazy(trans_str, lang_files='maude').__unicode__()
call_lang_files = ['maude'] + settings.DOTLANG_FILES
trans_patch.assert_called_with(trans_str, call_lang_files)

# test the case when LANG_FILES is a list
lang_files_list = ['maude', 'bunny', 'uli']
_lazy(trans_str, lang_files=lang_files_list).__unicode__()
print lang_files_list
call_lang_files = lang_files_list + settings.DOTLANG_FILES
trans_patch.assert_called_with(trans_str, call_lang_files)

@patch('l10n_utils.dotlang.translate')
def test_lazy_gettext_searches_specified_lang_files(self, trans_patch):
"""
The `l10n_utils.dotlang._lazy` function should search .lang files
specified in the module from which it's called before the
default files.
"""
from l10n_utils.tests.test_files import extract_me_with_langfiles_lazy

dude_says = extract_me_with_langfiles_lazy.do_translate()
dirty_string = u"I'm The Dude, so that's what you call me, man."
self.assertFalse(trans_patch.called)
# have to call __unicode__ directly because the value is a Mock
# object, and the `unicode()` function throws an exception.
dude_says.__unicode__()
trans_patch.assert_called_with(dirty_string, ['donnie', 'walter'] +
settings.DOTLANG_FILES)

@patch('l10n_utils.dotlang.translate')
def test_gettext_works_without_extra_lang_files(self, trans_patch):
"""
Expand Down
16 changes: 16 additions & 0 deletions lib/l10n_utils/tests/test_files/extract_me_with_langfiles_lazy.py
@@ -0,0 +1,16 @@
# coding: utf-8

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from l10n_utils.dotlang import _lazy as _


LANG_FILES = [
'donnie',
'walter',
]

def do_translate():
return _(u"I'm The Dude, so that's what you call me, man.")

0 comments on commit b843560

Please sign in to comment.