From 90932e78af3818703af1d09e0204b498bbb0c2c4 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 16 Feb 2018 12:24:17 +0530 Subject: [PATCH] locale: Implement utilities for setting/getting language Separate language cookie are only used if sessions (session middleware) are not available. Otherwise, even anonymous users have their language preference in sessions instead of cookies. This is default Django behavior, conform to it. Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- plinth/modules/users/forms.py | 3 +- plinth/translation.py | 73 +++++++++++++++++++++++++++++++++++ plinth/views.py | 15 ++----- 3 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 plinth/translation.py diff --git a/plinth/modules/users/forms.py b/plinth/modules/users/forms.py index 336cb9e45..28cd80d60 100644 --- a/plinth/modules/users/forms.py +++ b/plinth/modules/users/forms.py @@ -31,6 +31,7 @@ from plinth import forms as plinthForms from plinth.errors import ActionError from plinth.modules import first_boot, users from plinth.modules.security import set_restricted_access +from plinth.translation import set_language from plinth.utils import is_user_admin from plinth.models import UserProfile @@ -186,7 +187,7 @@ class UserUpdateForm(ValidNewUsernameCheckMixin, forms.ModelForm, plinthForms.La # If user is updating their own profile then only translate the pages if self.username == self.request.user.username: - self.request.session[translation.LANGUAGE_SESSION_KEY] = user.userprofile.preferred_language + set_language(self.request, None, user.userprofile.language) if commit: output = actions.superuser_run('users', diff --git a/plinth/translation.py b/plinth/translation.py new file mode 100644 index 000000000..357a6b7b0 --- /dev/null +++ b/plinth/translation.py @@ -0,0 +1,73 @@ +# +# This file is part of Plinth. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +Utility methods for managing translations. +""" + +from django.conf import settings +from django.contrib.auth.signals import user_logged_in +from django.dispatch import receiver +from django.utils import translation + + +def get_language_from_request(request): + """Get the language in the session or as separate cookie. + + Django methods should be used for regular cases. This is only useful for + very narrow cases. + + """ + if hasattr(request, 'session'): + language_code = request.session.get(translation.LANGUAGE_SESSION_KEY) + if language_code: + return language_code + + return request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME) + + +def set_language(request, response, language_code): + """Set the language in session or as a separate cookie. + + Sending language code as None removes the preference. If response is None, + cookies are not touched and setting/deleting language cookie will not work. + + """ + if not language_code: + if hasattr(request, 'session'): + try: + del request.session[translation.LANGUAGE_SESSION_KEY] + except KeyError: + pass + + if response: + try: + response.delete_cookie(settings.LANGUAGE_COOKIE_NAME) + except KeyError: + pass + + return + + translation.activate(language_code) + if hasattr(request, 'session'): + request.session[translation.LANGUAGE_SESSION_KEY] = language_code + else: + response.set_cookie( + settings.LANGUAGE_COOKIE_NAME, language_code, + max_age=settings.LANGUAGE_COOKIE_AGE, + path=settings.LANGUAGE_COOKIE_PATH, + domain=settings.LANGUAGE_COOKIE_DOMAIN, + ) diff --git a/plinth/views.py b/plinth/views.py index b0887581a..e231cd041 100644 --- a/plinth/views.py +++ b/plinth/views.py @@ -23,9 +23,7 @@ from django.core.exceptions import ImproperlyConfigured from django.template.response import TemplateResponse from django.views.generic import TemplateView from django.views.generic.edit import FormView -from django.conf import settings from django.urls import reverse -from django.utils import translation from django.utils.http import is_safe_url from django.utils.translation import ugettext as _ from stronghold.decorators import public @@ -35,6 +33,7 @@ from . import forms, frontpage import plinth from plinth import package from plinth.modules.storage import views as disk_views +from plinth.translation import get_language_from_request, set_language REDIRECT_FIELD_NAME = 'next' @@ -76,20 +75,12 @@ class LanguageSelectionView(FormView): def get_initial(self): """Return the initial values for the form.""" - return {'language': translation.get_language()} + return {'language': get_language_from_request(self.request)} def form_valid(self, form): """Set or reset the current language.""" - selected_language = form.cleaned_data['language'] response = super().form_valid(form) - if not selected_language: - response.delete_cookie(settings.LANGUAGE_COOKIE_NAME) - else: - translation.activate(selected_language) - # send a cookie for selected language - response.set_cookie(settings.LANGUAGE_COOKIE_NAME, - selected_language) - + set_language(self.request, response, form.cleaned_data['language']) return response def get_success_url(self):