feat: add Arabic translations and fix frontend i18n gaps

- Add backend/locale/ar_SA/LC_MESSAGES/django.po with Arabic (ar-sa) translations
  for all 62 user-facing error/validation strings across accounts, bookings,
  payments, and notifications apps; compile to django.mo
- Add common.loading and salon.unknownStaff keys to both ar-sa.json and en.json
- ProtectedRoute: replace hardcoded "Loading..." with t("common.loading")
- BookPage, SalonDetailPage: replace `Staff ${s.id}` fallback with
  t("salon.unknownStaff", { id: s.id })
- BookingsPage: pass getActiveLocale() to toLocaleString so date/time
  format matches the active app language

All 35 backend tests and 7 frontend tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-02 00:53:24 +03:00
parent ef60218c4c
commit 2305c3dc9d
8 changed files with 268 additions and 8 deletions
Binary file not shown.
+251
View File
@@ -0,0 +1,251 @@
# Arabic (Saudi Arabia) translations for Salon booking platform.
# Copyright (C) 2026
#
msgid ""
msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-02 00:45+0300\n"
"PO-Revision-Date: 2026-03-02 00:45+0300\n"
"Last-Translator: Claude\n"
"Language-Team: Arabic (Saudi Arabia)\n"
"Language: ar_SA\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
#: apps/accounts/services/otp.py:26
msgid "Too many OTP requests. Try again later."
msgstr "طلبات رمز التحقق كثيرة جداً. حاول مرة أخرى لاحقاً."
#: apps/accounts/services/otp.py:32
msgid "Please wait before requesting another code."
msgstr "يرجى الانتظار قبل طلب رمز آخر."
#: apps/accounts/services/otp.py:71
msgid "Twilio credentials are not configured"
msgstr "لم يتم تكوين بيانات اعتماد Twilio"
#: apps/accounts/services/otp.py:85
msgid "Twilio WhatsApp sender is not configured"
msgstr "لم يتم تكوين مُرسِل WhatsApp لـ Twilio"
#: apps/accounts/services/otp.py:100
msgid "Unifonic credentials are not configured"
msgstr "لم يتم تكوين بيانات اعتماد Unifonic"
#: apps/accounts/services/otp.py:104
msgid "Unifonic SMS adapter not implemented yet"
msgstr "محول SMS لـ Unifonic لم يتم تنفيذه بعد"
#: apps/accounts/services/otp.py:109
msgid "Unifonic WhatsApp sender is not configured"
msgstr "لم يتم تكوين مُرسِل WhatsApp لـ Unifonic"
#: apps/accounts/services/otp.py:110
msgid "Unifonic WhatsApp adapter not implemented yet"
msgstr "محول WhatsApp لـ Unifonic لم يتم تنفيذه بعد"
#: apps/accounts/services/otp.py:126
msgid "Authentica API key is not configured"
msgstr "لم يتم تكوين مفتاح API لـ Authentica"
#: apps/accounts/services/otp.py:149 apps/accounts/services/otp.py:162
msgid "Authentica request failed"
msgstr "فشل طلب Authentica"
#: apps/accounts/services/otp.py:159
#, python-format
msgid "Authentica request failed: %(status)s %(body)s"
msgstr "فشل طلب Authentica: %(status)s %(body)s"
#: apps/accounts/services/otp.py:168 apps/accounts/services/otp.py:276
msgid "Unsupported OTP channel"
msgstr "قناة رمز التحقق غير مدعومة"
#: apps/accounts/services/otp.py:179
#, python-format
msgid "Authentica verify failed: %(response)s"
msgstr "فشل التحقق بـ Authentica: %(response)s"
#: apps/accounts/services/otp.py:184
msgid "Authentica sender name is not configured"
msgstr "لم يتم تكوين اسم مُرسِل Authentica"
#: apps/accounts/services/otp.py:195
msgid "Authentica WhatsApp messaging is not supported"
msgstr "مراسلة WhatsApp غير مدعومة لـ Authentica"
#: apps/accounts/services/otp.py:209
#, python-format
msgid "Unknown OTP provider: %(provider)s"
msgstr "مزود رمز التحقق غير معروف: %(provider)s"
#: apps/accounts/services/otp.py:256
#, python-format
msgid "Your verification code is %(code)s. It expires in %(minutes)s minutes."
msgstr "رمز التحقق الخاص بك هو %(code)s. ينتهي في %(minutes)s دقيقة."
#: apps/accounts/services/phone.py:8
msgid "Phone number is required"
msgstr "رقم الهاتف مطلوب"
#: apps/accounts/services/phone.py:17
msgid "Invalid phone number format"
msgstr "تنسيق رقم الهاتف غير صالح"
#: apps/accounts/services/phone.py:28
msgid "Phone number must be in E.164 format or a valid Saudi mobile"
msgstr "يجب أن يكون رقم الهاتف بصيغة E.164 أو رقم جوال سعودي صالح"
#: apps/accounts/views.py:75 apps/accounts/views.py:138
msgid "Invalid or expired code"
msgstr "الرمز غير صالح أو منتهي الصلاحية"
#: apps/accounts/views.py:82
msgid "Phone verified"
msgstr "تم التحقق من رقم الهاتف"
#: apps/accounts/views.py:99
msgid "Email already in use."
msgstr "البريد الإلكتروني مستخدم بالفعل."
#: apps/accounts/views.py:142
msgid "User not found"
msgstr "المستخدم غير موجود"
#: apps/accounts/views.py:164
msgid "Social login not configured yet. Add OAuth provider config."
msgstr "لم يتم تكوين تسجيل الدخول الاجتماعي بعد. أضف إعداد مزود OAuth."
#: apps/bookings/serializers.py:54
msgid "Only staff or managers can confirm bookings."
msgstr "يمكن للموظفين والمدراء فقط تأكيد الحجوزات."
#: apps/bookings/serializers.py:56
msgid "Only staff or managers can complete bookings."
msgstr "يمكن للموظفين والمدراء فقط إكمال الحجوزات."
#: apps/bookings/serializers.py:58
msgid "You are not allowed to cancel this booking."
msgstr "لا يُسمح لك بإلغاء هذا الحجز."
#: apps/bookings/serializers.py:101 apps/bookings/services.py:49
msgid "Booking overlaps an existing appointment"
msgstr "يتداخل الحجز مع موعد قائم"
#: apps/bookings/services.py:13
msgid "Staff is required for booking"
msgstr "يجب تحديد موظف للحجز"
#: apps/bookings/services.py:16
msgid "Selected staff does not belong to this salon"
msgstr "الموظف المختار لا ينتمي إلى هذا الصالون"
#: apps/bookings/services.py:19
msgid "End time must be after start time"
msgstr "يجب أن يكون وقت الانتهاء بعد وقت البدء"
#: apps/bookings/services.py:23
msgid "End time must match service duration"
msgstr "يجب أن يتطابق وقت الانتهاء مع مدة الخدمة"
#: apps/bookings/services.py:40
msgid "Booking is outside staff availability"
msgstr "الحجز خارج أوقات توفر الموظف"
#: apps/notifications/services.py:31
#, python-format
msgid "Unknown notification provider: %(provider)s"
msgstr "مزود الإشعارات غير معروف: %(provider)s"
#: apps/notifications/services.py:47
#, python-format
msgid ""
"Your booking request is received for %(service)s at %(salon)s on %(start)s."
msgstr "تم استلام طلب حجزك لخدمة %(service)s في %(salon)s بتاريخ %(start)s."
#: apps/notifications/services.py:55
#, python-format
msgid "Your booking is confirmed for %(service)s at %(salon)s on %(start)s."
msgstr "تم تأكيد حجزك لخدمة %(service)s في %(salon)s بتاريخ %(start)s."
#: apps/notifications/services.py:63
#, python-format
msgid "Your booking was cancelled for %(service)s at %(salon)s on %(start)s."
msgstr "تم إلغاء حجزك لخدمة %(service)s في %(salon)s بتاريخ %(start)s."
#: apps/notifications/services.py:70
#, python-format
msgid "Booking update for %(service)s at %(salon)s on %(start)s."
msgstr "تحديث الحجز لخدمة %(service)s في %(salon)s بتاريخ %(start)s."
#: apps/notifications/services.py:85
msgid "Unsupported notification channel"
msgstr "قناة الإشعارات غير مدعومة"
#: apps/payments/serializers.py:49
msgid "Booking not found"
msgstr "الحجز غير موجود"
#: apps/payments/serializers.py:56 apps/payments/services/payments.py:79
msgid "Provider integration not implemented"
msgstr "تكامل المزود غير مُنفَّذ"
#: apps/payments/serializers.py:58
msgid "Payment source is required"
msgstr "مصدر الدفع مطلوب"
#: apps/payments/serializers.py:61
msgid "Payment source type is required"
msgstr "نوع مصدر الدفع مطلوب"
#: apps/payments/serializers.py:64
msgid "Card data must not be sent to the backend; use frontend tokenization"
msgstr "لا يجب إرسال بيانات البطاقة إلى الخادم؛ استخدم التحويل إلى رمز في الواجهة الأمامية"
#: apps/payments/serializers.py:67
msgid "Callback URL is required for token payments"
msgstr "رابط الاستجابة مطلوب لمدفوعات الرمز"
#: apps/payments/services/payments.py:84
msgid "Idempotency key already used"
msgstr "مفتاح الإيدمبوتنسي مستخدم بالفعل"
#: apps/payments/services/payments.py:89
msgid "Unsupported payment source type"
msgstr "نوع مصدر الدفع غير مدعوم"
#: apps/payments/services/payments.py:130
#: apps/payments/services/payments.py:141
msgid "Payment provider error"
msgstr "خطأ في مزود الدفع"
#: apps/payments/views.py:50
msgid "Not allowed"
msgstr "غير مسموح"
#: apps/payments/views.py:70
msgid "Webhook secret not configured"
msgstr "لم يتم تكوين رمز الـ webhook"
#: apps/payments/views.py:73
msgid "Invalid webhook signature"
msgstr "توقيع الـ webhook غير صالح"
#: apps/payments/views.py:79
msgid "Missing payment reference"
msgstr "مرجع الدفع مفقود"
#: apps/payments/views.py:84
msgid "Payment not found"
msgstr "لم يتم العثور على الدفعة"
#: apps/payments/views.py:88
msgid "Event ignored"
msgstr "تم تجاهل الحدث"
#: apps/payments/views.py:89
msgid "Webhook processed"
msgstr "تمت معالجة الـ webhook"