redesign the homepage
Build & Deploy / Build & Push Docker Image (push) Failing after 47s
Build & Deploy / Deploy to VPS (push) Has been skipped
Test / API Unit Tests (push) Failing after 5m4s
Test / Marketplace Unit Tests (push) Failing after 4m55s
Test / Admin Unit Tests (push) Successful in 9m37s
Test / Dashboard Unit Tests (push) Successful in 9m37s
Test / API Integration Tests (push) Successful in 9m54s
Build & Deploy / Build & Push Docker Image (push) Failing after 47s
Build & Deploy / Deploy to VPS (push) Has been skipped
Test / API Unit Tests (push) Failing after 5m4s
Test / Marketplace Unit Tests (push) Failing after 4m55s
Test / Admin Unit Tests (push) Successful in 9m37s
Test / Dashboard Unit Tests (push) Successful in 9m37s
Test / API Integration Tests (push) Successful in 9m54s
This commit is contained in:
@@ -0,0 +1,373 @@
|
||||
import type { Locale } from '@/lib/localization/config';
|
||||
|
||||
export interface ComponentLabCopy {
|
||||
developmentLabel: string;
|
||||
title: string;
|
||||
body: string;
|
||||
actions: { primary: string; conversion: string; loading: string; disabled: string };
|
||||
form: {
|
||||
label: string;
|
||||
supporting: string;
|
||||
placeholder: string;
|
||||
error: string;
|
||||
checkbox: string;
|
||||
switch: string;
|
||||
};
|
||||
tabs: { label: string; items: Array<{ id: string; label: string; content: string }> };
|
||||
accordion: { items: Array<{ id: string; title: string; content: string }> };
|
||||
alert: { title: string; body: string };
|
||||
workflow: Array<{ id: string; ordinal: string; title: string; description: string }>;
|
||||
comparison: { beforeTitle: string; afterTitle: string; before: string[]; after: string[] };
|
||||
preview: {
|
||||
title: string;
|
||||
caption: string;
|
||||
illustrative: string;
|
||||
rows: Array<{ id: string; primary: string; secondary: string; status: string }>;
|
||||
};
|
||||
metric: { value: string; label: string; qualification: string; status: string };
|
||||
cta: { title: string; body: string; primary: string; unavailable: string };
|
||||
dialog: { open: string; title: string; description: string; close: string; content: string };
|
||||
menu: { label: string; first: string; second: string };
|
||||
}
|
||||
|
||||
const copy = {
|
||||
en: {
|
||||
developmentLabel: 'Development fixture, not production content',
|
||||
title: 'Core component system',
|
||||
body: 'A deterministic test surface for accessible, localized, theme-aware, and RTL-native components.',
|
||||
actions: {
|
||||
primary: 'Primary action',
|
||||
conversion: 'Create account',
|
||||
loading: 'Submitting',
|
||||
disabled: 'Unavailable action',
|
||||
},
|
||||
form: {
|
||||
label: 'Work email',
|
||||
supporting: 'Use a fictional address in this development fixture.',
|
||||
placeholder: 'name@fictional.invalid',
|
||||
error: 'Enter an address in the required format.',
|
||||
checkbox: 'Send a fictional confirmation',
|
||||
switch: 'Enable compact preview',
|
||||
},
|
||||
tabs: {
|
||||
label: 'Operations views',
|
||||
items: [
|
||||
{ id: 'reservations', label: 'Reservations', content: 'Reservation fixture content.' },
|
||||
{
|
||||
id: 'fleet',
|
||||
label: 'Fleet availability',
|
||||
content: 'Fleet fixture content with intentionally expanded wording.',
|
||||
},
|
||||
{ id: 'returns', label: 'Returns', content: 'Return inspection fixture content.' },
|
||||
],
|
||||
},
|
||||
accordion: {
|
||||
items: [
|
||||
{
|
||||
id: 'a1',
|
||||
title: 'How does the component system handle localization?',
|
||||
content:
|
||||
'Copy is passed as complete localized values rather than concatenated fragments.',
|
||||
},
|
||||
{
|
||||
id: 'a2',
|
||||
title: 'Does this submit data?',
|
||||
content: 'No. External submission remains blocked pending CRM and legal approval.',
|
||||
},
|
||||
],
|
||||
},
|
||||
alert: {
|
||||
title: 'Development-only fixture',
|
||||
body: 'This surface demonstrates behavior without publishing customer evidence or operational claims.',
|
||||
},
|
||||
workflow: [
|
||||
{
|
||||
id: 'reserve',
|
||||
ordinal: '1',
|
||||
title: 'Reservation',
|
||||
description: 'Capture an illustrative reservation request.',
|
||||
},
|
||||
{
|
||||
id: 'prepare',
|
||||
ordinal: '2',
|
||||
title: 'Preparation',
|
||||
description: 'Review a fictional vehicle readiness state.',
|
||||
},
|
||||
{
|
||||
id: 'handover',
|
||||
ordinal: '3',
|
||||
title: 'Handover',
|
||||
description: 'Present a controlled pickup checklist.',
|
||||
},
|
||||
{
|
||||
id: 'return',
|
||||
ordinal: '4',
|
||||
title: 'Return',
|
||||
description: 'Record an illustrative inspection outcome.',
|
||||
},
|
||||
],
|
||||
comparison: {
|
||||
beforeTitle: 'Fragmented operations',
|
||||
afterTitle: 'Connected workflow',
|
||||
before: ['Repeated manual entry', 'Scattered status checks', 'Unclear ownership'],
|
||||
after: ['One shared workflow', 'Visible state changes', 'Explicit responsibility'],
|
||||
},
|
||||
preview: {
|
||||
title: 'Fleet availability preview',
|
||||
caption: 'Illustrative interface fixture. It is not live operational data.',
|
||||
illustrative: 'Illustrative data',
|
||||
rows: [
|
||||
{ id: 'RDG-1042', primary: 'Compact vehicle', secondary: 'RDG-1042', status: 'Available' },
|
||||
{ id: 'RDG-2088', primary: 'Utility vehicle', secondary: 'RDG-2088', status: 'Preparing' },
|
||||
],
|
||||
},
|
||||
metric: {
|
||||
value: '24',
|
||||
label: 'Illustrative workflow checkpoints',
|
||||
qualification: 'Development fixture only. Not a public performance claim.',
|
||||
status: 'Research only',
|
||||
},
|
||||
cta: {
|
||||
title: 'CTA destination remains governed',
|
||||
body: 'The conversion treatment is reusable, while unresolved destinations stay disabled.',
|
||||
primary: 'Create account',
|
||||
unavailable: 'Destination pending approval',
|
||||
},
|
||||
dialog: {
|
||||
open: 'Open dialog',
|
||||
title: 'Accessible dialog fixture',
|
||||
description: 'Focus moves into this native modal and returns to the trigger.',
|
||||
close: 'Close dialog',
|
||||
content: 'No data is submitted from this component fixture.',
|
||||
},
|
||||
menu: { label: 'More actions', first: 'Review fixture', second: 'Archive fixture' },
|
||||
},
|
||||
fr: {
|
||||
developmentLabel: 'Exemple de développement, contenu non destiné à la production',
|
||||
title: 'Système de composants principal',
|
||||
body: 'Une surface de test déterministe pour des composants accessibles, localisés, adaptés aux thèmes et natifs en RTL.',
|
||||
actions: {
|
||||
primary: 'Action principale',
|
||||
conversion: 'Créer un compte',
|
||||
loading: 'Envoi en cours',
|
||||
disabled: 'Action indisponible',
|
||||
},
|
||||
form: {
|
||||
label: 'Adresse e-mail professionnelle',
|
||||
supporting: 'Utilisez une adresse fictive dans cet exemple de développement.',
|
||||
placeholder: 'nom@fictif.invalid',
|
||||
error: 'Saisissez une adresse au format requis.',
|
||||
checkbox: 'Envoyer une confirmation fictive',
|
||||
switch: 'Activer l’aperçu compact',
|
||||
},
|
||||
tabs: {
|
||||
label: 'Vues des opérations',
|
||||
items: [
|
||||
{ id: 'reservations', label: 'Réservations', content: 'Contenu fictif des réservations.' },
|
||||
{
|
||||
id: 'fleet',
|
||||
label: 'Disponibilité du parc automobile',
|
||||
content: 'Contenu fictif du parc avec un libellé volontairement plus long.',
|
||||
},
|
||||
{ id: 'returns', label: 'Retours', content: 'Contenu fictif de l’inspection au retour.' },
|
||||
],
|
||||
},
|
||||
accordion: {
|
||||
items: [
|
||||
{
|
||||
id: 'a1',
|
||||
title: 'Comment le système gère-t-il la localisation ?',
|
||||
content:
|
||||
'Le texte est transmis sous forme de valeurs localisées complètes, sans concaténation de fragments.',
|
||||
},
|
||||
{
|
||||
id: 'a2',
|
||||
title: 'Ces composants transmettent-ils des données ?',
|
||||
content:
|
||||
'Non. La transmission externe reste bloquée jusqu’à l’approbation du CRM et du contenu juridique.',
|
||||
},
|
||||
],
|
||||
},
|
||||
alert: {
|
||||
title: 'Exemple réservé au développement',
|
||||
body: 'Cette surface démontre les comportements sans publier de preuves client ni d’allégations opérationnelles.',
|
||||
},
|
||||
workflow: [
|
||||
{
|
||||
id: 'reserve',
|
||||
ordinal: '1',
|
||||
title: 'Réservation',
|
||||
description: 'Saisir une demande de réservation illustrative.',
|
||||
},
|
||||
{
|
||||
id: 'prepare',
|
||||
ordinal: '2',
|
||||
title: 'Préparation',
|
||||
description: 'Examiner un état fictif de préparation du véhicule.',
|
||||
},
|
||||
{
|
||||
id: 'handover',
|
||||
ordinal: '3',
|
||||
title: 'Remise du véhicule',
|
||||
description: 'Présenter une liste de contrôle maîtrisée.',
|
||||
},
|
||||
{
|
||||
id: 'return',
|
||||
ordinal: '4',
|
||||
title: 'Retour',
|
||||
description: 'Consigner un résultat d’inspection illustratif.',
|
||||
},
|
||||
],
|
||||
comparison: {
|
||||
beforeTitle: 'Opérations fragmentées',
|
||||
afterTitle: 'Flux de travail connecté',
|
||||
before: ['Saisie manuelle répétée', 'Vérifications dispersées', 'Responsabilités imprécises'],
|
||||
after: ['Un flux partagé', 'Des changements d’état visibles', 'Une responsabilité explicite'],
|
||||
},
|
||||
preview: {
|
||||
title: 'Aperçu de la disponibilité du parc',
|
||||
caption:
|
||||
'Exemple d’interface illustratif. Il ne s’agit pas de données opérationnelles en direct.',
|
||||
illustrative: 'Données illustratives',
|
||||
rows: [
|
||||
{
|
||||
id: 'RDG-1042',
|
||||
primary: 'Véhicule compact',
|
||||
secondary: 'RDG-1042',
|
||||
status: 'Disponible',
|
||||
},
|
||||
{
|
||||
id: 'RDG-2088',
|
||||
primary: 'Véhicule utilitaire',
|
||||
secondary: 'RDG-2088',
|
||||
status: 'En préparation',
|
||||
},
|
||||
],
|
||||
},
|
||||
metric: {
|
||||
value: '24',
|
||||
label: 'Points de contrôle illustratifs',
|
||||
qualification: 'Exemple de développement uniquement. Ce n’est pas une allégation publique.',
|
||||
status: 'Recherche uniquement',
|
||||
},
|
||||
cta: {
|
||||
title: 'La destination du CTA reste contrôlée',
|
||||
body: 'Le traitement de conversion est réutilisable, tandis que les destinations non résolues restent désactivées.',
|
||||
primary: 'Créer un compte',
|
||||
unavailable: 'Destination en attente d’approbation',
|
||||
},
|
||||
dialog: {
|
||||
open: 'Ouvrir la boîte de dialogue',
|
||||
title: 'Exemple de boîte de dialogue accessible',
|
||||
description: 'Le focus entre dans la fenêtre modale native puis revient au déclencheur.',
|
||||
close: 'Fermer la boîte de dialogue',
|
||||
content: 'Aucune donnée n’est transmise depuis cet exemple.',
|
||||
},
|
||||
menu: { label: 'Autres actions', first: 'Examiner l’exemple', second: 'Archiver l’exemple' },
|
||||
},
|
||||
ar: {
|
||||
developmentLabel: 'نموذج للتطوير وليس محتوى للإنتاج',
|
||||
title: 'نظام المكوّنات الأساسي',
|
||||
body: 'سطح اختبار ثابت لمكوّنات قابلة للوصول ومترجمة ومتوافقة مع السمات وداعمة لاتجاه الكتابة من اليمين إلى اليسار.',
|
||||
actions: {
|
||||
primary: 'إجراء أساسي',
|
||||
conversion: 'حجز عرض توضيحي',
|
||||
loading: 'جارٍ الإرسال',
|
||||
disabled: 'إجراء غير متاح',
|
||||
},
|
||||
form: {
|
||||
label: 'البريد الإلكتروني للعمل',
|
||||
supporting: 'استخدم عنواناً افتراضياً في نموذج التطوير هذا.',
|
||||
placeholder: 'name@fictional.invalid',
|
||||
error: 'أدخل عنواناً بالتنسيق المطلوب.',
|
||||
checkbox: 'إرسال تأكيد افتراضي',
|
||||
switch: 'تفعيل المعاينة المدمجة',
|
||||
},
|
||||
tabs: {
|
||||
label: 'عروض العمليات',
|
||||
items: [
|
||||
{ id: 'reservations', label: 'الحجوزات', content: 'محتوى افتراضي للحجوزات.' },
|
||||
{
|
||||
id: 'fleet',
|
||||
label: 'توفر أسطول المركبات',
|
||||
content: 'محتوى افتراضي للأسطول مع نص موسّع عمداً.',
|
||||
},
|
||||
{ id: 'returns', label: 'عمليات الإرجاع', content: 'محتوى افتراضي لفحص الإرجاع.' },
|
||||
],
|
||||
},
|
||||
accordion: {
|
||||
items: [
|
||||
{
|
||||
id: 'a1',
|
||||
title: 'كيف يتعامل نظام المكوّنات مع الترجمة؟',
|
||||
content: 'يُمرر النص كقيم مترجمة كاملة بدلاً من تجميع أجزاء الجمل.',
|
||||
},
|
||||
{
|
||||
id: 'a2',
|
||||
title: 'هل ترسل هذه المكوّنات بيانات؟',
|
||||
content:
|
||||
'لا. يظل الإرسال الخارجي محظوراً إلى حين اعتماد نظام إدارة علاقات العملاء والمحتوى القانوني.',
|
||||
},
|
||||
],
|
||||
},
|
||||
alert: {
|
||||
title: 'نموذج مخصص للتطوير',
|
||||
body: 'يوضح هذا السطح السلوك من دون نشر أدلة عملاء أو ادعاءات تشغيلية.',
|
||||
},
|
||||
workflow: [
|
||||
{ id: 'reserve', ordinal: '١', title: 'الحجز', description: 'تسجيل طلب حجز توضيحي.' },
|
||||
{
|
||||
id: 'prepare',
|
||||
ordinal: '٢',
|
||||
title: 'تجهيز المركبة',
|
||||
description: 'مراجعة حالة افتراضية لجاهزية المركبة.',
|
||||
},
|
||||
{
|
||||
id: 'handover',
|
||||
ordinal: '٣',
|
||||
title: 'التسليم',
|
||||
description: 'عرض قائمة تحقق مضبوطة للاستلام.',
|
||||
},
|
||||
{ id: 'return', ordinal: '٤', title: 'الإرجاع', description: 'تسجيل نتيجة فحص توضيحية.' },
|
||||
],
|
||||
comparison: {
|
||||
beforeTitle: 'عمليات مجزأة',
|
||||
afterTitle: 'سير عمل مترابط',
|
||||
before: ['إدخال يدوي متكرر', 'فحوصات حالة متفرقة', 'مسؤولية غير واضحة'],
|
||||
after: ['سير عمل مشترك', 'تغييرات حالة مرئية', 'مسؤولية محددة'],
|
||||
},
|
||||
preview: {
|
||||
title: 'معاينة توفر الأسطول',
|
||||
caption: 'نموذج واجهة توضيحي وليس بيانات تشغيلية مباشرة.',
|
||||
illustrative: 'بيانات توضيحية',
|
||||
rows: [
|
||||
{ id: 'RDG-1042', primary: 'مركبة مدمجة', secondary: 'RDG-1042', status: 'متاحة' },
|
||||
{ id: 'RDG-2088', primary: 'مركبة خدمية', secondary: 'RDG-2088', status: 'قيد التجهيز' },
|
||||
],
|
||||
},
|
||||
metric: {
|
||||
value: '٢٤',
|
||||
label: 'نقاط تحقق توضيحية لسير العمل',
|
||||
qualification: 'نموذج تطوير فقط وليس ادعاءً عاماً عن الأداء.',
|
||||
status: 'للبحث فقط',
|
||||
},
|
||||
cta: {
|
||||
title: 'تظل وجهة الدعوة إلى الإجراء خاضعة للحوكمة',
|
||||
body: 'يمكن إعادة استخدام نمط التحويل، بينما تبقى الوجهات غير المحسومة معطلة.',
|
||||
primary: 'حجز عرض توضيحي',
|
||||
unavailable: 'الوجهة بانتظار الاعتماد',
|
||||
},
|
||||
dialog: {
|
||||
open: 'فتح مربع الحوار',
|
||||
title: 'نموذج مربع حوار قابل للوصول',
|
||||
description: 'ينتقل التركيز إلى النافذة الأصلية ثم يعود إلى زر الفتح.',
|
||||
close: 'إغلاق مربع الحوار',
|
||||
content: 'لا تُرسل أي بيانات من نموذج المكوّن هذا.',
|
||||
},
|
||||
menu: { label: 'إجراءات إضافية', first: 'مراجعة النموذج', second: 'أرشفة النموذج' },
|
||||
},
|
||||
} satisfies Record<Locale, ComponentLabCopy>;
|
||||
|
||||
export function getComponentLabCopy(locale: Locale): ComponentLabCopy {
|
||||
return copy[locale];
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
import type { ApprovedIconName } from '@/components/foundation/Icon';
|
||||
import type { PreviewRow } from '@/components/marketing/ProductPreview';
|
||||
import type { HomepageMessages, ShellMessages } from '@/lib/localization/messages';
|
||||
import {
|
||||
fleetBandIds,
|
||||
pricingPlanIds,
|
||||
type FleetBandId,
|
||||
type PricingPlanId,
|
||||
} from '@/content/pricing-config';
|
||||
|
||||
export interface HomepageAction {
|
||||
label: string;
|
||||
disabledReason: string;
|
||||
}
|
||||
|
||||
export interface TitledDescription {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
icon?: ApprovedIconName;
|
||||
}
|
||||
|
||||
export interface HomepageWorkflowStep extends TitledDescription {
|
||||
ordinal: string;
|
||||
}
|
||||
|
||||
export interface HomepageFaqItem {
|
||||
id: string;
|
||||
title: string;
|
||||
body: string;
|
||||
}
|
||||
|
||||
export interface HomepagePricingFleetBand {
|
||||
id: FleetBandId;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface HomepagePricingPlan {
|
||||
id: PricingPlanId;
|
||||
name: string;
|
||||
audience: string;
|
||||
features: string[];
|
||||
cta: string;
|
||||
}
|
||||
|
||||
export interface HomepageContent {
|
||||
hero: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
primary: HomepageAction;
|
||||
secondary: HomepageAction;
|
||||
preview: {
|
||||
title: string;
|
||||
caption: string;
|
||||
illustrativeLabel: string;
|
||||
rows: PreviewRow[];
|
||||
};
|
||||
};
|
||||
trust: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
items: TitledDescription[];
|
||||
};
|
||||
comparison: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
beforeTitle: string;
|
||||
beforeItems: string[];
|
||||
afterTitle: string;
|
||||
afterItems: string[];
|
||||
};
|
||||
workflow: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
steps: HomepageWorkflowStep[];
|
||||
};
|
||||
roles: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
items: TitledDescription[];
|
||||
};
|
||||
modules: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
items: TitledDescription[];
|
||||
};
|
||||
results: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
metrics: TitledDescription[];
|
||||
methodTitle: string;
|
||||
method: string[];
|
||||
};
|
||||
integrations: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
items: string[];
|
||||
};
|
||||
security: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
checks: TitledDescription[];
|
||||
};
|
||||
pricing: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
fleetSelectorLabel: string;
|
||||
fleetBands: HomepagePricingFleetBand[];
|
||||
billingLegend: string;
|
||||
billingMonthly: string;
|
||||
billingAnnual: string;
|
||||
billingSavings: string;
|
||||
recommended: string;
|
||||
startingAt: string;
|
||||
perMonth: string;
|
||||
annualEquivalent: string;
|
||||
pricePending: string;
|
||||
customPrice: string;
|
||||
plans: HomepagePricingPlan[];
|
||||
basisTitle: string;
|
||||
basis: string[];
|
||||
modulesTitle: string;
|
||||
modules: string[];
|
||||
assurances: string[];
|
||||
notSure: string;
|
||||
compare: string;
|
||||
note: string;
|
||||
actionDisabledReason: string;
|
||||
};
|
||||
faq: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
items: HomepageFaqItem[];
|
||||
};
|
||||
final: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
primary: HomepageAction;
|
||||
secondary: HomepageAction;
|
||||
};
|
||||
}
|
||||
|
||||
const trustIcons: ApprovedIconName[] = ['calendar', 'car', 'check', 'settings'];
|
||||
const roleIcons: ApprovedIconName[] = ['settings', 'calendar', 'car', 'check'];
|
||||
const moduleIcons: ApprovedIconName[] = ['calendar', 'car', 'check', 'search', 'globe', 'settings'];
|
||||
const resultIcons: ApprovedIconName[] = ['calendar', 'settings', 'car', 'warning'];
|
||||
const securityIcons: ApprovedIconName[] = ['settings', 'search', 'globe', 'warning'];
|
||||
|
||||
function pair(value: readonly string[], context: string): { title: string; description: string } {
|
||||
const title = value[0];
|
||||
const description = value[1];
|
||||
if (title === undefined || description === undefined) {
|
||||
throw new Error(`${context} must contain a title and description.`);
|
||||
}
|
||||
return { title, description };
|
||||
}
|
||||
|
||||
function triple(
|
||||
value: readonly string[],
|
||||
context: string,
|
||||
): { ordinal: string; title: string; description: string } {
|
||||
const ordinal = value[0];
|
||||
const title = value[1];
|
||||
const description = value[2];
|
||||
if (ordinal === undefined || title === undefined || description === undefined) {
|
||||
throw new Error(`${context} must contain an ordinal, title, and description.`);
|
||||
}
|
||||
return { ordinal, title, description };
|
||||
}
|
||||
|
||||
function asFleetBandId(value: string, context: string): FleetBandId {
|
||||
if (!(fleetBandIds as readonly string[]).includes(value)) {
|
||||
throw new Error(`${context} contains an unknown fleet band ID: ${value}`);
|
||||
}
|
||||
return value as FleetBandId;
|
||||
}
|
||||
|
||||
function asPricingPlanId(value: string, context: string): PricingPlanId {
|
||||
if (!(pricingPlanIds as readonly string[]).includes(value)) {
|
||||
throw new Error(`${context} contains an unknown pricing plan ID: ${value}`);
|
||||
}
|
||||
return value as PricingPlanId;
|
||||
}
|
||||
|
||||
function mapPairs(
|
||||
values: readonly (readonly string[])[],
|
||||
prefix: string,
|
||||
icons: readonly ApprovedIconName[] = [],
|
||||
): TitledDescription[] {
|
||||
return values.map((value, index) => {
|
||||
const item = pair(value, `${prefix}[${index}]`);
|
||||
const icon = icons[index];
|
||||
return {
|
||||
id: `${prefix}-${index + 1}`,
|
||||
...item,
|
||||
...(icon ? { icon } : {}),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function buildHomepageContent(
|
||||
homepage: HomepageMessages,
|
||||
shell: ShellMessages,
|
||||
): HomepageContent {
|
||||
const pendingReason = shell.states.pendingBody;
|
||||
|
||||
return {
|
||||
hero: {
|
||||
eyebrow: homepage.hero.eyebrow,
|
||||
title: homepage.hero.title,
|
||||
body: homepage.hero.body,
|
||||
primary: { label: homepage.hero.primary, disabledReason: shell.header.demoUnavailable },
|
||||
secondary: { label: homepage.hero.secondary, disabledReason: pendingReason },
|
||||
preview: {
|
||||
title: homepage.preview.title,
|
||||
caption: homepage.hero.caption,
|
||||
illustrativeLabel: `${homepage.preview.today} · ${homepage.preview.branch}`,
|
||||
rows: [
|
||||
{
|
||||
id: 'preview-reservation-1',
|
||||
primary: `${homepage.preview.r1} · ${homepage.preview.taskAssign}`,
|
||||
secondary: homepage.preview.plate1,
|
||||
status: homepage.preview.statusReady,
|
||||
statusTone: 'success',
|
||||
},
|
||||
{
|
||||
id: 'preview-reservation-2',
|
||||
primary: `${homepage.preview.r2} · ${homepage.preview.taskInspect}`,
|
||||
secondary: homepage.preview.plate2,
|
||||
status: homepage.preview.statusDue,
|
||||
statusTone: 'warning',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
trust: {
|
||||
eyebrow: homepage.trust.eyebrow,
|
||||
title: homepage.trust.title,
|
||||
body: homepage.trust.body,
|
||||
items: mapPairs(homepage.trust.items, 'lifecycle', trustIcons),
|
||||
},
|
||||
comparison: {
|
||||
eyebrow: homepage.comparison.eyebrow,
|
||||
title: homepage.comparison.title,
|
||||
body: homepage.comparison.body,
|
||||
beforeTitle: homepage.comparison.beforeTitle,
|
||||
beforeItems: homepage.comparison.beforeItems,
|
||||
afterTitle: homepage.comparison.afterTitle,
|
||||
afterItems: homepage.comparison.afterItems,
|
||||
},
|
||||
workflow: {
|
||||
eyebrow: homepage.workflow.eyebrow,
|
||||
title: homepage.workflow.title,
|
||||
body: homepage.workflow.body,
|
||||
steps: homepage.workflow.steps.map((value, index) => ({
|
||||
id: `workflow-${index + 1}`,
|
||||
...triple(value, `workflow.steps[${index}]`),
|
||||
})),
|
||||
},
|
||||
roles: {
|
||||
eyebrow: homepage.roles.eyebrow,
|
||||
title: homepage.roles.title,
|
||||
items: mapPairs(homepage.roles.roles, 'role', roleIcons),
|
||||
},
|
||||
modules: {
|
||||
eyebrow: homepage.modules.eyebrow,
|
||||
title: homepage.modules.title,
|
||||
body: homepage.modules.body,
|
||||
items: mapPairs(homepage.modules.items, 'module', moduleIcons),
|
||||
},
|
||||
results: {
|
||||
eyebrow: homepage.results.eyebrow,
|
||||
title: homepage.results.title,
|
||||
body: homepage.results.body,
|
||||
metrics: mapPairs(homepage.results.metrics, 'measurement', resultIcons),
|
||||
methodTitle: homepage.results.methodTitle,
|
||||
method: homepage.results.method,
|
||||
},
|
||||
integrations: {
|
||||
eyebrow: homepage.integrations.eyebrow,
|
||||
title: homepage.integrations.title,
|
||||
body: homepage.integrations.body,
|
||||
items: homepage.integrations.items,
|
||||
},
|
||||
security: {
|
||||
eyebrow: homepage.security.eyebrow,
|
||||
title: homepage.security.title,
|
||||
body: homepage.security.body,
|
||||
checks: mapPairs(homepage.security.checks, 'security', securityIcons),
|
||||
},
|
||||
pricing: {
|
||||
eyebrow: homepage.pricing.eyebrow,
|
||||
title: homepage.pricing.title,
|
||||
body: homepage.pricing.body,
|
||||
fleetSelectorLabel: homepage.pricing.fleetSelectorLabel,
|
||||
fleetBands: homepage.pricing.fleetBands.map((item, index) => ({
|
||||
id: asFleetBandId(item.id, `pricing.fleetBands[${index}]`),
|
||||
label: item.label,
|
||||
})),
|
||||
billingLegend: homepage.pricing.billingLegend,
|
||||
billingMonthly: homepage.pricing.billingMonthly,
|
||||
billingAnnual: homepage.pricing.billingAnnual,
|
||||
billingSavings: homepage.pricing.billingSavings,
|
||||
recommended: homepage.pricing.recommended,
|
||||
startingAt: homepage.pricing.startingAt,
|
||||
perMonth: homepage.pricing.perMonth,
|
||||
annualEquivalent: homepage.pricing.annualEquivalent,
|
||||
pricePending: homepage.pricing.pricePending,
|
||||
customPrice: homepage.pricing.customPrice,
|
||||
plans: homepage.pricing.plans.map((plan, index) => ({
|
||||
id: asPricingPlanId(plan.id, `pricing.plans[${index}]`),
|
||||
name: plan.name,
|
||||
audience: plan.audience,
|
||||
features: plan.features,
|
||||
cta: plan.cta,
|
||||
})),
|
||||
basisTitle: homepage.pricing.basisTitle,
|
||||
basis: homepage.pricing.basis,
|
||||
modulesTitle: homepage.pricing.modulesTitle,
|
||||
modules: homepage.pricing.modules,
|
||||
assurances: homepage.pricing.assurances,
|
||||
notSure: homepage.pricing.notSure,
|
||||
compare: homepage.pricing.compare,
|
||||
note: homepage.pricing.note,
|
||||
actionDisabledReason: pendingReason,
|
||||
},
|
||||
faq: {
|
||||
eyebrow: homepage.faq.eyebrow,
|
||||
title: homepage.faq.title,
|
||||
items: homepage.faq.items.map((value, index) => {
|
||||
const item = pair(value, `faq.items[${index}]`);
|
||||
return { id: `faq-${index + 1}`, title: item.title, body: item.description };
|
||||
}),
|
||||
},
|
||||
final: {
|
||||
eyebrow: homepage.final.eyebrow,
|
||||
title: homepage.final.title,
|
||||
body: homepage.final.body,
|
||||
primary: { label: homepage.final.primary, disabledReason: shell.header.demoUnavailable },
|
||||
secondary: { label: homepage.final.secondary, disabledReason: pendingReason },
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,403 @@
|
||||
{
|
||||
"meta": {
|
||||
"langName": "العربية",
|
||||
"dir": "rtl",
|
||||
"title": "RentalDriveGo | تشغيل مترابط لتأجير السيارات",
|
||||
"description": "أدِر الحجوزات والمركبات والعقود والتسليم والإرجاع ضمن منصة تشغيل مترابطة."
|
||||
},
|
||||
"header": {
|
||||
"nav": [
|
||||
["product", "المنتج"],
|
||||
["workflow", "سير العمل"],
|
||||
["modules", "الوحدات"],
|
||||
["pricing", "التسعير"],
|
||||
["faq", "الأسئلة الشائعة"]
|
||||
],
|
||||
"login": "تسجيل الدخول",
|
||||
"demo": "أنشئ حسابًا",
|
||||
"menu": "فتح القائمة",
|
||||
"language": "اللغة",
|
||||
"theme": "المظهر",
|
||||
"light": "فاتح",
|
||||
"dark": "داكن",
|
||||
"system": "النظام"
|
||||
},
|
||||
"hero": {
|
||||
"eyebrow": "تشغيل تأجير السيارات ضمن نظام مترابط",
|
||||
"title": "أدِر كل عملية تأجير من الحجز حتى إعادة المركبة في نظام واحد.",
|
||||
"body": "اجمع الحجوزات والمركبات والعقود والتسليم والإرجاع في سجل تشغيلي واحد، كي يرى كل فريق ما يتطلب المتابعة بعد ذلك.",
|
||||
"primary": "أنشئ حسابًا للمنتج",
|
||||
"secondary": "شاهد جولة المنتج",
|
||||
"caption": "واجهة توضيحية للمنتج. يجب أن تستخدم الشاشات النهائية بيانات ولقطات معتمدة."
|
||||
},
|
||||
"trust": {
|
||||
"eyebrow": "تغطية تشغيلية",
|
||||
"title": "سير عمل واحد يغطي دورة التأجير كاملة.",
|
||||
"body": "حافظ على ترابط سياق العميل والمركبة والعقد والمهام مع تقدم عملية التأجير.",
|
||||
"items": [
|
||||
["الحجز", "سجّل الطلب والبيانات المطلوبة."],
|
||||
["المركبة", "تابع التوافر والجاهزية."],
|
||||
["العقد", "اجمع مهام التسليم والسجلات في موضع واحد."],
|
||||
["الإرجاع", "سجّل الحالة وأغلق أعمال المتابعة."]
|
||||
]
|
||||
},
|
||||
"comparison": {
|
||||
"eyebrow": "لماذا التغيير",
|
||||
"title": "استبدل عمليات التسليم المجزأة بسير تشغيلي مشترك.",
|
||||
"body": "تكلفة الأدوات المنفصلة لا تظهر دائمًا في عطل كبير، بل تتراكم يوميًا عبر تكرار الإدخال وضياع السياق وتأخر المتابعة.",
|
||||
"beforeTitle": "تشغيل مجزأ",
|
||||
"beforeItems": [
|
||||
"نسخ بيانات الحجز بين أدوات متعددة",
|
||||
"تأكيد حالة المركبة عبر الرسائل",
|
||||
"متابعة مهام العقد بالاعتماد على الذاكرة",
|
||||
"اكتشاف مشكلات الإرجاع بعد مغادرة العميل"
|
||||
],
|
||||
"afterTitle": "تشغيل مترابط",
|
||||
"afterItems": [
|
||||
"حالة حجز واحدة يراها الفريق",
|
||||
"ربط جاهزية المركبة بعملية التأجير",
|
||||
"إظهار متطلبات التسليم قبل تسليم المركبة",
|
||||
"إنشاء متابعة الإرجاع بينما لا يزال السياق واضحًا"
|
||||
]
|
||||
},
|
||||
"workflow": {
|
||||
"eyebrow": "سير عمل متكامل",
|
||||
"title": "حرّك عملية التأجير إلى الأمام من دون فقدان السياق.",
|
||||
"body": "توضح كل خطوة القرار والمسؤول والإجراء التالي بدل دفن التشغيل داخل قائمة عامة من الميزات.",
|
||||
"steps": [
|
||||
["01", "تسجيل الحجز", "سجّل التواريخ وبيانات السائق والمتطلبات والمصدر."],
|
||||
["02", "تخصيص مركبة جاهزة", "طابق التوافر مع الفئة والموقع وحالة الجاهزية."],
|
||||
["03", "إكمال التسليم", "تحقق من المستندات والفحص والعقد ومهام تسليم المركبة."],
|
||||
["04", "معالجة الإرجاع", "سجّل الحالة وأغلق الأعمال المفتوحة وأعد المركبة إلى التوافر."]
|
||||
]
|
||||
},
|
||||
"roles": {
|
||||
"eyebrow": "مصمم لفريق التشغيل",
|
||||
"title": "امنح كل دور السياق الذي يحتاجه من دون إنشاء نسخ متعددة من الحقيقة.",
|
||||
"roles": [
|
||||
["المالك أو المدير", "اطّلع على عبء العمل والاستثناءات والمؤشرات التشغيلية عبر النشاط."],
|
||||
["فريق الحجوزات", "حوّل الطلبات إلى حجوزات مؤكدة مع عدد أقل من عمليات التسليم."],
|
||||
["الأسطول والتشغيل", "اعرف المركبات المتاحة أو المحجوبة أو المستحقة أو التي تنتظر إجراءً."],
|
||||
["مكتب الاستقبال", "حضّر مهام التسليم والإرجاع قبل انتظار العميل."]
|
||||
]
|
||||
},
|
||||
"modules": {
|
||||
"eyebrow": "وحدات المنتج",
|
||||
"title": "نواة مترابطة منظّمة حول أعمال التأجير الفعلية.",
|
||||
"body": "توضح حدود الوحدات المسؤوليات، بينما تمنع السجلات المشتركة فوضى النسخ واللصق المعتادة.",
|
||||
"items": [
|
||||
["الحجوزات", "التوافر والتواريخ ومتطلبات العميل والحالة ضمن سير واحد."],
|
||||
["جاهزية الأسطول", "توافر المركبات والحجوزات التشغيلية وحالة الخدمة وسياق الموقع."],
|
||||
["عقود الإيجار", "متطلبات التسليم وحالة العقد والسجلات التشغيلية."],
|
||||
["فحص المركبة", "فحوص منظمة عند التسليم والإرجاع مع مهام متابعة."],
|
||||
["سجلات العملاء", "سجل التأجير وبيانات الاتصال المرتبطة بالعمل الجاري."],
|
||||
["التقارير التشغيلية", "تعريفات وعروض تشغيلية يمكن التحقق منها مقابل النشاط المصدر."]
|
||||
]
|
||||
},
|
||||
"results": {
|
||||
"eyebrow": "نتائج قابلة للقياس",
|
||||
"title": "قِس التغيير، لا الخطاب التسويقي.",
|
||||
"body": "لا ينبغي نشر أي نتيجة قبل اعتماد خط أساس حقيقي لعميل وفترة مقارنة وتعريف واضح للبيانات. لذلك تعرض هذه النسخة منهجية القياس بدل نسب مئوية مختلقة.",
|
||||
"metrics": [
|
||||
["زمن معالجة الحجز", "من استلام طلب صالح للعمل حتى تأكيد الحجز."],
|
||||
["زمن إعادة المركبة إلى الجاهزية", "من تسجيل الإرجاع حتى حالة جاهز للتأجير."],
|
||||
["معدل استخدام الأسطول", "مقارنة أيام التوافر بأيام التأجير وفق تعريف واحد معتمد."],
|
||||
["متابعة حالات التأخير", "عمليات التأجير المتأخرة المفتوحة مع مسؤول وإجراء تالٍ."]
|
||||
],
|
||||
"methodTitle": "المنهجية المطلوبة قبل نشر أي نتيجة",
|
||||
"method": [
|
||||
"سجّل خط أساس قبل الإطلاق باستخدام تعريفات المؤشرات نفسها.",
|
||||
"قارن مواقع وفئات أسطول وفترات تشغيل متكافئة.",
|
||||
"انشر حجم العينة والاستثناءات وفترة القياس.",
|
||||
"اربط كل نتيجة منشورة بسجل دليل معتمد."
|
||||
]
|
||||
},
|
||||
"integrations": {
|
||||
"eyebrow": "التكاملات",
|
||||
"title": "اربط الأنظمة التي يعتمد عليها تشغيلك حاليًا.",
|
||||
"body": "يُعتمد نطاق التكامل خلال مرحلة الاستكشاف ليتوافق مع سوقك وبنيتك الحالية وملكية البيانات. لا تُعرض أسماء شركاء قبل التحقق من توافر الموصل.",
|
||||
"items": [
|
||||
"المحاسبة والمالية",
|
||||
"المدفوعات ومبالغ الضمان",
|
||||
"الاتصال بالمركبات وبياناتها",
|
||||
"خدمات الهوية والمستندات",
|
||||
"البريد الإلكتروني والرسائل والإشعارات",
|
||||
"الموقع الإلكتروني وقنوات الحجز"
|
||||
]
|
||||
},
|
||||
"security": {
|
||||
"eyebrow": "الأمن والموثوقية",
|
||||
"title": "قيّم المنصة بالأدلة، لا بالشعارات.",
|
||||
"body": "لا تُنشر شهادات أو وعود بمستوى الخدمة قبل وجود وثائق معتمدة. أثناء التقييم، اطلب إجابات محددة حول الضوابط المهمة لنشاطك.",
|
||||
"checks": [
|
||||
["التحكم في الوصول", "الأدوار والصلاحيات وإجراءات المسؤول وإنهاء وصول المستخدم."],
|
||||
["قابلية التدقيق", "التغييرات المسجلة والقابلة للبحث والتصدير."],
|
||||
["معالجة البيانات", "الملكية والاحتفاظ والتصدير والحذف والجهات الفرعية."],
|
||||
["استمرارية العمل", "النسخ الاحتياطي والاستعادة والتواصل عند الحوادث والدعم."]
|
||||
]
|
||||
},
|
||||
"pricing": {
|
||||
"eyebrow": "تسعير بسيط وقابل للتوسع",
|
||||
"title": "تسعير مبني حول حجم أسطولك",
|
||||
"body": "اختر نطاق الأسطول لعرض الباقة الأنسب لتشغيلك. يمكن تفعيل الأسعار الابتدائية العامة من ملف إعداد تجاري واحد بعد الاعتماد المالي.",
|
||||
"fleetSelectorLabel": "الحجم التقريبي للأسطول النشط",
|
||||
"fleetBands": [
|
||||
{
|
||||
"id": "small",
|
||||
"label": "من 1 إلى 25 مركبة"
|
||||
},
|
||||
{
|
||||
"id": "growing",
|
||||
"label": "من 26 إلى 75 مركبة"
|
||||
},
|
||||
{
|
||||
"id": "scale",
|
||||
"label": "من 76 إلى 200 مركبة"
|
||||
},
|
||||
{
|
||||
"id": "enterprise",
|
||||
"label": "أكثر من 200 مركبة"
|
||||
}
|
||||
],
|
||||
"billingLegend": "دورة الفوترة",
|
||||
"billingMonthly": "شهري",
|
||||
"billingAnnual": "سنوي",
|
||||
"billingSavings": "وفّر",
|
||||
"recommended": "موصى بها",
|
||||
"startingAt": "يبدأ من",
|
||||
"perMonth": "/ شهريًا",
|
||||
"annualEquivalent": "ما يعادل شهريًا مع فوترة سنوية",
|
||||
"pricePending": "السعر الابتدائي بانتظار الاعتماد",
|
||||
"customPrice": "تسعير مخصص",
|
||||
"plans": [
|
||||
{
|
||||
"id": "launch",
|
||||
"name": "Launch",
|
||||
"audience": "لشركات التأجير المستقلة التي تستبدل العمل اليدوي المتفرق.",
|
||||
"features": [
|
||||
"الحجوزات والتوافر",
|
||||
"سجلات الأسطول والمركبات",
|
||||
"عقود التأجير",
|
||||
"سجلات العملاء",
|
||||
"التقارير التشغيلية الأساسية",
|
||||
"الدعم القياسي"
|
||||
],
|
||||
"cta": "احصل على تقدير لباقة Launch"
|
||||
},
|
||||
{
|
||||
"id": "growth",
|
||||
"name": "Growth",
|
||||
"audience": "للأساطيل النامية التي تدير مركبات وموظفين ومواقع أكثر.",
|
||||
"features": [
|
||||
"كل ما تتضمنه Launch",
|
||||
"دعم عدة مواقع",
|
||||
"مسارات الحجز عبر الإنترنت",
|
||||
"التوقيع الرقمي والودائع",
|
||||
"مسارات الصيانة",
|
||||
"تقارير وأتمتة متقدمة",
|
||||
"دعم ذو أولوية"
|
||||
],
|
||||
"cta": "احجز عرضًا لباقة Growth"
|
||||
},
|
||||
{
|
||||
"id": "enterprise",
|
||||
"name": "Enterprise",
|
||||
"audience": "للأساطيل الكبيرة والامتيازات والعمليات ذات احتياجات التكامل المعقدة.",
|
||||
"features": [
|
||||
"كل ما تتضمنه Growth",
|
||||
"تكاملات مخصصة ووصول إلى API",
|
||||
"أدوار وصلاحيات متقدمة",
|
||||
"تخطيط ترحيل البيانات",
|
||||
"تهيئة مخصصة",
|
||||
"خيارات اتفاقية مستوى الخدمة",
|
||||
"دعم مخصص للحساب"
|
||||
],
|
||||
"cta": "تحدث مع المبيعات"
|
||||
}
|
||||
],
|
||||
"basisTitle": "العوامل التي تؤثر في السعر النهائي",
|
||||
"basis": [
|
||||
"المركبات والمواقع النشطة",
|
||||
"الوحدات المختارة",
|
||||
"نطاق الترحيل والتهيئة",
|
||||
"متطلبات التكامل والدعم"
|
||||
],
|
||||
"modulesTitle": "أضف القدرات مع نمو أعمالك",
|
||||
"modules": [
|
||||
"موقع حجز عبر الإنترنت",
|
||||
"نظام GPS والتليماتية",
|
||||
"تكاملات المحاسبة",
|
||||
"معالجة المدفوعات",
|
||||
"الأتمتة بالذكاء الاصطناعي",
|
||||
"تحليلات متقدمة"
|
||||
],
|
||||
"assurances": [
|
||||
"لا توجد وحدات إلزامية مخفية",
|
||||
"ترقية مع نمو الأسطول",
|
||||
"تحديد نطاق التهيئة قبل الالتزام"
|
||||
],
|
||||
"notSure": "غير متأكد من الباقة المناسبة؟",
|
||||
"compare": "استكشف وحدات المنتج",
|
||||
"note": "تظل الأسعار مخفية حتى اعتماد النموذج التجاري. أضف المبالغ الشهرية المعتمدة في src/content/pricing-config.ts لنشر أسعار ابتدائية شفافة تلقائيًا."
|
||||
},
|
||||
"faq": {
|
||||
"eyebrow": "الأسئلة الشائعة",
|
||||
"title": "أسئلة ينبغي للمشتري طرحها قبل إنشاء الحساب.",
|
||||
"items": [
|
||||
[
|
||||
"هل RentalDriveGo مخصص فقط لشركات التأجير الكبيرة؟",
|
||||
"لا يزال السوق المستهدف وهيكل الباقات قيد الاعتماد. يجب أن يحدد إنشاء الحساب حجم الأسطول والمواقع وسير العمل والوحدات المطلوبة بدل افتراض أن إعدادًا واحدًا يناسب الجميع."
|
||||
],
|
||||
[
|
||||
"هل يمكننا الاحتفاظ بأنظمتنا الحالية؟",
|
||||
"تُراجع التكاملات المحتملة خلال الاستكشاف. يجب تأكيد توافر الموصل وملكية البيانات وجهد الترحيل والمزامنة المستمرة قبل تقديم أي وعد."
|
||||
],
|
||||
[
|
||||
"هل تدعم المنصة لغات متعددة؟",
|
||||
"يدعم الموقع ونظام التصميم المعتمد الإنجليزية والفرنسية والعربية. تستخدم العربية اتجاهًا حقيقيًا للمستند من اليمين إلى اليسار، لا مجرد محاذاة شكلية."
|
||||
],
|
||||
[
|
||||
"كيف يُحسب السعر؟",
|
||||
"النموذج التجاري قيد الاعتماد. حتى ذلك الحين، يجب أن يوضح كل عرض النطاق والوحدات والحدود والتهيئة والتكاملات والدعم."
|
||||
],
|
||||
[
|
||||
"ما الشهادات الأمنية المتوفرة؟",
|
||||
"لا تدّعي هذه النسخة وجود أي شهادة. يجب تقديم الأدلة الأمنية عبر وثائق معتمدة أثناء التقييم وعدم نشرها إلا بعد التحقق."
|
||||
],
|
||||
[
|
||||
"ماذا يحدث أثناء إنشاء الحساب؟",
|
||||
"ينبغي أن ترسم الجلسة سير عملك من الحجز حتى الإرجاع، وتعرض المسار المناسب في المنتج، وتحدد احتياجات التكامل، وتوثق أسئلة الملاءمة غير المحسومة."
|
||||
]
|
||||
]
|
||||
},
|
||||
"final": {
|
||||
"eyebrow": "شاهد سير العمل كاملًا",
|
||||
"title": "أحضر عملية تأجير حقيقية.",
|
||||
"body": "سنتتبع عمليات التسليم والاستثناءات والمعلومات التي يحتاجها فريقك من الحجز حتى إعادة المركبة.",
|
||||
"primary": "أنشئ حسابًا للمنتج",
|
||||
"secondary": "تواصل مع المبيعات"
|
||||
},
|
||||
"footer": {
|
||||
"tagline": "تشغيل مترابط لتأجير السيارات من الحجز حتى الإرجاع.",
|
||||
"groups": [
|
||||
[
|
||||
"المنتج",
|
||||
[
|
||||
["سير العمل", "#workflow"],
|
||||
["الوحدات", "#modules"],
|
||||
["التسعير", "#pricing"]
|
||||
]
|
||||
],
|
||||
[
|
||||
"الشركة",
|
||||
[
|
||||
["تواصل مع المبيعات", "#contact"],
|
||||
["أنشئ حسابًا", "#signup"]
|
||||
]
|
||||
],
|
||||
[
|
||||
"الحساب",
|
||||
[
|
||||
["تسجيل الدخول", "#login"],
|
||||
["اللغة", "#language"],
|
||||
["المظهر", "#theme"]
|
||||
]
|
||||
],
|
||||
[
|
||||
"قانوني",
|
||||
[
|
||||
["الخصوصية", "#!"],
|
||||
["الشروط", "#!"],
|
||||
["إمكانية الوصول", "#!"]
|
||||
]
|
||||
]
|
||||
],
|
||||
"copyright": "© 2026 RentalDriveGo. تظل الأدلة والادعاءات التجارية خاضعة للاعتماد."
|
||||
},
|
||||
"form": {
|
||||
"title": "أنشئ حسابًا للمنتج",
|
||||
"body": "أخبرنا كيف يعمل نشاط تأجير السيارات لديك. الحقول المطلوبة مميزة.",
|
||||
"name": "الاسم الكامل",
|
||||
"email": "البريد الإلكتروني للعمل",
|
||||
"company": "الشركة",
|
||||
"fleet": "الحجم التقريبي للأسطول",
|
||||
"market": "الدولة أو سوق التشغيل",
|
||||
"language": "اللغة المفضلة",
|
||||
"message": "ما الموضوع الذي ينبغي أن نركز عليه؟",
|
||||
"submit": "إنشاء حسابي",
|
||||
"privacy": "يتحقق وضع غير الإنتاج من سير العمل ثم يتخلص من الطلب. لا يُرسل أي عميل محتمل إلى نظام مبيعات. يظل نص الخصوصية والموافقة النهائي محظورًا إلى حين الاعتماد القانوني.",
|
||||
"close": "إغلاق",
|
||||
"required": "مطلوب",
|
||||
"emailError": "أدخل عنوان بريد إلكتروني صالحًا للعمل.",
|
||||
"requiredError": "هذا الحقل مطلوب.",
|
||||
"fleetOptions": [
|
||||
"اختر خيارًا",
|
||||
"من 1 إلى 9 مركبات",
|
||||
"من 10 إلى 24 مركبة",
|
||||
"من 25 إلى 49 مركبة",
|
||||
"من 50 إلى 99 مركبة",
|
||||
"من 100 إلى 249 مركبة",
|
||||
"250 مركبة أو أكثر"
|
||||
],
|
||||
"langOptions": ["English", "Français", "العربية"],
|
||||
"successTitle": "تم تسجيل إنشاء الحساب",
|
||||
"successBody": "اكتمل مسار الحجز في هذا النموذج الأولي. لم يُرسل أي طلب إلى نظام مبيعات فعلي.",
|
||||
"submitAnother": "إرسال طلب آخر",
|
||||
"submissionError": "تعذر على النموذج الأولي إكمال الطلب. ما زالت بياناتك متاحة. حاول مرة أخرى.",
|
||||
"errorSummary": "راجع الحقول المميزة ثم حاول مرة أخرى.",
|
||||
"optional": "اختياري",
|
||||
"messageHelp": "لا تُدرج معلومات شخصية حساسة أو معلومات دفع.",
|
||||
"messageCount": "حرفًا",
|
||||
"submitting": "جارٍ إرسال الطلب",
|
||||
"retry": "حاول مرة أخرى",
|
||||
"closeBlocked": "انتظر حتى يكتمل الإرسال الحالي قبل الإغلاق.",
|
||||
"invalidOptionError": "اختر خيارًا صالحًا.",
|
||||
"tooLongError": "هذا الإدخال طويل جدًا.",
|
||||
"configurationError": "إنشاء الحساب غير متاح لأن اعتماد تكامل الإنتاج لم يكتمل.",
|
||||
"timeoutError": "انتهت مهلة الطلب. لا تزال بياناتك متاحة؛ حاول مرة أخرى.",
|
||||
"duplicateError": "تمت معالجة هذا الطلب بالفعل. لم يُنشأ عميل محتمل ثانٍ.",
|
||||
"rateLimitError": "تم استلام عدد كبير جدًا من الطلبات. حاول مرة أخرى لاحقًا.",
|
||||
"genericError": "تعذر إكمال الطلب. لا تزال بياناتك متاحة.",
|
||||
"localModeLabel": "موصل محلي آمن",
|
||||
"marketDefault": "المغرب"
|
||||
},
|
||||
"preview": {
|
||||
"today": "اليوم",
|
||||
"branch": "الفرع المركزي",
|
||||
"title": "نظرة عامة على التشغيل",
|
||||
"reservations": "الحجوزات",
|
||||
"ready": "مركبات جاهزة",
|
||||
"attention": "تحتاج متابعة",
|
||||
"active": "عمليات تأجير نشطة",
|
||||
"r1": "تسليم الساعة 10:30",
|
||||
"r2": "إرجاع مستحق الساعة 14:00",
|
||||
"r3": "الفحص مطلوب",
|
||||
"vehicle": "المركبة",
|
||||
"customer": "العميل",
|
||||
"status": "الحالة",
|
||||
"task": "الإجراء التالي",
|
||||
"plate1": "ABC-2048",
|
||||
"plate2": "RNT-7712",
|
||||
"statusReady": "جاهزة",
|
||||
"statusDue": "مستحقة اليوم",
|
||||
"taskAssign": "تأكيد مستندات السائق",
|
||||
"taskInspect": "إكمال فحص الإرجاع"
|
||||
},
|
||||
"tour": {
|
||||
"title": "جولة في المنتج",
|
||||
"intro": "تابع عملية تأجير واحدة من الحجز حتى الإرجاع.",
|
||||
"back": "السابق",
|
||||
"next": "التالي",
|
||||
"finish": "إنهاء الجولة",
|
||||
"close": "إغلاق جولة المنتج",
|
||||
"step": "الخطوة",
|
||||
"of": "من"
|
||||
},
|
||||
"research": {
|
||||
"title": "وضع البحث",
|
||||
"events": "أحداث",
|
||||
"export": "تصدير الأحداث",
|
||||
"clear": "مسح",
|
||||
"close": "إغلاق"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"skipToContent": "الانتقال إلى المحتوى الرئيسي",
|
||||
"brandLabel": "الصفحة الرئيسية لـ RentalDriveGo",
|
||||
"foundationLabel": "أساس التطبيق",
|
||||
"header": {
|
||||
"navigationLabel": "التنقل الرئيسي",
|
||||
"controlsLabel": "عناصر التحكم في العرض واللغة",
|
||||
"menuOpen": "فتح قائمة التنقل",
|
||||
"menuClose": "إغلاق قائمة التنقل",
|
||||
"nav": {
|
||||
"product": "المنتج",
|
||||
"workflow": "سير العمل",
|
||||
"modules": "الوحدات",
|
||||
"pricing": "التسعير",
|
||||
"faq": "الأسئلة الشائعة"
|
||||
},
|
||||
"login": "تسجيل الدخول",
|
||||
"loginUnavailable": "وجهة تسجيل الدخول في انتظار الاعتماد",
|
||||
"demo": "أنشئ حسابًا",
|
||||
"demoUnavailable": "إنشاء الحساب في انتظار اعتماد التكامل"
|
||||
},
|
||||
"controls": {
|
||||
"language": "اللغة",
|
||||
"theme": "المظهر",
|
||||
"themeStatus": "تفضيل المظهر الحالي: {value}",
|
||||
"localeNames": {
|
||||
"en": "الإنجليزية",
|
||||
"fr": "الفرنسية",
|
||||
"ar": "العربية"
|
||||
},
|
||||
"themes": {
|
||||
"light": "فاتح",
|
||||
"dark": "داكن",
|
||||
"system": "النظام"
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"landmarkLabel": "تذييل الموقع",
|
||||
"tagline": "تشغيل مترابط لتأجير السيارات من الحجز حتى الإرجاع.",
|
||||
"groups": {
|
||||
"product": "المنتج",
|
||||
"company": "الشركة",
|
||||
"account": "الحساب",
|
||||
"legal": "قانوني"
|
||||
},
|
||||
"links": {
|
||||
"workflow": "سير العمل",
|
||||
"modules": "الوحدات",
|
||||
"pricing": "التسعير",
|
||||
"faq": "الأسئلة الشائعة",
|
||||
"contact": "تواصل مع المبيعات",
|
||||
"demo": "أنشئ حسابًا",
|
||||
"login": "تسجيل الدخول",
|
||||
"privacy": "الخصوصية",
|
||||
"terms": "الشروط",
|
||||
"accessibility": "إمكانية الوصول"
|
||||
},
|
||||
"pending": "في انتظار الاعتماد",
|
||||
"copyrightPrefix": "©",
|
||||
"releaseNotice": "يظل النشر العام متوقفًا حتى معالجة العوائق الموثقة."
|
||||
},
|
||||
"states": {
|
||||
"loadingTitle": "جارٍ التحميل",
|
||||
"loadingBody": "جارٍ تجهيز هيكل التطبيق.",
|
||||
"errorTitle": "حدث خطأ",
|
||||
"errorBody": "تعذر عرض الصفحة، ولم تُكشف أي تفاصيل تقنية.",
|
||||
"retry": "إعادة المحاولة",
|
||||
"notFoundTitle": "الصفحة غير موجودة",
|
||||
"notFoundBody": "لا يطابق هذا العنوان مسارًا محليًا معتمدًا.",
|
||||
"backHome": "العودة إلى الصفحة الرئيسية",
|
||||
"pendingTitle": "الوجهة غير متاحة",
|
||||
"pendingBody": "هذا المسار معرّف، لكن محتواه أو وجهته الإنتاجية ما زالت في انتظار الاعتماد."
|
||||
},
|
||||
"foundation": {
|
||||
"eyebrow": "أساس المرحلة 11",
|
||||
"title": "هيكل تطبيق محلي ومتوافق مع المظاهر",
|
||||
"body": "تثبت هذه النسخة الأسس المرئية وأسس التوجيه والاتجاه وإمكانية الوصول والبيانات الوصفية من دون الادعاء بأن الصفحة التسويقية الكاملة أصبحت جاهزة.",
|
||||
"readinessLabel": "مجالات الأساس المنفذة",
|
||||
"items": [
|
||||
["الرموز الدلالية", "تستهلك أنماط المكونات طبقة دلالية موثقة."],
|
||||
["سلوك المظهر", "تُحل تفضيلات المظهر الفاتح والداكن والنظام وتُحفظ."],
|
||||
["التوطين", "تُعرض الإنجليزية والفرنسية والعربية من مسارات مسبوقة باللغة."],
|
||||
["اتجاه المستند", "تُعرض العربية باتجاه حقيقي من اليمين إلى اليسار على مستوى المستند."],
|
||||
["إمكانية الوصول", "رابط التخطي والتركيز المرئي والمعالم وتقليل الحركة مدمجة."],
|
||||
["هيكل التطبيق", "يتوفر رأس متجاوب وتنقل للجوال وتذييل وحالات عامة."]
|
||||
],
|
||||
"deferredLabel": "وجهات الصفحة الرئيسية المؤجلة",
|
||||
"deferredBody": "ترتبط وجهة التنقل المعتمدة هذه ببيان المسارات، بينما يظل قسمها الإنتاجي خارج نطاق المرحلة 11."
|
||||
},
|
||||
"metadata": {
|
||||
"pendingTitle": "وجهة غير متاحة | RentalDriveGo",
|
||||
"pendingDescription": "وجهة RentalDriveGo المحلية هذه معرّفة، لكن نشرها في بيئة الإنتاج غير معتمد."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
{
|
||||
"meta": {
|
||||
"langName": "English",
|
||||
"dir": "ltr",
|
||||
"title": "RentalDriveGo | Connected rental-car operations",
|
||||
"description": "Run reservations, vehicles, agreements, handovers, and returns in one connected rental operations platform."
|
||||
},
|
||||
"header": {
|
||||
"nav": [
|
||||
["product", "Product"],
|
||||
["workflow", "Workflow"],
|
||||
["modules", "Modules"],
|
||||
["pricing", "Pricing"],
|
||||
["faq", "FAQ"]
|
||||
],
|
||||
"login": "Log in",
|
||||
"demo": "Create account",
|
||||
"menu": "Open menu",
|
||||
"language": "Language",
|
||||
"theme": "Theme",
|
||||
"light": "Light",
|
||||
"dark": "Dark",
|
||||
"system": "System"
|
||||
},
|
||||
"hero": {
|
||||
"eyebrow": "Rental operations, connected",
|
||||
"title": "Run every rental from reservation to return in one system.",
|
||||
"body": "Give reservations, fleet, agreements, handovers, and returns one operational record, so each team sees what needs attention next.",
|
||||
"primary": "Create account",
|
||||
"secondary": "Watch product tour",
|
||||
"caption": "Illustrative product interface. Final screens must use approved product data and captures."
|
||||
},
|
||||
"trust": {
|
||||
"eyebrow": "Operational coverage",
|
||||
"title": "One workflow across the rental lifecycle.",
|
||||
"body": "Keep the customer, vehicle, agreement, and task context connected as the rental moves forward.",
|
||||
"items": [
|
||||
["Reservation", "Capture the request and required details."],
|
||||
["Vehicle", "Track availability and readiness."],
|
||||
["Agreement", "Keep pickup tasks and records together."],
|
||||
["Return", "Record condition and close follow-up work."]
|
||||
]
|
||||
},
|
||||
"comparison": {
|
||||
"eyebrow": "Why change",
|
||||
"title": "Replace fragmented handoffs with a shared operating flow.",
|
||||
"body": "The cost of disconnected tools is rarely one dramatic failure. It is the daily accumulation of duplicate entry, missing context, and delayed follow-up.",
|
||||
"beforeTitle": "Fragmented operation",
|
||||
"beforeItems": [
|
||||
"Reservation details copied between tools",
|
||||
"Vehicle status confirmed through messages",
|
||||
"Agreement tasks tracked from memory",
|
||||
"Return issues discovered after the customer leaves"
|
||||
],
|
||||
"afterTitle": "Connected operation",
|
||||
"afterItems": [
|
||||
"One reservation status visible to the team",
|
||||
"Vehicle readiness attached to the rental",
|
||||
"Pickup requirements shown before handover",
|
||||
"Return follow-up created while context is fresh"
|
||||
]
|
||||
},
|
||||
"workflow": {
|
||||
"eyebrow": "End-to-end workflow",
|
||||
"title": "Move the rental forward without losing the thread.",
|
||||
"body": "Each step exposes the decision, owner, and next action instead of burying operations inside a generic feature list.",
|
||||
"steps": [
|
||||
["01", "Capture the reservation", "Record dates, driver details, requirements, and source."],
|
||||
["02", "Assign a ready vehicle", "Match availability with class, location, and readiness."],
|
||||
["03", "Complete pickup", "Confirm documents, inspection, agreement, and handover tasks."],
|
||||
["04", "Process the return", "Record condition, close open work, and release the vehicle."]
|
||||
]
|
||||
},
|
||||
"roles": {
|
||||
"eyebrow": "Built for the operating team",
|
||||
"title": "Give each role the context it needs, without creating separate versions of the truth.",
|
||||
"roles": [
|
||||
["Owner or manager", "See workload, exceptions, and operating signals across the business."],
|
||||
["Reservations team", "Move requests from inquiry to confirmed rental with fewer handoffs."],
|
||||
[
|
||||
"Fleet and operations",
|
||||
"Know which vehicles are available, blocked, due, or awaiting action."
|
||||
],
|
||||
["Front desk", "Prepare pickup and return tasks before the customer is waiting."]
|
||||
]
|
||||
},
|
||||
"modules": {
|
||||
"eyebrow": "Product modules",
|
||||
"title": "A connected core, organized around real rental work.",
|
||||
"body": "Module boundaries clarify responsibility while shared records prevent the usual copy-and-paste archaeology.",
|
||||
"items": [
|
||||
["Reservations", "Availability, dates, customer requirements, and status in one flow."],
|
||||
["Fleet readiness", "Vehicle availability, blocks, service state, and location context."],
|
||||
["Rental agreements", "Pickup requirements, agreement status, and operational records."],
|
||||
[
|
||||
"Vehicle inspections",
|
||||
"Structured pickup and return condition checks with follow-up tasks."
|
||||
],
|
||||
["Customer records", "Rental history and contact context attached to active work."],
|
||||
[
|
||||
"Operations reporting",
|
||||
"Definitions and operational views that can be validated against source activity."
|
||||
]
|
||||
]
|
||||
},
|
||||
"results": {
|
||||
"eyebrow": "Measured results",
|
||||
"title": "Measure the change, not the marketing.",
|
||||
"body": "No outcome claim should appear until a real customer baseline, comparison period, and data definition are approved. The production page therefore shows the measurement plan instead of fictional percentages.",
|
||||
"metrics": [
|
||||
["Reservation handling time", "From usable request to confirmed reservation."],
|
||||
["Vehicle turnaround time", "From return recorded to ready-for-rental status."],
|
||||
[
|
||||
"Fleet utilization",
|
||||
"Available rental days compared with rented days, using one approved definition."
|
||||
],
|
||||
["Overdue follow-up", "Open overdue rentals with an assigned owner and next action."]
|
||||
],
|
||||
"methodTitle": "Methodology required before publishing results",
|
||||
"method": [
|
||||
"Capture a pre-launch baseline using the same KPI definitions.",
|
||||
"Compare equivalent locations, fleet classes, and operating periods.",
|
||||
"Report sample size, exclusions, and measurement window.",
|
||||
"Link every public result to an approved evidence record."
|
||||
]
|
||||
},
|
||||
"integrations": {
|
||||
"eyebrow": "Integrations",
|
||||
"title": "Connect the systems your operation already depends on.",
|
||||
"body": "Integration scope is confirmed during discovery so the proposal reflects your market, current stack, and data ownership. Named partners are not shown until connector availability is verified.",
|
||||
"items": [
|
||||
"Accounting and finance",
|
||||
"Payments and deposits",
|
||||
"Telematics and vehicle data",
|
||||
"Identity and document services",
|
||||
"Email, SMS, and notifications",
|
||||
"Website and booking channels"
|
||||
]
|
||||
},
|
||||
"security": {
|
||||
"eyebrow": "Security and reliability",
|
||||
"title": "Evaluate the platform with evidence, not badges.",
|
||||
"body": "Certifications and service-level claims remain unpublished until approved documentation exists. During evaluation, request concrete answers for the controls that matter to your operation.",
|
||||
"checks": [
|
||||
["Access control", "Roles, permissions, administrator actions, and offboarding."],
|
||||
["Auditability", "Which changes are recorded, searchable, and exportable."],
|
||||
["Data handling", "Ownership, retention, export, deletion, and subprocessors."],
|
||||
["Continuity", "Backup, recovery, incident communication, and support process."]
|
||||
]
|
||||
},
|
||||
"pricing": {
|
||||
"eyebrow": "Simple, scalable pricing",
|
||||
"title": "Pricing built around your fleet",
|
||||
"body": "Choose a fleet range to see the plan designed for your operation. Public starting prices can be enabled from one commercial configuration file after finance approval.",
|
||||
"fleetSelectorLabel": "Approximate active fleet size",
|
||||
"fleetBands": [
|
||||
{
|
||||
"id": "small",
|
||||
"label": "1–25 vehicles"
|
||||
},
|
||||
{
|
||||
"id": "growing",
|
||||
"label": "26–75 vehicles"
|
||||
},
|
||||
{
|
||||
"id": "scale",
|
||||
"label": "76–200 vehicles"
|
||||
},
|
||||
{
|
||||
"id": "enterprise",
|
||||
"label": "200+ vehicles"
|
||||
}
|
||||
],
|
||||
"billingLegend": "Billing period",
|
||||
"billingMonthly": "Monthly",
|
||||
"billingAnnual": "Annual",
|
||||
"billingSavings": "Save",
|
||||
"recommended": "Recommended",
|
||||
"startingAt": "Starting at",
|
||||
"perMonth": "/ month",
|
||||
"annualEquivalent": "monthly equivalent, billed annually",
|
||||
"pricePending": "Starting price pending approval",
|
||||
"customPrice": "Custom pricing",
|
||||
"plans": [
|
||||
{
|
||||
"id": "launch",
|
||||
"name": "Launch",
|
||||
"audience": "For independent rental companies replacing fragmented manual work.",
|
||||
"features": [
|
||||
"Reservations and availability",
|
||||
"Fleet and vehicle records",
|
||||
"Rental agreements",
|
||||
"Customer records",
|
||||
"Basic operational reporting",
|
||||
"Standard support"
|
||||
],
|
||||
"cta": "Estimate Launch pricing"
|
||||
},
|
||||
{
|
||||
"id": "growth",
|
||||
"name": "Growth",
|
||||
"audience": "For growing fleets coordinating more vehicles, staff, and locations.",
|
||||
"features": [
|
||||
"Everything in Launch",
|
||||
"Multiple locations",
|
||||
"Online booking workflows",
|
||||
"Digital signatures and deposits",
|
||||
"Maintenance workflows",
|
||||
"Advanced reporting and automation",
|
||||
"Priority support"
|
||||
],
|
||||
"cta": "Book a Growth demo"
|
||||
},
|
||||
{
|
||||
"id": "enterprise",
|
||||
"name": "Enterprise",
|
||||
"audience": "For large fleets, franchises, and operations with complex integration needs.",
|
||||
"features": [
|
||||
"Everything in Growth",
|
||||
"Custom integrations and API access",
|
||||
"Advanced roles and permissions",
|
||||
"Data migration planning",
|
||||
"Custom onboarding",
|
||||
"Service-level agreement options",
|
||||
"Dedicated account support"
|
||||
],
|
||||
"cta": "Talk to sales"
|
||||
}
|
||||
],
|
||||
"basisTitle": "What affects the final price",
|
||||
"basis": [
|
||||
"Active vehicles and locations",
|
||||
"Selected modules",
|
||||
"Migration and onboarding scope",
|
||||
"Integration and support requirements"
|
||||
],
|
||||
"modulesTitle": "Add capabilities as you grow",
|
||||
"modules": [
|
||||
"Online booking website",
|
||||
"GPS and telematics",
|
||||
"Accounting integrations",
|
||||
"Payment processing",
|
||||
"AI automation",
|
||||
"Advanced analytics"
|
||||
],
|
||||
"assurances": [
|
||||
"No hidden mandatory modules",
|
||||
"Upgrade as your fleet grows",
|
||||
"Onboarding scope agreed before commitment"
|
||||
],
|
||||
"notSure": "Not sure which plan fits?",
|
||||
"compare": "Explore product modules",
|
||||
"note": "Prices remain hidden until the commercial model is approved. Add approved monthly amounts in src/content/pricing-config.ts to publish transparent starting prices automatically."
|
||||
},
|
||||
"faq": {
|
||||
"eyebrow": "FAQ",
|
||||
"title": "Questions buyers should ask before creating an account.",
|
||||
"items": [
|
||||
[
|
||||
"Is RentalDriveGo only for large rental companies?",
|
||||
"The final market and packaging are still being defined. The onboarding should qualify fleet size, locations, workflows, and required modules rather than pretend one setup fits everyone."
|
||||
],
|
||||
[
|
||||
"Can we keep our existing systems?",
|
||||
"Potential integrations are reviewed during discovery. Connector availability, data ownership, migration effort, and ongoing synchronization must be confirmed before they are promised."
|
||||
],
|
||||
[
|
||||
"Does the platform support multiple languages?",
|
||||
"The website and approved design system support English, French, and Arabic. Arabic uses true document-level right-to-left behavior rather than a mirrored-looking patch."
|
||||
],
|
||||
[
|
||||
"How is pricing calculated?",
|
||||
"The commercial model is pending approval. Until then, proposals should state the scope, included modules, limits, onboarding, integrations, and support explicitly."
|
||||
],
|
||||
[
|
||||
"What security certifications do you have?",
|
||||
"No certification is claimed in this baseline. Security evidence should be supplied through approved documentation during evaluation and published only after verification."
|
||||
],
|
||||
[
|
||||
"What happens during account creation?",
|
||||
"The session should map your current reservation-to-return flow, show the relevant product path, identify integration needs, and document unresolved fit questions."
|
||||
]
|
||||
]
|
||||
},
|
||||
"final": {
|
||||
"eyebrow": "See the full workflow",
|
||||
"title": "Bring one real rental process.",
|
||||
"body": "We will trace the handoffs, exceptions, and information your team needs from reservation through vehicle return.",
|
||||
"primary": "Create account",
|
||||
"secondary": "Contact sales"
|
||||
},
|
||||
"footer": {
|
||||
"tagline": "Connected rental-car operations from reservation to return.",
|
||||
"groups": [
|
||||
[
|
||||
"Product",
|
||||
[
|
||||
["Workflow", "#workflow"],
|
||||
["Modules", "#modules"],
|
||||
["Pricing", "#pricing"]
|
||||
]
|
||||
],
|
||||
[
|
||||
"Company",
|
||||
[
|
||||
["Contact sales", "#contact"],
|
||||
["Create account", "#signup"]
|
||||
]
|
||||
],
|
||||
[
|
||||
"Account",
|
||||
[
|
||||
["Log in", "#login"],
|
||||
["Language", "#language"],
|
||||
["Theme", "#theme"]
|
||||
]
|
||||
],
|
||||
[
|
||||
"Legal",
|
||||
[
|
||||
["Privacy", "#!"],
|
||||
["Terms", "#!"],
|
||||
["Accessibility", "#!"]
|
||||
]
|
||||
]
|
||||
],
|
||||
"copyright": "© 2026 RentalDriveGo. Evidence and commercial claims remain subject to approval."
|
||||
},
|
||||
"form": {
|
||||
"title": "Create account",
|
||||
"body": "Tell us how your rental operation works. Required fields are marked.",
|
||||
"name": "Full name",
|
||||
"email": "Work email",
|
||||
"company": "Company",
|
||||
"fleet": "Approximate fleet size",
|
||||
"market": "Country or operating market",
|
||||
"marketDefault": "Morocco",
|
||||
"language": "Preferred language",
|
||||
"message": "What should we focus on?",
|
||||
"submit": "Create my account",
|
||||
"privacy": "Non-production mode validates the workflow and discards the request. No lead is sent to a sales system. Final privacy and consent text remains blocked pending legal approval.",
|
||||
"close": "Close",
|
||||
"required": "Required",
|
||||
"emailError": "Enter a valid work email address.",
|
||||
"requiredError": "This field is required.",
|
||||
"fleetOptions": [
|
||||
"Select an option",
|
||||
"1–9 vehicles",
|
||||
"10–24 vehicles",
|
||||
"25–49 vehicles",
|
||||
"50–99 vehicles",
|
||||
"100–249 vehicles",
|
||||
"250 or more vehicles"
|
||||
],
|
||||
"langOptions": ["English", "Français", "العربية"],
|
||||
"successTitle": "Account creation recorded",
|
||||
"successBody": "This prototype has completed the booking flow. No request was sent to a real sales system.",
|
||||
"submitAnother": "Submit another request",
|
||||
"submissionError": "The prototype could not complete the request. Your entries are still available. Try again.",
|
||||
"errorSummary": "Review the highlighted fields and try again.",
|
||||
"optional": "Optional",
|
||||
"messageHelp": "Do not include sensitive personal or payment information.",
|
||||
"messageCount": "characters",
|
||||
"submitting": "Submitting request",
|
||||
"retry": "Try again",
|
||||
"closeBlocked": "Wait for the current submission to finish before closing.",
|
||||
"invalidOptionError": "Select a valid option.",
|
||||
"tooLongError": "This entry is too long.",
|
||||
"configurationError": "Account creation is not available because production integration approval is incomplete.",
|
||||
"timeoutError": "The request timed out. Your entries are still available; try again.",
|
||||
"duplicateError": "This request has already been processed. No second lead was created.",
|
||||
"rateLimitError": "Too many requests were received. Try again later.",
|
||||
"genericError": "The request could not be completed. Your entries are still available.",
|
||||
"localModeLabel": "Safe local adapter"
|
||||
},
|
||||
"preview": {
|
||||
"today": "Today",
|
||||
"branch": "Central branch",
|
||||
"title": "Operations overview",
|
||||
"reservations": "Reservations",
|
||||
"ready": "Vehicles ready",
|
||||
"attention": "Needs attention",
|
||||
"active": "Active rentals",
|
||||
"r1": "Pickup at 10:30",
|
||||
"r2": "Return due at 14:00",
|
||||
"r3": "Inspection required",
|
||||
"vehicle": "Vehicle",
|
||||
"customer": "Customer",
|
||||
"status": "Status",
|
||||
"task": "Next action",
|
||||
"plate1": "ABC-2048",
|
||||
"plate2": "RNT-7712",
|
||||
"statusReady": "Ready",
|
||||
"statusDue": "Due today",
|
||||
"taskAssign": "Confirm driver documents",
|
||||
"taskInspect": "Complete return inspection"
|
||||
},
|
||||
"tour": {
|
||||
"title": "Product tour",
|
||||
"intro": "Follow one rental from reservation through return.",
|
||||
"back": "Previous",
|
||||
"next": "Next",
|
||||
"finish": "Finish tour",
|
||||
"close": "Close product tour",
|
||||
"step": "Step",
|
||||
"of": "of"
|
||||
},
|
||||
"research": {
|
||||
"title": "Research mode",
|
||||
"events": "events",
|
||||
"export": "Export events",
|
||||
"clear": "Clear",
|
||||
"close": "Close"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"skipToContent": "Skip to main content",
|
||||
"brandLabel": "RentalDriveGo home",
|
||||
"foundationLabel": "Application foundation",
|
||||
"header": {
|
||||
"navigationLabel": "Primary navigation",
|
||||
"controlsLabel": "Display and language controls",
|
||||
"menuOpen": "Open navigation menu",
|
||||
"menuClose": "Close navigation menu",
|
||||
"nav": {
|
||||
"product": "Product",
|
||||
"workflow": "Workflow",
|
||||
"modules": "Modules",
|
||||
"pricing": "Pricing",
|
||||
"faq": "FAQ"
|
||||
},
|
||||
"login": "Log in",
|
||||
"loginUnavailable": "Login destination pending approval",
|
||||
"demo": "Create account",
|
||||
"demoUnavailable": "Account creation pending integration approval"
|
||||
},
|
||||
"controls": {
|
||||
"language": "Language",
|
||||
"theme": "Theme",
|
||||
"themeStatus": "Current theme preference: {value}",
|
||||
"localeNames": {
|
||||
"en": "English",
|
||||
"fr": "French",
|
||||
"ar": "Arabic"
|
||||
},
|
||||
"themes": {
|
||||
"light": "Light",
|
||||
"dark": "Dark",
|
||||
"system": "System"
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"landmarkLabel": "Site footer",
|
||||
"tagline": "Connected rental-car operations from reservation to return.",
|
||||
"groups": {
|
||||
"product": "Product",
|
||||
"company": "Company",
|
||||
"account": "Account",
|
||||
"legal": "Legal"
|
||||
},
|
||||
"links": {
|
||||
"workflow": "Workflow",
|
||||
"modules": "Modules",
|
||||
"pricing": "Pricing",
|
||||
"faq": "FAQ",
|
||||
"contact": "Contact sales",
|
||||
"demo": "Create account",
|
||||
"login": "Log in",
|
||||
"privacy": "Privacy",
|
||||
"terms": "Terms",
|
||||
"accessibility": "Accessibility"
|
||||
},
|
||||
"pending": "Pending approval",
|
||||
"copyrightPrefix": "©",
|
||||
"releaseNotice": "Public release remains gated until documented blockers are resolved."
|
||||
},
|
||||
"states": {
|
||||
"loadingTitle": "Loading",
|
||||
"loadingBody": "Preparing the application shell.",
|
||||
"errorTitle": "Something went wrong",
|
||||
"errorBody": "The page could not be displayed. Technical details were not exposed.",
|
||||
"retry": "Try again",
|
||||
"notFoundTitle": "Page not found",
|
||||
"notFoundBody": "This address does not match an approved localized route.",
|
||||
"backHome": "Return home",
|
||||
"pendingTitle": "Destination not available",
|
||||
"pendingBody": "This route is defined, but its production content or destination is still awaiting approval."
|
||||
},
|
||||
"foundation": {
|
||||
"eyebrow": "Phase 11 foundation",
|
||||
"title": "A localized, theme-aware application shell",
|
||||
"body": "This implementation proves the shared visual, routing, direction, accessibility, and metadata foundations without pretending the full marketing homepage already exists.",
|
||||
"readinessLabel": "Implemented foundation areas",
|
||||
"items": [
|
||||
["Semantic tokens", "Component styles consume a documented semantic layer."],
|
||||
["Theme behavior", "Light, dark, and system preferences resolve and persist."],
|
||||
["Localization", "English, French, and Arabic render from locale-prefixed routes."],
|
||||
["Directionality", "Arabic renders with document-level right-to-left direction."],
|
||||
[
|
||||
"Accessibility",
|
||||
"Skip navigation, focus treatment, landmarks, and reduced motion are built in."
|
||||
],
|
||||
[
|
||||
"Application shell",
|
||||
"Responsive header, mobile navigation, footer, and global states are available."
|
||||
]
|
||||
],
|
||||
"deferredLabel": "Deferred homepage destinations",
|
||||
"deferredBody": "This approved navigation destination is wired to the route manifest, while its production section remains outside Phase 11."
|
||||
},
|
||||
"metadata": {
|
||||
"pendingTitle": "Unavailable destination | RentalDriveGo",
|
||||
"pendingDescription": "This localized RentalDriveGo destination is defined but not approved for production publication."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
{
|
||||
"meta": {
|
||||
"langName": "Français",
|
||||
"dir": "ltr",
|
||||
"title": "RentalDriveGo | Opérations de location connectées",
|
||||
"description": "Pilotez les réservations, véhicules, contrats, remises et retours dans une plateforme connectée."
|
||||
},
|
||||
"header": {
|
||||
"nav": [
|
||||
["product", "Produit"],
|
||||
["workflow", "Parcours"],
|
||||
["modules", "Modules"],
|
||||
["pricing", "Tarifs"],
|
||||
["faq", "FAQ"]
|
||||
],
|
||||
"login": "Se connecter",
|
||||
"demo": "Créer un compte",
|
||||
"menu": "Ouvrir le menu",
|
||||
"language": "Langue",
|
||||
"theme": "Thème",
|
||||
"light": "Clair",
|
||||
"dark": "Sombre",
|
||||
"system": "Système"
|
||||
},
|
||||
"hero": {
|
||||
"eyebrow": "Opérations de location connectées",
|
||||
"title": "Pilotez chaque location, de la réservation au retour du véhicule, dans un seul système.",
|
||||
"body": "Reliez les réservations, le parc, les contrats, les remises et les retours dans un même dossier opérationnel, afin que chaque équipe sache quelle action vient ensuite.",
|
||||
"primary": "Créer un compte",
|
||||
"secondary": "Voir la visite du produit",
|
||||
"caption": "Interface produit illustrative. Les écrans définitifs doivent utiliser des données et captures approuvées."
|
||||
},
|
||||
"trust": {
|
||||
"eyebrow": "Couverture opérationnelle",
|
||||
"title": "Un même parcours pour tout le cycle de location.",
|
||||
"body": "Conservez le contexte du client, du véhicule, du contrat et des tâches au fil de la location.",
|
||||
"items": [
|
||||
["Réservation", "Saisir la demande et les informations nécessaires."],
|
||||
["Véhicule", "Suivre la disponibilité et l’état de préparation."],
|
||||
["Contrat", "Regrouper les tâches de départ et les documents."],
|
||||
["Retour", "Enregistrer l’état et clôturer les actions de suivi."]
|
||||
]
|
||||
},
|
||||
"comparison": {
|
||||
"eyebrow": "Pourquoi changer",
|
||||
"title": "Remplacez les transmissions fragmentées par un flux opérationnel partagé.",
|
||||
"body": "Le coût des outils déconnectés n’est pas toujours une panne spectaculaire. Il s’accumule dans les doubles saisies, le contexte perdu et les suivis tardifs.",
|
||||
"beforeTitle": "Fonctionnement fragmenté",
|
||||
"beforeItems": [
|
||||
"Informations de réservation recopiées entre plusieurs outils",
|
||||
"État du véhicule confirmé par messages",
|
||||
"Tâches contractuelles suivies de mémoire",
|
||||
"Problèmes de retour découverts après le départ du client"
|
||||
],
|
||||
"afterTitle": "Fonctionnement connecté",
|
||||
"afterItems": [
|
||||
"Un statut de réservation visible par l’équipe",
|
||||
"Préparation du véhicule rattachée à la location",
|
||||
"Exigences de départ affichées avant la remise",
|
||||
"Suivi du retour créé pendant que le contexte est encore précis"
|
||||
]
|
||||
},
|
||||
"workflow": {
|
||||
"eyebrow": "Parcours de bout en bout",
|
||||
"title": "Faites avancer la location sans perdre le fil.",
|
||||
"body": "Chaque étape met en évidence la décision, le responsable et l’action suivante, au lieu d’enfouir le travail dans une liste générique de fonctionnalités.",
|
||||
"steps": [
|
||||
[
|
||||
"01",
|
||||
"Saisir la réservation",
|
||||
"Enregistrer les dates, le conducteur, les exigences et la source."
|
||||
],
|
||||
[
|
||||
"02",
|
||||
"Affecter un véhicule prêt",
|
||||
"Faire correspondre disponibilité, catégorie, agence et état de préparation."
|
||||
],
|
||||
[
|
||||
"03",
|
||||
"Finaliser le départ",
|
||||
"Confirmer documents, inspection, contrat et tâches de remise."
|
||||
],
|
||||
[
|
||||
"04",
|
||||
"Traiter le retour",
|
||||
"Enregistrer l’état, clôturer les actions et libérer le véhicule."
|
||||
]
|
||||
]
|
||||
},
|
||||
"roles": {
|
||||
"eyebrow": "Conçu pour l’équipe opérationnelle",
|
||||
"title": "Donnez à chaque rôle le contexte utile, sans multiplier les versions de la vérité.",
|
||||
"roles": [
|
||||
["Direction ou responsable", "Voir la charge, les exceptions et les signaux d’exploitation."],
|
||||
[
|
||||
"Équipe réservations",
|
||||
"Faire passer les demandes vers une location confirmée avec moins de transmissions."
|
||||
],
|
||||
[
|
||||
"Parc et opérations",
|
||||
"Savoir quels véhicules sont disponibles, bloqués, attendus ou en attente d’action."
|
||||
],
|
||||
["Comptoir", "Préparer les tâches de départ et de retour avant que le client n’attende."]
|
||||
]
|
||||
},
|
||||
"modules": {
|
||||
"eyebrow": "Modules produit",
|
||||
"title": "Un socle connecté, organisé autour du travail réel de location.",
|
||||
"body": "Les modules clarifient les responsabilités, tandis que les dossiers partagés évitent l’archéologie du copier-coller.",
|
||||
"items": [
|
||||
["Réservations", "Disponibilités, dates, besoins du client et statut dans un même flux."],
|
||||
["Préparation du parc", "Disponibilité, blocages, état de service et contexte d’agence."],
|
||||
["Contrats de location", "Exigences de départ, état du contrat et dossiers opérationnels."],
|
||||
[
|
||||
"Inspections des véhicules",
|
||||
"Contrôles structurés au départ et au retour avec actions de suivi."
|
||||
],
|
||||
["Dossiers clients", "Historique de location et coordonnées rattachés au travail en cours."],
|
||||
["Rapports opérationnels", "Définitions et vues vérifiables par rapport à l’activité source."]
|
||||
]
|
||||
},
|
||||
"results": {
|
||||
"eyebrow": "Résultats mesurés",
|
||||
"title": "Mesurez le changement, pas le discours commercial.",
|
||||
"body": "Aucun résultat ne doit être publié sans référence client, période de comparaison et définition de données approuvées. Cette version présente donc la méthode plutôt que des pourcentages fictifs.",
|
||||
"metrics": [
|
||||
[
|
||||
"Temps de traitement des réservations",
|
||||
"De la demande exploitable à la réservation confirmée."
|
||||
],
|
||||
["Temps de remise en service", "Du retour enregistré au statut prêt à louer."],
|
||||
[
|
||||
"Taux d’utilisation du parc",
|
||||
"Jours louables comparés aux jours loués, selon une définition approuvée."
|
||||
],
|
||||
["Suivi des retards", "Locations en retard avec responsable et prochaine action."]
|
||||
],
|
||||
"methodTitle": "Méthode requise avant toute publication",
|
||||
"method": [
|
||||
"Établir une référence avant lancement avec les mêmes définitions de KPI.",
|
||||
"Comparer des agences, catégories de parc et périodes équivalentes.",
|
||||
"Publier la taille de l’échantillon, les exclusions et la fenêtre de mesure.",
|
||||
"Relier chaque résultat public à une preuve approuvée."
|
||||
]
|
||||
},
|
||||
"integrations": {
|
||||
"eyebrow": "Intégrations",
|
||||
"title": "Reliez les systèmes dont votre exploitation dépend déjà.",
|
||||
"body": "Le périmètre d’intégration est confirmé pendant la découverte afin de refléter votre marché, votre environnement actuel et la propriété des données. Aucun partenaire n’est nommé avant vérification du connecteur.",
|
||||
"items": [
|
||||
"Comptabilité et finance",
|
||||
"Paiements et dépôts",
|
||||
"Télématique et données véhicules",
|
||||
"Identité et documents",
|
||||
"E-mail, SMS et notifications",
|
||||
"Site web et canaux de réservation"
|
||||
]
|
||||
},
|
||||
"security": {
|
||||
"eyebrow": "Sécurité et fiabilité",
|
||||
"title": "Évaluez la plateforme avec des preuves, pas avec des badges.",
|
||||
"body": "Aucune certification ni promesse de niveau de service n’est publiée sans documentation approuvée. Pendant l’évaluation, demandez des réponses concrètes sur les contrôles utiles à votre activité.",
|
||||
"checks": [
|
||||
["Contrôle des accès", "Rôles, autorisations, actions administrateur et départs."],
|
||||
["Traçabilité", "Modifications enregistrées, recherchables et exportables."],
|
||||
["Gestion des données", "Propriété, conservation, export, suppression et sous-traitants."],
|
||||
["Continuité", "Sauvegarde, reprise, communication d’incident et support."]
|
||||
]
|
||||
},
|
||||
"pricing": {
|
||||
"eyebrow": "Tarification simple et évolutive",
|
||||
"title": "Des tarifs adaptés à votre parc",
|
||||
"body": "Sélectionnez une taille de parc pour voir l’offre conçue pour votre exploitation. Les prix publics de départ peuvent être activés depuis un seul fichier de configuration après validation financière.",
|
||||
"fleetSelectorLabel": "Taille approximative du parc actif",
|
||||
"fleetBands": [
|
||||
{
|
||||
"id": "small",
|
||||
"label": "1 à 25 véhicules"
|
||||
},
|
||||
{
|
||||
"id": "growing",
|
||||
"label": "26 à 75 véhicules"
|
||||
},
|
||||
{
|
||||
"id": "scale",
|
||||
"label": "76 à 200 véhicules"
|
||||
},
|
||||
{
|
||||
"id": "enterprise",
|
||||
"label": "Plus de 200 véhicules"
|
||||
}
|
||||
],
|
||||
"billingLegend": "Période de facturation",
|
||||
"billingMonthly": "Mensuelle",
|
||||
"billingAnnual": "Annuelle",
|
||||
"billingSavings": "Économisez",
|
||||
"recommended": "Recommandé",
|
||||
"startingAt": "À partir de",
|
||||
"perMonth": "/ mois",
|
||||
"annualEquivalent": "équivalent mensuel, facturé annuellement",
|
||||
"pricePending": "Prix de départ en attente de validation",
|
||||
"customPrice": "Tarification personnalisée",
|
||||
"plans": [
|
||||
{
|
||||
"id": "launch",
|
||||
"name": "Launch",
|
||||
"audience": "Pour les loueurs indépendants qui remplacent des processus manuels dispersés.",
|
||||
"features": [
|
||||
"Réservations et disponibilités",
|
||||
"Dossiers du parc et des véhicules",
|
||||
"Contrats de location",
|
||||
"Dossiers clients",
|
||||
"Rapports opérationnels essentiels",
|
||||
"Support standard"
|
||||
],
|
||||
"cta": "Estimer le tarif Launch"
|
||||
},
|
||||
{
|
||||
"id": "growth",
|
||||
"name": "Growth",
|
||||
"audience": "Pour les parcs en croissance qui coordonnent davantage de véhicules, d’équipes et d’agences.",
|
||||
"features": [
|
||||
"Tout ce qui est inclus dans Launch",
|
||||
"Plusieurs agences",
|
||||
"Parcours de réservation en ligne",
|
||||
"Signatures numériques et dépôts",
|
||||
"Flux de maintenance",
|
||||
"Rapports avancés et automatisation",
|
||||
"Support prioritaire"
|
||||
],
|
||||
"cta": "Réserver une démo Growth"
|
||||
},
|
||||
{
|
||||
"id": "enterprise",
|
||||
"name": "Enterprise",
|
||||
"audience": "Pour les grands parcs, franchises et exploitations ayant des besoins d’intégration complexes.",
|
||||
"features": [
|
||||
"Tout ce qui est inclus dans Growth",
|
||||
"Intégrations personnalisées et accès API",
|
||||
"Rôles et autorisations avancés",
|
||||
"Planification de la migration des données",
|
||||
"Accompagnement personnalisé",
|
||||
"Options d’accord de niveau de service",
|
||||
"Suivi de compte dédié"
|
||||
],
|
||||
"cta": "Parler à l’équipe commerciale"
|
||||
}
|
||||
],
|
||||
"basisTitle": "Ce qui influence le prix final",
|
||||
"basis": [
|
||||
"Véhicules et agences actifs",
|
||||
"Modules sélectionnés",
|
||||
"Périmètre de migration et de démarrage",
|
||||
"Besoins d’intégration et de support"
|
||||
],
|
||||
"modulesTitle": "Ajoutez des capacités au rythme de votre croissance",
|
||||
"modules": [
|
||||
"Site de réservation en ligne",
|
||||
"GPS et télématique",
|
||||
"Intégrations comptables",
|
||||
"Traitement des paiements",
|
||||
"Automatisation par IA",
|
||||
"Analyses avancées"
|
||||
],
|
||||
"assurances": [
|
||||
"Aucun module obligatoire caché",
|
||||
"Évolution avec la croissance du parc",
|
||||
"Périmètre de démarrage convenu avant engagement"
|
||||
],
|
||||
"notSure": "Vous ne savez pas quelle offre choisir ?",
|
||||
"compare": "Explorer les modules du produit",
|
||||
"note": "Les prix restent masqués tant que le modèle commercial n’est pas approuvé. Ajoutez les montants mensuels validés dans src/content/pricing-config.ts pour publier automatiquement des prix de départ transparents."
|
||||
},
|
||||
"faq": {
|
||||
"eyebrow": "FAQ",
|
||||
"title": "Les questions à poser avant de créer un compte.",
|
||||
"items": [
|
||||
[
|
||||
"RentalDriveGo est-il réservé aux grands loueurs ?",
|
||||
"Le marché cible et les offres finales restent à définir. La création de compte doit qualifier la taille du parc, les agences, les flux et les modules nécessaires au lieu de prétendre qu’une configuration convient à tous."
|
||||
],
|
||||
[
|
||||
"Pouvons-nous conserver nos systèmes actuels ?",
|
||||
"Les intégrations possibles sont examinées pendant la découverte. La disponibilité du connecteur, la propriété des données, l’effort de migration et la synchronisation doivent être confirmés avant toute promesse."
|
||||
],
|
||||
[
|
||||
"La plateforme prend-elle en charge plusieurs langues ?",
|
||||
"Le site et le système de design approuvé prennent en charge l’anglais, le français et l’arabe. L’arabe utilise une vraie direction de document de droite à gauche."
|
||||
],
|
||||
[
|
||||
"Comment les tarifs sont-ils calculés ?",
|
||||
"Le modèle commercial est en attente d’approbation. En attendant, toute proposition doit préciser le périmètre, les modules, les limites, l’accompagnement, les intégrations et le support."
|
||||
],
|
||||
[
|
||||
"Quelles certifications de sécurité possédez-vous ?",
|
||||
"Aucune certification n’est revendiquée dans cette version. Les preuves de sécurité doivent être fournies pendant l’évaluation puis publiées uniquement après vérification."
|
||||
],
|
||||
[
|
||||
"Que se passe-t-il pendant la création du compte ?",
|
||||
"La session doit cartographier votre flux de la réservation au retour, montrer le parcours produit pertinent, identifier les intégrations et consigner les questions de compatibilité non résolues."
|
||||
]
|
||||
]
|
||||
},
|
||||
"final": {
|
||||
"eyebrow": "Voir le parcours complet",
|
||||
"title": "Apportez un processus de location réel ",
|
||||
"body": "Nous suivrons les transmissions, les exceptions et les informations dont votre équipe a besoin de la réservation au retour du véhicule.",
|
||||
"primary": "Créer un compte",
|
||||
"secondary": "Contacter le service commercial"
|
||||
},
|
||||
"footer": {
|
||||
"tagline": "Des opérations de location connectées, de la réservation au retour.",
|
||||
"groups": [
|
||||
[
|
||||
"Produit",
|
||||
[
|
||||
["Parcours", "#workflow"],
|
||||
["Modules", "#modules"],
|
||||
["Tarifs", "#pricing"]
|
||||
]
|
||||
],
|
||||
[
|
||||
"Entreprise",
|
||||
[
|
||||
["Contacter le service commercial", "#contact"],
|
||||
["Créer un compte", "#signup"]
|
||||
]
|
||||
],
|
||||
[
|
||||
"Compte",
|
||||
[
|
||||
["Se connecter", "#login"],
|
||||
["Langue", "#language"],
|
||||
["Thème", "#theme"]
|
||||
]
|
||||
],
|
||||
[
|
||||
"Mentions légales",
|
||||
[
|
||||
["Confidentialité", "#!"],
|
||||
["Conditions", "#!"],
|
||||
["Accessibilité", "#!"]
|
||||
]
|
||||
]
|
||||
],
|
||||
"copyright": "© 2026 RentalDriveGo. Les preuves et conditions commerciales restent soumises à approbation."
|
||||
},
|
||||
"form": {
|
||||
"title": "Créer un compte du produit",
|
||||
"body": "Décrivez-nous le fonctionnement de votre activité de location. Les champs obligatoires sont signalés.",
|
||||
"name": "Nom complet",
|
||||
"email": "Adresse e-mail professionnelle",
|
||||
"company": "Entreprise",
|
||||
"fleet": "Taille approximative du parc",
|
||||
"market": "Pays ou marché d’exploitation",
|
||||
"language": "Langue souhaitée",
|
||||
"message": "Sur quoi devons-nous nous concentrer ?",
|
||||
"submit": "Créer mon compte",
|
||||
"privacy": "Le mode hors production valide le parcours puis supprime la demande. Aucun prospect n’est envoyé à un système commercial. Le texte final de confidentialité et de consentement reste bloqué dans l’attente de l’approbation juridique.",
|
||||
"close": "Fermer",
|
||||
"required": "Obligatoire",
|
||||
"emailError": "Saisissez une adresse e-mail professionnelle valide.",
|
||||
"requiredError": "Ce champ est obligatoire.",
|
||||
"fleetOptions": [
|
||||
"Sélectionnez une option",
|
||||
"1 à 9 véhicules",
|
||||
"10 à 24 véhicules",
|
||||
"25 à 49 véhicules",
|
||||
"50 à 99 véhicules",
|
||||
"100 à 249 véhicules",
|
||||
"250 véhicules ou plus"
|
||||
],
|
||||
"langOptions": ["English", "Français", "العربية"],
|
||||
"successTitle": "Création de compte enregistrée",
|
||||
"successBody": "Ce prototype a terminé le parcours de réservation. Aucune demande n’a été envoyée à un véritable système commercial.",
|
||||
"submitAnother": "Envoyer une autre demande",
|
||||
"submissionError": "Le prototype n’a pas pu terminer la demande. Vos informations sont conservées. Réessayez.",
|
||||
"errorSummary": "Vérifiez les champs signalés, puis réessayez.",
|
||||
"optional": "Facultatif",
|
||||
"messageHelp": "N’incluez aucune donnée personnelle sensible ni information de paiement.",
|
||||
"messageCount": "caractères",
|
||||
"submitting": "Envoi de la demande",
|
||||
"retry": "Réessayer",
|
||||
"closeBlocked": "Attendez la fin de l’envoi en cours avant de fermer.",
|
||||
"invalidOptionError": "Sélectionnez une option valide.",
|
||||
"tooLongError": "Cette saisie est trop longue.",
|
||||
"configurationError": "L’envoi de création de compte est indisponible car l’intégration de production n’est pas encore approuvée.",
|
||||
"timeoutError": "La demande a expiré. Vos informations sont toujours disponibles ; réessayez.",
|
||||
"duplicateError": "Cette demande a déjà été traitée. Aucun deuxième prospect n’a été créé.",
|
||||
"rateLimitError": "Trop de demandes ont été reçues. Réessayez plus tard.",
|
||||
"genericError": "La demande n’a pas pu être terminée. Vos informations sont toujours disponibles.",
|
||||
"localModeLabel": "Adaptateur local sécurisé",
|
||||
"marketDefault": "Maroc"
|
||||
},
|
||||
"preview": {
|
||||
"today": "Aujourd’hui",
|
||||
"branch": "Agence centrale",
|
||||
"title": "Vue des opérations",
|
||||
"reservations": "Réservations",
|
||||
"ready": "Véhicules prêts",
|
||||
"attention": "À traiter",
|
||||
"active": "Locations actives",
|
||||
"r1": "Départ à 10 h 30",
|
||||
"r2": "Retour prévu à 14 h 00",
|
||||
"r3": "Inspection requise",
|
||||
"vehicle": "Véhicule",
|
||||
"customer": "Client",
|
||||
"status": "Statut",
|
||||
"task": "Prochaine action",
|
||||
"plate1": "ABC-2048",
|
||||
"plate2": "RNT-7712",
|
||||
"statusReady": "Prêt",
|
||||
"statusDue": "Prévu aujourd’hui",
|
||||
"taskAssign": "Confirmer les documents du conducteur",
|
||||
"taskInspect": "Finaliser l’inspection de retour"
|
||||
},
|
||||
"tour": {
|
||||
"title": "Visite du produit",
|
||||
"intro": "Suivez une location de la réservation au retour.",
|
||||
"back": "Précédent",
|
||||
"next": "Suivant",
|
||||
"finish": "Terminer la visite",
|
||||
"close": "Fermer la visite du produit",
|
||||
"step": "Étape",
|
||||
"of": "sur"
|
||||
},
|
||||
"research": {
|
||||
"title": "Mode recherche",
|
||||
"events": "événements",
|
||||
"export": "Exporter les événements",
|
||||
"clear": "Effacer",
|
||||
"close": "Fermer"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"skipToContent": "Aller au contenu principal",
|
||||
"brandLabel": "Accueil RentalDriveGo",
|
||||
"foundationLabel": "Fondation de l’application",
|
||||
"header": {
|
||||
"navigationLabel": "Navigation principale",
|
||||
"controlsLabel": "Commandes d’affichage et de langue",
|
||||
"menuOpen": "Ouvrir le menu de navigation",
|
||||
"menuClose": "Fermer le menu de navigation",
|
||||
"nav": {
|
||||
"product": "Produit",
|
||||
"workflow": "Parcours",
|
||||
"modules": "Modules",
|
||||
"pricing": "Tarifs",
|
||||
"faq": "FAQ"
|
||||
},
|
||||
"login": "Se connecter",
|
||||
"loginUnavailable": "Destination de connexion en attente d’approbation",
|
||||
"demo": "Créer un compte",
|
||||
"demoUnavailable": "Création de compte en attente d’approbation de l’intégration"
|
||||
},
|
||||
"controls": {
|
||||
"language": "Langue",
|
||||
"theme": "Thème",
|
||||
"themeStatus": "Préférence de thème actuelle : {value}",
|
||||
"localeNames": {
|
||||
"en": "Anglais",
|
||||
"fr": "Français",
|
||||
"ar": "Arabe"
|
||||
},
|
||||
"themes": {
|
||||
"light": "Clair",
|
||||
"dark": "Sombre",
|
||||
"system": "Système"
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"landmarkLabel": "Pied de page du site",
|
||||
"tagline": "Des opérations de location connectées, de la réservation au retour.",
|
||||
"groups": {
|
||||
"product": "Produit",
|
||||
"company": "Entreprise",
|
||||
"account": "Compte",
|
||||
"legal": "Mentions légales"
|
||||
},
|
||||
"links": {
|
||||
"workflow": "Parcours",
|
||||
"modules": "Modules",
|
||||
"pricing": "Tarifs",
|
||||
"faq": "FAQ",
|
||||
"contact": "Contacter le service commercial",
|
||||
"demo": "Créer un compte",
|
||||
"login": "Se connecter",
|
||||
"privacy": "Confidentialité",
|
||||
"terms": "Conditions",
|
||||
"accessibility": "Accessibilité"
|
||||
},
|
||||
"pending": "En attente d’approbation",
|
||||
"copyrightPrefix": "©",
|
||||
"releaseNotice": "La publication reste bloquée jusqu’à la résolution des obstacles documentés."
|
||||
},
|
||||
"states": {
|
||||
"loadingTitle": "Chargement",
|
||||
"loadingBody": "Préparation de la structure de l’application.",
|
||||
"errorTitle": "Une erreur s’est produite",
|
||||
"errorBody": "La page n’a pas pu être affichée. Aucun détail technique n’a été exposé.",
|
||||
"retry": "Réessayer",
|
||||
"notFoundTitle": "Page introuvable",
|
||||
"notFoundBody": "Cette adresse ne correspond à aucune route localisée approuvée.",
|
||||
"backHome": "Retour à l’accueil",
|
||||
"pendingTitle": "Destination indisponible",
|
||||
"pendingBody": "Cette route est définie, mais son contenu ou sa destination de production attend encore une approbation."
|
||||
},
|
||||
"foundation": {
|
||||
"eyebrow": "Fondation de la phase 11",
|
||||
"title": "Une structure localisée compatible avec les thèmes",
|
||||
"body": "Cette implémentation valide les fondations visuelles, de routage, de direction, d’accessibilité et de métadonnées sans prétendre que la page marketing complète existe déjà.",
|
||||
"readinessLabel": "Fondations implémentées",
|
||||
"items": [
|
||||
[
|
||||
"Jetons sémantiques",
|
||||
"Les styles des composants consomment une couche sémantique documentée."
|
||||
],
|
||||
[
|
||||
"Gestion des thèmes",
|
||||
"Les préférences claire, sombre et système sont résolues et conservées."
|
||||
],
|
||||
[
|
||||
"Localisation",
|
||||
"L’anglais, le français et l’arabe utilisent des routes préfixées par la langue."
|
||||
],
|
||||
[
|
||||
"Direction",
|
||||
"L’arabe utilise une direction droite-à-gauche au niveau du document."
|
||||
],
|
||||
[
|
||||
"Accessibilité",
|
||||
"Le lien d’évitement, le focus visible, les repères et le mouvement réduit sont intégrés."
|
||||
],
|
||||
[
|
||||
"Structure de l’application",
|
||||
"L’en-tête adaptatif, la navigation mobile, le pied de page et les états globaux sont disponibles."
|
||||
]
|
||||
],
|
||||
"deferredLabel": "Destinations de la page d’accueil différées",
|
||||
"deferredBody": "Cette destination de navigation approuvée est reliée au manifeste de routes, tandis que sa section de production reste hors du périmètre de la phase 11."
|
||||
},
|
||||
"metadata": {
|
||||
"pendingTitle": "Destination indisponible | RentalDriveGo",
|
||||
"pendingDescription": "Cette destination localisée de RentalDriveGo est définie, mais sa publication en production n’est pas approuvée."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
export const fleetBandIds = ['small', 'growing', 'scale', 'enterprise'] as const;
|
||||
export type FleetBandId = (typeof fleetBandIds)[number];
|
||||
|
||||
export const pricingPlanIds = ['launch', 'growth', 'enterprise'] as const;
|
||||
export type PricingPlanId = (typeof pricingPlanIds)[number];
|
||||
|
||||
export type BillingPeriod = 'monthly' | 'annual';
|
||||
|
||||
export interface PricingCommercialConfig {
|
||||
currency: string;
|
||||
annualDiscountPercent: number | null;
|
||||
publicPricesApproved: boolean;
|
||||
monthlyPrices: Record<PricingPlanId, Record<FleetBandId, number | null>>;
|
||||
recommendedPlanByFleetBand: Record<FleetBandId, PricingPlanId>;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the only file that should contain commercial pricing numbers.
|
||||
* Keep publicPricesApproved=false until finance and product approve the amounts,
|
||||
* included limits, onboarding policy, taxes, and annual billing terms.
|
||||
*/
|
||||
export const pricingCommercialConfig: PricingCommercialConfig = {
|
||||
currency: 'USD',
|
||||
annualDiscountPercent: null,
|
||||
publicPricesApproved: false,
|
||||
monthlyPrices: {
|
||||
launch: {
|
||||
small: null,
|
||||
growing: null,
|
||||
scale: null,
|
||||
enterprise: null,
|
||||
},
|
||||
growth: {
|
||||
small: null,
|
||||
growing: null,
|
||||
scale: null,
|
||||
enterprise: null,
|
||||
},
|
||||
enterprise: {
|
||||
small: null,
|
||||
growing: null,
|
||||
scale: null,
|
||||
enterprise: null,
|
||||
},
|
||||
},
|
||||
recommendedPlanByFleetBand: {
|
||||
small: 'launch',
|
||||
growing: 'growth',
|
||||
scale: 'growth',
|
||||
enterprise: 'enterprise',
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user