Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix Bug 1097785 - Legal-docs-based pages should not rely on active ta…
…gs in .lang files
  • Loading branch information
kyoshino committed Jan 27, 2015
1 parent 42c7a4b commit 0957843
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 23 deletions.
43 changes: 34 additions & 9 deletions bedrock/legal_docs/tests.py
Expand Up @@ -16,32 +16,44 @@


class TestLoadLegalDoc(TestCase):
def test_legal_doc_not_found(self):
@patch.object(views, 'listdir')
def test_legal_doc_not_found(self, listdir_mock):
listdir_mock.return_value = ['en-US.md']
doc = views.load_legal_doc('the_dude_is_legal', 'de')
self.assertIsNone(doc)
self.assertIsNone(doc['content'])
self.assertFalse(doc['localized'])
self.assertDictEqual(doc['translations'], {'en-US': 'English (US)'})

@patch.object(views, 'listdir')
@patch.object(views, 'StringIO')
@patch.object(views, 'md')
def test_legal_doc_exists(self, md_mock, sio_mock):
def test_legal_doc_exists(self, md_mock, sio_mock, listdir_mock):
"""Should return the content of the en-US file if it exists."""
sio_mock.StringIO.return_value.getvalue.return_value = "You're not wrong Walter..."
listdir_mock.return_value = ['.mkdir', 'de.md', 'en-US.md']
doc = views.load_legal_doc('the_dude_exists', 'de')
good_path = join(views.LEGAL_DOCS_PATH, 'the_dude_exists', 'en-US.md')
md_mock.markdownFromFile.assert_called_with(
input=good_path, output=ANY, extensions=ANY)
self.assertEqual(doc, "You're not wrong Walter...")
self.assertEqual(doc['content'], "You're not wrong Walter...")
self.assertTrue(doc['localized'])
self.assertDictEqual(doc['translations'], {'de': 'Deutsch', 'en-US': 'English (US)'})

@patch('os.path.exists')
@patch.object(views, 'listdir')
@patch.object(views, 'StringIO')
@patch.object(views, 'md')
def test_localized_legal_doc_exists(self, md_mock, sio_mock, exists_mock):
def test_localized_legal_doc_exists(self, md_mock, sio_mock, listdir_mock, exists_mock):
sio_mock.StringIO.return_value.getvalue.return_value = "You're not wrong Walter..."
exists_mock.return_value = True
listdir_mock.return_value = ['.mkdir', 'de.md', 'en-US.md']
doc = views.load_legal_doc('the_dude_exists', 'de')
good_path = join(views.LEGAL_DOCS_PATH, 'the_dude_exists', 'de.md')
md_mock.markdownFromFile.assert_called_with(
input=good_path, output=ANY, extensions=ANY)
self.assertEqual(doc, "You're not wrong Walter...")
self.assertEqual(doc['content'], "You're not wrong Walter...")
self.assertTrue(doc['localized'])
self.assertDictEqual(doc['translations'], {'de': 'Deutsch', 'en-US': 'English (US)'})


class TestLegalDocView(TestCase):
Expand All @@ -62,7 +74,11 @@ def test_missing_doc_is_404(self, lld_mock):
def test_good_doc_okay(self, render_mock, lld_mock):
"""Should render correct thing when all is well"""
doc_value = "Donny, you're out of your element!"
lld_mock.return_value = doc_value
lld_mock.return_value = {
'content': doc_value,
'localized': True,
'translations': {'de': 'Deutsch', 'en-US': 'English (US)'},
}
good_resp = HttpResponse(doc_value)
render_mock.return_value = good_resp
req = RequestFactory().get('/dude/exists/')
Expand All @@ -73,14 +89,19 @@ def test_good_doc_okay(self, render_mock, lld_mock):
eq_(resp['cache-control'], 'max-age={0!s}'.format(views.CACHE_TIMEOUT))
eq_(resp.content, doc_value)
eq_(render_mock.call_args[0][2]['doc'], doc_value)
self.assertTrue(render_mock.call_args[0][2]['localized'])
lld_mock.assert_called_with('the_dude_exists', 'de')

@patch.object(views, 'load_legal_doc')
@patch.object(views.l10n_utils, 'render')
def test_cache_settings(self, render_mock, lld_mock):
"""Should use the cache_timeout value from view."""
doc_value = "Donny, you're out of your element!"
lld_mock.return_value = doc_value
lld_mock.return_value = {
'content': doc_value,
'localized': True,
'translations': {'es-ES': 'Espa\u00f1ol (de Espa\u00f1a)', 'en-US': 'English (US)'},
}
good_resp = HttpResponse(doc_value)
render_mock.return_value = good_resp
req = RequestFactory().get('/dude/exists/cached/')
Expand All @@ -96,7 +117,11 @@ def test_cache_settings(self, render_mock, lld_mock):
def test_cache_class_attrs(self, render_mock, lld_mock):
"""Should use the cache_timeout value from view class."""
doc_value = "Donny, you're out of your element!"
lld_mock.return_value = doc_value
lld_mock.return_value = {
'content': doc_value,
'localized': True,
'translations': {'es-ES': 'Espa\u00f1ol (de Espa\u00f1a)', 'en-US': 'English (US)'},
}
good_resp = HttpResponse(doc_value)
render_mock.return_value = good_resp
req = RequestFactory().get('/dude/exists/cached/2/')
Expand Down
37 changes: 28 additions & 9 deletions bedrock/legal_docs/views.py
Expand Up @@ -2,7 +2,7 @@
# 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 os import path
from os import path, listdir
import StringIO

