Skip to content

Commit

Permalink
Support language on user level
Browse files Browse the repository at this point in the history
Fix issue

use ser prefered language

Some fixes

support translating password reset email

Use custom password form in the view
  • Loading branch information
nasief committed Sep 13, 2017
1 parent 33278e9 commit 3687b1c
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 3 deletions.
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,8 @@ Quick start
3. For more information on those libraries, check the following docs::
1. [django-axes](https://django-axes.readthedocs.io/en/latest/)
2. [django-recaptcha](https://github.com/praekelt/django-recaptcha)


8. If you have i18n enabled within your application, you can set a preferred language for the user
1. If you define a default language `LANGUAGE_CODE` it will be used as default or `en`
2. Languages supported are those languages you define in your application in `LANGUAGES` setting
2 changes: 1 addition & 1 deletion accountsplus/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__version__ = '1.4.2'
__version__ = '1.4.3'

default_app_config = 'accountsplus.apps.AccountsConfig'
24 changes: 23 additions & 1 deletion accountsplus/forms.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
from __future__ import unicode_literals

from contextlib import contextmanager

import django.forms
from django.conf import settings
from django.apps import apps
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm
from django.contrib.admin.forms import AdminAuthenticationForm
from django.utils import translation

from captcha.fields import ReCaptchaField


@contextmanager
def language(lang):
old_language = translation.get_language()
try:
translation.activate(lang)
yield
finally:
translation.activate(old_language)


class CaptchaForm(django.forms.Form):
captcha = ReCaptchaField()
username = django.forms.CharField()
Expand All @@ -31,3 +44,12 @@ class EmailBasedAdminAuthenticationForm(AdminAuthenticationForm):

def clean_username(self):
return self.data['username'].lower()


class CustomPasswordResetForm(PasswordResetForm):

def send_mail(self, subject_template_name, email_template_name,
context, from_email, to_email, html_email_template_name=None):
with language(context['email_lang']):
super(CustomPasswordResetForm, self).send_mail(subject_template_name, email_template_name, context,
from_email, to_email, html_email_template_name)
16 changes: 16 additions & 0 deletions accountsplus/middleware.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
from __future__ import unicode_literals
import django.utils.timezone
from django.utils.deprecation import MiddlewareMixin
from django.utils import translation


class TimezoneMiddleware(MiddlewareMixin):

def process_request(self, request):
if request.user.is_authenticated() and request.user.timezone:
django.utils.timezone.activate(request.user.timezone)
else:
django.utils.timezone.deactivate()


class UserLanguageMiddleware(MiddlewareMixin):

# Update user preferred language each time a request has a new language and activate translation for that user.
# Should be added after LocaleMiddleware as it depends on having request.LANGUAGE_CODE configured there.
def process_request(self, request):
user = request.user
if not user.preferred_language:
user.preferred_language = request.LANGUAGE_CODE
user.save()
else:
translation.activate(user.preferred_language)
request.LANGUAGE_CODE = translation.get_language()
4 changes: 4 additions & 0 deletions accountsplus/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import timezone_field
import localflavor.us.models

import settings

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -103,6 +105,8 @@ class BaseUser(django.contrib.auth.base_user.AbstractBaseUser, django.contrib.au
last_name = django.db.models.CharField(_('Last Name'), max_length=50)
email = django.db.models.EmailField(_('Email'), unique=True)
timezone = timezone_field.TimeZoneField(default='America/New_York')
preferred_language = django.db.models.CharField(_('Preferred Language'), choices=settings.SUPPORTED_LANGUAGES,
blank=True, null=True, max_length=10)

objects = UserManager()

Expand Down
19 changes: 19 additions & 0 deletions accountsplus/settings.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.apps import apps
from django.utils.translation import ugettext_lazy as _


# Default values
LOCKOUT_TEMPLATE = 'accounts/locked_out.html'

ENGLISH_LANGUAGE = 'en-us'
SPANISH_LANGUAGE = 'es'
FRENCH_LANGUAGE = 'fr'
PORTUGUESE_LANGUAGE = 'pt'
ARABIC_LANGUAGE = 'ar'
DEFAULT_SUPPORTED_LANGUAGES = (
(ENGLISH_LANGUAGE, _('English')),
(SPANISH_LANGUAGE, _('Spanish')),
(FRENCH_LANGUAGE, _('French')),
(PORTUGUESE_LANGUAGE, _('Portuguese')),
(ARABIC_LANGUAGE, _('Arabic')),
)


def get_setting(setting_str, is_required, default_value=None):
try:
return getattr(settings, setting_str)
Expand Down Expand Up @@ -60,3 +75,7 @@ def get_lockout_template():
LOGIN_FAILURE_LIMIT = int(get_login_failure_limit())
LOCKOUT_URL = str(get_lockout_url())
LOCKOUT_TEMPLATE = get_lockout_template()


SUPPORTED_LANGUAGES = get_setting('LANGUAGES', False, DEFAULT_SUPPORTED_LANGUAGES)
DEFAULT_LANGUAGE = get_setting('LANGUAGE_CODE', False, ENGLISH_LANGUAGE)
10 changes: 9 additions & 1 deletion accountsplus/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def password_reset(request,
template_name='registration/password_reset_form.html',
email_template_name='registration/password_reset_email.html',
subject_template_name='registration/password_reset_subject.txt',
password_reset_form=django.contrib.auth.forms.PasswordResetForm,
password_reset_form=forms.CustomPasswordResetForm,
token_generator=django.contrib.auth.views.default_token_generator,
post_reset_redirect=None,
from_email=None,
Expand All @@ -172,6 +172,14 @@ def password_reset(request,
html_email_template_name=None,
extra_email_context=None):
User = django.contrib.auth.get_user_model()
# We set this always in the middleware to the preferred language of the user
if request.method == 'POST':
email = request.POST['email']
try:
user = User.objects.get(email=email)
extra_email_context['email_lang'] = user.preferred_language or request.LANGUAGE_CODE
except User.DoesNotExist:
pass

response = django.contrib.auth.views.password_reset(
request, template_name, email_template_name,
Expand Down

0 comments on commit 3687b1c

Please sign in to comment.