When side-wide language is set via LANGUAGE_CODE site configuration, some elements of legacy UI still use the language set in user preferences (or None, which fallsback to 'en' if nothing is set in preferences). The expectation is that everything should be translated to the language which is set in the site configuration. In legacy UI (i.e. templates) the code of the current language sometimes is needed, and in these cases `user_language` variable from the context is used. The value for that variable is inserted via context processor, which takes the value from the user preferences. The solution modifies the context processor to check if there is a language set in site configuration, and if there is, send that value, instead of whatever value there was in user peferences.
92 lines
3.2 KiB
Python
92 lines
3.2 KiB
Python
"""
|
|
This is the courseware context_processor module.
|
|
|
|
This is meant to simplify the process of sending user preferences (espec. time_zone and pref-lang)
|
|
to the templates without having to append every view file.
|
|
|
|
"""
|
|
|
|
from pytz import timezone
|
|
|
|
from edx_django_utils.cache import TieredCache
|
|
from lms.djangoapps.courseware.models import LastSeenCoursewareTimezone
|
|
from openedx.core.djangoapps.site_configuration.helpers import get_value
|
|
from openedx.core.djangoapps.user_api.errors import UserAPIInternalError, UserNotFound
|
|
from openedx.core.djangoapps.user_api.preferences.api import get_user_preference, get_user_preferences
|
|
from openedx.core.lib.cache_utils import get_cache
|
|
|
|
|
|
RETRIEVABLE_PREFERENCES = {
|
|
'user_timezone': 'time_zone',
|
|
'user_language': 'pref-lang'
|
|
}
|
|
CACHE_NAME = "context_processor.user_timezone_preferences"
|
|
|
|
|
|
def user_timezone_locale_prefs(request):
|
|
"""
|
|
Checks if request has an authenticated user.
|
|
If so, sends set (or none if unset) time_zone and language prefs.
|
|
If site-wide language is set, that language is used over the language set
|
|
in user preferences.
|
|
|
|
This interacts with the DateUtils to either display preferred or attempt to determine
|
|
system/browser set time_zones and languages
|
|
|
|
"""
|
|
cached_value = get_cache(CACHE_NAME)
|
|
if not cached_value:
|
|
user_prefs = {
|
|
'user_timezone': None,
|
|
'user_language': None,
|
|
}
|
|
if hasattr(request, 'user') and request.user.is_authenticated:
|
|
try:
|
|
user_preferences = get_user_preferences(request.user)
|
|
except (UserNotFound, UserAPIInternalError):
|
|
cached_value.update(user_prefs)
|
|
else:
|
|
user_prefs = {
|
|
key: user_preferences.get(pref_name, None)
|
|
for key, pref_name in RETRIEVABLE_PREFERENCES.items()
|
|
}
|
|
site_wide_language = get_value('LANGUAGE_CODE', None)
|
|
if site_wide_language:
|
|
user_prefs['user_language'] = site_wide_language
|
|
|
|
cached_value.update(user_prefs)
|
|
return cached_value
|
|
|
|
|
|
def get_last_seen_courseware_timezone(user):
|
|
"""
|
|
The above method is for the timezone that is set on the user's account.
|
|
That timezone is often not set, so this field retrieves the browser timezone
|
|
from a recent courseware visit (updated daily)
|
|
"""
|
|
cache_key = 'browser_timezone_{}'.format(str(user.id))
|
|
cached_value = TieredCache.get_cached_response(cache_key)
|
|
if not cached_value.is_found:
|
|
try:
|
|
LastSeenCoursewareTimezone.objects.get(user=user)
|
|
except LastSeenCoursewareTimezone.DoesNotExist:
|
|
return None
|
|
|
|
else:
|
|
return cached_value.value
|
|
|
|
|
|
def get_user_timezone_or_last_seen_timezone_or_utc(user):
|
|
"""
|
|
Helper method for returning a reasonable timezone for a user.
|
|
This method returns the timezone in the user's account if that is set.
|
|
If that is not set, it returns a recent timezone that we have recorded from a user's visit to the courseware.
|
|
If that is not set, it returns UTC.
|
|
"""
|
|
user_timezone = (
|
|
get_user_preference(user, 'time_zone') or
|
|
get_last_seen_courseware_timezone(user) or
|
|
'UTC'
|
|
)
|
|
return timezone(user_timezone)
|