Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cms/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@
path('api/user/', include('openedx.core.djangoapps.user_api.urls')),

# Update session view
path('lang_pref/session_language', openedx.core.djangoapps.lang_pref.views.update_session_language,
Comment thread
robrap marked this conversation as resolved.
name='session_language'
path('lang_pref/update_language', openedx.core.djangoapps.lang_pref.views.update_language,
name='update_language'
),

# Darklang View to change the preview language (or dark language)
Expand Down
2 changes: 1 addition & 1 deletion lms/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@
namespace='catalog')),

# Update session view
path('lang_pref/session_language', lang_pref_views.update_session_language, name='session_language'),
path('lang_pref/update_language', lang_pref_views.update_language, name='update_language'),

# Multiple course modes and identity verification
path(
Expand Down
4 changes: 1 addition & 3 deletions openedx/core/djangoapps/dark_lang/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@


from django.conf import settings
from django.utils.translation import LANGUAGE_SESSION_KEY
from django.utils.translation.trans_real import parse_accept_lang_header
from django.utils.deprecation import MiddlewareMixin

Expand Down Expand Up @@ -155,6 +154,5 @@ def _activate_preview_language(self, request, response):
if not preview_lang:
return

# Set the session key to the requested preview lang
request.session[LANGUAGE_SESSION_KEY] = preview_lang
# Set the response language_cookie to the requested preview lang
set_language_cookie(request, response, preview_lang)
88 changes: 30 additions & 58 deletions openedx/core/djangoapps/dark_lang/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from django.conf import settings
from django.http import HttpRequest
from django.test.client import Client
from django.utils.translation import LANGUAGE_SESSION_KEY

from openedx.core.djangoapps.dark_lang.middleware import DarkLangMiddleware
from openedx.core.djangoapps.dark_lang.models import DarkLangConfig
Expand Down Expand Up @@ -50,23 +49,22 @@ def setUp(self):
enabled=True
).save()

def process_middleware_request(self, language_session_key=UNSET, accept=UNSET):
def process_middleware_request(self, cookie_language=UNSET, accept=UNSET):
"""
Build a request and then process it using the ``DarkLangMiddleware``.

Args:
language_session_key (str): The language code to set in request.session[LANUGAGE_SESSION_KEY]
cookie_language (str): The language code to set in self.client.cookies[LANGUAGE_COOKIE_NAME]
accept (str): The accept header to set in request.META['HTTP_ACCEPT_LANGUAGE']
"""
session = {}
set_if_set(session, LANGUAGE_SESSION_KEY, language_session_key)

meta = {}
set_if_set(meta, 'HTTP_ACCEPT_LANGUAGE', accept)
# Setting language cookie
set_if_set(self.client.cookies, settings.LANGUAGE_COOKIE_NAME, cookie_language)

request = Mock(
spec=HttpRequest,
session=session,
session={},
META=meta,
GET={},
method='GET',
Expand Down Expand Up @@ -235,11 +233,19 @@ def test_partial_match_es_la(self, latin_america_code):
self.process_middleware_request(accept=b'{};q=1.0, pt;q=0.5'.format(latin_america_code)) # pylint:disable=no-member
)

def assert_session_lang_equals(self, value, session):
def _set_client_cookie_language(self, cookie_language):
"""
Set the cookie language in the Client
"""
self.client.cookies[settings.LANGUAGE_COOKIE_NAME] = cookie_language
Comment thread
robrap marked this conversation as resolved.

def assert_cookie_lang_equals(self, value):
"""
Assert that the LANGUAGE_SESSION_KEY set in session is equal to value
Assert that the language set in cookies is equal to value
"""
assert value == session.get(LANGUAGE_SESSION_KEY, UNSET)
lang_cookie = self.client.cookies.get(settings.LANGUAGE_COOKIE_NAME)
lang_cookie_value = lang_cookie.value if lang_cookie is not None and lang_cookie.value != '' else UNSET
assert value == lang_cookie_value

def _post_set_preview_lang(self, preview_language):
"""
Expand All @@ -253,77 +259,49 @@ def _post_clear_preview_lang(self):
"""
return self.client.post('/update_lang/', {'action': 'reset_preview_language'})

def _set_client_session_language(self, session_language):
"""
Set the session language in the Client
"""
session = self.client.session
session[LANGUAGE_SESSION_KEY] = session_language
session.save()

def test_preview_lang_with_released_language(self):
# Preview lang should always override selection
self._post_set_preview_lang('rel')
# Refresh the page with a get request to confirm the preview language was set
self.client.get('/home')
self.assert_session_lang_equals(
'rel',
self.client.session
)
self.assert_cookie_lang_equals('rel')

# Set the session language and ensure that the preview language overrides
self._set_client_session_language('notrel')
self._set_client_cookie_language('notrel')
self._post_set_preview_lang('rel')
self.client.get('/home')
self.assert_session_lang_equals(
'rel',
self.client.session
)
self.assert_cookie_lang_equals('rel')

