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 <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2018-02-16 12:24:17 +05:30 committed by James Valleroy
parent e644e5c86a
commit 90932e78af
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
3 changed files with 78 additions and 13 deletions

View File

@ -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',

73
plinth/translation.py Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
#
"""
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,
)

View File

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