Add translation for many meesages and errors

This commit is contained in:
EsmaeilBeygi 2016-02-10 09:38:08 +03:30
parent 7c8a34f700
commit 7ae6c89718
9 changed files with 85 additions and 45 deletions

View File

@ -1,5 +1,6 @@
from django.http import HttpRequest from django.http import HttpRequest
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext_lazy as _
try: try:
from allauth.account import app_settings as allauth_settings from allauth.account import app_settings as allauth_settings
@ -22,7 +23,6 @@ if 'allauth.socialaccount' in settings.INSTALLED_APPS:
pass pass
class SocialLoginSerializer(serializers.Serializer): class SocialLoginSerializer(serializers.Serializer):
access_token = serializers.CharField(required=False, allow_blank=True) access_token = serializers.CharField(required=False, allow_blank=True)
code = serializers.CharField(required=False, allow_blank=True) code = serializers.CharField(required=False, allow_blank=True)
@ -43,7 +43,8 @@ class SocialLoginSerializer(serializers.Serializer):
:return: :return: A populated instance of the `allauth.socialaccount.SocialLoginView` instance :return: :return: A populated instance of the `allauth.socialaccount.SocialLoginView` instance
""" """
request = self._get_request() request = self._get_request()
social_login = adapter.complete_login(request, app, token, response=response) social_login = adapter.complete_login(
request, app, token, response=response)
social_login.token = token social_login.token = token
return social_login return social_login
@ -53,12 +54,13 @@ class SocialLoginSerializer(serializers.Serializer):
if not view: if not view:
raise serializers.ValidationError( raise serializers.ValidationError(
'View is not defined, pass it as a context variable' _('View is not defined, pass it as a context variable')
) )
adapter_class = getattr(view, 'adapter_class', None) adapter_class = getattr(view, 'adapter_class', None)
if not adapter_class: if not adapter_class:
raise serializers.ValidationError('Define adapter_class in view') raise serializers.ValidationError(
_('Define adapter_class in view'))
adapter = adapter_class() adapter = adapter_class()
app = adapter.get_provider().get_app(request) app = adapter.get_provider().get_app(request)
@ -77,11 +79,11 @@ class SocialLoginSerializer(serializers.Serializer):
if not self.callback_url: if not self.callback_url:
raise serializers.ValidationError( raise serializers.ValidationError(
'Define callback_url in view' _('Define callback_url in view')
) )
if not self.client_class: if not self.client_class:
raise serializers.ValidationError( raise serializers.ValidationError(
'Define client_class in view' _('Define client_class in view')
) )
code = attrs.get('code') code = attrs.get('code')
@ -101,7 +103,8 @@ class SocialLoginSerializer(serializers.Serializer):
access_token = token['access_token'] access_token = token['access_token']
else: else:
raise serializers.ValidationError('Incorrect input. access_token or code is required.') raise serializers.ValidationError(
_('Incorrect input. access_token or code is required.'))
token = adapter.parse_token({'access_token': access_token}) token = adapter.parse_token({'access_token': access_token})
token.app = app token.app = app
@ -139,7 +142,7 @@ class RegisterSerializer(serializers.Serializer):
if allauth_settings.UNIQUE_EMAIL: if allauth_settings.UNIQUE_EMAIL:
if email and email_address_exists(email): if email and email_address_exists(email):
raise serializers.ValidationError( raise serializers.ValidationError(
"A user is already registered with this e-mail address.") _("A user is already registered with this e-mail address."))
return email return email
def validate_password1(self, password): def validate_password1(self, password):
@ -147,7 +150,8 @@ class RegisterSerializer(serializers.Serializer):
def validate(self, data): def validate(self, data):
if data['password1'] != data['password2']: if data['password1'] != data['password2']:
raise serializers.ValidationError("The two password fields didn't match.") raise serializers.ValidationError(
_("The two password fields didn't match."))
return data return data
def custom_signup(self, request, user): def custom_signup(self, request, user):

View File

