Browse Source

error messages language expanded for ru,en and fa language codes

master
Mohsen Taba 1 month ago
parent
commit
61b6c18d13
  1. 97
      apps/account/messages.py
  2. 10
      apps/account/serializers/user.py
  3. 33
      apps/account/utils.py
  4. 13
      apps/account/views/auth.py
  5. 37
      apps/account/views/user.py

97
apps/account/messages.py

@ -0,0 +1,97 @@
ACCOUNT_MESSAGES = {
'email_already_registered': [
{'language_code': 'en', 'text': 'This email is already registered.'},
{'language_code': 'ru', 'text': 'Этот адрес электронной почты уже зарегистрирован.'},
{'language_code': 'fa', 'text': 'این ایمیل قبلاً ثبت شده است.'},
],
'device_id_required': [
{'language_code': 'en', 'text': 'Device ID is required for guest users.'},
{'language_code': 'ru', 'text': 'ID устройства обязателен для гостевых пользователей.'},
{'language_code': 'fa', 'text': 'ارسال شناسه دستگاه الزامی است.'},
],
'device_id_required_web': [
{'language_code': 'en', 'text': 'Device ID is required for web guest users.'},
{'language_code': 'ru', 'text': 'ID устройства обязателен для веб-гостей.'},
{'language_code': 'fa', 'text': 'ارسال شناسه دستگاه برای کاربران وب الزامی است.'},
],
'otp_sent': [
{'language_code': 'en', 'text': "The otp code was sent to the user's email"},
{'language_code': 'ru', 'text': 'Одноразовый код был отправлен на электронную почту пользователя.'},
{'language_code': 'fa', 'text': 'کد تایید به ایمیل کاربر ارسال شد.'},
],
'verification_data_not_found': [
{'language_code': 'en', 'text': 'Verification data not found or expired.'},
{'language_code': 'ru', 'text': 'Данные для подтверждения не найдены или истек срок их действия.'},
{'language_code': 'fa', 'text': 'اطلاعات تایید یافت نشد یا منقضی شده است.'},
],
'verification_code_expired': [
{'language_code': 'en', 'text': 'The verification code has expired.'},
{'language_code': 'ru', 'text': 'Срок действия кода подтверждения истек.'},
{'language_code': 'fa', 'text': 'کد تایید منقضی شده است.'},
],
'code_not_found': [
{'language_code': 'en', 'text': 'The verification code is incorrect.'},
{'language_code': 'ru', 'text': 'Неверный код подтверждения.'},
{'language_code': 'fa', 'text': 'کد وارد شده صحیح نیست.'},
],
'user_not_exists': [
{'language_code': 'en', 'text': 'No user exists with this email.'},
{'language_code': 'ru', 'text': 'Пользователь с такой электронной почтой не существует.'},
{'language_code': 'fa', 'text': 'کاربری با این ایمیل یافت نشد.'},
],
'password_incorrect': [
{'language_code': 'en', 'text': 'Password is incorrect.'},
{'language_code': 'ru', 'text': 'Неверный пароль.'},
{'language_code': 'fa', 'text': 'رمز عبور اشتباه است.'},
],
'forgot_password_sent': [
{'language_code': 'en', 'text': 'Forgot password code sent.'},
{'language_code': 'ru', 'text': 'Код для восстановления пароля отправлен.'},
{'language_code': 'fa', 'text': 'کد بازیابی رمز عبور ارسال شد.'},
],
'password_reset_success': [
{'language_code': 'en', 'text': 'Your password has been changed successfully.'},
{'language_code': 'ru', 'text': 'Ваш пароль был успешно изменен.'},
{'language_code': 'fa', 'text': 'رمز عبور شما با موفقیت تغییر کرد.'},
],
'account_deleted': [
{'language_code': 'en', 'text': 'Your account has been deleted.'},
{'language_code': 'ru', 'text': 'Ваша учетная запись была удалена.'},
{'language_code': 'fa', 'text': 'حساب کاربری شما حذف شد.'},
],
'user_not_found': [
{'language_code': 'en', 'text': 'User does not exist.'},
{'language_code': 'ru', 'text': 'Пользователь не существует.'},
{'language_code': 'fa', 'text': 'کاربر یافت نشد.'},
],
'fcm_token_required': [
{'language_code': 'en', 'text': 'FCM token is required.'},
{'language_code': 'ru', 'text': 'FCM-токен обязателен.'},
{'language_code': 'fa', 'text': 'ارسال توکن FCM الزامی است.'},
],
'fcm_token_updated': [
{'language_code': 'en', 'text': 'FCM token updated successfully.'},
{'language_code': 'ru', 'text': 'FCM-токен успешно обновлен.'},
{'language_code': 'fa', 'text': 'توکن FCM با موفقیت بروزرسانی شد.'},
],
'login_success': [
{'language_code': 'en', 'text': 'Login successful.'},
{'language_code': 'ru', 'text': 'Вход выполнен успешно.'},
{'language_code': 'fa', 'text': 'ورود موفقیت‌آمیز بود.'},
],
'token_missing': [
{'language_code': 'en', 'text': 'Token not provided.'},
{'language_code': 'ru', 'text': 'Токен не предоставлен.'},
{'language_code': 'fa', 'text': 'توکن ارسال نشده است.'},
],
'token_invalid_expired': [
{'language_code': 'en', 'text': 'Token invalid or expired.'},
{'language_code': 'ru', 'text': 'Токен недействителен или срок его действия истек.'},
{'language_code': 'fa', 'text': 'توکن نامعتبر یا منقضی شده است.'},
],
'token_invalid': [
{'language_code': 'en', 'text': 'Token is invalid.'},
{'language_code': 'ru', 'text': 'Токен недействителен.'},
{'language_code': 'fa', 'text': 'توکن نامعتبر است.'},
],
}

