93 lines
2.9 KiB
Python
93 lines
2.9 KiB
Python
"""
|
|
Middleware for dark-launching languages. These languages won't be used
|
|
when determining which translation to give a user based on their browser
|
|
header, but can be selected by setting the ``preview-lang`` query parameter
|
|
to the language code.
|
|
|
|
Adding the query parameter ``clear-lang`` will reset the language stored
|
|
in the user's session.
|
|
|
|
This middleware must be placed before the LocaleMiddleware, but after
|
|
the SessionMiddleware.
|
|
"""
|
|
|
|
from django.utils.translation.trans_real import parse_accept_lang_header
|
|
|
|
from dark_lang.models import DarkLangConfig
|
|
|
|
|
|
class DarkLangMiddleware(object):
|
|
"""
|
|
Middleware for dark-launching languages.
|
|
|
|
This is configured by creating ``DarkLangConfig`` rows in the database,
|
|
using the django admin site.
|
|
"""
|
|
|
|
@property
|
|
def released_langs(self):
|
|
"""
|
|
Current list of released languages
|
|
"""
|
|
return DarkLangConfig.current().released_languages_list
|
|
|
|
def process_request(self, request):
|
|
"""
|
|
Prevent user from requesting un-released languages except by using the preview-lang query string.
|
|
"""
|
|
if not DarkLangConfig.current().enabled:
|
|
return
|
|
|
|
self._clean_accept_headers(request)
|
|
self._activate_preview_language(request)
|
|
|
|
def _is_released(self, lang_code):
|
|
"""
|
|
``True`` iff one of the values in ``self.released_langs`` is a prefix of ``lang_code``.
|
|
"""
|
|
return any(lang_code.lower().startswith(released_lang.lower()) for released_lang in self.released_langs)
|
|
|
|
def _format_accept_value(self, lang, priority=1.0):
|
|
"""
|
|
Formats lang and priority into a valid accept header fragment.
|
|
"""
|
|
return "{};q={}".format(lang, priority)
|
|
|
|
def _clean_accept_headers(self, request):
|
|
"""
|
|
Remove any language that is not either in ``self.released_langs`` or
|
|
a territory of one of those languages.
|
|
"""
|
|
accept = request.META.get('HTTP_ACCEPT_LANGUAGE', None)
|
|
if accept is None or accept == '*':
|
|
return
|
|
|
|
new_accept = ", ".join(
|
|
self._format_accept_value(lang, priority)
|
|
for lang, priority
|
|
in parse_accept_lang_header(accept)
|
|
if self._is_released(lang)
|
|
)
|
|
|
|
request.META['HTTP_ACCEPT_LANGUAGE'] = new_accept
|
|
|
|
def _activate_preview_language(self, request):
|
|
"""
|
|
If the request has the get parameter ``preview-lang``,
|
|
and that language appears doesn't appear in ``self.released_langs``,
|
|
then set the session ``django_language`` to that language.
|
|
"""
|
|
if 'clear-lang' in request.GET:
|
|
if 'django_language' in request.session:
|
|
del request.session['django_language']
|
|
|
|
preview_lang = request.GET.get('preview-lang', None)
|
|
|
|
if not preview_lang:
|
|
return
|
|
|
|
if preview_lang in self.released_langs:
|
|
return
|
|
|
|
request.session['django_language'] = preview_lang
|