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):