10
apps/account/serializers/user.py

@ -3,6 +3,7 @@ from rest_framework.authtoken.models import Token
from django.contrib.auth.password_validation import validate_password from django.contrib.auth.password_validation import validate_password
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from apps.account.models import User from apps.account.models import User
from apps.account.utils import get_localized_msg
from utils import FileFieldSerializer, absolute_url from utils import FileFieldSerializer, absolute_url
from utils.validators import validate_type_code from utils.validators import validate_type_code
@ -89,7 +90,8 @@ class UserRegisterSerializer(serializers.ModelSerializer):
def validate_email(self, value): def validate_email(self, value):
normalized_email = User.objects.normalize_email(value) normalized_email = User.objects.normalize_email(value)
if User.objects.filter(email=normalized_email).exists(): if User.objects.filter(email=normalized_email).exists():
raise serializers.ValidationError("This email is already registered.")
msg = get_localized_msg('email_already_registered', self.context.get('request'))
raise serializers.ValidationError(msg)
return normalized_email return normalized_email
@ -194,7 +196,8 @@ class UserGuestSerializer(serializers.ModelSerializer):
def validate(self, data): def validate(self, data):
# Make sure at least device_id is provided # Make sure at least device_id is provided
if not data.get('device_id'): if not data.get('device_id'):
raise serializers.ValidationError({"device_id": "Device ID is required for guest users."})
msg = get_localized_msg('device_id_required', self.context.get('request'))
raise serializers.ValidationError({"device_id": msg})
return data return data
@ -211,7 +214,8 @@ class WebUserGuestSerializer(serializers.ModelSerializer):
def validate(self, data): def validate(self, data):
# Ensure device_id is provided (generated by view) # Ensure device_id is provided (generated by view)
if not data.get('device_id'): if not data.get('device_id'):
raise serializers.ValidationError({"device_id": "Device ID is required for web guest users."})
msg = get_localized_msg('device_id_required_web', self.context.get('request'))
raise serializers.ValidationError({"device_id": msg})
return data return data

33
apps/account/utils.py

@ -0,0 +1,33 @@
from django.utils.translation import get_language
from .messages import ACCOUNT_MESSAGES
def get_localized_msg(key, request=None, fallback_lang="en"):
"""
Get localized message from ACCOUNT_MESSAGES based on request or active language.
"""
json_list = ACCOUNT_MESSAGES.get(key)
if not json_list:
return key # Fallback to key itself if not found
# Get language from request (LocaleMiddleware sets LANGUAGE_CODE)
language_code = getattr(request, "LANGUAGE_CODE", None) if request else None
# Check if 'lang' query param is used (common in this project's mobile apps)
if not language_code and request:
language_code = request.query_params.get('lang')
if not language_code:
language_code = get_language() or fallback_lang
# 1) Exact match
for item in json_list:
if item.get("language_code") == language_code:
return item.get("text")
# 2) Fallback to English
for item in json_list:
if item.get("language_code") == "en":
return item.get("text")
# 3) First available
return json_list[0].get("text") if json_list else key

13
apps/account/views/auth.py

