Adds a 'language' dropdown field to the system configuration

- The language choice is stored with the session, not persistently
- This removes confirmation messages if nothing was changed
This commit is contained in:
fonfon 2015-11-18 18:29:54 +01:00
parent f8f7a979f2
commit aeaa6ab800
3 changed files with 60 additions and 8 deletions

View File

@ -213,6 +213,17 @@ def configure_django():
if cfg.secure_proxy_ssl_header: if cfg.secure_proxy_ssl_header:
secure_proxy_ssl_header = (cfg.secure_proxy_ssl_header, 'https') secure_proxy_ssl_header = (cfg.secure_proxy_ssl_header, 'https')
# Read translated languages from the 'locale' directory
languages = [('en', 'English')]
locale_dir = os.path.join(os.path.dirname(__file__), 'locale')
if os.path.isdir(locale_dir):
translated_language_codes = next(os.walk(locale_dir))[1]
all_languages = dict(django.conf.global_settings.LANGUAGES)
for code in translated_language_codes:
if code in all_languages:
languages.append((code, all_languages[code]))
languages = sorted(languages, key=lambda tup: tup[1])
django.conf.settings.configure( django.conf.settings.configure(
ALLOWED_HOSTS=['*'], ALLOWED_HOSTS=['*'],
CACHES={'default': CACHES={'default':
@ -222,6 +233,7 @@ def configure_django():
'NAME': cfg.store_file}}, 'NAME': cfg.store_file}},
DEBUG=cfg.debug, DEBUG=cfg.debug,
INSTALLED_APPS=applications, INSTALLED_APPS=applications,
LANGUAGES=languages,
LOGGING=logging_configuration, LOGGING=logging_configuration,
LOGIN_URL='users:login', LOGIN_URL='users:login',
LOGIN_REDIRECT_URL='apps:index', LOGIN_REDIRECT_URL='apps:index',

View File

@ -23,7 +23,9 @@ from django import forms
from django.contrib import messages from django.contrib import messages
from django.core import validators from django.core import validators
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.conf import settings
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.utils import translation
from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.translation import ugettext as _, ugettext_lazy
import logging import logging
import re import re
@ -51,6 +53,16 @@ def get_domainname():
return '.'.join(fqdn.split('.')[1:]) return '.'.join(fqdn.split('.')[1:])
def get_language(request):
"""Return the current language setting"""
# TODO: Store the language per user in kvstore,
# taking care of setting language on login, and adapting kvstore when
# renaming/deleting users
# The session contains more accurate information than request.LANGUAGE_CODE
return request.session[translation.LANGUAGE_SESSION_KEY]
class TrimmedCharField(forms.CharField): class TrimmedCharField(forms.CharField):
"""Trim the contents of a CharField""" """Trim the contents of a CharField"""
def clean(self, value): def clean(self, value):
@ -104,6 +116,14 @@ class ConfigurationForm(forms.Form):
ugettext_lazy('Invalid domain name')), ugettext_lazy('Invalid domain name')),
domain_label_validator]) domain_label_validator])
language = forms.ChoiceField(
label=ugettext_lazy('Language'),
help_text=\
ugettext_lazy('Language for this freedombox web administration '
'interface'),
required=False,
choices=settings.LANGUAGES)
def init(): def init():
"""Initialize the module""" """Initialize the module"""
@ -114,7 +134,7 @@ def init():
def index(request): def index(request):
"""Serve the configuration form""" """Serve the configuration form"""
status = get_status() status = get_status(request)
form = None form = None
@ -124,7 +144,7 @@ def index(request):
# pylint: disable-msg=E1101 # pylint: disable-msg=E1101
if form.is_valid(): if form.is_valid():
_apply_changes(request, status, form.cleaned_data) _apply_changes(request, status, form.cleaned_data)
status = get_status() status = get_status(request)
form = ConfigurationForm(initial=status, form = ConfigurationForm(initial=status,
prefix='configuration') prefix='configuration')
else: else:
@ -135,10 +155,11 @@ def index(request):
'form': form}) 'form': form})
def get_status(): def get_status(request):
"""Return the current status""" """Return the current status"""
return {'hostname': get_hostname(), return {'hostname': get_hostname(),
'domainname': get_domainname()} 'domainname': get_domainname(),
'language': get_language(request)}
def _apply_changes(request, old_status, new_status): def _apply_changes(request, old_status, new_status):
@ -151,8 +172,6 @@ def _apply_changes(request, old_status, new_status):
.format(exception=exception)) .format(exception=exception))
else: else:
messages.success(request, _('Hostname set')) messages.success(request, _('Hostname set'))
else:
messages.info(request, _('Hostname is unchanged'))
if old_status['domainname'] != new_status['domainname']: if old_status['domainname'] != new_status['domainname']:
try: try:
@ -162,8 +181,17 @@ def _apply_changes(request, old_status, new_status):
.format(exception=exception)) .format(exception=exception))
else: else:
messages.success(request, _('Domain name set')) messages.success(request, _('Domain name set'))
else:
messages.info(request, _('Domain name is unchanged')) if old_status['language'] != new_status['language']:
language = new_status['language']
try:
translation.activate(language)
request.session[translation.LANGUAGE_SESSION_KEY] = language
except Exception as exception:
messages.error(request, _('Error setting language: {exception}')
.format(exception=exception))
else:
messages.success(request, _('Language changed'))
def set_hostname(hostname): def set_hostname(hostname):

View File

@ -19,8 +19,11 @@
Tests for config module. Tests for config module.
""" """
import os
import unittest import unittest
from plinth import __main__ as plinth_main
from ..config import ConfigurationForm from ..config import ConfigurationForm
@ -65,3 +68,12 @@ class TestConfig(unittest.TestCase):
form = ConfigurationForm({'hostname': 'example', form = ConfigurationForm({'hostname': 'example',
'domainname': domainname}) 'domainname': domainname})
self.assertFalse(form.is_valid()) self.assertFalse(form.is_valid())
def test_locale_path(self):
"""
Test that the 'locale' directory is in the same folder as __main__.py.
This is required for detecting translated languages.
"""
plinth_dir = os.path.dirname(plinth_main.__file__)
locale_dir = os.path.join(plinth_dir, 'locale')
self.assertTrue(os.path.isdir(locale_dir))