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:
@@ -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"
|
||||
Reference in New Issue
Block a user