def test_preview_lang_with_dark_language(self):
self._post_set_preview_lang('unrel')
self.client.get('/home')
self.assert_session_lang_equals(
'unrel',
self.client.session
)
self.assert_cookie_lang_equals('unrel')

# Test a clear and then a set of the preview language
self._post_clear_preview_lang()
self._post_set_preview_lang('unrel')
self.client.get('/home')
self.assert_session_lang_equals(
'unrel',
self.client.session
)
self.assert_cookie_lang_equals('unrel')

def test_empty_preview_language(self):
# When posting an empty preview_language the currently set language should not change
self._set_client_session_language('rel')
self._set_client_cookie_language('rel')
self._post_set_preview_lang(' ')
self.client.get('/home')
self.assert_session_lang_equals(
'rel',
self.client.session
)
self.assert_cookie_lang_equals('rel')

def test_clear_lang(self):
Comment thread
robrap marked this conversation as resolved.
# Clear a language when no language was set
self._post_clear_preview_lang()
self.client.get('/home')
self.assert_session_lang_equals(
UNSET,
self.client.session
)
self.assert_cookie_lang_equals(UNSET)

# Set a language and clear it to ensure the clear is working as expected
self._post_set_preview_lang('notclear')
Comment thread
robrap marked this conversation as resolved.
self.assert_cookie_lang_equals('notclear')
self._post_clear_preview_lang()
self.client.get('/home')
self.assert_session_lang_equals(
UNSET,
self.client.session
)
self.assert_cookie_lang_equals(UNSET)

def test_disabled(self):
DarkLangConfig(enabled=False, changed_by=self.user).save()
Expand All @@ -334,22 +312,16 @@ def test_disabled(self):
)

# With DarkLang disabled the clear should not change the session language
self._set_client_session_language('rel')
self._set_client_cookie_language('rel')
self._post_clear_preview_lang()
self.client.get('/home')
self.assert_session_lang_equals(
'rel',
self.client.session
)
self.assert_cookie_lang_equals('rel')

# Test that setting the preview language with DarkLang disabled does nothing
self._set_client_session_language('unrel')
self._set_client_cookie_language('unrel')
self._post_set_preview_lang('rel')
self.client.get('/home')
self.assert_session_lang_equals(
'unrel',
self.client.session
)
self.assert_cookie_lang_equals('unrel')

def test_accept_chinese_language_codes(self):
DarkLangConfig(
Expand Down
3 changes: 0 additions & 3 deletions openedx/core/djangoapps/dark_lang/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from django.shortcuts import redirect
from django.template.loader import render_to_string
from django.utils.decorators import method_decorator
from django.utils.translation import LANGUAGE_SESSION_KEY
from django.utils.translation import gettext as _
from web_fragments.fragment import Fragment

Expand Down Expand Up @@ -104,8 +103,6 @@ def _clear_preview_language(self, request):
Clears the preview language for the current user.
"""
delete_user_preference(request.user, DARK_LANGUAGE_KEY)
if LANGUAGE_SESSION_KEY in request.session:
del request.session[LANGUAGE_SESSION_KEY]
Comment thread
robrap marked this conversation as resolved.
PageLevelMessages.register_success_message(
request,
_('Language reset to the default')
Expand Down
5 changes: 0 additions & 5 deletions openedx/core/djangoapps/lang_pref/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"""
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
from django.utils.translation import LANGUAGE_SESSION_KEY
from django.utils.translation.trans_real import parse_accept_lang_header

from openedx.core.djangoapps.dark_lang import DARK_LANGUAGE_KEY
Expand Down Expand Up @@ -53,10 +52,6 @@ def process_request(self, request):
accept_header = cookie_lang
request.META[LANGUAGE_HEADER] = accept_header

# Allow the new cookie setting to update the language in the user's session
Comment thread
robrap marked this conversation as resolved.
if LANGUAGE_SESSION_KEY in request.session and request.session[LANGUAGE_SESSION_KEY] != cookie_lang:
del request.session[LANGUAGE_SESSION_KEY]

# Apply language specified in SiteConfiguration, ignoring user preferences.
if language := get_value('LANGUAGE_CODE'):
request.COOKIES[settings.LANGUAGE_COOKIE_NAME] = language
Expand Down
41 changes: 13 additions & 28 deletions openedx/core/djangoapps/lang_pref/tests/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from django.http import HttpResponse
from django.test.client import Client, RequestFactory
from django.urls import reverse
from django.utils.translation import LANGUAGE_SESSION_KEY
from django.utils.translation.trans_real import parse_accept_lang_header

from openedx.core.djangoapps.lang_pref import COOKIE_DURATION, LANGUAGE_KEY
Expand Down Expand Up @@ -88,8 +87,6 @@ def test_preference_setting_changes_cookie(self, lang_pref_out):
domain=settings.SESSION_COOKIE_DOMAIN,
)