@ -5,7 +5,8 @@ from .views import RegisterView, VerifyEmailView
urlpatterns = [ urlpatterns = [
url(r'^$', RegisterView.as_view(), name='rest_register'), url(r'^$', RegisterView.as_view(), name='rest_register'),
url(r'^verify-email/$', VerifyEmailView.as_view(), name='rest_verify_email'), url(r'^verify-email/$', VerifyEmailView.as_view(),
name='rest_verify_email'),
# This url is used by django-allauth and empty TemplateView is # This url is used by django-allauth and empty TemplateView is
# defined just to allow reverse() call inside app, for example when email # defined just to allow reverse() call inside app, for example when email
@ -17,7 +18,8 @@ urlpatterns = [
# with proper key. # with proper key.
# If you don't want to use API on that step, then just use ConfirmEmailView # If you don't want to use API on that step, then just use ConfirmEmailView
# view from: # view from:
# djang-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py#L190 # djang-allauth
# https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py#L190
url(r'^account-confirm-email/(?P<key>\w+)/$', TemplateView.as_view(), url(r'^account-confirm-email/(?P<key>\w+)/$', TemplateView.as_view(),
name='account_confirm_email'), name='account_confirm_email'),
] ]

View File

@ -65,6 +65,7 @@ class VerifyEmailView(APIView, ConfirmEmailView):
class SocialLoginView(LoginView): class SocialLoginView(LoginView):
""" """
class used for social authentications class used for social authentications
example usage for facebook with access_token example usage for facebook with access_token

View File

@ -50,7 +50,8 @@ class LoginSerializer(serializers.Serializer):
elif username and password: elif username and password:
user = authenticate(username=username, password=password) user = authenticate(username=username, password=password)
else: else:
msg = _('Must include either "username" or "email" and "password".') msg = _(
'Must include either "username" or "email" and "password".')
raise exceptions.ValidationError(msg) raise exceptions.ValidationError(msg)
return user return user
@ -81,7 +82,8 @@ class LoginSerializer(serializers.Serializer):
# Authentication without using allauth # Authentication without using allauth
if email: if email:
try: try:
username = UserModel.objects.get(email__iexact=email).username username = UserModel.objects.get(
email__iexact=email).username
except UserModel.DoesNotExist: except UserModel.DoesNotExist:
pass pass
@ -103,13 +105,15 @@ class LoginSerializer(serializers.Serializer):
if app_settings.EMAIL_VERIFICATION == app_settings.EmailVerificationMethod.MANDATORY: if app_settings.EMAIL_VERIFICATION == app_settings.EmailVerificationMethod.MANDATORY:
email_address = user.emailaddress_set.get(email=user.email) email_address = user.emailaddress_set.get(email=user.email)
if not email_address.verified: if not email_address.verified:
raise serializers.ValidationError('E-mail is not verified.') raise serializers.ValidationError(_(
'E-mail is not verified.'))
attrs['user'] = user attrs['user'] = user
return attrs return attrs
class TokenSerializer(serializers.ModelSerializer): class TokenSerializer(serializers.ModelSerializer):
""" """
Serializer for Token model. Serializer for Token model.
""" """
@ -147,7 +151,8 @@ class PasswordResetSerializer(serializers.Serializer):
def validate_email(self, value): def validate_email(self, value):
# Create PasswordResetForm with the serializer # Create PasswordResetForm with the serializer
self.reset_form = self.password_reset_form_class(data=self.initial_data) self.reset_form = self.password_reset_form_class(
data=self.initial_data)
if not self.reset_form.is_valid(): if not self.reset_form.is_valid():
raise serializers.ValidationError(_('Error')) raise serializers.ValidationError(_('Error'))
@ -167,6 +172,7 @@ class PasswordResetSerializer(serializers.Serializer):
class PasswordResetConfirmSerializer(serializers.Serializer): class PasswordResetConfirmSerializer(serializers.Serializer):
""" """
Serializer for requesting a password reset e-mail. Serializer for requesting a password reset e-mail.
""" """
@ -190,7 +196,7 @@ class PasswordResetConfirmSerializer(serializers.Serializer):
uid = force_text(uid_decoder(attrs['uid'])) uid = force_text(uid_decoder(attrs['uid']))
self.user = UserModel._default_manager.get(pk=uid) self.user = UserModel._default_manager.get(pk=uid)
except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist): except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
raise ValidationError({'uid': ['Invalid value']}) raise ValidationError({'uid': [_('Invalid value')]})
self.custom_validation(attrs) self.custom_validation(attrs)
# Construct SetPasswordForm instance # Construct SetPasswordForm instance
@ -200,7 +206,7 @@ class PasswordResetConfirmSerializer(serializers.Serializer):
if not self.set_password_form.is_valid(): if not self.set_password_form.is_valid():
raise serializers.ValidationError(self.set_password_form.errors) raise serializers.ValidationError(self.set_password_form.errors)
if not default_token_generator.check_token(self.user, attrs['token']): if not default_token_generator.check_token(self.user, attrs['token']):
raise ValidationError({'token': ['Invalid value']}) raise ValidationError({'token': [_('Invalid value')]})
return attrs return attrs
@ -239,7 +245,7 @@ class PasswordChangeSerializer(serializers.Serializer):
) )
if all(invalid_password_conditions): if all(invalid_password_conditions):
raise serializers.ValidationError('Invalid password') raise serializers.ValidationError(_('Invalid password'))
return value return value
def validate(self, attrs): def validate(self, attrs):