from django.conf import settings
Expand All @@ -14,6 +14,7 @@

from bedrock.settings import path as base_path
from lib import l10n_utils
from product_details import product_details

LEGAL_DOCS_PATH = base_path('vendor-local', 'src', 'legal-docs')
CACHE_TIMEOUT = getattr(settings, 'LEGAL_DOCS_CACHE_TIMEOUT', 60 * 60)
Expand All @@ -25,24 +26,40 @@ def load_legal_doc(doc_name, locale):
:param doc_name: name of the legal doc folder
:param locale: preferred language version of the doc
:return: string content of the file or None
:return: dict containing string content of the file (or None), a boolean
value indicating whether the file is localized into the specified
locale, and a dict of all available locales for that document
"""
source = path.join(LEGAL_DOCS_PATH, doc_name, locale + '.md')
source_dir = path.join(LEGAL_DOCS_PATH, doc_name)
source_file = path.join(source_dir, locale + '.md')
output = StringIO.StringIO()
if not path.exists(source):
source = path.join(LEGAL_DOCS_PATH, doc_name, 'en-US.md')
locales = [f.replace('.md', '') for f in listdir(source_dir) if f.endswith('.md')]
translations = {}

if not path.exists(source_file):
source_file = path.join(LEGAL_DOCS_PATH, doc_name, 'en-US.md')

try:
# Parse the Markdown file
md.markdownFromFile(input=source, output=output,
md.markdownFromFile(input=source_file, output=output,
extensions=['attr_list', 'headerid', 'outline(wrapper_cls=)'])
content = output.getvalue().decode('utf8')
localized = locale != settings.LANGUAGE_CODE
except IOError:
return None
content = None
localized = False
finally:
output.close()

return content
for lang in locales:
if lang in product_details.languages:
translations[lang] = product_details.languages[lang]['native']

return {
'content': content,
'localized': localized,
'translations': translations,
}


class LegalDocView(TemplateView):
Expand Down Expand Up @@ -80,7 +97,9 @@ def get_context_data(self, **kwargs):
raise Http404('Legal doc not found')

context = super(LegalDocView, self).get_context_data(**kwargs)
context[self.legal_doc_context_name] = legal_doc
context[self.legal_doc_context_name] = legal_doc['content']
context['localized'] = legal_doc['localized']
context['translations'] = legal_doc['translations']
return context

@classmethod
Expand Down
11 changes: 7 additions & 4 deletions bedrock/privacy/views.py
Expand Up @@ -68,7 +68,8 @@ def process_legal_doc(content):
class PrivacyDocView(LegalDocView):
def get_legal_doc(self):
doc = super(PrivacyDocView, self).get_legal_doc()
return process_legal_doc(doc)
doc['content'] = process_legal_doc(doc['content'])
return doc


firefox_notices = PrivacyDocView.as_view(
Expand Down Expand Up @@ -138,13 +139,15 @@ def privacy(request):
form_submitted = form_results['form_submitted']
form_error = form_results['form_error']

doc = load_legal_doc('mozilla_privacy_policy', l10n_utils.get_locale(request))

template_vars = {
'form': form,
'form_submitted': form_submitted,
'form_error': form_error,
'doc': process_legal_doc(load_legal_doc('mozilla_privacy_policy',
l10n_utils.get_locale(request))
),
'doc': process_legal_doc(doc['content']),
'localized': doc['localized'],
'translations': doc['translations'],
}

return l10n_utils.render(request, 'privacy/index.html', template_vars)
10 changes: 9 additions & 1 deletion lib/l10n_utils/__init__.py
Expand Up @@ -41,14 +41,22 @@ def render(request, template, context=None, **kwargs):
context['langfile'] = get_lang_path(template)

# Get the available translation list of the current page
context['translations'] = translations_for_template(template)
context.setdefault('translations', {})
context['translations'].update(translations_for_template(template))

# Look for localized template if not default lang.
if hasattr(request, 'locale') and request.locale != settings.LANGUAGE_CODE:

# Redirect to one of the user's accept languages or the site's default
# language (en-US) if the current locale not active
if not template_is_active(template, get_locale(request)):
# Use the default (en-US) template to render instead of redirecting
# if the template is not localized yet but the content itself is
# localized. This is useful especially for legal documents where the
# content is translated in the external legal-docs repository.
if context.get('localized', False):
return django_render(request, template, context, **kwargs)

matched = None

for lang in get_accept_languages(request):
Expand Down

0 comments on commit 0957843

Please sign in to comment.