Driver onboarding now photographs the licence, ID card and vehicle
registration and reads the credential fields off them, plus a camera-only
profile selfie riders check the arriving driver against. Adds in-app chat
and WebRTC calls, push-backed ride offers, ratings, cancellation and
payment sheets, settlement, and the owner dashboard endpoints behind them.
Camera permission on Android:
- Declare CAMERA and READ_MEDIA_IMAGES in the manifest. expo-image-picker's
own plugin never declares CAMERA, and Android denies a request for an
undeclared permission instantly and silently — no dialog is ever shown,
which is indistinguishable from the app not asking at all.
- Handle canAskAgain: once Android stops showing the dialog, repeating why
we need it is a dead end, so offer Open Settings instead (lib/capture-
permission.ts), matching what the location flow already did.
Session: a 401 on a request that carried a token now ends the session
instead of being reinterpreted per-screen — driver-home had been reading it
as "this user has no driver profile" and showing an onboarding form to an
already-onboarded driver. Requests without a token are exempt so a failed
sign-in doesn't sign you out, and the notification is latched per token so
concurrent polls tear the session down once. (root) gains the auth guard
that turns that into the sign-in screen; app/index.tsx only guarded the way
in, leaving a session that ended mid-screen with nowhere to go.
Also ignore .uploads/ — it holds driver licence, ID and vehicle scans plus
profile photos, which are personal data and must not be committed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
837 lines
32 KiB
TypeScript
837 lines
32 KiB
TypeScript
export const fr = {
|
|
common: {
|
|
cancel: "Annuler",
|
|
continue: "Continuer",
|
|
back: "Retour",
|
|
retry: "Réessayer",
|
|
loading: "Chargement…",
|
|
saving: "Enregistrement…",
|
|
error: "Erreur",
|
|
save: "Enregistrer",
|
|
or: "Ou",
|
|
browseHome: "Accueil",
|
|
backHome: "Retour à l'accueil",
|
|
openSettings: "Ouvrir les réglages",
|
|
yourLocation: "Votre position",
|
|
},
|
|
|
|
onboarding: {
|
|
skip: "Passer",
|
|
next: "Suivant",
|
|
getStarted: "Commencer",
|
|
slide1: {
|
|
title: "La course parfaite à un geste près !",
|
|
desc: "Votre voyage commence avec Waseel. Trouvez votre course idéale sans effort.",
|
|
},
|
|
slide2: {
|
|
title: "La meilleure voiture avec Waseel",
|
|
desc: "Découvrez la facilité de trouver votre course idéale avec Waseel",
|
|
},
|
|
slide3: {
|
|
title: "Votre course, à votre façon. C'est parti !",
|
|
desc: "Saisissez votre destination, détendez-vous, et laissez-nous faire le reste.",
|
|
},
|
|
},
|
|
|
|
auth: {
|
|
signIn: {
|
|
welcome: "Bienvenue 👋",
|
|
email: "E-mail",
|
|
emailPlaceholder: "karim@email.com",
|
|
password: "Mot de passe",
|
|
passwordPlaceholder: "••••••••",
|
|
keepSignedIn: "Rester connecté",
|
|
signingIn: "Connexion…",
|
|
signInBtn: "Se connecter",
|
|
signInGoogle: "Se connecter avec Google",
|
|
forgotPassword: "Mot de passe oublié ?",
|
|
noAccount: "Pas encore de compte ? ",
|
|
signUpLink: "S'inscrire",
|
|
carAlt: "Voiture",
|
|
reset: {
|
|
title: "Réinitialiser le mot de passe",
|
|
requestBody:
|
|
"Saisissez votre e-mail et nous vous enverrons un code à 6 chiffres.",
|
|
emailPlaceholder: "karim@email.com",
|
|
sending: "Envoi…",
|
|
sendCode: "Envoyer le code",
|
|
newPassTitle: "Saisir le nouveau mot de passe",
|
|
resetBody: "Nous avons envoyé un code à {email}",
|
|
devBanner:
|
|
"L'envoi d'e-mails n'est pas configuré sur ce serveur. Votre code est ",
|
|
newPassLabel: "Nouveau mot de passe",
|
|
newPasswordPlaceholder: "••••••••",
|
|
resetting: "Réinitialisation…",
|
|
resetBtn: "Réinitialiser le mot de passe",
|
|
},
|
|
alertMissingTitle: "Informations manquantes",
|
|
alertMissingBody: "Saisissez votre e-mail et votre mot de passe.",
|
|
alertErrorTitle: "Erreur",
|
|
alertErrorFallback: "Connexion impossible. Réessayez.",
|
|
errEmail: "Saisissez votre adresse e-mail.",
|
|
errCode: "Saisissez le code à 6 chiffres.",
|
|
errPassword: "Le mot de passe doit comporter au moins 8 caractères.",
|
|
errReset: "Réinitialisation impossible. Réessayez.",
|
|
},
|
|
signUp: {
|
|
createAccount: "Créez votre compte",
|
|
howUse: "Comment utiliserez-vous Waseel ?",
|
|
riderTitle: "J'ai besoin d'une course",
|
|
riderDesc: "Réservez des courses et arrivez à destination",
|
|
driverTitle: "Je veux conduire",
|
|
driverDesc:
|
|
"Proposez des courses et gagnez de l'argent avec votre voiture",
|
|
carAlt: "Voiture",
|
|
name: "Nom",
|
|
namePlaceholder: "Karim Haddad",
|
|
email: "E-mail",
|
|
emailPlaceholder: "karim@email.com",
|
|
phoneOptional: "Téléphone (facultatif)",
|
|
phonePlaceholder: "70 123 456",
|
|
password: "Mot de passe",
|
|
passwordPlaceholder: "••••••••",
|
|
signUpBtn: "S'inscrire",
|
|
signUpGoogle: "S'inscrire avec Google",
|
|
haveAccount: "Vous avez déjà un compte ? ",
|
|
signInLink: "Se connecter",
|
|
verify: {
|
|
title: "Vérification",
|
|
body: "Nous avons envoyé un code de vérification à {email}",
|
|
devBanner:
|
|
"L'envoi d'e-mails n'est pas configuré sur ce serveur. Votre code de vérification est ",
|
|
verifying: "Vérification…",
|
|
verifyBtn: "Vérifier l'e-mail",
|
|
checkAlt: "Vérifié",
|
|
},
|
|
verified: {
|
|
title: "Vérifié",
|
|
body: "Votre compte a été vérifié avec succès.",
|
|
},
|
|
alertMissingTitle: "Informations manquantes",
|
|
alertMissingBody:
|
|
"Veuillez renseigner votre nom, votre e-mail et votre mot de passe.",
|
|
alertPhoneTitle: "Numéro de téléphone invalide",
|
|
alertPhoneBody: "Saisissez un numéro libanais valide, ex. 70 123 456.",
|
|
alertErrorTitle: "Erreur",
|
|
alertErrorFallback: "Création du compte impossible.",
|
|
errCode: "Saisissez le code à 6 chiffres.",
|
|
errVerify: "Échec de la vérification. Réessayez.",
|
|
},
|
|
role: {
|
|
title: "Comment utiliserez-vous Waseel ?",
|
|
subtitle: "Vous pouvez changer cela plus tard en contactant le support.",
|
|
riderTitle: "Je suis un passager",
|
|
riderDesc: "Réservez des courses et déplacez-vous au Liban",
|
|
driverTitle: "Je suis un chauffeur",
|
|
driverDesc: "Proposez des courses et gagnez de l'argent",
|
|
alertErrorTitle: "Erreur",
|
|
alertErrorBody: "Enregistrement du choix impossible. Réessayez.",
|
|
},
|
|
},
|
|
|
|
home: {
|
|
welcome: "Bienvenue {name} 👋",
|
|
logoutAlt: "Déconnexion",
|
|
currentLocation: "Votre position actuelle",
|
|
findingLocation: "Localisation en cours…",
|
|
whatNeed: "De quoi avez-vous besoin ?",
|
|
recentRides: "Courses récentes",
|
|
noRecent: "Aucune course récente.",
|
|
noRecentAlt: "Aucune course récente",
|
|
activeRideWithDriver: "{name} arrive",
|
|
rateLastRide: "Comment s'est passée votre dernière course ?",
|
|
rate: "Noter",
|
|
},
|
|
|
|
rides: {
|
|
allRides: "Toutes les courses",
|
|
noRecent: "Aucune course récente.",
|
|
noRecentAlt: "Aucune course récente",
|
|
},
|
|
|
|
tabs: {
|
|
home: "Accueil",
|
|
rides: "Courses",
|
|
chat: "Discussion",
|
|
profile: "Profil",
|
|
settings: "Réglages",
|
|
},
|
|
|
|
chat: {
|
|
title: "Discussion",
|
|
messageAlt: "message",
|
|
noMessages: "Pas encore de messages",
|
|
startConversation:
|
|
"La conversation s'ouvre avec votre chauffeur une fois la course attribuée.",
|
|
inputPlaceholder: "Message…",
|
|
send: "Envoyer",
|
|
loadError: "Impossible de charger les messages. Tirez pour réessayer.",
|
|
sendError: "Impossible d'envoyer le message. Réessayez.",
|
|
cannotMessage: "Cette course n'est plus active.",
|
|
call: "Appeler",
|
|
},
|
|
|
|
call: {
|
|
incoming: "Appel entrant",
|
|
outgoing: "Appel en cours…",
|
|
connecting: "Connexion…",
|
|
inCall: "En appel",
|
|
ended: "Appel terminé",
|
|
missed: "Appel manqué",
|
|
declined: "Appel refusé",
|
|
failed: "Échec de l'appel",
|
|
unavailable: "Aucune course active à appeler.",
|
|
accept: "Accepter",
|
|
decline: "Refuser",
|
|
end: "Terminer l'appel",
|
|
mute: "Muet",
|
|
unmute: "Activer le micro",
|
|
speaker: "Haut-parleur",
|
|
speakerOff: "Haut-parleur off",
|
|
cancel: "Annuler",
|
|
connectingWith: "Connexion à {name}…",
|
|
micDeniedTitle: "Microphone bloqué",
|
|
micDeniedBody:
|
|
"Waseel a besoin du microphone pour passer des appels. Activez-le dans les réglages.",
|
|
audioFailed: "Impossible de démarrer l'audio. Réessayez.",
|
|
},
|
|
|
|
profile: {
|
|
title: "Mon profil",
|
|
avatarAlt: "Votre avatar",
|
|
firstName: "Prénom",
|
|
firstNamePlaceholder: "Votre prénom",
|
|
lastName: "Nom",
|
|
lastNamePlaceholder: "Votre nom",
|
|
email: "E-mail",
|
|
emailPlaceholder: "Votre adresse e-mail",
|
|
},
|
|
|
|
adjustPin: {
|
|
pickupLabel: "Point de départ",
|
|
destinationLabel: "Point de dépose",
|
|
locating: "Localisation en cours…",
|
|
hint: "Faites glisser la carte pour placer le repère exactement où vous voulez.",
|
|
confirmPickup: "Confirmer le départ",
|
|
confirmDestination: "Confirmer la dépose",
|
|
recenter: "Aller à ma position",
|
|
},
|
|
|
|
findRide: {
|
|
adjustOnMap: "Placer sur la carte",
|
|
title: "Course",
|
|
from: "De",
|
|
to: "À",
|
|
findNow: "Rechercher",
|
|
service: "Type de course",
|
|
nAvailable: "{n} à proximité",
|
|
estimatedFare: "Tarif estimé",
|
|
setBothPoints: "Indiquez un départ et une destination",
|
|
payLaterHint:
|
|
"Les chauffeurs proches verront votre demande. Vous choisissez qui vous prend, et payez ensuite.",
|
|
sending: "Envoi de votre demande…",
|
|
},
|
|
|
|
confirmRide: {
|
|
noDriversInRadius: "Aucun chauffeur {service} dans un rayon de {km} km",
|
|
tryInstead: "Disponible près de vous maintenant :",
|
|
searchingRadius: "Recherche dans un rayon de {km} km…",
|
|
title: "Demander une course",
|
|
yourTrip: "Votre trajet",
|
|
pickup: "Départ",
|
|
destination: "Destination",
|
|
tripTime: "Durée {time}",
|
|
paymentMethod: "Mode de paiement",
|
|
cash: "💵 Espèces",
|
|
card: "💳 Carte",
|
|
fareDisplay: "${fare}",
|
|
lbpEstimate: "≈ {lbp}",
|
|
noDrivers: "Aucun chauffeur {service} en ligne pour l'instant",
|
|
findingDrivers: "Recherche de chauffeurs à proximité…",
|
|
driversNearby: {
|
|
one: "1 chauffeur à proximité",
|
|
other: "{n} chauffeurs à proximité",
|
|
zero: "Aucun chauffeur à proximité",
|
|
},
|
|
withinRadius: "Dans un rayon de {km} km",
|
|
nearestDriver: "Chauffeur le plus proche ≈ {eta} min",
|
|
requesting: "Demande en cours…",
|
|
noDriversOnline: "Aucun chauffeur en ligne",
|
|
requestCash: "Demander une course · Payer en espèces",
|
|
requestCard: "Demander une course · Payer par carte",
|
|
alertMissingRouteTitle: "Itinéraire manquant",
|
|
alertMissingRouteBody:
|
|
"Veuillez d'abord définir un départ et une destination.",
|
|
alertNoEstimateTitle: "Pas d'estimation",
|
|
alertNoEstimateBody: "Nous n'avons pas pu estimer ce tarif. Réessayez.",
|
|
alertErrorTitle: "Erreur",
|
|
alertErrorFallback:
|
|
"Une erreur est survenue lors de la réservation. Réessayez.",
|
|
alertPayCardTitle: "Payer par carte",
|
|
alertPayCardBody: "Votre carte sera débitée de ${fare}.",
|
|
alertInProgressTitle: "Course déjà en cours",
|
|
alertInProgressBody:
|
|
"Vous avez une course en cours. Terminez-la ou annulez-la avant d'en réserver une autre.",
|
|
viewRide: "Voir la course",
|
|
},
|
|
|
|
bookRide: {
|
|
status: {
|
|
requested: "Recherche de votre chauffeur…",
|
|
choosing: "Choisissez votre chauffeur",
|
|
accepted: "Chauffeur assigné — en route vers vous",
|
|
enRoute: "Course en cours",
|
|
completed: "Vous êtes arrivé !",
|
|
cancelled: "Course annulée",
|
|
arrived: "Votre chauffeur est arrivé",
|
|
expired: "Aucun chauffeur disponible",
|
|
},
|
|
rideNotFound: "Course introuvable.",
|
|
couldNotLoad: "Chargement de cette course impossible.",
|
|
backHome: "Retour à l'accueil",
|
|
matchingDriver:
|
|
"Nous vous mettons en relation avec le chauffeur {service} le plus proche.",
|
|
searchingFor: "Recherche depuis {seconds} s",
|
|
match: {
|
|
driverFallback: "Votre chauffeur",
|
|
alertBody: "Une erreur est survenue. Réessayez.",
|
|
},
|
|
offers: {
|
|
title: "Chauffeurs disponibles",
|
|
count: {
|
|
one: "1 proposition",
|
|
other: "{n} propositions",
|
|
zero: "Aucune proposition",
|
|
},
|
|
away: "{eta} min · {distance}",
|
|
seats: {
|
|
one: "1 place",
|
|
other: "{n} places",
|
|
zero: "",
|
|
},
|
|
pick: "Choisir",
|
|
goneTitle: "Ce chauffeur n'est plus libre",
|
|
goneBody:
|
|
"Il a pris une autre course. Choisissez-en un autre dans la liste.",
|
|
goneBodyPaid:
|
|
"Il a pris une autre course. Votre paiement n'a pas été utilisé — choisissez-en un autre et il lui sera versé.",
|
|
},
|
|
payment: {
|
|
title: "Comment souhaitez-vous payer ?",
|
|
titleNamed: "Course avec {name}",
|
|
subtitle: "Tarif ${fare}",
|
|
cash: "Payer en espèces",
|
|
cashHint: "Réglez la course au chauffeur à l'arrivée.",
|
|
card: "Payer par carte",
|
|
cardHint: "Débité maintenant, avant le départ du chauffeur.",
|
|
working: "En cours…",
|
|
},
|
|
ratingFallback: "—",
|
|
paymentCash: "💵 Espèces au chauffeur",
|
|
paymentCard: "💳 Payé par carte",
|
|
fare: "Tarif : ${fare}",
|
|
tripTime: "Durée {time}",
|
|
rideCancelled: "Cette course a été annulée.",
|
|
cancelRide: "Annuler la course",
|
|
cancelling: "Annulation…",
|
|
alertErrorTitle: "Erreur",
|
|
alertErrorBody: "Annulation de cette course impossible. Réessayez.",
|
|
pickupCodeLabel: "Votre code de prise en charge",
|
|
pickupCodeHint: "Donnez-le à votre chauffeur pour démarrer la course.",
|
|
driverHere: "Votre chauffeur est dehors",
|
|
cashDue: "Payez ${amount} en espèces à votre chauffeur.",
|
|
youRated: "Vous avez noté cette course {n}★",
|
|
rateDriver: "Noter votre chauffeur",
|
|
noDriversFound:
|
|
"Aucun chauffeur n'a accepté votre demande. Rien n'a été débité — réessayez dans un instant.",
|
|
cancelledByDriver: "Votre chauffeur a annulé cette course.",
|
|
enRouteNotice:
|
|
"Bonne route — votre chauffeur terminera la course à l'arrivée.",
|
|
},
|
|
|
|
driver: {
|
|
home: {
|
|
owesCompany: "Commission que vous devez",
|
|
owesCompanyHint: "Vos courses en espèces — à remettre au bureau.",
|
|
owedToDriver: "L'entreprise vous doit",
|
|
owedToDriverHint: "Courses par carte, à vous verser.",
|
|
afterFee: "après ${fee} de commission",
|
|
signOutAlt: "Déconnexion",
|
|
driverMode: "Mode chauffeur",
|
|
online: "● En ligne — réception des demandes",
|
|
goOnline: "○ Passer en ligne pour rouler",
|
|
todaysEarnings: "Gain du jour",
|
|
completedToday: "Terminées aujourd'hui",
|
|
incomingRequests: "Demandes entrantes",
|
|
incomingRequestsOffline: "Demandes entrantes (hors ligne)",
|
|
finishCurrentRide:
|
|
"Terminez votre course en cours pour voir les nouvelles demandes.",
|
|
waitingRequests: "En attente de demandes…",
|
|
goOnlineStart: "Passez en ligne pour commencer à rouler.",
|
|
welcome: "Bienvenue, {name}",
|
|
welcomeFallback: "chauffeur",
|
|
setupIntro:
|
|
"Configurez votre profil chauffeur pour commencer à recevoir des demandes.",
|
|
whatDrive: "Que allez-vous conduire ?",
|
|
carModel: "Modèle de voiture",
|
|
carModelPlaceholder: "ex. Toyota Camry",
|
|
carSeats: "Places",
|
|
carSeatsPlaceholder: "4",
|
|
saving: "Enregistrement…",
|
|
startDriving: "Commencer à rouler",
|
|
alertSeatsTitle: "Places invalides",
|
|
alertSeatsBody: "Le nombre de places doit être un entier entre 1 et 8.",
|
|
alertErrorTitle: "Erreur",
|
|
alertCreateBody: "Création du profil chauffeur impossible. Réessayez.",
|
|
alertToggleBody: "Changement de statut impossible. Réessayez.",
|
|
noRequestsAlt: "Aucune course récente",
|
|
cashInHand: "Espèces encaissées aujourd'hui",
|
|
uncollected: "Courses non encaissées aujourd'hui",
|
|
ratingCount: "{n} évaluations",
|
|
ratingNew: "Nouveau chauffeur",
|
|
alertOfflineBlocked:
|
|
"Terminez ou annulez votre course en cours avant de passer hors ligne.",
|
|
},
|
|
credentials: {
|
|
title: "Vos documents",
|
|
intro:
|
|
"Chaque chauffeur est vérifié avant sa première course. Notre équipe examine ces informations.",
|
|
licenseNumber: "Numéro de permis de conduire",
|
|
licenseNumberPlaceholder: "Tel qu'inscrit sur le permis",
|
|
licenseExpiry: "Expiration du permis",
|
|
nationalId: "Numéro de carte d'identité",
|
|
nationalIdPlaceholder: "Votre numéro d'identité",
|
|
plateNumber: "Numéro de plaque",
|
|
plateNumberPlaceholder: "ex. 123456/B",
|
|
reviewNote:
|
|
"Votre compte reste hors ligne jusqu'à validation, généralement en moins d'une journée.",
|
|
submit: "Envoyer pour vérification",
|
|
errorTitle: "Vérifiez vos informations",
|
|
errorMissing:
|
|
"Le numéro de permis, la carte d'identité et la plaque sont tous obligatoires.",
|
|
errorExpiryFormat:
|
|
"Saisissez l'expiration du permis au format AAAA-MM-JJ.",
|
|
errorExpired: "Ce permis est déjà expiré.",
|
|
errorScanRequired: "Scannez votre permis de conduire avant d'envoyer.",
|
|
alertResubmitBody: "Renvoi de vos informations impossible. Réessayez.",
|
|
},
|
|
captureUnavailable:
|
|
"La prise de photo n'est pas disponible dans cette version de l'application. Mettez-la à jour et réessayez.",
|
|
photo: {
|
|
title: "Votre photo",
|
|
hint: "Prise maintenant avec l'appareil photo, pas depuis votre galerie. Les passagers la voient à côté de votre nom au moment de choisir un chauffeur, et s'en servent pour vérifier que c'est bien vous au départ. Regardez l'objectif, dans une bonne lumière.",
|
|
take: "Prendre une photo",
|
|
retake: "Reprendre",
|
|
required: "Prenez une photo de profil avant d'envoyer.",
|
|
permissionTitle: "Autorisation requise",
|
|
permissionCamera:
|
|
"Waseel a besoin de l'appareil photo pour prendre votre photo. Autorisez-y l'accès pour continuer.",
|
|
permissionCameraBlocked:
|
|
"L'accès à l'appareil photo est désactivé pour Waseel, et Android ne le redemandera plus depuis ici. Ouvrez les réglages, puis activez Appareil photo dans les autorisations.",
|
|
errorTitle: "Photo non enregistrée",
|
|
errorBody: "Une erreur s'est produite. Réessayez.",
|
|
errorTooLarge: "Cette photo est trop lourde. Prenez-en une nouvelle.",
|
|
errorRateLimit: "Trop d'envois. Attendez quelques minutes et réessayez.",
|
|
errorUnsupported: "Utilisez une photo JPEG, PNG ou WebP.",
|
|
},
|
|
scan: {
|
|
licenseLabel: "Permis de conduire",
|
|
licenseHint:
|
|
"Posez-le à plat et remplissez le cadre. Nous y lisons le numéro et l'expiration.",
|
|
idLabel: "Carte d'identité",
|
|
idHint: "La face où figure votre numéro d'identité.",
|
|
vehicle_regLabel: "Carte grise",
|
|
vehicle_regHint:
|
|
"La page où figurent le numéro de plaque et le modèle du véhicule.",
|
|
optional: "Facultatif",
|
|
take: "Photographier",
|
|
retake: "Rescanner",
|
|
choose: "Choisir une photo",
|
|
reading: "Lecture de votre document…",
|
|
filled: {
|
|
one: "1 information remplie — vérifiez-la ci-dessous.",
|
|
other: "{n} informations remplies — vérifiez-les ci-dessous.",
|
|
},
|
|
savedNoFields:
|
|
"Photo enregistrée, mais les informations n'ont pas pu être lues. Saisissez-les ci-dessous.",
|
|
savedUnreadable:
|
|
"Photo enregistrée. La lecture est indisponible pour le moment — saisissez les informations ci-dessous.",
|
|
alreadyOnFile:
|
|
"Un scan est déjà enregistré. Rescannez seulement si nécessaire.",
|
|
allRead: "Lu sur vos documents",
|
|
missingPrompt:
|
|
"Nous n'avons pas pu lire ces informations sur vos documents. Ajoutez-les et c'est terminé.",
|
|
edit: "Vérifier ou modifier",
|
|
done: "Terminé",
|
|
checkPrompt: "Corrigez ce qui a été mal lu, puis appuyez sur Terminé.",
|
|
permissionTitle: "Autorisation requise",
|
|
permissionCamera:
|
|
"Autorisez l'appareil photo pour photographier vos documents, ou choisissez une photo existante.",
|
|
permissionCameraBlocked:
|
|
"L'accès à l'appareil photo est désactivé pour Waseel, et Android ne le redemandera plus depuis ici. Ouvrez les réglages et activez Appareil photo dans les autorisations — ou choisissez une photo existante.",
|
|
permissionLibrary:
|
|
"Autorisez l'accès aux photos pour choisir une image de vos documents.",
|
|
permissionLibraryBlocked:
|
|
"L'accès aux photos est désactivé pour Waseel, et Android ne le redemandera plus depuis ici. Ouvrez les réglages et activez Photos dans les autorisations — ou prenez une photo avec l'appareil photo.",
|
|
errorTitle: "Scan impossible",
|
|
errorBody:
|
|
"Une erreur s'est produite. Réessayez ou saisissez les informations ci-dessous.",
|
|
errorTooLarge: "Cette photo est trop lourde. Prenez-en une nouvelle.",
|
|
errorRateLimit: "Trop de scans. Attendez quelques minutes et réessayez.",
|
|
errorUnsupported: "Utilisez une photo JPEG, PNG ou WebP.",
|
|
errorRetry:
|
|
"Envoi échoué. Réessayez ou saisissez les informations ci-dessous.",
|
|
},
|
|
review: {
|
|
pendingTitle: "En cours de vérification",
|
|
pendingBody:
|
|
"Nous vérifions vos informations. Vous pourrez passer en ligne dès validation.",
|
|
rejectedTitle: "Non validé",
|
|
rejectedBody:
|
|
"Vos informations n'ont pas été validées. Corrigez-les ci-dessous et renvoyez-les.",
|
|
suspendedTitle: "Compte suspendu",
|
|
suspendedBody:
|
|
"Votre compte chauffeur a été suspendu. Contactez le support pour régulariser.",
|
|
approvedTitle: "Validé",
|
|
approvedBody: "Vous êtes autorisé à rouler.",
|
|
reasonLabel: "Motif",
|
|
checkAgain: "Vérifier à nouveau",
|
|
resubmitTitle: "Corrigez vos informations",
|
|
resubmitIntro: "Corrigez ce qui ne va pas et nous vérifierons à nouveau.",
|
|
resubmit: "Renvoyer",
|
|
},
|
|
offerCard: {
|
|
youEarn: "Vous gagnez",
|
|
newRequest: "Nouvelle demande · {service}",
|
|
openFor: "Disponible encore",
|
|
seconds: "{n} s",
|
|
awayFromPickup: "{km} km du point de départ",
|
|
firstIn: "Vous seriez le premier",
|
|
rivals: {
|
|
one: "1 autre chauffeur s'est proposé",
|
|
other: "{n} autres chauffeurs se sont proposés",
|
|
zero: "Vous seriez le premier",
|
|
},
|
|
cash: "💵 Espèces",
|
|
card: "💳 Carte",
|
|
fromAlt: "De",
|
|
toAlt: "À",
|
|
tripTime: "Durée",
|
|
fare: "Tarif",
|
|
offer: "Proposer cette course",
|
|
withdraw: "Retirer ma proposition",
|
|
waitingOnRider: "Proposé — en attente du choix du passager",
|
|
lostTitle: "Demande close",
|
|
lostBody:
|
|
"Le passager a choisi un autre chauffeur, ou la demande a expiré. Vous êtes libre pour la suivante.",
|
|
alertOfferBody: "Envoi de votre proposition impossible. Réessayez.",
|
|
alertWithdrawBody: "Retrait de votre proposition impossible. Réessayez.",
|
|
},
|
|
activeRide: {
|
|
youEarn: "Vous gagnez",
|
|
dropoffPin: "Dépose",
|
|
navigateToPickup: "Naviguer vers le départ",
|
|
navigateToDropoff: "Naviguer vers la dépose",
|
|
alertNavigateBody:
|
|
"Impossible d'ouvrir une application de navigation sur ce téléphone.",
|
|
headToPickup: "Direction le départ",
|
|
tripInProgress: "Course en cours",
|
|
rider: "{name}",
|
|
pickupPin: "Départ du passager",
|
|
fromAlt: "De",
|
|
toAlt: "À",
|
|
fare: "Tarif",
|
|
message: "Message",
|
|
call: "Appeler",
|
|
startTrip: "Démarrer la course",
|
|
completeTrip: "Terminer la course",
|
|
cancelRide: "Annuler la course",
|
|
cancelConfirmTitle: "Annuler cette course ?",
|
|
cancelConfirmBody:
|
|
"Le passager sera averti et la course sera marquée comme annulée.",
|
|
cancelConfirmDismiss: "Garder la course",
|
|
cancelConfirmConfirm: "Annuler la course",
|
|
alertErrorTitle: "Erreur",
|
|
alertAcceptBody:
|
|
"Acceptation impossible. La course a peut-être été prise ou a expiré.",
|
|
alertDeclineBody: "Refus de la course impossible. Réessayez.",
|
|
alertUpdateBody: "Mise à jour de la course impossible. Réessayez.",
|
|
alertCancelBody: "Annulation de la course impossible. Réessayez.",
|
|
imHere: "Je suis arrivé",
|
|
atPickup: "Sur place — en attente du passager",
|
|
askForCode: "Demandez au passager son code à 4 chiffres.",
|
|
cashConfirmTitle: "Encaisser la course",
|
|
cashConfirmBody: "Avez-vous encaissé ${amount} en espèces ?",
|
|
cashCollected: "Oui, encaissé",
|
|
cashNotCollected: "Non encaissé",
|
|
},
|
|
},
|
|
|
|
rating: {
|
|
rateDriverTitle: "Comment s'est passée votre course avec {name} ?",
|
|
rateRiderTitle: "Comment était {name} comme passager ?",
|
|
subtitle: "Votre note reste privée vis-à-vis de l'autre personne.",
|
|
starLabel: "{n} étoiles",
|
|
commentPlaceholder: "Ajouter un commentaire (facultatif)",
|
|
submit: "Envoyer la note",
|
|
notNow: "Plus tard",
|
|
error: "Envoi de votre note impossible. Réessayez.",
|
|
},
|
|
|
|
cancelSheet: {
|
|
title: "Annuler cette course ?",
|
|
subtitleRider: "Dites-nous pourquoi pour améliorer nos attributions.",
|
|
subtitleDriver:
|
|
"Le passager sera averti et la course sera marquée comme annulée.",
|
|
confirm: "Annuler la course",
|
|
keepRide: "Garder la course",
|
|
cancelling: "Annulation…",
|
|
reasons: {
|
|
changed_mind: "J'ai changé d'avis",
|
|
wait_too_long: "L'attente est trop longue",
|
|
wrong_address: "Mauvaise adresse de départ",
|
|
driver_no_show: "Le chauffeur n'est jamais arrivé",
|
|
rider_no_show: "Le passager ne s'est pas présenté",
|
|
unreachable: "Impossible de le joindre",
|
|
vehicle_issue: "Problème de véhicule",
|
|
other: "Autre raison",
|
|
},
|
|
},
|
|
|
|
pickupCode: {
|
|
title: "Démarrer la course",
|
|
subtitle: "Saisissez le code à 4 chiffres affiché chez le passager.",
|
|
startTrip: "Démarrer",
|
|
wrongCode: "Ce code ne correspond pas. Vérifiez avec le passager.",
|
|
},
|
|
|
|
services: {
|
|
nearbyCount: "{n} à proximité",
|
|
noneNearby: "Aucun à proximité",
|
|
car: {
|
|
label: "Voiture",
|
|
tagline: "Une course quotidienne, jusqu'à 4 places.",
|
|
},
|
|
moto: {
|
|
label: "Moto",
|
|
tagline: "Évitez le trafic — un passager, sans bagages.",
|
|
},
|
|
courier: {
|
|
label: "Coursier",
|
|
tagline: "Envoyez un colis en ville sans vous déplacer.",
|
|
},
|
|
chauffeur: {
|
|
label: "Ma voiture",
|
|
tagline: "Un chauffeur vient conduire votre propre voiture.",
|
|
},
|
|
},
|
|
|
|
pois: {
|
|
nearbyTitle: "Suggestions à proximité",
|
|
mall: "Centre commercial",
|
|
hospital: "Hôpital",
|
|
pharmacy: "Pharmacie",
|
|
restaurant: "Restaurant",
|
|
searching: "recherche…",
|
|
noneNearby: "rien à proximité",
|
|
kmAway: "{km} km",
|
|
routeAway: "{km} km · {min} min",
|
|
nearbyPlace: "Lieu à proximité",
|
|
},
|
|
|
|
units: {
|
|
min: { zero: "0 min", one: "{n} min", other: "{n} min" },
|
|
h: "{n}h",
|
|
m: "{n}m",
|
|
hoursMinutes: "{h}h {m}m",
|
|
seats: { zero: "{n} places", one: "{n} place", other: "{n} places" },
|
|
lbpSuffix: " LBP",
|
|
},
|
|
|
|
months: {
|
|
jan: "janv.",
|
|
feb: "févr.",
|
|
mar: "mars",
|
|
apr: "avr.",
|
|
may: "mai",
|
|
jun: "juin",
|
|
jul: "juil.",
|
|
aug: "août",
|
|
sep: "sept.",
|
|
oct: "oct.",
|
|
nov: "nov.",
|
|
dec: "déc.",
|
|
},
|
|
|
|
components: {
|
|
oauth: {
|
|
or: "Ou",
|
|
googleLogoAlt: "Logo Google",
|
|
alertFailTitle: "Échec de la connexion Google",
|
|
alertFailNoToken: "Aucun jeton renvoyé. Réessayez.",
|
|
alertFailFallback: "Réessayez.",
|
|
},
|
|
otp: {
|
|
code: "Code",
|
|
codePlaceholder: "123456",
|
|
pasteCode: "Coller le code depuis Gmail",
|
|
},
|
|
googleTextInput: {
|
|
searchAlt: "Rechercher",
|
|
placeholder: "Où voulez-vous aller ?",
|
|
},
|
|
inputField: {
|
|
labelIconAlt: "Icône {label}",
|
|
},
|
|
locationNotice: {
|
|
denied: {
|
|
title: "Accès à la position désactivé",
|
|
body: "Waseel a besoin de votre position pour afficher les chauffeurs à proximité et définir votre point de départ.",
|
|
action: "Ouvrir les réglages",
|
|
},
|
|
servicesOff: {
|
|
title: "Services de localisation désactivés",
|
|
body: "Activez la localisation sur votre appareil, puis réessayez.",
|
|
action: "Réessayer",
|
|
},
|
|
unavailable: {
|
|
title: "Position introuvable",
|
|
body: "Déplacez-vous vers une zone avec un meilleur signal, ou définissez votre départ manuellement.",
|
|
action: "Réessayer",
|
|
},
|
|
},
|
|
map: {
|
|
destination: "Destination",
|
|
webUnavailable:
|
|
"La carte n'est pas disponible sur le web.\nUtilisez Android ou iOS pour l'expérience complète.",
|
|
},
|
|
rideCard: {
|
|
outcomeCompleted: "Terminée",
|
|
outcomeCancelled: "Annulée",
|
|
outcomeExpired: "Aucun chauffeur trouvé",
|
|
cancelledByYou: "Vous avez annulé",
|
|
cancelledByDriver: "Le chauffeur a annulé",
|
|
cancelledBySystem: "Aucun chauffeur disponible",
|
|
noDriver: "Aucun chauffeur attribué",
|
|
paymentNotCharged: "Non débité",
|
|
paymentRefundDue: "Remboursement dû",
|
|
paymentCashCollected: "Payé en espèces",
|
|
mapAlt: "Carte",
|
|
originAlt: "Origine",
|
|
destinationAlt: "Destination",
|
|
dateTime: "Date & Heure",
|
|
driver: "Chauffeur",
|
|
carSeats: "Places",
|
|
fare: "Tarif",
|
|
paymentStatus: "Statut du paiement",
|
|
paymentCash: "Espèces · Payer au chauffeur",
|
|
paymentPaid: "Payé par carte",
|
|
paymentOther: "{status}",
|
|
},
|
|
rideLayout: {
|
|
goBack: "Retour",
|
|
backArrowAlt: "Flèche retour",
|
|
},
|
|
payment: {
|
|
paymentMethod: "Mode de paiement",
|
|
cash: "💵 Espèces",
|
|
card: "💳 Carte",
|
|
processing: "Traitement...",
|
|
bookCash: "Réserver · Payer en espèces au chauffeur",
|
|
confirmCard: "Confirmer & Payer par carte",
|
|
checkAlt: "Vérifié",
|
|
rideBooked: "Course réservée !",
|
|
successBody:
|
|
"Merci pour votre réservation.\n Votre commande a été enregistrée.\n",
|
|
cashInstruction: "Préparez {lbp}.",
|
|
backHome: "Retour à l'accueil",
|
|
alertPayCardTitle: "Payer par carte",
|
|
alertPayCardBody: "Votre carte sera débitée de ${amount}.",
|
|
alertErrorTitle: "Erreur",
|
|
alertErrorBody:
|
|
"Une erreur est survenue lors de la réservation. Réessayez.",
|
|
alertPaymentNotCompletedTitle: "Paiement non effectué",
|
|
alertPaymentNotCompletedBody:
|
|
"Votre paiement a été annulé ou n'a pas pu être vérifié. Réessayez.",
|
|
alertProcessingTitle: "Erreur",
|
|
alertProcessingBody:
|
|
"Une erreur est survenue lors du traitement du paiement. Réessayez.",
|
|
},
|
|
driverCard: {
|
|
avatarAlt: "Avatar du chauffeur",
|
|
starAlt: "Étoile",
|
|
dollarAlt: "Dollar",
|
|
carAlt: "Voiture",
|
|
seats: "{n} places",
|
|
},
|
|
},
|
|
|
|
settings: {
|
|
title: "Réglages",
|
|
maps: {
|
|
title: "Cartes & Navigation",
|
|
description:
|
|
"Waseel utilise votre position pour afficher les chauffeurs à proximité et naviguer vers votre départ.",
|
|
statusGranted: "Accordé",
|
|
statusDenied: "Non autorisé",
|
|
statusBlocked: "Bloqué",
|
|
statusUnknown: "Vérification…",
|
|
openSettings: "Ouvrir les réglages",
|
|
},
|
|
appearance: {
|
|
title: "Apparence",
|
|
description: "Choisissez l'apparence de Waseel.",
|
|
light: "Clair",
|
|
dark: "Sombre",
|
|
system: "Système",
|
|
},
|
|
safety: {
|
|
title: "Sécurité",
|
|
call112: "Appeler le 112 — Urgences",
|
|
call112Description:
|
|
"Appelez le numéro d'urgence du Liban pour la police, les secours ou les pompiers.",
|
|
callFailedTitle: "Appel impossible",
|
|
callFailedBody:
|
|
"Aucun composeur disponible sur cet appareil. Appelez le 112 manuellement.",
|
|
proactive: {
|
|
title: "Sécurité proactive",
|
|
body: "Partagez le statut de votre course et votre position en direct avec vos contacts de confiance, et voyagez en sachant que l'aide est à un geste près.",
|
|
},
|
|
verification: {
|
|
title: "Vérification des passagers",
|
|
body: "Passagers et chauffeurs vérifient leur numéro de téléphone et leur identité, afin que vous sachiez toujours avec qui vous roulez.",
|
|
},
|
|
privacy: {
|
|
title: "Protection de votre vie privée",
|
|
body: "Votre numéro de téléphone et vos coordonnées restent masqués dans la discussion. Les messages ne sont visibles qu'entre vous et votre chauffeur pour cette course.",
|
|
},
|
|
},
|
|
language: {
|
|
title: "Langue",
|
|
description: "Langue de l'application.",
|
|
en: "English",
|
|
ar: "العربية",
|
|
fr: "Français",
|
|
rtlRestartTitle: "Redémarrage pour l'arabe",
|
|
rtlRestartBody:
|
|
"La mise en page arabe s'appliquera pleinement à la prochaine ouverture de l'application.",
|
|
},
|
|
general: {
|
|
title: "Général",
|
|
},
|
|
keepAwake: {
|
|
title: "Ne pas verrouiller l'écran",
|
|
description:
|
|
"Maintenir l'écran allumé lorsque l'application est ouverte.",
|
|
},
|
|
overlay: {
|
|
title: "Affichage par-dessus d'autres applications",
|
|
description:
|
|
"Requis pour que les alertes de course apparaissent par-dessus les autres applications.",
|
|
allow: "Autoriser l'affichage par-dessus les autres applications",
|
|
openedHint: "Réglages système ouverts",
|
|
notAndroid: "Disponible uniquement sur Android.",
|
|
},
|
|
},
|
|
};
|