View File

@ -14,9 +14,11 @@ from django.views.decorators.cache import never_cache
class CustomRequestAuthenticationForm(AuthenticationForm): class CustomRequestAuthenticationForm(AuthenticationForm):
def __init__(self, request, *args, **kwargs): def __init__(self, request, *args, **kwargs):
assert isinstance(request, HttpRequest) assert isinstance(request, HttpRequest)
super(CustomRequestAuthenticationForm, self).__init__(request, *args, **kwargs) super(CustomRequestAuthenticationForm, self).__init__(
request, *args, **kwargs)
@never_cache @never_cache
@ -70,13 +72,18 @@ def custom_request_auth_login(request):
# special urls for auth test cases # special urls for auth test cases
urlpatterns += [ urlpatterns += [
url(r'^logout/custom_query/$', views.logout, dict(redirect_field_name='follow')), url(r'^logout/custom_query/$', views.logout,
dict(redirect_field_name='follow')),
url(r'^logout/next_page/$', views.logout, dict(next_page='/somewhere/')), url(r'^logout/next_page/$', views.logout, dict(next_page='/somewhere/')),
url(r'^logout/next_page/named/$', views.logout, dict(next_page='password_reset')), url(r'^logout/next_page/named/$', views.logout,
dict(next_page='password_reset')),
url(r'^remote_user/$', remote_user_auth_view), url(r'^remote_user/$', remote_user_auth_view),
url(r'^password_reset_from_email/$', views.password_reset, dict(from_email='staffmember@example.com')), url(r'^password_reset_from_email/$', views.password_reset,
url(r'^password_reset/custom_redirect/$', views.password_reset, dict(post_reset_redirect='/custom/')), dict(from_email='staffmember@example.com')),
url(r'^password_reset/custom_redirect/named/$', views.password_reset, dict(post_reset_redirect='password_reset')), url(r'^password_reset/custom_redirect/$', views.password_reset,
dict(post_reset_redirect='/custom/')),
url(r'^password_reset/custom_redirect/named/$', views.password_reset,
dict(post_reset_redirect='password_reset')),
url(r'^password_reset/html_email_template/$', views.password_reset, url(r'^password_reset/html_email_template/$', views.password_reset,
dict(html_email_template_name='registration/html_password_reset_email.html')), dict(html_email_template_name='registration/html_password_reset_email.html')),
url(r'^reset/custom/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', url(r'^reset/custom/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
@ -85,11 +92,15 @@ urlpatterns += [
url(r'^reset/custom/named/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', url(r'^reset/custom/named/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
views.password_reset_confirm, views.password_reset_confirm,
dict(post_reset_redirect='password_reset')), dict(post_reset_redirect='password_reset')),
url(r'^password_change/custom/$', views.password_change, dict(post_change_redirect='/custom/')), url(r'^password_change/custom/$', views.password_change,
url(r'^password_change/custom/named/$', views.password_change, dict(post_change_redirect='password_reset')), dict(post_change_redirect='/custom/')),
url(r'^admin_password_reset/$', views.password_reset, dict(is_admin_site=True)), url(r'^password_change/custom/named/$', views.password_change,
dict(post_change_redirect='password_reset')),
url(r'^admin_password_reset/$',
views.password_reset, dict(is_admin_site=True)),
url(r'^login_required/$', login_required(views.password_reset)), url(r'^login_required/$', login_required(views.password_reset)),
url(r'^login_required_login_url/$', login_required(views.password_reset, login_url='/somewhere/')), url(r'^login_required_login_url/$',
login_required(views.password_reset, login_url='/somewhere/')),
url(r'^auth_processor_no_attr_access/$', auth_processor_no_attr_access), url(r'^auth_processor_no_attr_access/$', auth_processor_no_attr_access),
url(r'^auth_processor_attr_access/$', auth_processor_attr_access), url(r'^auth_processor_attr_access/$', auth_processor_attr_access),
@ -100,6 +111,7 @@ urlpatterns += [
url(r'^custom_request_auth_login/$', custom_request_auth_login), url(r'^custom_request_auth_login/$', custom_request_auth_login),
url(r'^userpage/(.+)/$', userpage, name="userpage"), url(r'^userpage/(.+)/$', userpage, name="userpage"),
# This line is only required to render the password reset with is_admin=True # This line is only required to render the password reset with
# is_admin=True
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
] ]

View File

@ -12,6 +12,7 @@ from .test_base import BaseAPITestCase
class APITestCase1(TestCase, BaseAPITestCase): class APITestCase1(TestCase, BaseAPITestCase):
""" """
Case #1: Case #1:
- user profile: defined - user profile: defined
@ -68,7 +69,8 @@ class APITestCase1(TestCase, BaseAPITestCase):
self.post(self.password_change_url, status_code=403) self.post(self.password_change_url, status_code=403)
# create user # create user
user = get_user_model().objects.create_user(self.USERNAME, '', self.PASS) user = get_user_model().objects.create_user(
self.USERNAME, '', self.PASS)
self.post(self.login_url, data=payload, status_code=200) self.post(self.login_url, data=payload, status_code=200)
self.assertEqual('key' in self.response.json.keys(), True) self.assertEqual('key' in self.response.json.keys(), True)
@ -105,7 +107,8 @@ class APITestCase1(TestCase, BaseAPITestCase):
self.post(self.password_change_url, status_code=403) self.post(self.password_change_url, status_code=403)
# create user # create user
user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) user = get_user_model().objects.create_user(
self.USERNAME, self.EMAIL, self.PASS)
# test auth by email # test auth by email
self.post(self.login_url, data=payload, status_code=200) self.post(self.login_url, data=payload, status_code=200)
@ -216,7 +219,8 @@ class APITestCase1(TestCase, BaseAPITestCase):
self.post(self.login_url, data=login_payload, status_code=200) self.post(self.login_url, data=login_payload, status_code=200)
def test_password_reset(self): def test_password_reset(self):
user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) user = get_user_model().objects.create_user(
self.USERNAME, self.EMAIL, self.PASS)
# call password reset # call password reset
mail_count = len(mail.outbox) mail_count = len(mail.outbox)
@ -271,7 +275,8 @@ class APITestCase1(TestCase, BaseAPITestCase):
self.post(self.login_url, data=payload, status_code=200) self.post(self.login_url, data=payload, status_code=200)
def test_password_reset_with_email_in_different_case(self): def test_password_reset_with_email_in_different_case(self):
get_user_model().objects.create_user(self.USERNAME, self.EMAIL.lower(), self.PASS) get_user_model().objects.create_user(
self.USERNAME, self.EMAIL.lower(), self.PASS)
# call password reset in upper case # call password reset in upper case
mail_count = len(mail.outbox) mail_count = len(mail.outbox)
@ -283,7 +288,8 @@ class APITestCase1(TestCase, BaseAPITestCase):
""" """
Invalid email should not raise error, as this would leak users Invalid email should not raise error, as this would leak users
""" """
get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) get_user_model().objects.create_user(
self.USERNAME, self.EMAIL, self.PASS)
# call password reset # call password reset
mail_count = len(mail.outbox) mail_count = len(mail.outbox)
@ -292,7 +298,8 @@ class APITestCase1(TestCase, BaseAPITestCase):
self.assertEqual(len(mail.outbox), mail_count) self.assertEqual(len(mail.outbox), mail_count)
def test_user_details(self): def test_user_details(self):
user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) user = get_user_model().objects.create_user(
self.USERNAME, self.EMAIL, self.PASS)
payload = { payload = {
"username": self.USERNAME, "username": self.USERNAME,
"password": self.PASS "password": self.PASS
@ -313,9 +320,11 @@ class APITestCase1(TestCase, BaseAPITestCase):
# test empty payload # test empty payload
self.post(self.register_url, data={}, status_code=400) self.post(self.register_url, data={}, status_code=400)
result = self.post(self.register_url, data=self.REGISTRATION_DATA, status_code=201) result = self.post(
self.register_url, data=self.REGISTRATION_DATA, status_code=201)
self.assertIn('key', result.data) self.assertIn('key', result.data)
self.assertEqual(get_user_model().objects.all().count(), user_count + 1) self.assertEqual(
get_user_model().objects.all().count(), user_count + 1)
new_user = get_user_model().objects.latest('id') new_user = get_user_model().objects.latest('id')
self.assertEqual(new_user.username, self.REGISTRATION_DATA['username']) self.assertEqual(new_user.username, self.REGISTRATION_DATA['username'])
@ -350,7 +359,8 @@ class APITestCase1(TestCase, BaseAPITestCase):
status_code=status.HTTP_201_CREATED status_code=status.HTTP_201_CREATED
) )
self.assertNotIn('key', result.data) self.assertNotIn('key', result.data)
self.assertEqual(get_user_model().objects.all().count(), user_count + 1) self.assertEqual(
get_user_model().objects.all().count(), user_count + 1)
self.assertEqual(len(mail.outbox), mail_count + 1) self.assertEqual(len(mail.outbox), mail_count + 1)
new_user = get_user_model().objects.latest('id') new_user = get_user_model().objects.latest('id')
self.assertEqual(new_user.username, self.REGISTRATION_DATA['username']) self.assertEqual(new_user.username, self.REGISTRATION_DATA['username'])