@ -11,6 +11,7 @@ from rest_framework.permissions import AllowAny
from rest_framework.response import Response from rest_framework.response import Response
from apps.account.serializers import ExchangeTokenSerializer from apps.account.serializers import ExchangeTokenSerializer
from apps.account.utils import get_localized_msg
from utils import absolute_url from utils import absolute_url
from utils.redis import OnlineClassTokenManager from utils.redis import OnlineClassTokenManager
@ -77,25 +78,28 @@ class ExchangeTokenAPIView(GenericAPIView):
try: try:
token_data = manager.get_payload(temp_token) token_data = manager.get_payload(temp_token)
except Exception: except Exception:
msg = get_localized_msg('token_invalid_expired', request)
return Response({ return Response({
'success': False, 'success': False,
'message': 'توکن نامعتبر یا منقضی شده است'
'message': msg
}, status=status.HTTP_404_NOT_FOUND) }, status=status.HTTP_404_NOT_FOUND)
user_id = token_data.get('user_id') user_id = token_data.get('user_id')
if not user_id: if not user_id:
msg = get_localized_msg('token_invalid', request)
return Response({ return Response({
'success': False, 'success': False,
'message': 'توکن نامعتبر است'
'message': msg
}, status=status.HTTP_400_BAD_REQUEST) }, status=status.HTTP_400_BAD_REQUEST)
# دریافت کاربر # دریافت کاربر
try: try:
user = UserModel.objects.get(id=user_id) user = UserModel.objects.get(id=user_id)
except UserModel.DoesNotExist: except UserModel.DoesNotExist:
msg = get_localized_msg('user_not_found', request)
return Response({ return Response({
'success': False, 'success': False,
'message': 'کاربر یافت نشد'
'message': msg
}, status=status.HTTP_404_NOT_FOUND) }, status=status.HTTP_404_NOT_FOUND)
# حذف توکن موقت (one-time use) # حذف توکن موقت (one-time use)
@ -113,9 +117,10 @@ class ExchangeTokenAPIView(GenericAPIView):
avatar_url = None avatar_url = None
# برگرداندن اطلاعات کاربر با token واقعی # برگرداندن اطلاعات کاربر با token واقعی
msg = get_localized_msg('login_success', request)
return Response({ return Response({
'success': True, 'success': True,
'message': 'ورود موفق',
'message': msg,
'token': auth_token.key, 'token': auth_token.key,
'user': { 'user': {
'id': user.id, 'id': user.id,

37
apps/account/views/user.py

@ -22,6 +22,7 @@ from drf_yasg import openapi
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from utils.exceptions import InvaliedCodeVrify, ExpiredCodeException, ServiceUnavailableException from utils.exceptions import InvaliedCodeVrify, ExpiredCodeException, ServiceUnavailableException
from apps.account.utils import get_localized_msg
from apps.account.models import User from apps.account.models import User
from apps.account.serializers import UserRegisterSerializer, UserProfileSerializer, UserVerifySerializer, UserLoginSerializer, UserRecoverPasswordSerializer, UserResetPasswordSerializer, UserGuestSerializer,UserFCMSerializer,WebUserGuestSerializer from apps.account.serializers import UserRegisterSerializer, UserProfileSerializer, UserVerifySerializer, UserLoginSerializer, UserRecoverPasswordSerializer, UserResetPasswordSerializer, UserGuestSerializer,UserFCMSerializer,WebUserGuestSerializer
from apps.account.serializers.user_web import WebUserRegisterSerializer from apps.account.serializers.user_web import WebUserRegisterSerializer
@ -239,7 +240,7 @@ class UserRegisterView(CreateAPIView):
return Response( return Response(
data= { data= {
"user": data, "user": data,
"message": "The otp code was sent to the user's email"
"message": get_localized_msg('otp_sent', request)
}, },
status=status.HTTP_202_ACCEPTED, status=status.HTTP_202_ACCEPTED,
) )
@ -266,13 +267,15 @@ class UserVerifyView(CreateAPIView):
try: try:
verify_data = RedisManager().get_by_redis(data['email']) verify_data = RedisManager().get_by_redis(data['email'])
if not verify_data: if not verify_data:
raise ValidationError({"code": "Verification data not found or expired."})
msg = get_localized_msg('verification_data_not_found', request)
raise ValidationError({"code": msg})
# raise ExpiredCodeException("Verification data not found or expired.") # raise ExpiredCodeException("Verification data not found or expired.")
except (ServiceUnavailableException) as e: except (ServiceUnavailableException) as e:
return AppAPIException({"message": str(e)}, status_code=e.status_code) return AppAPIException({"message": str(e)}, status_code=e.status_code)
except ExpiredCodeException: except ExpiredCodeException:
# raise ExpiredCodeException("The verification code has expired.") # raise ExpiredCodeException("The verification code has expired.")
raise ValidationError({"code": "The verification code has expired."})
msg = get_localized_msg('verification_code_expired', request)
raise ValidationError({"code": msg})
code = self.valied_code(data['code'], verify_data['code']) code = self.valied_code(data['code'], verify_data['code'])
del verify_data['code'] del verify_data['code']
@ -293,7 +296,8 @@ class UserVerifyView(CreateAPIView):
if (current_code and save_code) and ( current_code != save_code): if (current_code and save_code) and ( current_code != save_code):
if current_code == "11111": if current_code == "11111":
return current_code return current_code
raise ValidationError({"code": "code notfound"})
msg = get_localized_msg('code_not_found', self.request)
raise ValidationError({"code": msg})
return current_code return current_code
@ -365,7 +369,7 @@ class WebUserRegisterView(CreateAPIView):
"fullname": data.get('fullname'), "fullname": data.get('fullname'),
"email": data.get('email'), "email": data.get('email'),
}, },
"message": "The otp code was sent to the user's email"
"message": get_localized_msg('otp_sent', request)
}, },
status=status.HTTP_202_ACCEPTED, status=status.HTTP_202_ACCEPTED,
) )
@ -400,12 +404,14 @@ class UserLoginView(CreateAPIView):
try: try:
user_obj = User.objects.get(email=email) user_obj = User.objects.get(email=email)
except User.DoesNotExist: except User.DoesNotExist:
raise ValidationError({"email": "user not exists with this email"})
msg = get_localized_msg('user_not_exists', request)
raise ValidationError({"email": msg})
# If user exists, try to authenticate (check password) # If user exists, try to authenticate (check password)
user = authenticate(request, username=email, password=data['password']) user = authenticate(request, username=email, password=data['password'])
if not user: if not user:
raise ValidationError({"password": "password is incorrect"})
msg = get_localized_msg('password_incorrect', request)
raise ValidationError({"password": msg})
user_timezone = serializer.validated_data.pop('timezone', None) user_timezone = serializer.validated_data.pop('timezone', None)
user.last_login = timezone.now() user.last_login = timezone.now()
@ -485,7 +491,7 @@ class UserRecoverPassword(CreateAPIView):
"phone_number": str(user.phone_number) if user.phone_number else None, "phone_number": str(user.phone_number) if user.phone_number else None,
"email": user.email if user.email else None, "email": user.email if user.email else None,
"avatar": request.build_absolute_uri(user.avatar.url) if user.avatar else None, "avatar": request.build_absolute_uri(user.avatar.url) if user.avatar else None,
"message": "Forgot password code sent"
"message": get_localized_msg('forgot_password_sent', request)
}, },
status=status.HTTP_202_ACCEPTED, status=status.HTTP_202_ACCEPTED,
) )
@ -513,7 +519,8 @@ class UserResetPassword(CreateAPIView):
user.save() user.save()
# Return a success response # Return a success response
return Response({"message": "Your password has been changed successfully."}, status=status.HTTP_200_OK)
msg = get_localized_msg('password_reset_success', request)
return Response({"message": msg}, status=status.HTTP_200_OK)
@ -532,11 +539,13 @@ class UserDeleteView(APIView):
if t := Token.objects.filter(user=user).first(): if t := Token.objects.filter(user=user).first():
t.delete() t.delete()
return Response({"detail": "Your account has been deleted."}, status=status.HTTP_204_NO_CONTENT)
msg = get_localized_msg('account_deleted', request)
return Response({"detail": msg}, status=status.HTTP_204_NO_CONTENT)
except Exception: except Exception:
# پیام خطای ثابت برای سایر خطاهای غیرمنتظره # پیام خطای ثابت برای سایر خطاهای غیرمنتظره
return Response({"detail": "User does not exist."}, status=status.HTTP_404_NOT_FOUND)
msg = get_localized_msg('user_not_found', request)
return Response({"detail": msg}, status=status.HTTP_404_NOT_FOUND)
class UpdateFCMView(GenericAPIView): class UpdateFCMView(GenericAPIView):
@ -550,9 +559,11 @@ class UpdateFCMView(GenericAPIView):
fcm_token = request.data.get('fcm') fcm_token = request.data.get('fcm')
if not fcm_token: if not fcm_token:
return Response({"detail": "FCM token is required."}, status=status.HTTP_200_OK)
msg = get_localized_msg('fcm_token_required', request)
return Response({"detail": msg}, status=status.HTTP_200_OK)
user.fcm = fcm_token user.fcm = fcm_token
user.save() user.save()
return Response({"detail": "FCM token updated successfully."}, status=status.HTTP_200_OK)
msg = get_localized_msg('fcm_token_updated', request)
return Response({"detail": msg}, status=status.HTTP_200_OK)
Loading…
Cancel
Save