This commit is contained in:
root
2026-05-22 02:43:13 -04:00
parent 191fb3cb4e
commit 99c429d69c
21 changed files with 276 additions and 94 deletions
@@ -45,7 +45,7 @@ export default async function CompanyProfilePage({ params }: { params: { slug: s
unavailable: 'Marketplace indisponible',
unavailableTitle: "Les détails de l'entreprise sont temporairement indisponibles.",
unavailableBody: "L'API marketplace fonctionne, mais la base de données n'est pas accessible dans cet environnement local.",
backToExplore: 'Retour à explorer',
backToExplore: 'Retour à lexploration',
partner: 'Partenaire marketplace',
vehicles: 'véhicules',
offers: 'offres actives',
@@ -62,10 +62,10 @@ export default async function CompanyProfilePage({ params }: { params: { slug: s
ar: {
unavailable: 'السوق غير متاح',
unavailableTitle: 'تفاصيل الشركة غير متاحة مؤقتاً.',
unavailableBody: 'واجهة marketplace تعمل، لكن قاعدة البيانات غير متاحة في هذا البيئة المحلية.',
unavailableBody: 'واجهة السوق تعمل، لكن قاعدة البيانات غير متاحة في هذه البيئة المحلية.',
backToExplore: 'العودة إلى الاستكشاف',
partner: 'شريك في السوق',
vehicles: 'سيارات',
vehicles: 'مركبات',
offers: 'عروض نشطة',
rating: 'التقييم',
new: 'جديد',
@@ -60,7 +60,7 @@ export default async function VehicleDetailPage({ params }: { params: { slug: st
unavailableTitle: 'Les détails du véhicule sont temporairement indisponibles.',
unavailableBody: "Le frontend marketplace fonctionne, mais la base de données n'est pas accessible pour le moment.",
backToFleet: 'Retour à la flotte',
backToExplore: 'Retour à explorer',
backToExplore: 'Retour à lexploration',
noPhotos: 'Aucune photo disponible.',
rentalCompany: 'Société de location',
perDay: '/ jour',
@@ -81,7 +81,7 @@ export default async function VehicleDetailPage({ params }: { params: { slug: st
ar: {
unavailable: 'السوق غير متاح',
unavailableTitle: 'تفاصيل السيارة غير متاحة مؤقتاً.',
unavailableBody: 'واجهة السوق تعمل، لكن قاعدة البيانات الخلفية غير متاحة حالياً.',
unavailableBody: 'واجهة السوق تعمل، لكن قاعدة البيانات في الخلفية غير متاحة حالياً.',
backToFleet: 'العودة إلى الأسطول',
backToExplore: 'العودة إلى الاستكشاف',
noPhotos: 'لا توجد صور متاحة.',
@@ -87,24 +87,24 @@ const copy = {
annual: 'Annuel',
yearly: '/ an',
youSave: 'Vous économisez',
withAnnual: 'avec la facturation annuelle prélevée en un seul paiement par an.',
withAnnual: 'avec la facturation annuelle, prélevée en un seul paiement par an.',
mostPopular: 'Le plus populaire',
perMonth: '/mois',
billedAs: 'Facturé à',
getStarted: 'Commencer',
footer: 'Tous les plans incluent un essai gratuit de 14 jours. Aucune carte bancaire requise.',
footer: 'Toutes les formules incluent un essai gratuit de 14 jours. Aucune carte bancaire nest requise.',
},
ar: {
monthly: 'شهري',
annual: 'سنوي',
yearly: '/ سنة',
youSave: 'توفر',
withAnnual: 'مع الفوترة السنوية دفعة واحدة كل سنة.',
withAnnual: 'مع الفوترة السنوية، تُسدد دفعة واحدة كل سنة.',
mostPopular: 'الأكثر شيوعاً',
perMonth: '/شهر',
billedAs: 'يتم الفوترة بمبلغ',
getStarted: 'ابدأ الآن',
footer: 'جميع الخطط تشمل تجربة مجانية لمدة 14 يوماً. لا حاجة إلى بطاقة ائتمان.',
footer: 'تشمل جميع الخطط تجربة مجانية لمدة 14 يوماً. لا حاجة إلى بطاقة ائتمان.',
},
} as const
@@ -19,24 +19,24 @@ const copy = {
fr: {
kicker: 'Tarifs',
title: 'Une seule plateforme pour toutes les tailles de flotte.',
body: 'Commencez gratuitement pendant 14 jours puis choisissez le plan qui accompagne votre activité. Changez ou annulez à tout moment.',
body: 'Commencez gratuitement pendant 14 jours, puis choisissez la formule qui accompagne votre activité. Vous pouvez changer de formule ou annuler à tout moment.',
faq: 'Questions fréquentes',
items: [
['Puis-je changer de plan plus tard ?', 'Oui. Vous pouvez monter ou descendre à tout moment — les changements prennent effet au prochain cycle de facturation.'],
['Quest-ce qui compte comme véhicule ?', 'Tout véhicule ajouté à votre tableau de bord flotte, actif ou non.'],
['Puis-je changer de formule plus tard ?', 'Oui. Vous pouvez passer à une formule supérieure ou inférieure à tout moment. Les changements prennent effet au cycle de facturation suivant.'],
['Quest-ce qui compte comme véhicule ?', 'Tout véhicule ajouté à votre tableau de bord de flotte, quil soit actif ou non.'],
['Y a-t-il des frais dinstallation ?', 'Aucun frais dinstallation. Vous payez uniquement labonnement mensuel ou annuel.'],
['Comment fonctionne la visibilité marketplace ?', 'Tous les plans payants incluent une présence publique sur RentalDriveGo. Les clients découvrent votre flotte puis sont redirigés vers votre site de réservation.'],
['Comment fonctionne la visibilité marketplace ?', 'Toutes les formules payantes incluent une présence publique sur RentalDriveGo. Les clients découvrent votre flotte puis sont redirigés vers votre site de réservation.'],
],
},
ar: {
kicker: 'الأسعار',
title: 'منصة واحدة لكل أحجام الأساطيل.',
body: 'ابدأ مجاناً لمدة 14 يوماً ثم اختر الخطة التي تنمو مع نشاطك. يمكنك تغيير الخطة أو الإلغاء في أي وقت.',
body: 'ابدأ مجاناً لمدة 14 يوماً، ثم اختر الخطة التي تناسب نمو نشاطك. يمكنك تغيير الخطة أو إلغاءها في أي وقت.',
faq: 'الأسئلة الشائعة',
items: [
['هل يمكنني تغيير الخطة لاحقاً؟', 'نعم. يمكنك الترقية أو التخفيض في أي وقت — وتدخل التغييرات حيز التنفيذ في دورة الفوترة التالية.'],
['ما الذي يُحتسب كسيارة؟', 'أي سجل سيارة تتم إضافته إلى لوحة الأسطول سواء كان نشطاً أم لا.'],
['هل توجد رسوم إعداد؟', 'لا توجد أي رسوم إعداد. أنت تدفع فقط الاشتراك الشهري أو السنوي.'],
['هل توجد رسوم إعداد؟', 'لا توجد أي رسوم إعداد. أنت تدفع فقط قيمة الاشتراك الشهري أو السنوي.'],
['كيف تعمل قائمة السوق؟', 'كل الخطط المدفوعة تشمل الظهور العام على RentalDriveGo. يكتشف المستأجرون أسطولك ثم يتم تحويلهم إلى موقع الحجز الخاص بك.'],
],
},
@@ -59,7 +59,7 @@ export default function RenterDashboardPage() {
fr: {
loadProfile: 'Impossible de charger le profil.',
reachServer: 'Impossible de joindre le serveur.',
backToExplore: 'Retour à explorer',
backToExplore: 'Retour à lexploration',
renterDashboard: 'Espace client',
welcome: 'Bon retour,',
exploreVehicles: 'Explorer les véhicules',
@@ -72,7 +72,7 @@ export default function RenterDashboardPage() {
yourProfile: 'Votre profil',
firstName: 'Prénom',
lastName: 'Nom',
email: 'Email',
email: 'E-mail',
phone: 'Téléphone',
savedCompanies: 'Entreprises sauvegardées',
noneSaved: 'Aucune pour le moment',
@@ -85,7 +85,7 @@ export default function RenterDashboardPage() {
loadProfile: 'تعذر تحميل الملف الشخصي.',
reachServer: 'تعذر الوصول إلى الخادم.',
backToExplore: 'العودة إلى الاستكشاف',
renterDashboard: 'لوحة المستأجر',
renterDashboard: 'بوابة المستأجر',
welcome: 'مرحباً بعودتك،',
exploreVehicles: 'استكشف السيارات',
logout: 'تسجيل الخروج',
@@ -35,7 +35,7 @@ export default function RenterNotificationsPage() {
renter: 'Client',
title: 'Notifications',
markAll: 'Tout marquer comme lu',
back: 'Retour au dashboard',
back: 'Retour au tableau de bord',
loading: 'Chargement des notifications…',
empty: 'Aucune notification client pour le moment.',
read: 'Lu',
@@ -47,12 +47,12 @@ export default function RenterNotificationsPage() {
updateAll: 'تعذر تحديث الإشعارات.',
renter: 'المستأجر',
title: 'الإشعارات',
markAll: حديد الكل كمقروء',
back: 'العودة إلى اللوحة',
markAll: عيين الكل كمقروء',
back: 'العودة إلى بوابة المستأجر',
loading: 'جارٍ تحميل الإشعارات…',
empty: 'لا توجد إشعارات للمستأجر حالياً.',
read: 'مقروء',
markRead: حديد كمقروء',
markRead: عيين كمقروء',
},
}[language]
const [notifications, setNotifications] = useState<RenterNotification[]>([])
@@ -24,7 +24,7 @@ export default function RenterSavedCompaniesPage() {
load: 'Impossible de charger les entreprises sauvegardées.',
renter: 'Client',
title: 'Entreprises sauvegardées',
back: 'Retour au dashboard',
back: 'Retour au tableau de bord',
loading: 'Chargement des entreprises sauvegardées…',
empty: 'Vous navez encore enregistré aucune entreprise.',
browse: 'Parcourir la marketplace',
@@ -34,7 +34,7 @@ export default function RenterSavedCompaniesPage() {
load: 'تعذر تحميل الشركات المحفوظة.',
renter: 'المستأجر',
title: 'الشركات المحفوظة',
back: 'العودة إلى اللوحة',
back: 'العودة إلى بوابة المستأجر',
loading: 'جارٍ تحميل الشركات المحفوظة…',
empty: 'لم تقم بحفظ أي شركة بعد.',
browse: 'تصفح السوق',
@@ -23,18 +23,19 @@ const copy = {
submit: 'Request reservation',
submitting: 'Sending…',
successTitle: 'Request received!',
successBody: 'Your reservation request has been sent. The company will review it and get in touch with you shortly.',
successBody: 'Your reservation request has been sent. The company will review it and contact you shortly.',
invalidDates: 'Return date must be after pick-up date.',
required: 'Please fill in all required fields.',
perDay: '/ day',
estimatedTotal: 'Estimated total',
days: 'day(s)',
genericError: 'Something went wrong. Please try again.',
},
fr: {
title: 'Réserver ce véhicule',
firstName: 'Prénom',
lastName: 'Nom',
email: 'Email',
email: 'E-mail',
phone: 'Téléphone',
startDate: 'Date de départ',
endDate: 'Date de retour',
@@ -42,12 +43,13 @@ const copy = {
submit: 'Demander une réservation',
submitting: 'Envoi…',
successTitle: 'Demande reçue !',
successBody: "Votre demande de réservation a été envoyée. La société va l'examiner et vous contactera prochainement.",
successBody: "Votre demande de réservation a été envoyée. Lentreprise va lexaminer et vous contactera prochainement.",
invalidDates: 'La date de retour doit être après la date de départ.',
required: 'Veuillez remplir tous les champs obligatoires.',
perDay: '/ jour',
estimatedTotal: 'Total estimé',
days: 'jour(s)',
genericError: 'Une erreur est survenue. Veuillez réessayer.',
},
ar: {
title: 'احجز هذه السيارة',
@@ -56,7 +58,7 @@ const copy = {
email: 'البريد الإلكتروني',
phone: 'الهاتف',
startDate: 'تاريخ الاستلام',
endDate: 'تاريخ الإعادة',
endDate: 'تاريخ الإرجاع',
notes: 'ملاحظات (اختيارية)',
submit: 'طلب حجز',
submitting: 'جارٍ الإرسال…',
@@ -67,6 +69,7 @@ const copy = {
perDay: '/ يوم',
estimatedTotal: 'الإجمالي التقديري',
days: 'يوم',
genericError: 'حدث خطأ ما. يرجى المحاولة مرة أخرى.',
},
} as const
@@ -123,7 +126,7 @@ export default function BookingForm({ vehicleId, companySlug, dailyRate }: Props
})
setSuccess(true)
} catch (err: any) {
setError(err.message ?? 'Something went wrong. Please try again.')
setError(err.message ?? t.genericError)
} finally {
setSubmitting(false)
}