View File

@ -24,6 +24,7 @@ class BaseAPITestCase(object):
* easy request calls, f.e.: self.post(url, data), self.get(url) * easy request calls, f.e.: self.post(url, data), self.get(url)
* easy status check, f.e.: self.post(url, data, status_code=200) * easy status check, f.e.: self.post(url, data, status_code=200)
""" """
def send_request(self, request_method, *args, **kwargs): def send_request(self, request_method, *args, **kwargs):
request_func = getattr(self.client, request_method) request_func = getattr(self.client, request_method)
status_code = None status_code = None

View File

@ -74,12 +74,14 @@ class TestSocialAuth(TestCase, BaseAPITestCase):
self.post(self.fb_login_url, data=payload, status_code=200) self.post(self.fb_login_url, data=payload, status_code=200)
self.assertIn('key', self.response.json.keys()) self.assertIn('key', self.response.json.keys())
self.assertEqual(get_user_model().objects.all().count(), users_count + 1) self.assertEqual(
get_user_model().objects.all().count(), users_count + 1)
# make sure that second request will not create a new user # make sure that second request will not create a new user
self.post(self.fb_login_url, data=payload, status_code=200) self.post(self.fb_login_url, data=payload, status_code=200)
self.assertIn('key', self.response.json.keys()) self.assertIn('key', self.response.json.keys())
self.assertEqual(get_user_model().objects.all().count(), users_count + 1) self.assertEqual(
get_user_model().objects.all().count(), users_count + 1)
@responses.activate @responses.activate
@override_settings( @override_settings(

View File

@ -1,6 +1,7 @@
from django.contrib.auth import login, logout from django.contrib.auth import login, logout
from django.conf import settings from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext_lazy as _
from rest_framework import status from rest_framework import status
from rest_framework.views import APIView from rest_framework.views import APIView
@ -41,7 +42,8 @@ class LoginView(GenericAPIView):
def get_response(self): def get_response(self):
return Response( return Response(
self.response_serializer(self.token).data, status=status.HTTP_200_OK self.response_serializer(
self.token).data, status=status.HTTP_200_OK
) )
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
@ -69,7 +71,7 @@ class LogoutView(APIView):
logout(request) logout(request)
return Response({"success": "Successfully logged out."}, return Response({"success": _("Successfully logged out.")},
status=status.HTTP_200_OK) status=status.HTTP_200_OK)
@ -111,7 +113,7 @@ class PasswordResetView(GenericAPIView):
serializer.save() serializer.save()
# Return the success message with OK HTTP status # Return the success message with OK HTTP status
return Response( return Response(
{"success": "Password reset e-mail has been sent."}, {"success": _("Password reset e-mail has been sent.")},
status=status.HTTP_200_OK status=status.HTTP_200_OK
) )
@ -133,7 +135,7 @@ class PasswordResetConfirmView(GenericAPIView):
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
serializer.save() serializer.save()
return Response({"success": "Password has been reset with the new password."}) return Response({"success": _("Password has been reset with the new password.")})
class PasswordChangeView(GenericAPIView): class PasswordChangeView(GenericAPIView):
@ -152,4 +154,4 @@ class PasswordChangeView(GenericAPIView):
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
serializer.save() serializer.save()
return Response({"success": "New password has been saved."}) return Response({"success": _("New password has been saved.")})