assert LANGUAGE_SESSION_KEY not in self.request.session

@ddt.data(*itertools.product(
(None, 'eo', 'es'), # LANGUAGE_COOKIE_NAME
(None, 'es', 'en'), # Language Preference In
Expand All @@ -115,32 +112,26 @@ def test_preference_cookie_changes_setting(self, lang_cookie, lang_pref_in, mock
(logged_in, ) + test_def
for logged_in in (True, False)
for test_def in [
# (LANGUAGE_COOKIE_NAME, LANGUAGE_SESSION_KEY, Accept-Language In,
# Accept-Language Out, Session Lang Out)
(None, None, None, None, None),
(None, 'eo', None, None, 'eo'),
(None, 'en', None, None, 'en'),
(None, 'eo', 'en', 'en', 'eo'),
(None, None, 'en', 'en', None),
('en', None, None, 'en', None),
('en', 'en', None, 'en', 'en'),
('en', None, 'eo', 'en;q=1.0,eo', None),
('en', None, 'en', 'en', None),
('en', 'eo', 'en', 'en', None),
('en', 'eo', 'eo', 'en;q=1.0,eo', None)
# (LANGUAGE_COOKIE_NAME, Accept-Language In, Accept-Language Out)
(None, None, None),
(None, None, None),
(None, None, None),
(None, 'en', 'en'),
(None, 'en', 'en'),
('en', None, 'en'),
('en', None, 'en'),
('en', 'eo', 'en;q=1.0,eo'),
('en', 'en', 'en'),
('en', 'en', 'en'),
('en', 'eo', 'en;q=1.0,eo')
]
))
@ddt.unpack
def test_preference_cookie_overrides_browser(
self, logged_in, lang_cookie, lang_session_in, accept_lang_in, accept_lang_out,
lang_session_out,
):
def test_preference_cookie_overrides_browser(self, logged_in, lang_cookie, accept_lang_in, accept_lang_out):
if not logged_in:
self.request.user = self.anonymous_user
if lang_cookie:
self.request.COOKIES[settings.LANGUAGE_COOKIE_NAME] = lang_cookie
if lang_session_in:
self.request.session[LANGUAGE_SESSION_KEY] = lang_session_in
if accept_lang_in:
self.request.META['HTTP_ACCEPT_LANGUAGE'] = accept_lang_in
else:
Expand All @@ -160,8 +151,6 @@ def test_preference_cookie_overrides_browser(
else:
assert accept_lang_result == accept_lang_out

assert self.request.session.get(LANGUAGE_SESSION_KEY) == lang_session_out
Comment thread
robrap marked this conversation as resolved.

@ddt.data(None, 'es', 'en')
def test_logout_preserves_cookie(self, lang_cookie):
if lang_cookie:
Expand Down Expand Up @@ -293,10 +282,6 @@ def test_site_language_ignores_user_preferences(self, user_preference):

assert get_user_preference(self.user, LANGUAGE_KEY) == user_preference
assert response['Content-Language'] == 'eo'
# `LocaleMiddleware` no longer looks for language in the session since Django 3.2. It checks the cookie instead.
# See: https://docs.djangoproject.com/en/3.2/releases/3.0/#miscellaneous
assert self.client.session.get(LANGUAGE_SESSION_KEY) is None

# Clean up by making a request to a Site without specific configuration.
with with_site_configuration_context():
self.client.get('/')
22 changes: 5 additions & 17 deletions openedx/core/djangoapps/lang_pref/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,24 @@

import json

from django.contrib.sessions.middleware import SessionMiddleware
from django.test import TestCase
from django.test.client import RequestFactory
from django.urls import reverse
from django.utils.translation import LANGUAGE_SESSION_KEY, get_language
from common.djangoapps.student.tests.factories import UserFactory
from django.utils.translation import get_language


class TestLangPrefView(TestCase):
"""
Language preference view tests.
"""

def setUp(self):
super().setUp()
self.session_middleware = SessionMiddleware()
self.user = UserFactory.create()
self.request = RequestFactory().get('/somewhere')
self.request.user = self.user
self.session_middleware.process_request(self.request)

def test_language_session_update(self):
# test language session updating correctly.
self.request.session[LANGUAGE_SESSION_KEY] = 'ar'
response = self.client.patch(reverse("session_language"), json.dumps({'pref-lang': 'eo'}))
def test_language_update(self):
# test language updating correctly.
response = self.client.patch(reverse("update_language"), json.dumps({'pref-lang': 'eo'}))
assert response.status_code == 200
self.client.get('/')
assert get_language() == 'eo'

response = self.client.patch(reverse("session_language"), json.dumps({'pref-lang': 'en'}))
response = self.client.patch(reverse("update_language"), json.dumps({'pref-lang': 'en'}))
assert response.status_code == 200
self.client.get('/')
assert get_language() == 'en'
Loading