diff --git a/apps/sdp-web/messages/fr.json b/apps/sdp-web/messages/fr.json new file mode 100644 index 000000000..a6a0191a8 --- /dev/null +++ b/apps/sdp-web/messages/fr.json @@ -0,0 +1,28 @@ +{ + "Metadata": { + "title": "Solana Developer Platform", + "description": "Tableau de bord SDP" + }, + "Home": { + "solanaLogo": "Solana", + "docs": "Docs", + "dashboard": "Dashboard", + "title": "Construisez tout produit financier, sans gérer l’infrastructure", + "description": "Émission de stablecoin, paiements transfrontaliers ou tokenisation d’actifs réels : SDP fournit les APIs et l’infra les plus fiables pour y parvenir.", + "joinWaitlist": "Rejoindre la liste d’attente" + }, + "NotFound": { + "solanaLogo": "Solana", + "title": "Page introuvable", + "description": "Cette page n’existe pas ou a été déplacée.", + "backToDashboard": "Retour au dashboard", + "goHome": "Accueil" + }, + "Feedback": { + "label": "Feedback" + }, + "Error": { + "tryAgain": "Réessayer", + "reportIssue": "Signaler le problème" + } +} diff --git a/apps/sdp-web/messages/fr/dashboard-approvals.json b/apps/sdp-web/messages/fr/dashboard-approvals.json new file mode 100644 index 000000000..845bfc6ac --- /dev/null +++ b/apps/sdp-web/messages/fr/dashboard-approvals.json @@ -0,0 +1,112 @@ +{ + "DashboardApprovals": { + "title": "Demandes d'approbation", + "description": "Passez en revue les opérations mises en pause par les contrôles de portefeuille ou de clé API.", + "pendingCount": "{count} en attente", + "pendingTab": "En attente", + "historyTab": "Historique", + "walletFilter": "Portefeuille", + "allWallets": "Tous les portefeuilles", + "statusFilter": "Statut", + "allStatuses": "Tous les statuts", + "operationFilter": "Opération", + "allOperations": "Toutes les opérations", + "apiKeyFilter": "Clé API", + "allApiKeys": "Toutes les clés API", + "fromFilter": "De", + "toFilter": "À", + "clearFilters": "Effacer", + "statusColumn": "Statut", + "walletColumn": "Portefeuille", + "operationColumn": "Opération", + "amountAssetColumn": "Montant / actif", + "destinationColumn": "Destination", + "requestedByColumn": "Demandé par", + "policyReasonColumn": "Motif de la politique", + "submittedColumn": "Soumis", + "openRequest": "Ouvrir la demande d'approbation", + "emptyPending": "Aucune demande en attente d'approbation", + "emptyPendingDescription": "Les nouvelles opérations soumises à des politiques apparaîtront ici dès qu'elles seront soumises.", + "emptyHistory": "Aucun historique d'approbation", + "emptyHistoryDescription": "Les demandes approuvées, rejetées, annulées, expirées et échouées apparaîtront ici.", + "emptyFiltered": "Aucune demande ne correspond à ces filtres", + "emptyFilteredDescription": "Effacez un ou plusieurs filtres pour voir plus de demandes d'approbation.", + "range": "{from}–{to} sur {total} demandes", + "previousPage": "Page précédente", + "nextPage": "Page suivante", + "pageOf": "Page {page} sur {pageCount}", + "unableToLoad": "Impossible de charger les demandes d'approbation", + "unableToLoadDescription": "La liste des demandes n'a pas pu être récupérée. Essayez de la recharger.", + "reload": "Recharger", + "refreshFailed": "Les demandes d'approbation n'ont pas pu être actualisées. Affichage des derniers résultats chargés.", + "viewOnly": "Vous pouvez consulter les demandes d'approbation, mais votre rôle ne peut pas les décider.", + "noAccess": "Les demandes d'approbation ne sont pas disponibles pour votre rôle.", + "noAccessDescription": "Demandez à un administrateur de l'organisation un accès en lecture au portefeuille.", + "backToApprovals": "Retour aux approbations", + "reviewTitle": "Examiner {operation}", + "reviewDescription": "Confirmez le contexte de la politique et les détails de l'opération avant de prendre une décision.", + "approve": "Approuver", + "reject": "Rejeter", + "cancel": "Annuler", + "approveTitle": "Approuver cette demande ?", + "approveDescription": "L'opération sera libérée pour exécution. Cette décision est irréversible.", + "approveConfirm": "Approuver la demande", + "rejectTitle": "Rejeter cette demande ?", + "rejectDescription": "L'opération sera annulée et ne pourra pas être reprise à partir de cette demande.", + "rejectConfirm": "Rejeter la demande", + "cancelTitle": "Annuler cette demande ?", + "cancelDescription": "L'opération en attente sera annulée sans décision d'approbation.", + "cancelConfirm": "Annuler la demande", + "notNow": "Pas maintenant", + "decisionInProgress": "Mise à jour de la demande...", + "approvedToast": "Demande approuvée", + "rejectedToast": "Demande rejetée", + "canceledToast": "Demande annulée", + "alreadyDecided": "Cette demande a déjà été tranchée. Le dernier état est désormais affiché.", + "forbiddenDecision": "Votre rôle n'est pas autorisé à prendre des décisions sur les demandes d'approbation.", + "decisionFailed": "La demande n'a pas pu être mise à jour. Réessayez.", + "requestSection": "Demande", + "policyDecisionSection": "Décision de politique", + "operationDetailsSection": "Détails de l'opération", + "matchedControlsSection": "Contrôles correspondants", + "timelineSection": "Chronologie", + "submittedBy": "Soumis par", + "submittedAt": "Soumis le", + "expiresAt": "Expire le", + "policyDecision": "Décision", + "policyReason": "Motif", + "reasonCode": "Code motif", + "operationFamily": "Famille d'opérations", + "operationType": "Type d'opération", + "amount": "Montant", + "asset": "Actif", + "destination": "Destination", + "source": "Source", + "noMatchedControls": "Aucun contrôle correspondant n'a été signalé pour cette évaluation.", + "matchedControl": "Contrôle correspondant {number}", + "submittedEvent": "Demande soumise", + "submittedEventDescription": "L'opération a été mise en attente pour approbation.", + "resolvedEvent": "Demande {status}", + "resolvedEventDescription": "Décision enregistrée par {actor}.", + "metadata": "Contexte de la demande", + "wallet": "Portefeuille", + "walletAddress": "Adresse du portefeuille", + "requester": "Demandeur", + "apiKey": "Clé API", + "walletRevision": "Version du portefeuille", + "apiKeyRevision": "Version de la clé API", + "provider": "Fournisseur", + "providerStatus": "Statut du fournisseur", + "requestId": "ID de demande", + "submitted": "Soumise", + "currentStatus": "Statut actuel", + "resolvedBy": "Résolu par", + "resolvedAt": "Résolu le", + "notReported": "Non signalé", + "directRequest": "Demande directe", + "approvalRequiredByPolicy": "Approbation requise par la politique", + "copyRequestId": "Copier l'ID de demande", + "requestIdCopied": "ID de demande copié", + "loading": "Chargement des approbations..." + } +} diff --git a/apps/sdp-web/messages/fr/dashboard-custody.json b/apps/sdp-web/messages/fr/dashboard-custody.json new file mode 100644 index 000000000..40f0440e1 --- /dev/null +++ b/apps/sdp-web/messages/fr/dashboard-custody.json @@ -0,0 +1,740 @@ +{ + "DashboardCustody": { + "actions": "Actions", + "rotateKey": "Rotation ({hours}h grâce)", + "deleteKey": "Supprimer la clé", + "actionFailed": "Échec de l’action", + "notice": "Avis", + "existingApiKeys": "Clés API existantes", + "apiKeysDescription": "Clés actives et historiques pour cet espace de travail.", + "newApiKey": "Nouvelle clé API", + "noApiKeysFound": "Aucune clé API trouvée.", + "name": "Nom", + "prefix": "Préfixe", + "access": "Accès", + "status": "Statut", + "lastUsed": "Dernière utilisation", + "expires": "Expire", + "created": "Créée", + "never": "Jamais", + "admin": "Admin", + "developer": "Developer", + "readOnly": "Lecture seule", + "allWallets": "Tous les Wallets", + "selectedWallets": "Wallets sélectionnés", + "selected": "{count} sélectionnés", + "selectedWallet": "Wallet sélectionné", + "selectedLabel": "Sélectionné", + "noApiKeyPolicy": "Aucune politique de clé API", + "noAdditionalApiKeyPolicy": "Aucune politique de clé API supplémentaire n’est associée.", + "policyBinding": "Association de politique", + "policyBindingCount": "{count} association de politique", + "policyBindingsCount": "{count} associations de politique", + "apiProfile": "Profil API {id}{revision}", + "walletProfile": "Profil Wallet {id}{revision}", + "revision": " rév. {id}", + "roleAccess": "Accès {role}", + "createApiKey": "Créer une clé API", + "reviewApiKey": "Vérifier la clé API", + "walletAccess": "Accès aux Wallets", + "walletAccessDescription": "Choisissez si cette clé peut utiliser tous les Wallets concernés ou seulement ceux sélectionnés.", + "allWalletsDescription": "Cette clé peut utiliser tous les Wallets de son org ou projet.", + "selectedWalletsDescription": "Limitez cette clé à des Wallets précis et choisissez son Wallet de signature par défaut.", + "operationPolicy": "Politique d’opération", + "noActiveWallets": "Aucun Wallet actif n’est encore disponible pour l’association.", + "defaultSigningWallet": "Wallet de signature par défaut", + "nameLabel": "Nom", + "namePlaceholder": "Clé de déploiement CI", + "role": "Rôle", + "environment": "Environnement", + "expirationOptional": "Expiration (facultatif)", + "production": "Production", + "sandbox": "Sandbox", + "none": "Aucun", + "invalidDate": "Date non valide", + "endpointPermissions": "Autorisations des endpoints", + "policy": "Politique", + "securityNote": "Note de sécurité", + "creating": "Création...", + "createKey": "Créer la clé", + "createApiKeyDescription": "Définissez les détails de la clé et l’accès aux Wallets, puis confirmez.", + "reviewApiKeyDescription": "Vérifiez la demande avant de créer la clé.", + "deleteApiKey": "Supprimer la clé API", + "deleteApiKeyPlaceholder": "Collez le nom exact de la clé", + "deleting": "Suppression...", + "deleteKeyConfirm": "Supprimer la clé", + "apiKeyGenerated": "Clé API générée", + "keyPrefix": "Préfixe de clé", + "fullKeyShownOnce": "Votre clé complète (affichée une seule fois)", + "apiKeyPlaygroundSession": "Cette session de navigateur peut désormais utiliser cette clé dans l’API Playground sans la recoller.", + "dismiss": "Fermer", + "copyValue": "Copier", + "copied": "Copié", + "closeGeneratedKeyModal": "Fermer la modale de clé générée", + "closeConfirmationModal": "Fermer la modale de confirmation", + "delete": "Supprimer", + "deleteApiKeyDescription": "Cela supprime la clé sans supprimer la ligne.", + "typeKeyNameToConfirm": "Saisissez {name} pour confirmer.", + "confirmKeyName": "Confirmer le nom de la clé", + "cancel": "Annuler", + "waitingForOrganizationSync": "En attente de synchronisation de l’organisation", + "organizationSyncDescription": "SDP attend que le webhook Clerk crée le mappage de cette organisation.", + "organizationSyncHelp": "Création d’orga et sync membres via webhooks Clerk uniquement. Actualisez ; si ça persiste, vérifiez le webhook Clerk.", + "organizationName": "Nom de l’organisation", + "organizationSlug": "Slug de l’organisation", + "clerkOrganizationId": "ID d’organisation Clerk", + "unavailable": "Indisponible", + "unableToLoadWalletProviders": "Impossible de charger les fournisseurs de Wallet", + "unableToLoadWallets": "Impossible de charger les Wallets", + "trackedBalancesUnavailable": "Les soldes suivis sont indisponibles pour le moment. Affichage du solde indiqué par le Wallet.", + "walletControlsUnavailable": "Les contrôles du Wallet sont indisponibles pour le moment.", + "createWallet": "Créer un Wallet", + "wallet": "Wallet", + "balance": "Solde", + "purpose": "Usage", + "issuance": "Émission", + "compliance": "Conformité", + "mintAuthority": "Autorité de Mint", + "freezeAuthority": "Autorité de Freeze", + "feePayer": "Fee payer", + "transfers": "Transferts", + "address": "Adresse", + "walletId": "ID du Wallet", + "manage": "Gérer", + "createFirstWallet": "Créez votre premier Wallet", + "noWalletsAvailable": "Aucun Wallet disponible", + "createWalletDescription": "Choisissez le fournisseur qui créera et signera pour le Wallet.", + "walletCreationLimited": "La création de Wallet est limitée aux Admins. Une fois créé, vous pouvez toujours utiliser un Wallet dans le tableau de bord.", + "noWalletProvidersEnabled": "Aucun fournisseur de Wallet activé", + "noWalletProvidersEnabledDescription": "Activez un fournisseur pour cette organisation avant de créer un Wallet.", + "backToWallets": "Retour aux Wallets", + "chooseProvider": "Choisir un fournisseur", + "walletDetails": "Détails du Wallet", + "walletLabel": "Libellé du Wallet", + "walletLabelPlaceholder": "Trésorerie", + "project": "Projet", + "projectValue": "Projet actuel", + "environmentValue": "Environnement actuel", + "connectedProviderDescription": "{provider} utilise son Wallet déjà configuré dans ce flux.", + "chooseEnabledProvider": "Choisissez un fournisseur activé pour continuer.", + "back": "Retour", + "continue": "Continuer", + "createWalletPending": "Création...", + "saveWalletLabel": "Enregistrer le libellé du Wallet", + "cancelWalletLabelEdit": "Annuler la modification du libellé", + "editWalletLabel": "Modifier le libellé du Wallet", + "untitled": "Sans titre", + "updatingWalletLabel": "Mise à jour du libellé du Wallet.", + "walletLabelUpdated": "Libellé du Wallet mis à jour.", + "unableToUpdateWalletLabel": "Impossible de mettre à jour le libellé du Wallet.", + "unknownError": "Erreur inconnue", + "requestFailed": "Échec de la requête", + "httpRequestFailed": "{error} (HTTP {status})", + "walletIdRequired": "L’ID du Wallet est requis.", + "validWalletAddressRequired": "Une adresse de Wallet valide est requise.", + "signInToRequestDevnetSol": "Connectez-vous pour demander des SOL Devnet.", + "devnetFaucetHttpError": "Le fournisseur RPC du faucet Devnet {provider} a renvoyé HTTP {status}.", + "devnetFaucetEmptyResponse": "Le faucet Devnet a renvoyé une réponse RPC vide.", + "devnetFaucetProviderError": "Le fournisseur RPC du faucet Devnet {provider} a renvoyé : {error}", + "devnetFaucetProviderGenericError": "Le fournisseur RPC du faucet Devnet {provider} a renvoyé une erreur.", + "devnetFaucetNoSignature": "Le faucet Devnet n’a renvoyé aucune Signature de transaction.", + "walletAddress": "Adresse du Wallet", + "walletMetadataCopied": "{label} copié.", + "unableToCopy": "Impossible de copier {label}.", + "copy": "Copier {label}", + "recentActivity": "Activité récente", + "recentActivityDescription": "Activité de transfert et d’opérations de Token pour ce Wallet.", + "refreshing": "Actualisation...", + "refresh": "Actualiser", + "noWalletActivity": "Aucune activité de Wallet trouvée.", + "activity": "Activité", + "asset": "Asset", + "direction": "Sens", + "counterparty": "Counterparty", + "signature": "Signature", + "unknownAsset": "Asset inconnu", + "unknown": "Inconnu", + "pending": "En attente", + "incoming": "Entrant", + "outgoing": "Sortant", + "transfer": "Transfert", + "unableToLoadIssuanceActivity": "Impossible de charger l’activité d’émission", + "paymentsActivityUnavailable": "L’activité des paiements est indisponible pour le moment.", + "issuanceActivityUnavailable": "L’activité d’émission est indisponible pour le moment.", + "noActivitySources": "Aucune source d’activité n’est disponible pour ce Wallet.", + "walletActivityUnavailable": "L’activité du Wallet est indisponible pour le moment.", + "unableToVerifyWalletVisibility": "Impossible de vérifier la visibilité du Wallet.", + "invalidWalletId": "ID de Wallet non valide.", + "walletActivityRequestFailed": "Échec de la requête d’activité du Wallet.", + "previous": "Précédent", + "active": "Actif", + "noWalletProvidersTier": "Aucun fournisseur de Wallet n’est activé pour ce niveau d’organisation pour le moment.", + "newWallet": "Nouveau Wallet", + "providerAdditionalWalletUnavailable": "{provider} est déjà connecté, mais les Wallets supplémentaires ne sont pas encore disponibles.", + "walletCreationAvailable": "La création de Wallet est disponible après l’activation d’un fournisseur de custody pour cette organisation.", + "stale": "(obsolète)", + "organizationSettings": "Paramètres de l’organisation", + "organizationSettingsDescription": "Configurez le fournisseur RPC utilisé dans cette organisation.", + "failedToLoadOrganizationSettings": "Échec du chargement des paramètres de l’organisation.", + "organizationNotFound": "Organisation introuvable.", + "organizationNotLinked": "Cette organisation Clerk n’est pas encore liée à une organisation SDP.", + "editingOrganization": "Modification de l’organisation : {name}", + "viewOnlyRpcSettings": "Vous pouvez voir les paramètres RPC de l’organisation, mais seuls les Admins peuvent les modifier.", + "noRpcProviders": "Aucun fournisseur RPC n’est activé pour cette organisation dans l’environnement actuel.", + "rpcFallback": "Le fournisseur RPC enregistré pour cette organisation n’est plus disponible au niveau actuel. Le formulaire utilise {provider} jusqu’à l’enregistrement d’un fournisseur activé.", + "saving": "Enregistrement...", + "saveFallback": "Enregistrer le secours", + "rpcProvider": "Fournisseur RPC", + "testing": "Test...", + "testRpc": "Tester RPC", + "saveInProgress": "Enregistrement en cours.", + "tryAgainSoon": "Réessayez dans un instant.", + "checkingRpcProvider": "Vérification du fournisseur RPC.", + "rpcCheckPassed": "Vérification RPC réussie.", + "providerMismatch": "Fournisseur non correspondant.", + "rpcCheckFailed": "Échec de la vérification RPC.", + "anotherProvider": "un autre fournisseur", + "failedToSaveRpcSettings": "Échec de l’enregistrement des paramètres RPC.", + "missingOrganizationId": "ID d’organisation manquant.", + "rpcProviderSaveMismatch": "Incohérence d’enregistrement du fournisseur RPC (demandé : {requested}, enregistré : {persisted}).", + "rpcSettingsSaved": "Paramètres RPC enregistrés.", + "failedToTestRpcProvider": "Échec du test du fournisseur RPC.", + "rpcTestFailed": "Échec du test RPC.", + "rpcTestFailedStatus": "Échec du test RPC ({status}).", + "rpcTestMismatch": "Incohérence du test RPC (demandé : {requested}, résolu : {resolved}).", + "rpcUpstreamReturned": "L’amont RPC a renvoyé {status} {statusText}.", + "rpcTestPassed": "Test RPC réussi ({status} {statusText}) en {latency} ms.", + "missingApiKeyIdForDeletion": "ID de clé API manquant pour la suppression.", + "missingApiKeyNameForDeletion": "Nom de clé API manquant pour confirmer la suppression.", + "confirmApiKeyDeletion": "Saisissez le nom de la clé pour confirmer la suppression de la clé API.", + "apiKeyConfirmationMismatch": "La confirmation ne correspond pas au nom de la clé.", + "apiKeyDeactivated": "La clé API « {name} » a été désactivée.", + "apiKeyDeleteFailed": "Échec de la suppression : {error}", + "apiKeyNameRequired": "Le nom de la clé API est requis.", + "apiKeyWalletScopeRequired": "Choisissez si cette clé peut accéder à tous les Wallets ou aux Wallets sélectionnés.", + "apiKeyWalletRequired": "Sélectionnez au moins un Wallet pour une clé API limitée à un Wallet.", + "invalidExpirationDate": "Date d’expiration non valide.", + "apiKeyCreated": "Clé API « {name} » créée. Enregistrez-la maintenant ; elle ne sera plus affichée.", + "apiKeyCreateFailed": "Échec de la création : {error}", + "missingApiKeyIdForRotation": "ID de clé API manquant pour la rotation.", + "apiKeyRotated": "Clé API renouvelée. La clé précédente reste valide jusqu’au {deadline}.", + "apiKeyRotateFailed": "Échec de la rotation : {error}", + "providerLocalDescription": "Signer de paire de clés Ed25519 auto-hébergée depuis CUSTODY_PRIVATE_KEY.", + "providerPrivyDescription": "Infrastructure de Wallet hébergée pour la signature API.", + "providerFireblocksDescription": "Custody MPC avec contrôles de Wallet basés sur les vaults.", + "providerCoinbaseCdpDescription": "Provisionnement programmatique de Wallet via Coinbase CDP.", + "providerParaDescription": "Custody de Wallet intégré pour les opérations au niveau de l’organisation.", + "providerTurnkeyDescription": "Custody de clés fondée sur des politiques pour les charges de signature de production.", + "providerDfnsDescription": "Orchestration de Wallet MPC avec signature sécurisée pilotée par API.", + "providerIbmHavenDescription": "Custody institutionnelle sur IBM Digital Asset Haven.", + "providerAnchorageDescription": "Custody institutionnelle avec gestion du cycle de vie des Wallets.", + "providerUtilaDescription": "Signature de Wallet Solana adossée à un vault via les comptes de service Utila.", + "apiKeyAdminDescription": "Admin inclut les privilèges de custody et de plateforme. Developer exclut les actions de custody.", + "apiKeyEnvironmentDescription": "Changez l’environnement de l’espace de travail dans la barre latérale pour créer une clé dans l’autre environnement.", + "expiresOn": "Expire le {date}", + "default": "Par défaut :", + "fullKeyOnlyShownOnce": "La clé complète ne sera affichée qu’une fois après sa création.", + "closeApiKeyCreationModal": "Fermer la modale de création de clé API", + "policyDraftSaveFailed": "Le Draft n’a pas pu être enregistré.", + "policyDraftSaveFailedDescription": "Vous pouvez continuer, mais les changements peuvent être perdus si vous quittez.", + "policyDraftSaved": "Draft enregistré.", + "policyDraftSavedDescription": "Le profil n’est pas encore actif.", + "policyChooseRestriction": "Choisissez au moins une catégorie de restriction.", + "policyCheckDestinations": "Vérifiez les adresses de destination.", + "policyCheckDestinationsDescription": "Utilisez des adresses Solana valides avant la vérification.", + "policyChooseOperations": "Choisissez les contrôles d’accès aux opérations.", + "policyChooseOperationsDescription": "Sélectionnez au moins une famille d’opérations à bloquer.", + "policyCheckLimits": "Vérifiez les limites de transfert.", + "policyCheckLimitsDescription": "Saisissez un nombre positif pour chaque limite configurée.", + "policyChooseApprovals": "Choisissez les contrôles d’approbation.", + "policyChooseApprovalsDescription": "Sélectionnez au moins une famille d’opérations nécessitant une approbation.", + "policyChooseAdvanced": "Choisissez les contrôles de signature avancés.", + "policyChooseAdvancedDescription": "Sélectionnez la signature brute, les interactions de programme, ou les deux.", + "policyActivating": "Activation des contrôles du Wallet.", + "policyActive": "Contrôles du Wallet actifs.", + "policyActiveDescription": "Les restrictions sélectionnées sont maintenant actives.", + "policyActivationFailed": "Échec de l’activation.", + "policySaveFailed": "Les contrôles du Wallet n’ont pas pu être enregistrés.", + "policyDisabling": "Désactivation des contrôles du Wallet.", + "policyDisabled": "Contrôles du Wallet désactivés.", + "policyDisabledDescription": "Le Wallet revient à l’autorisation par défaut.", + "policyDisableFailed": "Échec de la désactivation.", + "wallets": "Wallets", + "playgroundListWallets": "Lister les Wallets", + "playgroundListWalletConfigs": "Lister les configurations de Wallet", + "playgroundGetWallet": "Obtenir le Wallet", + "playgroundGetWalletPublicKey": "Obtenir la clé publique du Wallet", + "playgroundAggregateBalances": "Agréger les soldes des Wallets", + "playgroundCreateWallet": "Créer un Wallet", + "playgroundSignerCheck": "Vérification du Signer", + "rootWallet": "Wallet racine", + "mainWallet": "Wallet principal", + "mainSettlementWallet": "Wallet principal de règlement", + "selectWalletPurpose": "Sélectionner l’usage du Wallet", + "ownershipProof": "Preuve de propriété depuis le playground Wallet", + "untitledWallet": "Wallet sans titre", + "publicKey": "Clé publique", + "provider": "Fournisseur", + "totalBalance": "Solde total", + "balances": "Soldes", + "noTrackedBalances": "Aucun solde suivi trouvé pour ce Wallet.", + "walletControls": "Contrôles du Wallet", + "walletRestrictionsActive": "Ce Wallet a des restrictions actives sur les paiements sortants.", + "walletDefaultAllow": "Ce Wallet démarre en allow par défaut. Ajoutez des restrictions seulement si besoin.", + "destinations": "Destinations", + "open": "Ouvrir", + "perTransfer": "Par transfert", + "daily": "Quotidien", + "noCap": "Aucun plafond", + "reviewControls": "Vérifier les contrôles", + "startProfile": "Démarrer le profil", + "policyIntent": "Intention", + "policySetWalletPolicies": "Définir les politiques de Wallet", + "policyIntentDescription": "Choisissez où les fonds peuvent aller et combien ce Wallet peut transférer.", + "policyRules": "Règles", + "policyStartingRules": "Règles initiales", + "policyRulesDescription": "Configurez les zones de règles sélectionnées avant vérification.", + "policyReview": "Vérification", + "policyFinalReview": "Vérification finale", + "policyReviewDescription": "Vérifiez les changements avant d’appliquer les contrôles du Wallet.", + "policyOperationAccess": "Accès aux opérations", + "policyOperationAccessDescription": "Bloquez les familles d’opérations à risque tout en conservant l’usage normal.", + "policyAllowedDestinations": "Destinations autorisées", + "policyAllowedDestinationsDescription": "À utiliser lorsque ce Wallet ne doit payer que des adresses connues.", + "policyTransferLimits": "Limites de transfert", + "policyTransferLimitsDescription": "À utiliser lorsque ce Wallet requiert des plafonds de dépense ou de sortie quotidienne.", + "policyAdvancedSigning": "Signature avancée", + "policyAdvancedSigningDescription": "Limitez la signature brute et les interactions directes avec les programmes.", + "policyPayments": "Paiements", + "policyRamps": "Ramps", + "policyIssuance": "Émission", + "policyProviderAdmin": "Admin fournisseur", + "policyRawSigning": "Signature brute", + "policyProgramInteractions": "Interactions de programme", + "policyAllowed": "Autorisé", + "policyDenied": "Refusé", + "policyApprovalRequired": "Approbation requise", + "policyProviderApprovalRequired": "Approbation du fournisseur requise", + "policyNotEvaluated": "Non évalué", + "policyFailed": "Échec", + "recentPolicyDecisions": "Décisions de politique récentes", + "policyEvaluationsShown": "{count} évaluations affichées pour ce Wallet", + "needsApproval": "Nécessite une approbation", + "stepOf": "Étape {current} sur {total}", + "collapse": "Réduire", + "expand": "Développer", + "policyActivationOutcome": "Résultat de l’activation", + "policyDefault": "Par défaut", + "policyAllowUnmatched": "Autoriser les opérations sans correspondance", + "policyRevision": "Révision", + "policyProviderMapping": "Mappage du fournisseur", + "policySdpEnforced": "Appliqué par SDP", + "policyNoRestrictionCategory": "Aucune catégorie de restriction sélectionnée.", + "policyNoOperationsBlocked": "Aucune famille d’opérations bloquée", + "policyNoAddresses": "Aucune adresse", + "policyNoApprovalChecks": "Aucun contrôle d’approbation", + "policyNoAdvancedControls": "Aucun contrôle de signature avancé", + "savedDraft": "Draft enregistré", + "policyApplyControls": "Appliquer les contrôles", + "policyChooseOperationFamilies": "Choisissez les familles d’opérations à bloquer.", + "policyPasteAddresses": "Collez les adresses Solana approuvées ou une colonne d’adresses CSV.", + "policySetCaps": "Définissez un plafond par transfert, quotidien, ou les deux.", + "policyChooseApprovalFamilies": "Choisissez les familles d’opérations devant être suspendues pour approbation.", + "policyBlockAdvanced": "Bloquez la signature brute, les interactions de programme, ou les deux.", + "new": "Nouveau", + "policyProviderMappingPending": "Mappage du fournisseur en attente", + "policyProviderMapped": "Fournisseur mappé", + "policyProviderPartiallyMapped": "Fournisseur partiellement mappé", + "policyProviderMappingFailed": "Échec du mappage du fournisseur", + "policyBlockFamilies": "Bloquer {families}", + "policyDenyFamilies": "Refuser {families}", + "policyDestinationCount": "{count} adresses", + "policyInvalidCount": "{count} non valides", + "policyAllowedCount": "{count} autorisées", + "policyPerTransferValue": "Par transfert : {value}", + "policyDailyValue": "Quotidien : {value}", + "sandboxProjectUnavailable": "Projet Sandbox indisponible. Rechargez le tableau de bord et réessayez.", + "sendingSignerCheck": "Envoi de la vérification du Signer.", + "signerCheckFailed": "Échec de la vérification du Signer.", + "signerCheckSent": "Vérification du Signer envoyée.", + "memoTransactionSubmitted": "Transaction Memo soumise.", + "viewOnSolanaExplorer": "Voir dans Solana Explorer", + "requestingDevnetSol": "Demande de SOL Devnet.", + "devnetFaucetFailed": "Échec du faucet Devnet.", + "devnetSolRequested": "{amount} SOL Devnet demandés.", + "faucetTransactionSubmitted": "Transaction du faucet soumise.", + "walletActionsFor": "Actions du Wallet pour {wallet}", + "proving": "Preuve...", + "proveOwnershipUnsupported": "Prouver la propriété (non pris en charge)", + "proveOwnership": "Prouver la propriété", + "proveOwnershipAdminOnly": "Prouver la propriété (Admin uniquement)", + "requesting": "Demande...", + "requestDevnetSol": "Demander des SOL Devnet", + "policyRuleAllowedDestinations": "Destinations autorisées", + "policyRulePerTransferLimit": "Limite par transfert", + "policyRuleApprovalChecks": "Contrôles d’approbation", + "policyRevisionNew": "Nouveau", + "policyPerTransferCap": "Plafond par transfert", + "policyDailyCap": "Plafond quotidien", + "policyPositiveNumber": "Saisissez un nombre positif.", + "policyAddressPlaceholder": "adresse 9xQeWvG816bUx9EPfuxEzHh9VY5k...", + "policyDisable": "Désactiver", + "policyApprovalRequest": " / Approbation {id}", + "playgroundProviderField": "Fournisseur", + "playgroundLabelField": "Libellé", + "playgroundPurposeField": "Usage", + "playgroundMemoField": "Memo", + "policyOperationEditorDescription": "Les familles sélectionnées sont refusées avant signature/exécution. Les autres restent en allow par défaut sauf autre règle.", + "policyDestinationEditorDescription": "Collez des adresses Solana séparées par des sauts de ligne, virgules, points-virgules, tabulations ou une colonne CSV.", + "policyInvalidAddress": "Adresse non valide : {addresses}", + "policyInvalidAddresses": "Adresses non valides : {addresses}", + "policyApprovalEditorDescription": "Les familles sélectionnées sont mises en pause (approbation requise). Le routage inbox est géré par le workflow d’approbation.", + "policyAdvancedEditorDescription": "Ces contrôles sont volontairement stricts, car ils peuvent contourner l’intention de paiement de haut niveau.", + "providerCategoryApi": "API", + "providerCategoryApiDescription": "Infrastructure de Wallet pour les flux produit, opérationnels et automatisés pilotés par API.", + "providerCategoryInstitutional": "Institutionnel", + "providerCategoryInstitutionalDescription": "Custody politique pour trésorerie, settlement et approbations multiparty.", + "existingApiKeysDescription": "Clés actives et historiques pour cet espace de travail.", + "apiKeysViewOnly": "Vous pouvez voir les clés API, mais seuls les Admins peuvent les créer, renouveler ou supprimer.", + "apiKeyRotationHint": "Conseil : ne rotatez que les clés actives. Grâce dashboard 24 h ; API pour 0–168 h. Nouveau secret affiché une fois.", + "editApiKey": "Modifier la clé API", + "walletSearchPlaceholder": "Rechercher par nom, ID de portefeuille, adresse, fournisseur ou objectif", + "clearWalletSearch": "Effacer la recherche de portefeuille", + "clearWalletSearchAction": "Effacer la recherche", + "walletSearchResults": "Affichage de {count} sur {total} portefeuilles", + "noWalletSearchResults": "Aucun portefeuille ne correspond à cette recherche", + "noWalletSearchResultsDescription": "Essayez un autre nom, ID de portefeuille, adresse, fournisseur ou objectif.", + "next": "Suivant", + "policyAuthoringIntentTitle": "Que doit contrôler ce portefeuille ?", + "policyAuthoringIntentDescription": "Définissez la décision par défaut, puis choisissez les domaines nécessitant des contrôles explicites.", + "policyAuthoringLimitsTitle": "Limites et actifs", + "policyAuthoringLimitsDescription": "Définissez des limites de transfert génériques et choisissez les actifs couverts par ce profil.", + "policyAuthoringDestinationsTitle": "Destinations et opérations", + "policyAuthoringDestinationsDescription": "Contrôlez où ce portefeuille peut agir et quelles opérations nécessitent une décision spécifique.", + "policyAuthoringReviewTitle": "Vérifier et activer", + "policyAuthoringReviewDescription": "Confirmez le profil complet avant qu'il ne modifie l'application active.", + "policyDefaultAction": "Décision par défaut", + "policyDefaultActionDescription": "S'applique uniquement lorsqu'aucune règle ne correspond.", + "policyDefaultAllow": "Autoriser par défaut", + "policyDefaultApproval": "Exiger une approbation par défaut", + "policyDefaultDeny": "Refuser par défaut", + "policyRestrictionCategories": "Catégories de restrictions", + "policyRestrictionCategoriesDescription": "Choisissez les domaines de contrôle à configurer dans ce profil.", + "policyRestrictionRequired": "Choisissez au moins une catégorie de restriction lorsque l'action par défaut est autoriser.", + "policyCategoryLimitsDescription": "Définissez un maximum par transaction ou sur une journée.", + "policyAllowedAssets": "Actifs autorisés", + "policyAllowedAssetsDescription": "Limitez ce profil aux actifs de portefeuille sélectionnés ou à toute adresse de mint Solana.", + "policyDestinationControls": "Contrôles de destination", + "policyDestinationControlsDescription": "Maintenez une liste d'autorisation ou de blocage ordonnée d'adresses Solana.", + "policyOperationControls": "Contrôles d'opérations", + "policyOperationControlsDescription": "Choisissez une décision pour les familles d'opérations du portefeuille et les types d'opérations exacts.", + "policyPerTransaction": "Par transaction", + "policyDailyTotal": "Total quotidien", + "policyNoGenericLimit": "Laissez vide pour aucune limite générique.", + "policyInvalidDecimal": "Saisissez une valeur décimale positive.", + "policyDailyBelowTransaction": "Le total quotidien ne peut pas être inférieur au montant par transaction.", + "policySearchAssets": "Rechercher des actifs du portefeuille ou saisir une adresse de mint", + "policyWalletAssets": "Actifs du portefeuille", + "policySelectedAssets": "Actifs sélectionnés", + "policySelectedAssetCount": "{count} sélectionné(s)", + "policyCustomMint": "Mint personnalisé", + "policyNoMatchingAssets": "Aucun actif de portefeuille correspondant.", + "policyAddCustomMint": "Ajouter un mint personnalisé", + "policyInvalidMint": "Entrez une adresse de mint Solana valide.", + "policyDuplicateAsset": "Cet actif est déjà sélectionné.", + "policyAssetRequired": "Sélectionnez au moins un actif ou supprimez cette catégorie.", + "policyRemoveAsset": "Supprimer {asset}", + "policyNoStepControls": "Aucun contrôle de cette étape n'a été sélectionné. Vous pouvez continuer ou revenir à Intent pour les ajouter.", + "policyAllowList": "Liste d'autorisation", + "policyBlockList": "Liste de blocage", + "policyWalletAddresses": "Adresses de portefeuille", + "policyWalletAddressesPlaceholder": "11111111111111111111111111111111, So11111111111111111111111111111111111111112", + "policyCommaSeparatedAddresses": "Séparez les adresses Solana par des virgules.", + "policyValidAddressCount": "{count} adresses valides", + "policyInvalidAddressEntry": "Entrée {position} : {address} n'est pas une adresse Solana valide.", + "policyDestinationRequired": "Ajoutez au moins une adresse valide ou supprimez cette catégorie.", + "policyOperationFamilies": "Familles d'opérations", + "policyTransfers": "Transferts", + "policyProgramOperations": "Opérations de programme", + "policyProviderAdministration": "Administration du fournisseur", + "policyActionAllow": "Autoriser", + "policyActionDeny": "Refuser", + "policyActionApproval": "Exiger une approbation", + "policyAdvancedOperationTypes": "Types d'opérations avancés", + "policyAdvancedOperationDescription": "Ajoutez des chaînes de type d'opération exactes lorsqu'une décision au niveau de la famille n'est pas assez spécifique.", + "policyViewOperationPermissions": "Voir toutes les permissions d'opération prises en charge", + "policyOperationTypePlaceholder": "ex. : payment_transfer_execute", + "policyAddOperationType": "Ajouter un type d'opération", + "policyOperationTypeDuplicate": "Ce type d'opération est déjà configuré.", + "policyOperationTypeTooLong": "Les types d'opération doivent comporter 120 caractères ou moins.", + "policyOperationRequired": "Configurez au moins une famille ou un type d'opération, ou supprimez cette catégorie.", + "policyRemoveOperationType": "Supprimer {operationType}", + "policyApprovalRequiredAuthoring": "Sélectionnez au moins un contrôle d'approbation ou supprimez cette catégorie.", + "policySummary": "Récapitulatif de la politique", + "policySummaryWallet": "Portefeuille", + "policySummaryAddress": "Adresse", + "policySummaryStatus": "Statut", + "policySummaryDefaultAction": "Décision par défaut", + "policySummaryControlAreas": "Zones de contrôle", + "policySummarySelectedCount": "{count} sélectionné(s)", + "policySummaryRules": "Règles configurées", + "policySummaryAllowedAssets": "Actifs autorisés", + "policySummaryDestinations": "Entrées de destination", + "policySummaryApprovals": "Contrôles d'approbation", + "policySummaryProvider": "Correspondance du fournisseur", + "policyCopyAddress": "Copier l'adresse du portefeuille", + "policyAddressCopied": "Adresse du portefeuille copiée.", + "policyStatusDefaultAllow": "Autorisation par défaut", + "policyStatusNotActivated": "Non activé", + "policyStatusActive": "Actif", + "policyStatusDraft": "Brouillon", + "policyStatusDisabled": "Désactivé", + "policyStatusArchived": "Archivé", + "policyNotConfigured": "Non configuré", + "policyEdit": "Modifier", + "policyReviewTransferLimits": "Limites de transfert", + "policyReviewAllowedAssets": "Actifs autorisés", + "policyReviewDestinationControls": "Contrôles de destination", + "policyReviewOperationControls": "Contrôles d'opération", + "policyReviewProviderMapping": "Mappage du fournisseur", + "policyReviewPerTransaction": "Par transaction {amount}", + "policyReviewDailyTotal": "Total quotidien {amount}", + "policyReviewAssetCount": "{count} actifs", + "policyReviewDestinationCount": "{count} entrées {mode}", + "policyReviewOperationCount": "{count} contrôles d'opération", + "policyReviewPreservedRules": "Inclut {count} règles avancées existantes.", + "policySaveDraft": "Enregistrer le brouillon", + "policyActivateControls": "Activer les contrôles", + "policyControlsActive": "Contrôles actifs", + "policyMoreActions": "Plus d'actions de politique", + "policyDisableControls": "Désactiver les contrôles", + "policyDisableTitle": "Désactiver les contrôles du portefeuille ?", + "policyDisableConfirmation": "Désactiver les contrôles pour {wallet} ? Cela rétablit l'autorisation par défaut du portefeuille.", + "policyCancel": "Annuler", + "policyConfirmDisable": "Désactiver les contrôles", + "policyDraftStoredLocally": "Enregistré sur cet appareil {date}", + "policyActivationValidation": "Vérifiez les champs de politique surlignés avant l'activation.", + "policyProviderWarning": "Certains contrôles ne sont pas entièrement mappés au fournisseur de conservation et restent appliqués par SDP.", + "policyAuditTitle": "Audit de politique", + "policyAuditBreadcrumb": "Navigation dans l'audit de politique", + "policyAuditEvaluation": "Évaluation", + "policyAuditBackToWalletControls": "Retour aux contrôles du portefeuille", + "policyAuditBackToAudit": "Retour à l'audit", + "policyAuditRevisionHistory": "Historique des révisions", + "policyAuditWalletHistory": "Historique des politiques de {wallet}", + "policyAuditWalletHistoryDescription": "Examinez les décisions de politique en utilisant la révision qui était appliquée lors de l'évaluation de chaque opération.", + "policyAuditDecision": "Décision", + "policyAuditAllowed": "Autorisé", + "policyAuditBlocked": "Bloqué", + "policyAuditApprovalRequired": "Approbation requise", + "policyAuditReview": "Révision", + "policyAuditNotEvaluated": "Non évalué", + "policyAuditAllDecisions": "Toutes les décisions", + "policyAuditOperationStatus": "Statut de l'opération", + "policyAuditAllStatuses": "Tous les statuts", + "policyAuditOperationFamily": "Famille d'opérations", + "policyAuditAllFamilies": "Toutes les familles", + "policyAuditReasonCode": "Code de motif", + "policyAuditAllReasons": "Tous les motifs", + "policyAuditFromDate": "Date de début", + "policyAuditToDate": "Date de fin", + "policyAuditApplyFilters": "Appliquer les filtres", + "policyAuditClearFilters": "Effacer les filtres", + "policyAuditMoreFilters": "Plus de filtres", + "policyAuditOperation": "Opération", + "policyAuditAssetAmount": "Actif / montant", + "policyAuditDestination": "Destination", + "policyAuditApiKeyActor": "Clé API / acteur", + "policyAuditAppliedRevision": "Révision appliquée", + "policyAuditActiveRevision": "Révision active", + "policyAuditEvaluated": "Évalué", + "policyAuditOpenEvaluation": "Ouvrir l'évaluation", + "policyAuditEmpty": "Aucune évaluation de règle pour l'instant", + "policyAuditEmptyDescription": "Les décisions de règle apparaîtront ici après l'évaluation des opérations du portefeuille.", + "policyAuditEmptyFiltered": "Aucune évaluation ne correspond aux filtres actifs.", + "policyAuditDefaultAllow": "Autorisation par défaut", + "policyAuditNoActiveRevision": "Aucune révision active", + "policyAuditUnavailable": "Indisponible", + "policyAuditUnavailableApiKey": "Clé API indisponible", + "policyAuditRange": "{from}-{to} sur {total}", + "policyAuditPreviousPage": "Page précédente", + "policyAuditNextPage": "Page suivante", + "policyAuditPageOf": "Page {page} sur {pageCount}", + "policyAuditTransferAllowed": "Transfert autorisé", + "policyAuditTransferBlocked": "Transfert bloqué", + "policyAuditSentToReview": "Envoyé pour examen", + "policyAuditPrevious": "Précédent", + "policyAuditNext": "Suivant", + "policyAuditRequest": "Requête", + "policyAuditRevisions": "Révisions", + "policyAuditDetailTabs": "Détail de l'audit de règle", + "policyAuditEvaluationSequence": "Séquence d'évaluation", + "policyAuditWalletPolicyEvaluation": "Évaluation de la règle du portefeuille", + "policyAuditApiKeyPolicyEvaluation": "Évaluation de la règle de la clé API", + "policyAuditMatchedRule": "Règle correspondante", + "policyAuditObservedValueContext": "Valeur observée / contexte", + "policyAuditEffectiveLimitExpectation": "Limite effective / attente", + "policyAuditFinalDecision": "Décision finale", + "policyAuditRecorded": "Enregistré", + "policyAuditApplied": "Appliqué", + "policyAuditRawDetails": "Voir les détails bruts", + "policyAuditNoRecordedValues": "Aucune valeur n'a été enregistrée.", + "policyAuditYes": "Oui", + "policyAuditNo": "Non", + "policyAuditNone": "Aucun", + "policyAuditAppliedRevisionAtEvaluation": "Révision appliquée lors de l'évaluation", + "policyAuditCurrentlyActiveRevision": "Révision actuellement active", + "policyAuditHistoricalRevisionNotice": "Cette décision historique utilisait une révision différente de celle qui est active actuellement.", + "policyAuditApiKeyAppliedRevision": "Révision de la clé API lors de l'évaluation", + "policyAuditApiKeyActiveRevision": "Révision de la clé API actuellement active", + "policyAuditNoAdditionalRestriction": "Aucune restriction supplémentaire", + "policyAuditEvaluatedAt": "Évalué le {date}", + "policyAuditRevisionId": "ID de révision", + "policyAuditEvaluationId": "ID d'évaluation", + "policyAuditOperationId": "ID d'opération", + "policyAuditRequestId": "ID de demande", + "policyAuditApiKeyId": "ID de clé API", + "policyAuditRequestContext": "Contexte de la demande", + "policyAuditRedactedContext": "Contexte expurgé enregistré avec cette évaluation.", + "policyAuditLegacyContextEmpty": "Aucun contexte de demande structuré n'a été enregistré pour cette évaluation.", + "policyAuditEvaluationContext": "Contexte d'évaluation", + "policyAuditApiKey": "Clé API", + "policyAuditActor": "Acteur", + "policyAuditProviderMapping": "Mappage du fournisseur", + "policyAuditApprovalRequest": "Demande d'approbation", + "policyAuditProviderPending": "Mappage du fournisseur en attente", + "policyAuditProviderPartial": "Partiellement mappé", + "policyAuditProviderFailed": "Échec du mappage du fournisseur", + "policyAuditProviderApproval": "Approbation du fournisseur requise", + "policyAuditSdpEnforced": "SDP appliqué", + "policyAuditViewWalletControls": "Voir les contrôles du portefeuille", + "policyAuditViewApiKey": "Voir la clé API", + "policyAuditViewApprovalRequest": "Voir la demande d'approbation", + "policyAuditUnavailableTitle": "Historique des politiques indisponible", + "policyAuditUnavailableDescription": "L'historique des politiques du portefeuille n'a pas pu être chargé pour le moment.", + "policyRevisionsTitle": "Révisions de politique", + "policyRevisionsWalletHistory": "Historique des révisions de {wallet}", + "policyRevisionsDescription": "Inspectez les instantanés de règles immuables sans modifier les contrôles actifs du portefeuille.", + "policyRevisionsEmpty": "Aucune révision de politique pour l'instant", + "policyRevisionsEmptyDescription": "Une révision apparaîtra après l'enregistrement des contrôles du portefeuille.", + "policyRevisionsNewestFirst": "Révision la plus récente en premier", + "policyRevisionNumber": "Révision v{number}", + "policyRevisionsCreated": "Créée", + "policyRevisionsActivated": "Activée", + "policyRevisionsRules": "Règles", + "policyRevisionsCreator": "Créateur", + "policyRevisionsSystem": "Système", + "policyRevisionsActive": "Active", + "policyRevisionsHistorical": "Historique", + "policyRevisionsDraft": "Brouillon", + "policyRevisionsRuleSnapshot": "Instantané de règles en lecture seule", + "policyRevisionsSnapshotDescription": "Cet instantané immuable est affiché exactement tel qu'il a été stocké pour cette révision.", + "policyRevisionsDefaultAction": "Action par défaut", + "policyRevisionsNoRules": "Aucune règle explicite n'a été stockée dans cette révision.", + "policyRevisionsRuleNumber": "Règle {number}", + "policyRevisionsRawRule": "Voir les données brutes de la règle", + "apiKeyStepDetails": "Détails", + "apiKeyStepPermissions": "Autorisations", + "apiKeyStepWalletAccess": "Accès au portefeuille", + "apiKeyStepReview": "Vérifier", + "apiKeyAuthoringProgress": "Progression de la création de la clé API", + "apiKeyDetailsTitle": "Détails de la clé", + "apiKeyDetailsDescription": "Nommez la clé et choisissez sa date d'expiration.", + "apiKeyIdentity": "Identité de la clé", + "apiKeyPermissionsTitle": "Autorisations des points de terminaison", + "apiKeyPermissionsDescription": "Choisissez les points de terminaison SDP auxquels cette clé peut accéder.", + "apiKeyRoleFixedOnEdit": "Le rôle reste fixe après la création. Le périmètre du portefeuille et de la politique peut encore être mis à jour.", + "apiKeyRoleDescription": { + "api_admin": "Accès complet aux points de terminaison, y compris les opérations administratives.", + "api_developer": "Accès standard aux jetons, paiements, contreparties, portefeuilles, conformité et webhooks.", + "api_readonly": "Accès en lecture seule aux ressources opérationnelles et aux données d'audit." + }, + "apiKeyFullEndpointAccess": "Accès complet aux points de terminaison", + "apiKeyPermissionCount": "{count} autorisations de point de terminaison", + "apiKeyPermissionsSeparateFromPolicy": "Les autorisations des points de terminaison déterminent la portée. Les contrôles du portefeuille et les restrictions de clé API sont évalués séparément pour chaque opération.", + "apiKeyWalletPolicyTitle": "Accès au portefeuille et à la politique", + "apiKeyWalletPolicyDescription": "Choisissez où cette clé peut signer et quels contrôles supplémentaires s'appliquent.", + "apiKeyAllWalletsHelper": "Cette clé peut accéder aux portefeuilles autorisés par ses permissions de point de terminaison.", + "apiKeySelectedWalletCount": "Portefeuilles sélectionnés ({count})", + "apiKeySearchWallets": "Rechercher des portefeuilles", + "apiKeyNoWalletSearchResults": "Aucun portefeuille ne correspond à cette recherche.", + "apiKeySelectWallet": "Sélectionner {wallet}", + "apiKeyMakeDefaultWallet": "Faire de {wallet} le portefeuille de signature par défaut", + "apiKeyMakeDefaultSigningWallet": "Définir comme portefeuille de signature par défaut", + "apiKeyWalletControlsEnforced": "Les contrôles du portefeuille sont toujours appliqués.", + "apiKeyWalletControlsDescription": "Les restrictions de clé API peuvent réduire ces contrôles, mais ne peuvent pas les contourner ni les remplacer.", + "apiKeyNoWalletBaseline": "Aucune référence de contrôle du portefeuille n'est disponible tant qu'un portefeuille n'est pas sélectionné.", + "apiKeyPolicyStatusDefaultAllow": "Autorisation par défaut", + "apiKeyPolicyStatusDraft": "Brouillon", + "apiKeyPolicyStatusDisabled": "Désactivé", + "apiKeyActiveRevision": "Révision {revision}", + "apiKeyRestrictionsTitle": "Restrictions de clé API", + "apiKeyAddRestrictions": "Ajouter des restrictions de clé API", + "apiKeyNoAdditionalRestrictions": "Aucune restriction de clé API supplémentaire", + "apiKeyRestrictionsNarrowCopy": "Ces restrictions réduisent l'accès en plus des contrôles du portefeuille.", + "apiKeyExistingRestrictionsActive": "Restrictions de clé API actives", + "apiKeyExistingRestrictionsPreserved": "Le profil actif reste inchangé jusqu'à ce que vous remplaciez explicitement ses détails de restriction.", + "apiKeyExistingRestrictionsPreservedShort": "Restrictions existantes conservées", + "apiKeyReplaceRestrictionDetails": "Remplacer les détails de restriction", + "apiKeyAdditionalDefaultAction": "Restriction supplémentaire : action par défaut", + "apiKeyAdditionalOperationFamilies": "Restriction supplémentaire : familles d'opérations", + "apiKeyAdditionalOperationTypes": "Restriction supplémentaire : types d'opérations", + "apiKeyAdditionalAssets": "Restriction supplémentaire : actifs", + "apiKeyAdditionalAmounts": "Restriction supplémentaire : contraintes de montant", + "apiKeyAdditionalDestinations": "Restriction supplémentaire : destinations", + "apiKeyAdditionalApprovals": "Restriction supplémentaire : exigences d'approbation", + "apiKeyFamilyTransfer": "Transferts", + "apiKeyFamilyPayment": "Paiements", + "apiKeyFamilyRamp": "Rampes", + "apiKeyFamilyIssuance": "Émission", + "apiKeyFamilyRawSign": "Signature brute", + "apiKeyFamilyProgram": "Interactions de programme", + "apiKeyFamilyProviderAdmin": "Administration du fournisseur", + "apiKeyOperationTypesPlaceholder": "payment_transfer_execute, token_mint", + "apiKeyAssetsPlaceholder": "USDC, SOL", + "apiKeyMaximumAmount": "Montant maximal d'opération", + "apiKeyMaximumAmountPlaceholder": "2500", + "apiKeyDestinationsPlaceholder": "Collez les adresses Solana autorisées", + "apiKeyRequireApproval": "Exiger une approbation pour les opérations atteignables", + "apiKeyRequireApprovalDescription": "Les opérations correspondantes sont suspendues jusqu'à ce qu'une décision d'approbation soit enregistrée.", + "apiKeyRestrictionAmountInvalid": "Saisissez un montant décimal positif.", + "apiKeyReviewTitle": "Vérifier la clé API", + "apiKeyReviewDescription": "Confirmez l'identité, la portée des points de terminaison, les contrôles de portefeuille et les restrictions supplémentaires.", + "apiKeyReviewIdentity": "Identité de la clé", + "apiKeyReviewPermissions": "Autorisations des points de terminaison", + "apiKeyReviewWalletAccess": "Accès au portefeuille", + "apiKeyReviewWalletBaseline": "Référence des contrôles de portefeuille", + "apiKeyReviewRestrictions": "Restrictions supplémentaires de clé API", + "apiKeyReviewBindingChanges": "Modifications des liaisons", + "apiKeyRestrictionRuleCount": "{count} règles de restriction supplémentaires", + "apiKeyDefaultAllowWarning": "Les contrôles de portefeuille utilisent l'autorisation par défaut pour : {wallets}.", + "apiKeyRestrictionNoReachableWalletWarning": "Des restrictions de clé API sont configurées, mais aucun portefeuille sélectionné n'est atteignable.", + "apiKeySummaryTitle": "Résumé de la clé", + "apiKeySummaryPermissions": "Autorisations", + "apiKeySummarySelectedWallets": "Portefeuilles sélectionnés", + "apiKeySummaryWalletBaseline": "Référence des contrôles de portefeuille", + "apiKeySummaryRestrictions": "Restrictions de clé API", + "apiKeySummaryBindingScope": "Périmètre de liaison", + "apiKeyAllReachableWallets": "Tous les portefeuilles atteignables", + "apiKeyWalletControlsAlwaysApply": "Les contrôles de portefeuille s'appliquent toujours. Les restrictions de clé API ne réduisent que l'accès résultant.", + "apiKeyNoPolicyBindings": "Aucune liaison de stratégie ne sera créée", + "apiKeyBindingsUnchanged": "Les liaisons existantes restent inchangées", + "apiKeyBindingsWillClear": "Les liaisons existantes seront supprimées après confirmation", + "apiKeyBindingsWillCreate": "Les restrictions seront liées à ce périmètre de portefeuille", + "apiKeyBindingsWillReplace": "Les liaisons existantes seront remplacées après confirmation", + "apiKeyRestrictionReplacementRequired": "Remplacez les détails de restriction existants avant de modifier le périmètre du portefeuille pour cette clé.", + "apiKeyAffectedWallets": "Portefeuilles concernés", + "apiKeyReplaceBindings": "Remplacer les liaisons", + "apiKeyClearBindings": "Supprimer les liaisons", + "apiKeyReplaceBindingsTitle": "Remplacer les liaisons de stratégie ?", + "apiKeyClearBindingsTitle": "Supprimer les liaisons de stratégie ?", + "apiKeyReplaceBindingsDescription": "Les liaisons actuelles pour ces portefeuilles seront supprimées et remplacées par le périmètre proposé.", + "apiKeyClearBindingsDescription": "Les liaisons actuelles pour ces portefeuilles seront supprimées. Les contrôles de portefeuille continueront de s'appliquer.", + "apiKeySaveChanges": "Enregistrer les modifications", + "apiKeyUpdated": "Clé API \"{name}\" mise à jour.", + "apiKeySaveFailed": "La clé API n'a pas pu être enregistrée : {error}", + "apiKeyEditMissingId": "L'identifiant de la clé API est requis pour enregistrer les modifications.", + "apiKeyReplaceBindingsConfirmationRequired": "Confirmez Remplacer les liaisons avant d'enregistrer cette modification de liaison.", + "apiKeyClearBindingsConfirmationRequired": "Confirmez Supprimer les liaisons avant d'enregistrer cette modification de liaison." + } +} diff --git a/apps/sdp-web/messages/fr/dashboard-issuance.json b/apps/sdp-web/messages/fr/dashboard-issuance.json new file mode 100644 index 000000000..40d536234 --- /dev/null +++ b/apps/sdp-web/messages/fr/dashboard-issuance.json @@ -0,0 +1,867 @@ +{ + "DashboardIssuance": { + "transactions": { + "title": "Transactions", + "description": "Opérations Token récentes", + "loading": "Chargement de l'historique des opérations…", + "empty": "Aucune transaction.", + "type": "Type", + "status": "Statut", + "signature": "Signature", + "created": "Créé", + "showing": "Affichage des {count} premières transactions{total}. Utilisez la pagination pour voir les anciennes." + }, + "errors": { + "unknown": "Erreur inconnue", + "requestFailed": "Échec de la demande", + "unavailable": "indisponible", + "apiRequestFailed": "{resource} API {status} : {error}", + "tokenResource": "Token", + "templateResource": "Template", + "walletResource": "Wallet", + "tokenListRetry": "Impossible de charger la liste des Token. Actualisez la page pour réessayer.", + "tokenListCreateOrRetry": "Impossible de charger la liste des Token. Vous pouvez créer un Token ou réessayer bientôt.", + "unableToLoadTemplates": "Impossible de charger les Templates", + "unableToLoadTokens": "Impossible de charger les Token", + "unableToLoadSignerWallets": "Impossible de charger les Wallets Signer.", + "mintUnavailable": "Mint indisponible — {reason}", + "burnUnavailable": "Burn indisponible — {reason}", + "assetProfileNotFound": "Profil Asset introuvable.", + "assetProfileLoadFailed": "Impossible de charger le profil Asset ({status}) : {error}", + "tokenDetailsSaveFailed": "Impossible d'enregistrer les détails du Token ({status}) : {error}", + "assetProfileUpdateFailed": "Les détails du Token sont enregistrés, mais la mise à jour du profil Asset a échoué ({status}) : {error}. Réessayez.", + "changesSaved": "Modifications enregistrées.", + "unableToSaveChanges": "Impossible d'enregistrer les modifications.", + "assetProfilesDisabled": "Les profils Asset ne sont pas activés pour cet environnement.", + "assetDraftCreateFailed": "Impossible de créer le Draft Asset ({status}) : {error}", + "assetDraftCreated": "Draft Asset créé.", + "unableToCreateAssetDraft": "Impossible de créer le Draft Asset.", + "metadataUriHttp": "L'URI des métadonnées doit utiliser http ou https.", + "metadataUriValid": "L'URI des métadonnées doit être une URL valide.", + "tokenNameRequired": "Le nom du Token est requis.", + "symbolFormat": "Le symbole doit compter 1 à 10 caractères : lettres, chiffres ou points.", + "invalidTemplate": "Sélection de Template invalide.", + "decimalsRange": "Decimals doit être compris entre 0 et 18.", + "createFailed": "Échec de création ({status}) : {error}", + "draftCreated": "Draft {name} créé. Deploy Onchain depuis la page Token.", + "unexpected": "Erreur inattendue", + "symbolRequired": "Le symbole est requis.", + "symbolCharacters": "Utilisez 1 à 10 lettres, chiffres ou points.", + "decimalsWholeNumber": "Saisissez un nombre entier entre 0 et 18.", + "descriptionRequired": "La description est requise.", + "validUrl": "Saisissez une URL valide (https://…).", + "fieldRequired": "{field} est requis.", + "field": "Champ", + "classificationRequired": "Choisissez une classification et un sous-type d'Asset.", + "assetNameRequired": "Le nom de l'Asset est requis." + }, + "controlLists": { + "title": "Listes de contrôle", + "controlList": "Liste de contrôle", + "entriesTitle": "Entrées {label}", + "descriptionWithList": "Entrées {label} et statut des comptes Freeze", + "descriptionWithoutList": "Statut des comptes Freeze", + "entriesCount": "{count} entrées", + "showingEntries": "Affichage des {count} premières entrées.", + "frozenAccounts": "Comptes Freeze", + "accountsCount": "{count} comptes", + "showingAccounts": "Affichage des {count} premiers comptes." + }, + "wallet": { + "none": "Aucun", + "unlabeled": "Wallet sans libellé", + "walletId": "ID Wallet", + "publicKey": "Clé publique", + "customAddress": "Adresse personnalisée", + "chooseOrPaste": "Choisissez un Wallet ou collez une adresse Solana", + "clear": "Effacer {label}", + "selectExisting": "Sélectionner un Wallet existant", + "filterHint": "Saisissez pour filtrer les Wallets, utilisez la liste ou collez une adresse Solana." + }, + "saveBar": { + "unsaved": "Vous avez des modifications non enregistrées", + "unsavedWithErrors": "Modifications non enregistrées — {count} champ{suffix} à vérifier", + "discard": "Ignorer", + "save": "Enregistrer", + "saving": "Enregistrement…" + }, + "confirmation": { + "notNow": "Pas maintenant" + }, + "modal": { + "close": "Fermer la fenêtre", + "closeConfirmation": "Fermer la confirmation", + "tokenManagementAction": "Action de gestion du Token" + }, + "signer": { + "label": "Signer", + "select": "Sélectionner un Wallet Signer", + "requiredAuthorityHint": "SDP signera cette action avec le Wallet de l'autorité requise.", + "selectedWalletHint": "SDP signera cette transaction avec le Wallet sélectionné.", + "defaultSignerHint": "Aucun Wallet Signer disponible — SDP utilisera le Signer par défaut du projet.", + "noneAvailable": "Aucun Wallet Signer disponible." + }, + "header": { + "tokenLogo": "Logo du Token {name}", + "notDeployed": "Non Deploy", + "copyTokenAddress": "Copier l'adresse du Token", + "tokenId": "ID Token", + "copyTokenId": "Copier l'ID Token", + "explorer": "Explorer", + "deploy": "Deploy", + "unpause": "Unpause" + }, + "create": { + "title": "Nouveau brouillon Token", + "closeModal": "Fermer la création de Token", + "createDraft": "Créer le Draft", + "requiredFields": "Les champs marqués * sont requis.", + "required": "(requis)", + "tokenName": "Nom du Token", + "tokenNamePlaceholder": "ex. USD Coin", + "symbol": "Symbole", + "symbolPlaceholder": "ex. USDC", + "decimals": "Decimals", + "decimalsPlaceholder": "ex. 6", + "decimalsError": "Saisissez un nombre entier entre 0 et 18.", + "stablecoinDecimalsHelper": "Stablecoin utilise 6 Decimals par défaut, mais vous pouvez choisir de 0 à 18.", + "customDecimalsHelper": "Les Token personnalisés utilisent 9 Decimals par défaut. Choisissez de 0 à 18.", + "tokenizedSecurityDecimalsHelper": "Tokenized Security utilise 8 Decimals par défaut, mais vous pouvez choisir de 0 à 18.", + "decimalsHelper": "Choisissez une valeur de 0 à 18.", + "back": "Retour", + "continue": "Continuer", + "mainSigner": "Signer principal", + "selectSignerWallet": "Sélectionner le Wallet Signer", + "mainSignerHint": "Ce Wallet sera le Signer principal du Token pour le Deploy et les actions ultérieures.", + "loadingSignerWallets": "Chargement des Wallets Signer…", + "noControlledWallets": "Aucun Wallet contrôlé disponible. Le Token utilisera le Signer par défaut.", + "transferControls": "Contrôles de transfert", + "transferControlsHint": "Choisissez le traitement des adresses de destination approuvées ou bloquées.", + "creating": "Création...", + "creatingDraft": "Création du Draft Token.", + "unableToLoadSignerWallets": "Impossible de charger les Wallets Signer.", + "unableToCreateDraft": "Impossible de créer le Draft Token.", + "draftCreated": "Draft créé. Deploy Onchain depuis la page Token.", + "configureDraft": "Configurez le Draft, puis Deploy Onchain depuis la page Token.", + "chooseTemplate": "Choisissez un Template pour créer un Draft, puis Deploy Onchain.", + "stablecoinTemplateName": "Stablecoin", + "tokenizedSecurityTemplateName": "Tokenized Security", + "customTemplateName": "Token personnalisé", + "stablecoinTemplateDescription": "Créez un Stablecoin conforme avec restrictions de transfert.", + "tokenizedSecurityTemplateDescription": "Créez un Tokenized Security conforme avec Scaled UI Amount et contrôles essentiels.", + "customTemplateDescription": "Créez votre Token avec contrôle total des extensions et paramètres.", + "createStablecoinDraft": "Créer un Draft Stablecoin", + "createTokenizedSecurityDraft": "Créer un Draft Tokenized Security", + "createCustomTokenDraft": "Créer un Draft Token personnalisé", + "createTokenDraft": "Créer un Draft Token", + "denylist": "Denylist", + "allowlist": "Allowlist", + "disabled": "Désactivé", + "denylistDescription": "Les destinations listées sont bloquées avant de recevoir des actions contrôlées.", + "allowlistDescription": "Seules les destinations approuvées peuvent recevoir des actions Token contrôlées.", + "disabledDescription": "Ce Token n'utilisera pas de liste de contrôle des transferts.", + "stablecoinDenylistNote": "Recommandé par défaut pour les Stablecoin.", + "stablecoinAllowlistNote": "À utiliser si les transferts doivent rester entre Wallets connus.", + "securityAllowlistNote": "Par défaut pour les Tokenized Security.", + "securityDenylistNote": "À utiliser si le Token reste ouvert sauf pour les Wallets bloqués.", + "customDisabledNote": "Idéal pour les Token personnalisés sans restriction.", + "customAllowlistNote": "Activez si le Token exige un accès de transfert restreint." + }, + "status": { + "draft": "Draft", + "active": "Actif", + "paused": "En pause", + "revoked": "Révoqué" + }, + "tabs": { + "overview": "Aperçu", + "details": "Détails", + "publicInformation": "Informations publiques", + "compliance": "Conformité", + "operations": "Opérations", + "permissions": "Permissions" + }, + "workspace": { + "tokenLoadWarning": "Avertissement de chargement du Token", + "tokenPaused": "Le Token est en pause", + "pausedHint": "Les actions Mint, Burn et transfert administratif sont désactivées jusqu'à Unpause du Token.", + "unpauseToken": "Unpause Token", + "deployToken": "Deploy Token", + "deployHint": "Ceci va Deploy le Token Onchain pour permettre les opérations.", + "cancel": "Annuler", + "deployNow": "Deploy maintenant", + "runningAction": "Exécution de l'action...", + "tokenListUnavailable": "Liste des Token indisponible", + "search": "Rechercher", + "createDraft": "Créer un Draft", + "noTokensMatch": "Aucun Token ne correspond à votre recherche.", + "tokenLogo": "Logo {name}", + "type": "Type", + "supply": "Supply", + "created": "Créé", + "manage": "Gérer", + "addNewToken": "Ajouter un Token", + "active": "Actif", + "draft": "Draft" + }, + "management": { + "tokenAmountDescription": "Unités Token (ex. 1 ou 1,5). Conversion en unités brutes selon les Decimals.", + "untitledToken": "Token sans titre", + "allowlist": "Allowlist", + "denylist": "Denylist", + "allowlistDescription": "Gérez les adresses de destination approuvées pour ce Token.", + "denylistDescription": "Gérez les adresses de destination bloquées pour ce Token.", + "allowlistSummaryDescription": "Entrées Allowlist et statut des comptes Freeze", + "denylistSummaryDescription": "Entrées Denylist et statut des comptes Freeze", + "allowlistEntries": "Entrées Allowlist", + "denylistEntries": "Entrées Denylist", + "addAllowlistEntry": "Ajouter une entrée Allowlist", + "addDenylistEntry": "Ajouter une entrée Denylist", + "removeEntry": "Supprimer l'entrée", + "noAllowlistEntries": "Aucune entrée Allowlist.", + "noDenylistEntries": "Aucune entrée Denylist.", + "allowlistAddressRequired": "L'adresse Allowlist est requise.", + "denylistAddressRequired": "L'adresse Denylist est requise.", + "allowlistExtensionHelper": "Les destinations Mint et de transfert contrôlé doivent être dans l'Allowlist du Token.", + "denylistExtensionHelper": "Les destinations listées sont bloquées pour les opérations Mint et de transfert contrôlé.", + "denylistFreezeHint": "Restreindre un Wallet avant son compte Token ? Ajoutez-le d'abord à la Denylist.", + "defaultAccountState": "État de compte par défaut", + "defaultAccountStateHelper": "État par défaut des nouveaux comptes Token.", + "transferFee": "Frais de transfert", + "transferFeeHelper": "Configuration des frais pour les transferts Token.", + "scaledUiAmount": "Scaled UI Amount", + "scaledUiAmountHelper": "Contrôles du multiplicateur de Supply UI.", + "transferHook": "Transfer Hook", + "transferHookHelper": "Hook de programme de logique de transfert personnalisée.", + "interestBearing": "Interest Bearing", + "interestBearingHelper": "Mises à jour de solde basées sur le taux d'intérêt.", + "nonTransferable": "Non transférable", + "nonTransferableHelper": "Désactive les transferts standard entre comptes.", + "template": "Template", + "templateHelper": "Template de base appliqué à ce Token.", + "mintable": "Compatible Mint", + "mintableHelper": "Autorise les opérations Mint après Deploy.", + "freezable": "Compatible Freeze", + "freezableHelper": "Autorise les contrôles Freeze/Unfreeze des comptes.", + "configured": "Configuré", + "enabled": "Activé", + "disabled": "Désactivé", + "overview": "Aperçu", + "permissions": "Permissions", + "permissionsDescription": "Clés Onchain contrôlant Mint, Freeze et métadonnées de ce Token.", + "extensions": "Extensions", + "extensionsDescription": "Configurées à la création et en lecture seule après Deploy.", + "edit": "Modifier", + "compliance": "Conformité", + "metadata": "Métadonnées", + "operations": "Opérations", + "mintTokens": "Mint Tokens", + "mintHelper": "Créez une nouvelle Supply dans un Wallet ou compte Token de destination.", + "mint": "Mint", + "burnTokens": "Burn Tokens", + "burnHelper": "Retirez la Supply d'un Wallet ou compte Token source.", + "burn": "Burn", + "unableToLoadData": "Impossible de charger les données de gestion du Token.", + "supportingDataRequestFailed": "Échec de la demande de données Token ({status}).", + "supportingDataEmpty": "La réponse des données Token était vide.", + "authorityWalletRequestFailed": "Échec de la demande du Wallet d'autorité ({status}).", + "unableToLoadSignerWallets": "Impossible de charger les Wallets Signer.", + "loadingSignerWallets": "Chargement des Wallets Signer…", + "onlyAdminsCanEditAuthorities": "Seuls les administrateurs peuvent modifier les autorités Token.", + "deployToken": "Deploy Token", + "deployHelper": "Deploy ce Token Onchain avant les autres opérations de fonds.", + "deployConfirmationTitle": "Deploy Token ?", + "deployConfirmationDescription": "Ceci soumettra la transaction Deploy Onchain.", + "deployNow": "Deploy maintenant", + "copied": "Copié", + "unableToCopy": "Impossible de copier", + "tokenNameRequired": "Le nom du Token est requis.", + "updateToken": "Mettre à jour le Token", + "submittingDeploy": "Soumission de la transaction Deploy...", + "deployFinalized": "Transaction Deploy finalisée.", + "refreshSupply": "Actualiser la Supply", + "mintDetailsRequired": "La destination Mint et le montant sont requis.", + "amountPositive": "Le montant doit être positif.", + "mintConfirmationTitle": "Mint Tokens ?", + "mintConfirmationDescription": "Ceci soumettra une transaction Mint Onchain.", + "mintNow": "Mint maintenant", + "submittingMint": "Soumission de la transaction Mint...", + "mintFinalized": "Transaction Mint finalisée.", + "burnDetailsRequired": "La source Burn et le montant sont requis.", + "burnConfirmationTitle": "Burn Tokens ?", + "burnConfirmationDescription": "Ceci soumettra une transaction Burn Onchain.", + "burnNow": "Burn maintenant", + "submittingBurn": "Soumission de la transaction Burn...", + "burnFinalized": "Transaction Burn finalisée.", + "seizeDetailsRequired": "La source, la destination et le montant Seize sont requis.", + "seizeConfirmationTitle": "Force transfer ?", + "seizeConfirmationDescription": "Ceci soumettra une transaction Seize (Force transfer) Onchain.", + "transferNow": "Transfer maintenant", + "submittingForceTransfer": "Soumission de la transaction Force transfer...", + "forceTransferFinalized": "Transaction Force transfer finalisée.", + "forceBurnDetailsRequired": "La source Force burn et le montant sont requis.", + "forceBurnConfirmationTitle": "Force burn Tokens ?", + "forceBurnConfirmationDescription": "Ceci soumettra une transaction Force burn Onchain.", + "forceBurnNow": "Force burn maintenant", + "submittingForceBurn": "Soumission de la transaction Force burn...", + "forceBurnFinalized": "Transaction Force burn finalisée.", + "updateAuthority": "Mettre à jour l'autorité", + "updateAuthorityLabel": "Mettre à jour {authority}", + "updatingAuthority": "Mise à jour de {authority}...", + "authorityUpdated": "{authority} mise à jour.", + "authorityConfirmationTitle": "Mettre à jour l'autorité ?", + "authorityConfirmationDescription": "Ceci soumettra une transaction de mise à jour d'autorité Onchain.", + "updateNow": "Mettre à jour", + "submittingAuthority": "Soumission de la mise à jour d'autorité...", + "authorityFinalized": "Mise à jour d'autorité finalisée.", + "pauseToken": "Mettre le Token en pause", + "unpauseToken": "Unpause Token", + "pauseConfirmationTitle": "Mettre le Token en pause ?", + "unpauseConfirmationTitle": "Unpause Token ?", + "pauseConfirmationDescription": "Ceci soumettra une transaction de pause Onchain.", + "unpauseConfirmationDescription": "Ceci soumettra une transaction Unpause Onchain.", + "pauseNow": "Mettre en pause", + "unpauseNow": "Unpause maintenant", + "submittingPause": "Soumission de la transaction de pause...", + "submittingUnpause": "Soumission de la transaction Unpause...", + "pauseFinalized": "Transaction de pause finalisée.", + "unpauseFinalized": "Transaction Unpause finalisée.", + "accountAddressRequired": "L'adresse du compte est requise.", + "unfreezeAccount": "Unfreeze compte", + "unfreezeConfirmationTitle": "Unfreeze compte ?", + "unfreezeConfirmationDescription": "Ceci soumettra une transaction Unfreeze Onchain.", + "unfreezeNow": "Unfreeze maintenant", + "submittingUnfreeze": "Soumission de la transaction Unfreeze...", + "unfreezeFinalized": "Transaction Unfreeze finalisée.", + "freezeAccount": "Freeze compte", + "freezeConfirmationTitle": "Freeze compte ?", + "freezeConfirmationDescription": "Ceci soumettra une transaction Freeze Onchain.", + "freezeNow": "Freeze maintenant", + "submittingFreeze": "Soumission de la transaction Freeze...", + "freezeFinalized": "Transaction Freeze finalisée.", + "removeAllowlistEntry": "Supprimer l'entrée Allowlist", + "tokenIdCopied": "ID Token copié", + "loadingAuthorityWalletAccess": "Chargement de l'accès au Wallet d'autorité…", + "loadingComplianceControls": "Chargement des contrôles de conformité…", + "deploySignerHint": "Payez les frais de transaction et de compte depuis le Wallet Signer ou avec le parrainage Kora.", + "deployWithWallet": "Deploy avec Wallet", + "koraUnavailable": "Le parrainage Kora est indisponible.", + "deployWithKora": "Deploy avec Kora", + "destinationNotAllowlisted": "La destination n'est pas dans l'Allowlist de ce Token.", + "destinationDenylisted": "La destination est dans la Denylist de ce Token.", + "actionPaused": "Le Token est en pause. Unpause pour {action}.", + "actionRequiresActive": "Le Token doit être actif pour {action}.", + "actionRevoked": "Le Token est révoqué et ne peut plus {action}.", + "forceTransfer": "Force transfer", + "forceBurn": "Force burn", + "mintingDisabled": "Mint est désactivé pour ce Token.", + "noMintAuthorityConfigured": "Aucune autorité Mint n'est configurée.", + "maximumSupplyReached": "La Supply maximale est atteinte.", + "supplyZero": "La Supply est nulle.", + "noPermanentDelegateAuthority": "L'autorité Permanent Delegate n'est pas configurée.", + "noSupplyHeld": "Aucune Supply n'est actuellement détenue.", + "revokedTokensCannotPause": "Les Token révoqués ne peuvent pas être mis en pause ou Unpause.", + "pauseRequiresActiveToken": "Le Token doit être Deploy et actif avant les contrôles de pause.", + "noPauseAuthorityConfigured": "Aucune autorité de pause n'est configurée. Définissez d'abord une autorité pausable ou Mint.", + "freezingDisabled": "Freeze est désactivé pour ce Token.", + "noFreezeAuthorityConfigured": "Aucune autorité Freeze n'est configurée.", + "unknownError": "Erreur inconnue", + "unknown": "inconnu", + "ok": "ok", + "executionRouteFailed": "Échec de la route d'exécution ({status})", + "actionFailed": "Échec de {action} ({status}) : {error}", + "actionSucceeded": "{action} réussi ({status})", + "requestFailed": "Échec de la demande", + "mintAuthorityHelper": "Peut Mint de nouveaux Tokens.", + "freezeAuthorityHelper": "Peut Freeze et Unfreeze les comptes Token.", + "metadataAuthorityHelper": "Peut mettre à jour les métadonnées Token.", + "permanentDelegateHelper": "Peut effectuer des opérations déléguées de transfert/Burn.", + "noControlledWalletsAvailable": "Aucun Wallet contrôlé ne peut signer cette action.", + "noSignerConfigured": "Aucun Signer n'est configuré pour cette action.", + "requiredSignerNotControlled": "Le Signer requis ne fait pas partie de vos Wallets contrôlés.", + "mintAuthorityNotControlled": "L'autorité Mint ne fait pas partie de vos Wallets contrôlés.", + "permanentDelegateNotControlled": "L'autorité Permanent Delegate ne fait pas partie de vos Wallets contrôlés.", + "authority": "autorité", + "noAuthorityConfigured": "Aucune {authority} n'est configurée.", + "authorityNotControlled": "{authority} ne fait pas partie de vos Wallets contrôlés.", + "freezeAuthorityNotControlled": "L'autorité Freeze ne fait pas partie de vos Wallets contrôlés.", + "pauseAuthorityNotControlled": "L'autorité de pause ne fait pas partie de vos Wallets contrôlés.", + "validMintAmount": "Saisissez un montant Mint valide pour ce Token.", + "mintAmountPositive": "Le montant Mint doit être supérieur à zéro.", + "mintAmountExceedsSupplyCap": "Le montant Mint dépasse le plafond de Supply restant de {amount} {symbol}.", + "validBurnAmount": "Saisissez un montant Burn valide pour ce Token.", + "burnAmountPositive": "Le montant Burn doit être supérieur à zéro.", + "burnAmountExceedsSupply": "Le montant Burn dépasse la Supply actuelle de {amount} {symbol}.", + "standardBurnSignerOnly": "Le Burn standard ne fonctionne que depuis le Wallet Signer sélectionné. Utilisez Force burn pour un autre Wallet.", + "selectedSignerDoesNotHoldToken": "Le Wallet Signer sélectionné ne détient pas ce Token.", + "selectedWalletOnlyShows": "Le Wallet sélectionné affiche seulement {amount} {symbol}.", + "destinationMustDiffer": "La destination doit différer de la source.", + "validTransferAmount": "Saisissez un montant de transfert valide pour ce Token.", + "transferAmountPositive": "Le montant du transfert doit être supérieur à zéro.", + "selectedSourceDoesNotHoldToken": "Le Wallet source sélectionné ne détient pas ce Token.", + "forceBurnAmountPositive": "Le montant Force burn doit être supérieur à zéro.", + "forceBurnAmountExceedsSupply": "Le montant Force burn dépasse la Supply actuelle de {amount} {symbol}.", + "submittingAction": "Soumission de {action}...", + "transactionFinalized": "Transaction finalisée.", + "transactionFailed": "Échec de la transaction.", + "sendTransaction": "Envoyer la transaction ?", + "sendTransactionDescription": "Ceci soumettra une transaction Onchain. Voulez-vous continuer ?", + "goAhead": "Continuer", + "token": "Token" + }, + "forms": { + "saveMetadata": "Enregistrer les métadonnées", + "updateMetadata": "Mettre à jour les métadonnées", + "updateMetadataDescription": "Modifier les métadonnées Token.", + "name": "Nom", + "enterTokenName": "Saisissez un nom de Token.", + "description": "Description", + "uri": "URI", + "imageUrl": "URL de l'image", + "mintDescription": "Mint vers le Wallet ou compte Token de destination.", + "destination": "Destination", + "enterSolanaAddress": "Saisissez une adresse Solana valide.", + "destinationPlaceholder": "Wallet ou compte Token de destination", + "amount": "Montant", + "memo": "Memo", + "burnDescription": "Burn depuis le Wallet ou compte Token source.", + "source": "Source", + "sourcePlaceholder": "Wallet Signer ou son compte Token", + "sourceWalletPlaceholder": "Wallet ou compte Token source", + "forceTransferDescription": "Transfert Seize administratif entre comptes.", + "forceBurnDescription": "Force burn administratif depuis le compte source.", + "mintAuthority": "Autorité Mint", + "freezeAuthority": "Autorité Freeze", + "permanentDelegate": "Permanent Delegate", + "metadataAuthority": "Autorité des métadonnées", + "updateAuthority": "Mettre à jour l'autorité", + "updateAuthorityDescription": "Faites pivoter ou supprimez les autorités Token.", + "role": "Rôle", + "currentAuthorityOptional": "Autorité actuelle (facultatif)", + "newAuthorityEmptyToRemove": "Nouvelle autorité (vide pour supprimer)", + "pauseControls": "Contrôles de pause", + "pauseControlsDescription": "Mettre en pause ou reprendre les transferts du Token.", + "alreadyPaused": "Le Token est déjà en pause.", + "notPaused": "Le Token n'est pas en pause.", + "freezeControls": "Contrôles Freeze", + "freezeControlsDescription": "Freeze ou libérez les avoirs Token d'un Wallet pour ce Mint.", + "walletAddress": "Adresse Wallet", + "enterWalletAddress": "Saisissez l'adresse Wallet. SDP dérivera automatiquement le compte Token associé pour ce Mint.", + "walletAddressPlaceholder": "Adresse Wallet détenant ce Token", + "walletAddressInstruction": "Saisissez l'adresse Wallet détenant ce Token. SDP dérive automatiquement le compte Token associé pour ce Mint.", + "freezeReason": "Motif (Freeze uniquement)", + "controlListDescription": "Gérez les adresses de destination approuvées pour ce Token.", + "address": "Adresse", + "label": "Libellé", + "enterLabel": "Saisissez un libellé ou laissez vide.", + "noLabel": "Sans libellé", + "removeEntry": "Supprimer l'entrée" + }, + "authority": { + "resolvedAutomatically": "Résolu automatiquement depuis l'état du Token", + "closeModal": "Fermer la fenêtre d'autorité", + "save": "Enregistrer l'autorité", + "current": "Autorité actuelle", + "whatThisMeans": "Ce que cela implique", + "confirmNone": "Oui, définir sur Aucun", + "new": "Nouvelle autorité", + "selectWallet": "Sélectionner un Wallet contrôlé", + "custom": "Autorité personnalisée", + "solanaAddress": "Adresse Solana", + "noneWalletWarning": "Choisir Aucun effacera cette autorité. Vous confirmerez avant soumission.", + "noneDescription": "Cette autorité sera effacée si vous enregistrez cette modification.", + "controlledWalletHint": "Les Wallets contrôlés sont les cibles d'autorité recommandées.", + "useCustom": "Utiliser une adresse personnalisée", + "chooseWallet": "Choisir un Wallet contrôlé", + "solanaAddressOrNone": "Adresse Solana ou laissez vide pour définir Aucun", + "enterAddressOrNone": "Saisissez une adresse Solana valide ou laissez vide pour définir l'autorité sur Aucun.", + "noWalletsHint": "Aucun Wallet contrôlé disponible. Saisissez une adresse ou laissez vide pour définir l'autorité sur Aucun.", + "noneFieldWarning": "Définir ce champ sur Aucun effacera l'autorité. Vous confirmerez avant soumission.", + "mintNoneTitle": "Définir l'autorité Mint sur Aucun ?", + "mintNoneDescription": "Ceci effacera l'autorité Mint du Token.", + "mintNoneImpact": "Aucun Wallet ne pourra Mint de Supply supplémentaire après cette modification.", + "freezeNoneTitle": "Définir l'autorité Freeze sur Aucun ?", + "freezeNoneDescription": "Ceci effacera l'autorité Freeze du Token.", + "freezeNoneImpact": "Les comptes Token ne pourront plus être Freeze ou Unfreeze après cette modification.", + "delegateNoneTitle": "Définir l'autorité Permanent Delegate sur Aucun ?", + "delegateNoneDescription": "Ceci effacera l'autorité Permanent Delegate du Token.", + "delegateNoneImpact": "Les actions administratives de transfert délégué et Burn ne seront plus disponibles après cette modification.", + "metadataNoneTitle": "Définir l'autorité des métadonnées sur Aucun ?", + "metadataNoneDescription": "Ceci effacera l'autorité des métadonnées du Token.", + "metadataNoneImpact": "Les mises à jour de métadonnées ne seront plus disponibles via cette autorité après cette modification." + }, + "wizard": { + "stepOf": "Étape {current} sur {total}", + "creatingDraft": "Création du Draft Asset…", + "draftCreated": "Draft Asset créé.", + "failedToCreate": "Échec de création du Draft.", + "creating": "Création…", + "reviewAndFinish": "Vérifier et terminer", + "reviewDescription": "Vérifiez tous les détails ci-dessous. Vous pouvez modifier chaque section avant de créer votre Draft." + }, + "confirmDraft": { + "ariaLabel": "Créer le Draft Asset", + "title": "Créer ce Draft Asset ?", + "descriptionStart": "Ceci crée un Draft", + "of": "de", + "descriptionEnd": ". Vous pouvez continuer à le modifier et le publier lorsque vous êtes prêt." + }, + "summary": { + "title": "Résumé", + "assetCategory": "Catégorie d'Asset", + "assetType": "Type d'Asset", + "peggedTo": "Indexé sur", + "accessControl": "Contrôle d'accès", + "transferRestrictions": "Restrictions de transfert", + "investorReporting": "Reporting investisseurs", + "enabled": "Activé", + "lastUpdated": "Dernière mise à jour", + "resolveBeforeCreating": "À résoudre avant création", + "readyToCreate": "Vous pouvez créer un Draft", + "readyDescription": "Vous pouvez vérifier, modifier et publier lorsque vous êtes prêt.", + "privateByDefault": "Privé par défaut", + "privateDescription": "Les détails fournis sont privés et servent uniquement à configurer votre Asset." + }, + "classificationRail": { + "title": "Fonctionnement", + "assetProfile": "Profil Asset", + "assetProfileDescription": "Vous sélectionnez la catégorie et le type. SDP stocke vos métadonnées d'émission canoniques.", + "issuanceMetadata": "Métadonnées d'émission", + "issuanceMetadataDescription": "Inclut les champs Asset, conformité, chaîne et personnalisés (client/intégration).", + "publicProjection": "Projection publique", + "publicProjectionDescription": "SDP projette un sous-ensemble public sûr vers les métadonnées Token.", + "tokenMetadataUri": "URI des métadonnées Token", + "tokenMetadataUriDescription": "SDP héberge l'URI par défaut qui renvoie uniquement les métadonnées publiques.", + "privateDescription": "Les métadonnées de conformité et personnalisées restent privées sauf inclusion explicite dans la projection publique." + }, + "assetProfileForm": { + "fixHighlightedFields": "Corrigez les champs en surbrillance avant d'enregistrer." + }, + "templates": { + "stablecoinName": "Stablecoin", + "stablecoinDescription": "Stablecoin adossés à l'USD avec contrôles de conformité.", + "stablecoinHelper": "Idéal pour Assets fiat-pegged avec contrôles de transfert et Freeze admin.", + "tokenizedSecurityName": "Tokenized Security", + "tokenizedSecurityDescription": "Assets réglementés avec Allowlist par défaut.", + "tokenizedSecurityHelper": "Conçu pour les instruments réglementés exigeant des contrôles des participants.", + "customName": "Personnalisé", + "customDescription": "Configuration Token-2022 entièrement personnalisable.", + "customHelper": "Commencez par un profil vide et ajustez les paramètres d'émission aux exigences avancées." + }, + "overview": { + "title": "Aperçu du Token", + "tokenAddress": "Adresse Token", + "mintAuthority": "Autorité Mint", + "supply": "Supply", + "template": "Template", + "totalSupply": "Supply totale", + "readyForDeploy": "Prêt pour Deploy", + "readyForDeployDescription": "Cet Asset est prêt pour Deploy — continuez dans l'onglet Opérations.", + "mintAddress": "Adresse Mint", + "notDeployedYet": "Pas encore Deploy", + "noDescription": "Aucune description — ajoutez-en une dans l'onglet Détails." + }, + "operations": { + "deployHelper": "Deploy ce Token Onchain avant les autres opérations de fonds." + }, + "taxonomy": { + "stablecoin": "Stablecoin", + "stablecoinDescription": "Assets conçus pour maintenir une valeur stable, généralement adossés à des monnaies fiat ou autres Assets liquides.", + "fiatBacked": "Adossé à une monnaie fiat", + "fiatBackedDescription": "Adossé à 1:1 à des réserves de monnaie fiat détenues dans des institutions financières réglementées.", + "cryptoBacked": "Adossé aux crypto-actifs", + "cryptoBackedDescription": "Garanti par des crypto-actifs sous garde pour maintenir la parité.", + "tokenizedSecurity": "Tokenized Security", + "tokenizedSecurityDescription": "Instruments financiers réglementés ou représentations numériques de titres.", + "equity": "Actions", + "equityDescription": "Actions Tokenized ou intérêts assimilés dans une entreprise.", + "debt": "Dette / Obligation", + "debtDescription": "Obligations, billets ou autres instruments de dette.", + "fund": "Fonds / ETF", + "fundDescription": "Parts de fonds ou actions de fonds négociés en bourse.", + "generic": "Asset numérique hors titre", + "genericDescription": "Autres Assets Tokenized ne relevant pas des catégories ci-dessus.", + "commodities": "Matières premières", + "commoditiesDescription": "Créances sur des matières premières physiques ou ressources naturelles.", + "realEstate": "Immobilier", + "realEstateDescription": "Intérêts immobiliers ou biens Tokenized.", + "collectibles": "Objets de collection", + "collectiblesDescription": "Assets de collection uniques ou en édition limitée." + }, + "config": { + "advanced": "Avancé", + "advancedCapacitiesDescription": "Les capacités recommandées sont présélectionnées selon le profil Asset.", + "usd": "USD", + "eur": "EUR", + "gbp": "GBP", + "jpy": "JPY", + "sgd": "SGD", + "unitedStates": "États-Unis", + "europeanUnion": "Union européenne", + "unitedKingdom": "Royaume-Uni", + "singapore": "Singapour", + "other": "Autre", + "regD": "Reg D", + "regS": "Reg S", + "regA": "Reg A+", + "publicOffering": "Offre publique", + "commodityBacked": "Adossé à une matière première", + "algorithmic": "Algorithmique", + "financialDetails": "Détails financiers", + "financialDetailsDescription": "Attributs financiers clés de l'Asset.", + "issuerName": "Nom de l'émetteur", + "issuerNamePlaceholder": "ex. Acme Financial Inc.", + "backingType": "Type de garantie", + "currency": "Devise", + "selectField": "Sélectionner {field}", + "searchCurrencies": "Rechercher des devises", + "pegTarget": "Parité ou cible", + "pegTargetPlaceholder": "1,00 USD", + "reserveAsset": "Asset de réserve", + "reserveAssetPlaceholder": "USD (dollar américain)", + "reserveCustodian": "Conservateur de réserve", + "reserveCustodianPlaceholder": "ex. Acme Treasury Ltd.", + "redemption": "Rachat", + "redemptionHelp": "Les détenteurs peuvent échanger les Tokens contre les réserves sous-jacentes.", + "securityDetails": "Détails du titre", + "securityDetailsDescription": "Informations sur l'émetteur et l'offre.", + "jurisdiction": "Juridiction", + "offeringType": "Type d'offre", + "categoryAssetDetails": "Détails de l'Asset", + "categoryAssetDetailsDescription": "Ce qui sous-tend ou représente cet Asset.", + "underlyingAsset": "Asset sous-jacent", + "underlyingAssetPlaceholder": "ex. Or, immobilier", + "custodian": "Conservateur", + "custodianPlaceholder": "ex. Acme Custody", + "allowList": "Liste autorisée", + "blockList": "Liste bloquée", + "kyc": "KYC", + "kycDescription": "Exige une vérification d'identité avant la détention ou le transfert de Tokens.", + "restrictTradingHours": "Restreindre les heures de négociation", + "restrictTradingHoursDescription": "Limitez les transferts Token à certains jours et créneaux horaires.", + "freezeTransfers": "Freeze les transferts", + "freezeTransfersDescription": "Freeze les Tokens en réponse à des événements de conformité ou enquêtes.", + "issueRetireControls": "Contrôles d'émission et retrait", + "issueRetireControlsDescription": "Contrôlez qui peut émettre de nouveaux Tokens ou retirer la Supply existante.", + "redemptionApprovals": "Approbations de rachat", + "redemptionApprovalsDescription": "Exige une approbation avant de racheter des Tokens contre les réserves sous-jacentes.", + "investorReporting": "Reporting investisseurs", + "investorReportingDescription": "Générez des rapports périodiques pour les investisseurs et parties prenantes.", + "transferApprovals": "Approbations de transfert", + "transferApprovalsDescription": "Exige une approbation pour les transferts au-delà d'un seuil défini." + }, + "playground": { + "tokenNameExample": "Acme Dollar", + "tokenSymbolExample": "ACME", + "selectTemplate": "Sélectionner un Template", + "settlementAssetExample": "Asset de règlement adossé à l'USD", + "metadataUriExample": "https://example.com/metadata/acme-usd.json", + "optionalHostedUri": "uri (facultatif — SDP héberge si omis)", + "updatedTokenName": "Nom du Token mis à jour", + "updatedTokenDescription": "Description du Token mise à jour", + "updatedMetadataUri": "https://example.com/updated-metadata.json", + "tokenImageUrl": "https://example.com/token.png", + "selectStatus": "Sélectionner un statut", + "active": "Actif", + "paused": "En pause", + "productName": "Émission", + "none": "Aucun", + "low": "Faible", + "medium": "Moyen", + "high": "Élevé", + "true": "Vrai", + "false": "Faux", + "selectPriorityFee": "Sélectionner options priorityFee", + "selectSimulate": "Sélectionner options simulate", + "amountPlaceholder": "ex. 1000", + "listTemplates": "Lister les Templates", + "getTemplate": "Obtenir le Template", + "createToken": "Créer un Token", + "listTokens": "Lister les Tokens", + "getToken": "Obtenir le Token", + "updateToken": "Mettre à jour le Token", + "listTokenTransactions": "Lister les transactions Token", + "refreshTotalSupply": "Actualiser la Supply totale", + "deployToken": "Deploy Token", + "mintTokens": "Mint Tokens", + "burnTokens": "Burn Tokens", + "seizeTokens": "Seize Tokens", + "forceBurn": "Force Burn", + "updateAuthority": "Mettre à jour l'autorité", + "pauseToken": "Mettre le Token en pause", + "unpauseToken": "Unpause Token", + "freezeAccount": "Freeze compte", + "unfreezeAccount": "Unfreeze compte", + "listFrozenAccounts": "Lister les comptes Freeze", + "listAllowlist": "Lister l'Allowlist", + "addAllowlistEntry": "Ajouter une entrée Allowlist", + "removeAllowlistEntry": "Supprimer une entrée Allowlist", + "tokenIdPlaceholder": "ID Token (ex. tok_abc123)", + "templateIdPlaceholder": "ID Template (ex. stablecoin)", + "authorityRoleMint": "Mint", + "authorityRoleFreeze": "Freeze", + "authorityRolePermanentDelegate": "Permanent Delegate", + "authorityRoleMetadata": "Métadonnées", + "solanaAddressPlaceholder": "Adresse Solana (32-44 caractères)", + "optionalMemo": "Memo facultatif", + "tokenAccountAddressPlaceholder": "Adresse de compte Token (32-44 caractères)", + "sourceTokenAccountAddress": "Adresse du compte Token source", + "destinationTokenAccountAddress": "Adresse du compte Token de destination", + "delegateAuthorityAddress": "Adresse de l'autorité Delegate", + "tokenAccountAddress": "Adresse de compte Token", + "selectAuthorityRole": "Sélectionner un rôle d'autorité", + "currentAuthorityAddress": "Adresse de l'autorité actuelle", + "newAuthorityAddress": "Adresse de la nouvelle autorité", + "walletAddressToFreeze": "Adresse Wallet à Freeze", + "optionalFreezeReason": "Motif Freeze facultatif", + "walletAddressToUnfreeze": "Adresse Wallet à Unfreeze", + "treasuryExample": "Trésorerie", + "addressToAllowlist": "Adresse à ajouter à l'Allowlist", + "optionalLabel": "Libellé facultatif", + "allowlistEntryIdPlaceholder": "ID d'entrée Allowlist (ex. allow_123)" + }, + "compliance": { + "forceTransfer": "Force transfer", + "forceBurn": "Force burn", + "freeze": "Freeze", + "pause": "Pause", + "accessPolicy": "Politique d'accès", + "accessPolicyDescription": "Documente la politique d'accès prévue pour cet Asset.", + "accessControl": "Contrôle d'accès", + "notSet": "Non défini", + "lockReason": "Verrouillé après Deploy — l'application Onchain ne peut pas être modifiée.", + "selectAccessControl": "Sélectionner un contrôle d'accès", + "appliedOnDeploy": "Appliqué Onchain lors du Deploy du Token.", + "controls": "Contrôles de conformité", + "controlsDescription": "Actions Onchain pour ce Token — elles prennent effet immédiatement." + }, + "classification": { + "title": "Quel est cet Asset ?", + "description": "Commencez par nous indiquer ce que représente cet Asset et sa classification.", + "name": "Nom", + "namePlaceholder": "ex. USD Workshop Money Market Fund", + "nameHint": "Un nom clair pour identifier cet Asset.", + "chooseClassification": "Choisir une classification", + "notSure": "Je ne sais pas quoi choisir", + "chooseAssetType": "Choisir un type d'Asset" + }, + "review": { + "assetTitle": "Asset", + "assetDescription": "L'Asset et sa représentation.", + "assetCategory": "Catégorie d'Asset", + "assetType": "Type d'Asset", + "name": "Nom", + "symbol": "Symbole", + "assetDetailsTitle": "Détails de l'Asset", + "assetDetailsDescription": "Informations clés sur l'Asset.", + "description": "Description", + "issuerName": "Nom de l'émetteur", + "decimals": "Decimals", + "website": "Site web", + "complianceAccessTitle": "Conformité et accès", + "complianceAccessDescription": "Contrôle de l'Asset et utilisateurs autorisés à interagir.", + "accessControl": "Contrôle d'accès", + "allowlist": "Liste autorisée", + "blocklist": "Liste bloquée", + "none": "Aucun", + "allowlistHint": "Seules les adresses approuvées peuvent détenir ou transférer.", + "blocklistHint": "Les adresses bloquées ne peuvent détenir ou transférer.", + "transferRestrictions": "Restrictions de transfert", + "enabled": "Activé", + "disabled": "Désactivé", + "transferRestrictionsHint": "Transferts limités aux participants approuvés.", + "investorReporting": "Reporting investisseurs", + "investorReportingHint": "Rapports d'activité disponibles pour investisseurs et parties prenantes.", + "publicInformationTitle": "Informations publiques", + "publicInformationDescription": "Les informations sûres visibles par tous.", + "publicName": "Nom public", + "publicSymbol": "Symbole public", + "logo": "Logo", + "publicDescription": "Description (publique)", + "edit": "Modifier", + "notProvided": "—" + }, + "publicInfo": { + "name": "Nom", + "symbol": "Symbole", + "description": "Description", + "decimals": "Decimals", + "category": "Catégorie", + "assetType": "Type d'Asset", + "logo": "Logo", + "untitledAsset": "Asset sans titre", + "notProvided": "—", + "publicTokenInformation": "Informations publiques du Token", + "publicTokenInfoHelp": "Voici comment votre Asset apparaîtra dans les Wallets, Explorers et au public.", + "includedInPublicView": "Inclus dans la vue publique", + "publicCount": "{count} publics", + "publicCoverage": "{publicCount} champs publics sur {totalCount}", + "notIncludedByDefault": "Non inclus par défaut", + "notIncludedHelp": "Ces champs restent privés sauf si vous choisissez de les inclure.", + "preview": "Aperçu", + "token": "Token", + "explorer": "Explorer", + "wallet": "Wallet", + "assetLogo": "Logo {name}", + "asset": "Asset", + "mintAddress": "Adresse Mint", + "copyMintAddress": "Copier l'adresse Mint", + "viewOnExplorer": "Voir dans Explorer", + "copied": "Copié", + "noPublicDescription": "Aucune description publique", + "decimalsValue": "{count} Decimals", + "alwaysPublic": "Toujours public — ne peut être masqué", + "hidePublicField": "Public — masquer ce champ", + "showPublicField": "Masqué — afficher ce champ publiquement" + }, + "assetDetails": { + "title": "Détails de l'Asset", + "description": "Ajoutez les informations clés sur cet Asset. Vous pouvez les modifier à tout moment.", + "tabs": { + "overview": "Aperçu", + "compliance": "Conformité et accès", + "operational": "Opérationnel", + "custom": "Champs personnalisés" + }, + "about": "À propos de cet Asset", + "namePlaceholder": "ex. Verde Dollar", + "lockedAfterCreation": "Verrouillé après création", + "aboutDescription": "Informations de base décrivant cet Asset.", + "symbolPlaceholder": "ex. vUSD", + "descriptionLabel": "Description", + "descriptionPlaceholder": "Décrivez ce que représente cet Asset.", + "website": "Site web", + "websitePlaceholder": "https://…", + "logoImageUrl": "URL de l'image du logo", + "logoPlaceholder": "https://…/logo.png", + "logoHint": "Affiché à côté de votre Token dans les Wallets et Explorers.", + "documents": "Documents et références", + "documentsDescription": "Documents et références importants liés à cet Asset.", + "accessControlDescription": "Choisissez comment ce Token traite les adresses de destination approuvées ou bloquées.", + "learnLists": "Découvrez la différence entre listes autorisées et bloquées", + "operational": "Opérationnel", + "operationalDescription": "Paramètres opérationnels facultatifs.", + "signingWallet": "Wallet de signature", + "optionalSignerHint": "Facultatif — ne sélectionnez rien pour utiliser le Signer par défaut du projet.", + "customFields": "Champs personnalisés", + "customFieldsDescription": "Ajoutez vos champs privés, stockés sous custom.customer.", + "projectDefaultSigner": "Signer par défaut du projet", + "signingWalletLockReason": "Défini à la création — les opérations peuvent utiliser un autre Signer.", + "documentTypePlaceholder": "Type de document", + "documentNamePlaceholder": "Nom", + "removeDocument": "Supprimer le document", + "addDocument": "Ajouter un document", + "hideJson": "Masquer JSON", + "viewJson": "Voir JSON", + "copied": "Copié !", + "customFieldKey": "Clé", + "customFieldValue": "Valeur", + "removeCustomField": "Supprimer le champ", + "addCustomField": "Ajouter un champ", + "copyJson": "Copier JSON" + }, + "assetProfileDetails": { + "privateByDefault": "Ces informations sont privées par défaut et ne seront pas visibles au public, sauf si vous choisissez de les inclure." + } + } +} diff --git a/apps/sdp-web/messages/fr/dashboard-payments.json b/apps/sdp-web/messages/fr/dashboard-payments.json new file mode 100644 index 000000000..3ee7c2fed --- /dev/null +++ b/apps/sdp-web/messages/fr/dashboard-payments.json @@ -0,0 +1,1016 @@ +{ + "DashboardPayments": { + "page": { + "unavailableStatus": "indisponible", + "unknownError": "Erreur inconnue", + "walletApiError": "Wallet API {status} : {error}", + "walletAggregateApiError": "Wallet agrégat API {status} : {error}", + "transferApiError": "Transfer API {status} : {error}" + }, + "workspace": { + "walletListRequestFailed": "Échec de la demande de liste Wallet ({status}).", + "walletAggregateRequestFailed": "Échec de la demande d'agrégation Wallet ({status}).", + "walletAggregateMissing": "La réponse globale Wallet ne contient pas de détails globaux.", + "walletPolicyRequestFailed": "Échec de la demande de stratégie Wallet ({status}).", + "transferListRequestFailed": "Échec de la demande de liste Transfer ({status}).", + "transferListMissing": "La réponse de la liste Transfer ne contient pas de données Transfer.", + "transferLookupFailed": "La recherche Transfer a échoué ({status}).", + "transferLookupMissing": "La réponse de recherche Transfer ne contient pas de données Transfer.", + "transferLookupMultiple": "La recherche Transfer a renvoyé plusieurs Transfers.", + "transferCancellationFailed": "Échec de l'annulation de Transfer ({status}).", + "rampEstimateRequestFailed": "Échec de la demande d'estimation Ramp ({status}).", + "rampEstimateMissing": "La réponse d'estimation Ramp ne contient pas d'estimations.", + "walletBalancesRequestFailed": "Échec de la demande de soldes Wallet ({status}).", + "walletBalancesMissing": "La réponse aux soldes Wallet ne contient pas de détails sur le solde.", + "walletPolicyUpdateFailed": "Échec de la mise à jour de la stratégie Wallet ({status}).", + "walletPolicyUpdateEmpty": "La mise à jour de la stratégie Wallet a renvoyé une réponse vide.", + "transferRequestFailed": "La requête Transfer a échoué ({status}).", + "transferMissing": "La réponse Transfer ne contient pas de détails sur Transfer.", + "recipientListRequestFailed": "La demande de liste de destinataires a échoué ({status}).", + "recipientListMissing": "La réponse de la liste des destinataires ne contient pas de destinataires.", + "batchEstimateRequestFailed": "Échec de la demande d'estimation Batch ({status}).", + "batchEstimateMissing": "La réponse d'estimation Batch ne contient pas de détails d'estimation.", + "batchTransferRequestFailed": "La requête Batch Transfer a échoué ({status}).", + "batchTransferMissing": "La réponse Batch Transfer ne contient pas de détails sur Batch.", + "rampEventRequestFailed": "La demande d'événement {provider} a échoué ({status}).", + "rampEventMissing": "La réponse à l'événement {provider} ne contient pas les détails de Transfer.", + "counterpartyAccountsRequestFailed": "Échec du chargement des comptes ({status}).", + "sandboxSimulationRequestFailed": "La simulation Sandbox a échoué ({status}).", + "requirementsRequestFailed": "Échec de la demande d'exigences ({status}).", + "requirementsAdvanceFailed": "Échec de l'avancement des exigences ({status}).", + "requirementsContextMissing": "Impossible de faire progresser les exigences sans provider et Counterparty.", + "complianceCheckFailed": "Le contrôle de conformité a échoué.", + "destinationRequired": "L'adresse de destination est requise.", + "transferBlocked": "Transfer bloqué.", + "transferBlockedDescription": "Exécutez un contrôle de conformité ou utilisez une destination déjà présente dans la source Wallet Allowlist.", + "transactionSent": "Transaction envoyée.", + "viewOnSolanaExplorer": "Afficher sur Solana Explorer", + "walletsLoadFailed": "Échec du chargement de Wallets.", + "walletPolicyLoadFailed": "Échec du chargement de la stratégie Wallet.", + "addressRequired": "L'adresse est requise.", + "complianceCheckRequired": "Exécutez un contrôle de conformité avant d’ajouter l’adresse.", + "addressAlreadyAllowlisted": "L'adresse est déjà dans la destination Allowlist.", + "addressAddedToAllowlist": "Adresse ajoutée à la destination Wallet Allowlist.", + "destinationAddressAddFailed": "Échec de l'ajout de l'adresse de destination.", + "sourceWalletRequired": "Sélectionnez d'abord une source Wallet.", + "destinationAllowlistLoadFailed": "Échec du chargement de la destination Allowlist." + }, + "paymentMethods": { + "onchainTransfer": "Transfer Onchain", + "onchainTransferDescription": "Envoyez du crypto depuis un SDP Wallet vers l'adresse Solana d'un Counterparty.", + "payWithFiat": "Payer en fiat", + "payWithFiatDescription": "Convertissez la crypto en fiat et payez via un provider.", + "onchainDeposit": "Dépôt Onchain", + "onchainDepositDescription": "Recevez du crypto directement à une adresse SDP Wallet.", + "depositWithFiat": "Déposer en fiat", + "depositWithFiatDescription": "Achetez de la crypto avec fiat via un provider et déposez-la dans un Wallet." + }, + "cancelTransaction": { + "ariaLabel": "Annuler la transaction", + "title": "Annuler cette transaction ?", + "description": "Cette transaction a déjà été lancée. Si vous annulez maintenant, vous quitterez le flux.", + "keepGoing": "Continuer", + "cancel": "Annuler la transaction" + }, + "sendMode": { + "single": "Unique", + "batch": "Batch", + "onchain": "Onchain" + }, + "ramps": { + "max": "MAX", + "recentTransfersRequestFailed": "La demande de Transfer récente a échoué.", + "recentTransfers": "Transfers récents", + "noRecentTransactions": "Aucune transaction récente.", + "chooseProvider": "Choisir un provider", + "unavailableCount": "{count} indisponible", + "noProvidersAvailable": "Aucun provider n'est disponible pour cette sélection.", + "unavailableProviders": "providers indisponibles", + "walletAddressQrCode": "Code QR d’adresse du Wallet", + "walletReceiveDescription": "Scannez ce code QR ou copiez l'adresse pour recevoir USDC ou n'importe quel SPL Token sur Solana dans le Wallet sélectionné.", + "addressCopied": "Adresse copiée.", + "copyAddress": "Copier l'adresse", + "convertTo": "Convertir en", + "currency": "Devise", + "selectCurrency": "Sélectionnez une devise", + "searchCurrencies": "Rechercher des devises", + "searchAssets": "Rechercher des Assets", + "balanceAvailable": "{amount} disponible", + "amount": "Montant", + "destinationWallet": "Wallet destination", + "sourceWallet": "Wallet source", + "detailsStep": "Détails", + "onrampDepositStep": "Dépôt", + "onrampDepositTitle": "Combien souhaitez-vous déposer ?", + "onrampProviderTitle": "Complétez votre dépôt", + "onrampRequirementsTitle": "Quelques détails pour continuer", + "offrampWalletStep": "Wallet", + "offrampWalletTitle": "De quel Wallet vous retirez-vous ?", + "offrampWithdrawStep": "Se retirer", + "offrampWithdrawTitle": "Combien souhaiteriez-vous retirer ?", + "offrampCompleteStep": "Terminé", + "offrampCompleteTitle": "Complétez votre paiement", + "payoutDetailsStep": "Détails du paiement", + "payoutDetailsTitle": "Où devons-nous envoyer le paiement ?", + "selectDestinationWallet": "Sélectionner un Wallet destination", + "selectSourceWallet": "Sélectionner un Wallet source", + "searchWallets": "Rechercher Wallets", + "fees": "Honoraires {providerFee} {providerCurrency} + {networkFee} {networkCurrency}", + "noFees": "Pas de frais", + "fee": "Frais {amount} {currency}", + "estimatedReceived": "Est. reçu", + "rateKnownAtQuote": "Taux connu à Quote", + "unavailable": "Indisponible", + "acceptTerms": "Accepter les conditions", + "completeVerification": "Vérification complète", + "tryAgain": "Réessayez", + "quoteMissingInstructions": "Il manque des instructions de paiement à Ramp Quote.", + "sendCrypto": "Envoyer {amount} {token}", + "quoteExpired": "Quote expiré", + "sending": "Envoi...", + "transferSubmitted": "Transfer soumis", + "transferFailed": "Échec de Transfer.", + "transactionSentSuccessfully": "Transaction envoyée avec succès.", + "transferStatus": "Statut : {status}", + "submittingOnchainTransfer": "Soumission en chaîne de Transfer.", + "simulatingQuoteFunding": "Simulation du financement Quote.", + "quoteFundingSimulated": "Financement Quote simulé.", + "quoteSimulationFailed": "La simulation Quote a échoué.", + "sandboxSimulationFailed": "La simulation Sandbox a échoué.", + "muralSandboxCurrencyUnsupported": "Le paiement Mural sandbox ne prend pas en charge {currency}.", + "transferSignatureMissing": "Transfer n'a pas renvoyé de signature (statut : {status}).", + "offrampManualDescription": "Envoyez {amount} {token} à l'adresse de dépôt ci-dessous avant l'expiration du Quote. Le provider le convertit au taux verrouillé et le verse automatiquement sur le compte bancaire enregistré.", + "noPayoutProviders": "Aucun provider de paiement n'est activé pour cette organisation.", + "providerPayout": "Paiement {provider}", + "noDepositProviders": "Aucun provider de dépôt n'est activé pour cette organisation.", + "providerDeposit": "Dépôt {provider}", + "quoteRequestFailedStatus": "La requête Ramp Quote a échoué ({status}).", + "quoteResponseMissingDetails": "La réponse Ramp Quote ne contient pas de détails sur Quote.", + "creatingQuote": "Création de Quote.", + "widgetReady": "Widget prêt.", + "quoteReady": "Quote prêt.", + "unableToCreateQuote": "Impossible de créer Quote.", + "quoteRequestFailed": "La requête Ramp Quote a échoué.", + "settingUpAccount": "Configuration de votre compte.", + "moreDetailsNeeded": "Nous avons besoin de quelques détails supplémentaires avant de continuer.", + "unableToStartOnboarding": "Impossible de commencer l'intégration.", + "requirementsRequestFailed": "La demande d'exigences a échoué.", + "nextStepSoon": "Prochaine étape à venir.", + "cannotCancelWithoutQuote": "Impossible d'annuler sans un Quote actif.", + "cancelingTransaction": "Annulation de la transaction.", + "transactionCanceled": "Transaction annulée.", + "unableToCancelTransaction": "Impossible d'annuler la transaction.", + "cancellationFailed": "L'annulation a échoué.", + "funded": "Financé", + "sent": "Envoyé", + "provider": "provider", + "finalFundedAmount": "Montant final financé", + "finalSentAmount": "Montant final envoyé", + "finalReceivedAmount": "Montant final reçu", + "finalPayoutAmount": "Montant du paiement final", + "completed": "Terminé", + "transferId": "Identifiant Transfer", + "quoteId": "Identifiant Quote", + "depositComplete": "Dépôt terminé", + "payoutComplete": "Paiement terminé", + "depositCompleteDescription": "Les fonds ont été réglés à la destination Wallet.", + "payoutCompleteDescription": "Le paiement a été réglé sur le compte bancaire du destinataire.", + "fundedWith": "financé avec", + "from": "de", + "newPayeeHint": "Créez un nouveau bénéficiaire s'il ne figure pas encore dans la liste.", + "newBuyerHint": "Créez un nouvel acheteur s'il n'est pas encore dans la liste.", + "destinationAccount": "Compte de destination", + "selectCounterpartyFirst": "Sélectionnez d'abord un Counterparty", + "noSolanaAccounts": "Aucun compte Solana enregistré", + "selectDestinationAccount": "Sélectionnez un compte de destination", + "searchAccounts": "Rechercher des comptes", + "assetBreakdown": "Panne Asset", + "total": "{amount} total", + "selectCounterparty": "Sélectionnez un Counterparty", + "searchCounterparties": "Rechercher des contreparties", + "counterpartiesLoadFailed": "Échec du chargement des contreparties.", + "openFullScreen": "Ouvrir en plein écran", + "selectField": "Sélectionnez {field}", + "search": "Rechercher…", + "stripeLoadError": "Impossible de charger le paiement Stripe", + "stripeLoadHelp": "La caisse Stripe n'a pas pu être chargée. Vérifiez votre connexion et réessayez.", + "moneygramEventFailed": "Échec de l'enregistrement de l'événement MoneyGram.", + "eventRequestFailed": "La demande d'événement a échoué.", + "moneygramCompletionBeforeTransfer": "MoneyGram a signalé l'achèvement avant que le crypto Transfer ne soit enregistré.", + "moneygramWidgetLoadFailed": "Échec du chargement du widget MoneyGram.", + "unsupportedMoneygramTransaction": "Transaction non prise en charge : {asset} sur {chain}.", + "sourceWalletNoUsdc": "La source Wallet n'a pas de solde USDC à envoyer.", + "coinbaseEventFailed": "Échec de l'enregistrement de l'événement Coinbase.", + "coinbaseOnramp": "Coinbase onramp", + "status": { + "waitingForFunding": "En attente de financement", + "waitingToSend": "En attente d'envoi", + "waitingForFundingDescription": "Envoyez les fonds en suivant les instructions ci-dessus. Nous mettrons à jour ce dépôt automatiquement une fois que le provider aura reçu le paiement.", + "waitingToSendDescription": "Effectuez le paiement en suivant les instructions ci-dessus. Nous mettrons à jour ce Transfer sortant automatiquement une fois que le provider aura reçu votre crypto.", + "depositReceived": "Dépôt reçu", + "sendingPayout": "Envoi du paiement", + "depositReceivedDescription": "Le provider a reçu des fonds et règle le dépôt à la destination Wallet.", + "sendingPayoutDescription": "Le provider a reçu votre crypto et règle le paiement sortant au destinataire.", + "transferComplete": "Transfer terminé", + "payoutSent": "Paiement envoyé", + "transferCompleteDescription": "Le dépôt est terminé. Vous pouvez consulter le Transfer à partir de l'enregistrement Counterparty.", + "payoutSentDescription": "Le paiement sortant a été réglé. Vous pouvez consulter ce Transfer à partir de l'enregistrement Counterparty.", + "transferFailed": "Échec de Transfer", + "payoutFailed": "Le paiement a échoué", + "transferFailedDescription": "Le provider a signalé que ce dépôt avait échoué. Consultez l'enregistrement Counterparty pour connaître le dernier état de Transfer.", + "payoutFailedDescription": "Le provider a signalé que ce paiement sortant avait échoué. Consultez l'enregistrement Counterparty pour connaître le dernier état de Transfer.", + "quoteExpired": "Quote expiré", + "quoteExpiredFundingDescription": "Ce Quote a expiré avant la fin du Transfer. Créez un nouveau Quote pour continuer le financement.", + "quoteExpiredPayoutDescription": "Ce Quote a expiré avant la fin du paiement. Créez un nouveau Quote pour poursuivre le retrait.", + "updated": "Statut Transfer mis à jour", + "currentProviderStatus": "Statut actuel du provider : {status}.", + "preparing": "Préparation du statut Transfer", + "preparingDescription": "Nous attendons le record Transfer lié à ce Quote." + } + }, + "onchainSend": { + "noAssets": "Ce Wallet n'a aucun élément disponible à envoyer.", + "addSolanaAddress": "Ajouter l'adresse Solana", + "counterpartyNoAddress": "{counterparty} n’a pas encore d’adresse Solana enregistrée.", + "thisCounterparty": "Ce Counterparty", + "attachDestination": "Joignez une autre adresse de destination pour ce Counterparty.", + "sourceWallet": "Source Wallet", + "selectSourceWallet": "Sélectionnez une source Wallet", + "searchWallets": "Rechercher Wallets", + "amount": "Montant", + "asset": "Asset", + "selectAsset": "Sélectionnez un Asset", + "memoOptional": "Memo (facultatif)", + "memoPlaceholder": "Ajouter une note pour ce Transfer", + "to": "À", + "destination": "Destination", + "destinationTitle": "Où doivent aller les fonds ?", + "details": "Détails", + "detailsTitle": "Que souhaiteriez-vous envoyer ?", + "review": "Examen", + "reviewTitle": "Avis Transfer", + "submittingTransfer": "Soumission de Transfer.", + "memo": "Memo", + "counterparty": "Counterparty", + "toCounterparty": "à {counterparty}", + "transferSubmitted": "Transfer soumis", + "transactionSent": "Transaction envoyée avec succès.", + "transferFailed": "Échec de Transfer.", + "transferSuccess": "Votre Transfer a été envoyé avec succès.", + "transferStatus": "Statut : {status}", + "viewOnExplorer": "Afficher sur l'explorateur" + }, + "onchainReceive": { + "wallet": "Wallet", + "walletTitle": "Quel Wallet devrait recevoir des fonds ?", + "receive": "Recevoir", + "receiveTitle": "Recevoir des fonds onchain" + }, + "bvnk": { + "verificationRequiredTitle": "Vérifiez votre identité", + "verificationRequiredDescription": "BVNK s'associe à Sumsub pour confirmer votre identité avant d'activer votre compte de financement. Cliquez sur « Vérification complète » pour commencer : cette page s'actualise automatiquement une fois que vous êtes approuvé et vos instructions apparaîtront ici.", + "verificationInReviewTitle": "Vérification en cours d'examen", + "verificationInReviewDescription": "Sumsub examine vos informations – cela ne prend généralement que quelques minutes. N'hésitez pas à revenir plus tard ; vos instructions apparaîtront ici dès que vous serez approuvé.", + "verificationFailedTitle": "La vérification de l'identité n'a pas été approuvée", + "verificationFailedDescription": "BVNK n’a pas pu vérifier votre identité : ce compte de financement ne peut pas être activé. Contactez le support si erreur.", + "fundingAccountProvisioningTitle": "Configuration de votre compte de financement", + "fundingAccountProvisioningDescription": "Nous y sommes presque : nous approvisionnons votre compte virtuel maintenant. Vos instructions apparaîtront ici dans un instant.", + "provisioningFailedTitle": "Nous n'avons pas pu terminer la configuration de votre compte", + "provisioningFailedDescription": "Échec du provisioning du compte de financement. Réessayez.", + "readyTitle": "Préparer vos instructions", + "readyDescription": "Votre compte de financement est prêt – vous récupérez vos coordonnées maintenant.", + "onrampProvisioningDetail": "Provisionnement d'un BVNK Wallet et d'une règle de paiement fiat → crypto pour ce Quote.", + "offrampProvisioningDetail": "Mise à disposition d'un paiement BVNK dédié Wallet pour cette devise.", + "simulateDeposit": "Simuler un dépôt", + "simulating": "Simuler...", + "depositSimulated": "Dépôt simulé" + }, + "lightspark": { + "verificationRequiredTitle": "Vérifiez votre identité", + "verificationRequiredDescription": "Nous devons confirmer votre identité avant d'activer votre compte de financement. Cette page s'actualise automatiquement une fois que vous êtes approuvé.", + "verificationInReviewTitle": "Vérification en cours d'examen", + "verificationInReviewDescription": "Vos coordonnées sont en cours de révision – cela ne prend généralement que quelques minutes. Vos instructions apparaîtront ici dès que vous serez approuvé.", + "verificationFailedTitle": "La vérification de l'identité n'a pas été approuvée", + "verificationFailedDescription": "Impossible de vérifier votre identité : ce compte de financement ne peut pas être activé. Contactez le support si erreur.", + "fundingAccountProvisioningTitle": "Configuration de votre compte", + "fundingAccountProvisioningDescription": "Nous y sommes presque : nous préparons votre compte de financement. Vos instructions apparaîtront ici dans un instant.", + "provisioningFailedTitle": "Nous n'avons pas pu terminer la configuration de votre compte", + "provisioningFailedDescription": "Une erreur s'est produite lors de la préparation de votre compte de financement. Veuillez réessayer.", + "readyTitle": "Préparer vos instructions", + "readyDescription": "Votre compte est prêt – vous récupérez vos coordonnées maintenant.", + "onrampProvisioningDetail": "Provisionnement de votre client Lightspark et détails du dépôt pour ce Quote.", + "offrampProvisioningDetail": "Mise à disposition d'un compte de paiement Lightspark juste à temps pour ce retrait.", + "simulateQuote": "Simuler Quote", + "simulating": "Simuler...", + "quoteSimulated": "Quote Simulé" + }, + "mural": { + "termsTitle": "Accepter les conditions de Mural Pay", + "termsDescription": "Mural Pay nécessite que Counterparty accepte les conditions hébergées avant que la vérification d'identité puisse commencer.", + "verificationRequiredTitle": "Vérifiez votre identité", + "verificationRequiredDescription": "Mural Pay a besoin du Counterparty pour effectuer la vérification hébergée avant d'activer un compte de financement.", + "verificationInReviewTitle": "Vérification en cours d'examen", + "verificationInReviewDescription": "Mural Pay examine le Counterparty. Les instructions de financement apparaîtront une fois la vérification approuvée.", + "verificationFailedTitle": "La vérification de l'identité n'a pas été approuvée", + "verificationFailedDescription": "Mural Pay n'a pas pu approuver ce Counterparty, un compte de financement ne peut donc pas être activé.", + "fundingAccountProvisioningTitle": "Configuration de votre compte de financement", + "fundingAccountProvisioningDescription": "Mural Pay active un compte de financement. Les coordonnées bancaires apparaîtront ici lorsqu’elles seront prêtes.", + "readyTitle": "Préparer vos instructions", + "readyDescription": "Votre compte de financement Mural Pay est prêt. Récupération des derniers détails maintenant.", + "onrampProvisioningDetail": "Provisionnement d'un compte de financement Mural Pay pour ce Counterparty.", + "offrampProvisioningDetail": "Vérification de la vérification de l'organisation Mural Pay avant retrait.", + "simulateDeposit": "Simuler un dépôt", + "simulating": "Simuler...", + "depositSimulated": "Dépôt simulé" + }, + "batchSend": { + "recipientStatusPending": "En attente", + "recipientStatusProcessing": "Traitement", + "recipientStatusConfirmed": "Terminé", + "recipientStatusFailed": "Échec", + "recipientStatusArchived": "Archivé", + "resultConfirmed": "Batch envoyé", + "resultPartiallyFailed": "Batch a partiellement échoué", + "resultFailed": "Échec de Batch", + "resultSubmitted": "Batch soumis", + "recipientsStep": "Destinataires", + "recipientsTitle": "Payer plusieurs destinataires", + "reviewStep": "Examen", + "reviewTitle": "Avis Batch", + "customToken": "Personnalisé Token", + "tokenUnavailableOnNetwork": "{currency} n'est pas disponible sur ce réseau.", + "importExceedsMaximumRecipients": "Un Batch peut avoir au plus des destinataires {max}. Cette importation porterait le total à {total}.", + "submitting": "Soumission de Batch.", + "someRecipientsDidNotReceiveFunds": "Certains bénéficiaires n'ont pas reçu de fonds.", + "status": "Statut : {status}", + "estimateFailed": "L'estimation a échoué.", + "recipientSingular": "Destinataire {count}", + "recipientPlural": "Destinataires {count}", + "yourWallet": "votre Wallet", + "maximumRecipients": "Un Batch peut avoir au plus des destinataires {count}.", + "insufficientBalance": "Solde insuffisant", + "walletsSelectedSingular": "{count} Wallet sélectionné", + "walletsSelectedPlural": "{count} Wallets sélectionné", + "from": "De", + "selectSourceWallet": "Sélectionnez une source Wallet", + "searchWallets": "Rechercher Wallets", + "asset": "Asset", + "selectAsset": "Sélectionnez un Asset", + "noAssets": "Ce Wallet n'a aucun élément disponible à envoyer.", + "selectRecipientWallets": "Sélectionnez le destinataire Wallets", + "bulkImport": "Ou importation groupée", + "searchCounterparty": "Rechercher Counterparty", + "paginationSummary": "{page} / {pageCount}", + "noCounterpartiesWithSolanaAddress": "Aucune contrepartie avec une adresse Solana.", + "noMatches": "Aucun match.", + "addRecipient": "Ajouter {name}", + "totalAmount": "Total {total} {asset}", + "totalOfAmount": "de {available} {asset}", + "reviewSummary": "{total} {asset} → {recipients}", + "transactionCountSingular": "Transaction {count}", + "transactionCountPlural": "Transactions {count}", + "source": "Source", + "transactionFees": "Frais de transactions", + "rentFees": "Frais de loyer", + "total": "Total", + "sponsoredFee": "0 SOL", + "sponsoredBy": "Sponsorisé par SDP via Kora", + "estimating": "Estimation…", + "resultSummary": "Destinataires {recipients} · Transactions {transactions}", + "viewOnExplorer": "Afficher sur l'explorateur", + "bulkImportAriaLabel": "Destinataires de l'importation groupée", + "bulkImportTitle": "Destinataires de l'importation groupée", + "bulkImportDescriptionBefore": "Coller des lignes de", + "bulkImportFields": "contrepartie_wallet_id, devise connue ou adresse Mint, montant", + "bulkImportDescriptionAfter": "dans n’importe quel champ, ou ajoutez-les un par un.", + "counterpartyWalletIdPlaceholder": "contrepartie_wallet_id", + "currencyOrMintPlaceholder": "devise ou Mint", + "amountPlaceholder": "montant", + "removeRow": "Supprimer la ligne {row}", + "addRecipientRow": "Ajouter un destinataire", + "rowError": "Ligne {row} : {message}", + "addAtLeastOneRecipient": "Ajoutez au moins un destinataire.", + "oneCurrencyRequired": "Toutes les lignes doivent utiliser une devise ou une adresse Mint (trouvée {currencies}).", + "walletNotFound": "Wallet introuvable : {id}", + "importFailed": "L'importation a échoué.", + "cancel": "Annuler", + "importing": "Importation…", + "import": "Importer", + "reference": "Référence", + "referenceOptional": "Facultatif" + }, + "manualInstructions": { + "copied": "{label} copié.", + "copyFailed": "Échec de la copie de {label}.", + "copy": "Copier", + "instructions": "Instructions", + "quoteSummary": "Quote Résumé", + "quoteSummaryDescription": "Tarification verrouillée pour cette instruction de financement.", + "finalAmount": "Montant final", + "depositAmount": "Montant du dépôt", + "feesIncluded": "Frais inclus", + "exchangeRate": "Taux de change", + "expires": "Expire", + "bankName": "Nom de la banque", + "routingNumber": "Numéro de routage", + "accountNumber": "Numéro de compte", + "walletAddress": "Adresse de Wallet", + "reference": "Référence", + "supportedRails": "Rails supportés", + "notes": "Remarques", + "depositAddress": "Adresse de dépôt", + "bankCode": "Code banque", + "paymentReference": "Référence de paiement", + "identityVerificationRequired": "Vérification d'identité requise", + "completeVerification": "Vérification complète", + "provisioningAccount": "BVNK approvisionne votre compte bancaire virtuel", + "verificationInReview": "Vérification en cours d'examen", + "provisioningFundingAccount": "Compte de financement de provisionnement", + "checkingVerificationStatus": "Vérification de l'état de vérification", + "manualFundingInstructions": "Instructions de financement manuel", + "defaultDescription": "Envoyez {amount} via un rail supporté. Incluez la référence exacte pour que le provider rattache le dépôt à ce Quote.", + "quotedAmount": "le montant indiqué", + "cryptoDeposit": "Dépôt {currency}", + "virtualAccount": "Compte virtuel {currency}", + "payin": "{currency} payer" + }, + "providerRisk": { + "close": "Fermer {title}", + "description": "Ce screening vérifie sanctions et signaux de conformité des providers connectés.", + "provider": "provider", + "analysis": "Analyse", + "noTrmAttribution": "Aucune attribution TRM", + "unavailable": "Indisponible", + "error": "Erreur", + "notAvailable": "N/D", + "dismiss": "Rejeter" + }, + "counterparty": { + "loadFailed": "Impossible de charger les contreparties", + "metadataMissing": "La réponse aux métadonnées Counterparty était vide.", + "validation": { + "required": "Obligatoire", + "invalidEmail": "E-mail invalide", + "invalidDate": "Entrez une date au format AAAA-MM-JJ.", + "dateMustBePast": "Ça doit être du passé.", + "invalidPhone": "Saisissez un numéro de téléphone au format E.164 (par exemple, +14155551234).", + "selectCountry": "Sélectionnez un pays.", + "selectState": "Sélectionnez un état." + }, + "addExternalAccount": "Ajouter un compte externe", + "addExternalAccountDescription": "Attachez un crypto Wallet pour ce Counterparty. L'adresse est examinée pour détecter les risques avant d'être ajoutée.", + "addCounterparty": "Ajouter Counterparty", + "created": "{name} créé", + "createdSuccess": "Counterparty créé", + "transferType": "Tapez", + "transferProvider": "provider", + "transferWallet": "Wallet", + "transferAmount": "Montant", + "transferStatus": "Statut", + "transferDate": "Date", + "allProviders": "Tous les providers", + "noFilteredTransactions": "Aucune transaction ne correspond aux filtres sélectionnés.", + "fullName": "Nom complet", + "createdLabel": "Créé", + "youDeposit": "Vous déposez", + "youSend": "Vous envoyez", + "recipientGets": "Le destinataire obtient", + "viewOnExplorer": "Afficher sur l'explorateur", + "deleted": "{name} supprimé", + "createdButUnavailable": "Counterparty a été créé mais n'a pas pu être chargé.", + "somethingWentWrong": "Quelque chose s'est mal passé", + "addCryptoAccount": "Ajouter un compte crypto", + "addCryptoAccountDescription": "Ajoutez optionnellement un crypto Wallet pour ce Counterparty. Vous pourrez le faire plus tard.", + "cryptoWallet": "Crypto Wallet", + "done": "Terminé", + "skip": "Sauter", + "displayName": "Nom d'affichage", + "individualNamePlaceholder": "Jeanne Smith", + "businessNamePlaceholder": "Acme Corp.", + "email": "Courriel", + "emailPlaceholder": "contact@exemple.com", + "externalId": "ID externe", + "optional": "(facultatif)", + "externalIdPlaceholder": "votre-identifiant-interne", + "firstName": "Prénom", + "firstNamePlaceholder": "Jeanne", + "lastName": "Nom de famille", + "lastNamePlaceholder": "Forgeron", + "dateOfBirth": "Date de naissance", + "phone": "Téléphone", + "phonePlaceholder": "+1 555 000 0000", + "line1": "Ligne 1", + "line1Placeholder": "123, rue Principale", + "line2": "Ligne 2", + "line2Placeholder": "Suite 400", + "city": "Ville", + "cityPlaceholder": "New York", + "postalCode": "Code postal", + "country": "Pays", + "selectCountry": "Sélectionnez un pays", + "searchCountries": "Rechercher des pays…", + "state": "État", + "selectState": "Sélectionnez l'état", + "searchStates": "Rechercher des états…", + "stateProvince": "État/Province", + "statePlaceholder": "New York", + "basics": "Les bases", + "entityType": "Type d'entité", + "individual": "Individuel", + "business": "Affaires", + "personalInfo": "Informations personnelles", + "address": "Adresse", + "back": "Retour", + "creating": "Création", + "create": "Créer", + "next": "Suivant", + "stepProgress": "Étape {current} de {total}", + "deleteCounterparty": "Supprimer Counterparty", + "deleteNamedCounterparty": "Etes-vous sûr de vouloir supprimer {name} ? Cela archivera le Counterparty et ses comptes.", + "deleteThisCounterparty": "Etes-vous sûr de vouloir supprimer ce Counterparty ?", + "cancel": "Annuler", + "deleting": "Suppression", + "delete": "Supprimer", + "basicInfo": "Informations de base", + "basicInfoDescription": "Saisissez le nom et les coordonnées du Counterparty.", + "personal": "Personnel", + "personalDetails": "Données personnelles", + "personalDetailsDescription": "Informations d’identité de cette personne.", + "location": "Emplacement", + "locationDescription": "Cela nous aide à vérifier qui ils sont et où ils sont basés.", + "review": "Examen", + "reviewCreate": "Réviser et créer", + "reviewCreateDescription": "Confirmez que tout semble correct avant de créer.", + "adding": "Ajout", + "screening": "Dépistage", + "addAccount": "Ajouter un compte", + "cryptoAccountAttached": "Compte crypto attaché", + "label": "Étiquette", + "accountLabelPlaceholder": "par ex. Alice's Solana Wallet", + "network": "Réseau", + "selectNetwork": "Sélectionnez le réseau", + "walletAddress": "Adresse de Wallet", + "destinationWalletAddress": "Adresse de destination Wallet", + "screeningUnavailable": "Impossible de screener cette adresse — screening conformité indisponible. L’ajouter quand même ?", + "screeningWarning": "Un ou plusieurs checks ont signalé ce Wallet ou ont échoué. L’ajouter quand même ?", + "holdToAddAnyway": "Attendez pour ajouter quand même", + "searchAddress": "Rechercher une adresse", + "searchAddressPlaceholder": "Rechercher une adresse ou une entreprise…", + "failedToLoadPlaceDetails": "Échec du chargement des détails du lieu", + "searchFailed": "La recherche a échoué", + "searching": "Recherche…", + "noMatches": "Aucune correspondance trouvée.", + "updating": "Mise à jour…", + "searchToPreviewAddress": "Rechercher pour prévisualiser l'adresse", + "complianceScreening": "Vérification de la conformité", + "checking": "Vérification…", + "directory": "Annuaire", + "directoryDescription": "Particuliers et entreprises enregistrés dans votre espace de travail.", + "noCounterparties": "Pas encore de contreparties", + "noCounterpartiesDescription": "Ajoutez votre premier individu ou entreprise pour commencer.", + "type": "Tapez", + "manageCounterparty": "Gérer Counterparty", + "counterpartyActions": "Actions Counterparty", + "transactionDetails": "Détails de la transaction", + "playgroundProductName": "Counterparty", + "playgroundCounterpartyIdPlaceholder": "ID Counterparty (par exemple, cpty_abc123)", + "listCounterparties": "Liste des contreparties", + "getCounterparty": "Obtenez Counterparty", + "createCounterparty": "Créer Counterparty", + "playgroundEmailPlaceholder": "contact@acme.com", + "playgroundIndividualOnly": "Requis si entityType est individual ; laisser vide pour business.", + "playgroundAddressRequired": "Requis pour tous les types d'entité.", + "playgroundDateOfBirthPlaceholder": "1990-01-15", + "playgroundPhonePlaceholder": "+14155551234", + "selectEntityType": "Sélectionnez le type d'entité", + "updateCounterparty": "Mettre à jour Counterparty", + "updatedDisplayNamePlaceholder": "Nom d'affichage mis à jour", + "updatedEmailPlaceholder": "mise à jour@exemple.com", + "noTransactions": "Aucune transaction liée à ce Counterparty pour l'instant.", + "allTypes": "Tous types", + "identity": "Identité", + "personalInformation": "Informations personnelles", + "noPersonalInformation": "Aucune information personnelle au dossier.", + "externalAccounts": "Comptes externes", + "noExternalAccounts": "Pas encore de comptes externes.", + "addExternalAccountTitle": "Ajouter un compte externe", + "manage": "Gérer", + "details": "Détails", + "transactions": "Opérations", + "copyAddress": "Copier l'adresse", + "addressCopied": "Adresse copiée" + }, + "playground": { + "moonPay": "MoonPay", + "lightspark": "Lightspark", + "bvnk": "BVNK", + "walletIdPlaceholder": "ID Wallet (par exemple, wal_ops_123)", + "transferIdPlaceholder": "ID Transfer (par exemple, xfr_123)", + "custodyWalletIdPlaceholder": "ID Wallet de garde (par exemple, wal_ops_123)", + "destinationWalletIdPlaceholder": "ID Wallet de destination", + "sourceWalletIdPlaceholder": "Identifiant source Wallet", + "getWalletBalances": "Obtenez les soldes Wallet", + "getWalletPolicy": "Obtenir la politique Wallet", + "updateWalletPolicy": "Mettre à jour la politique Wallet", + "destinationAllowlistPlaceholder": "Adresses de destination séparées par des virgules", + "executeTransfer": "Exécuter Transfer", + "solanaAddressPlaceholder": "Adresse Solana (32-44 caractères)", + "usdc": "USDC", + "optionalMemo": "memo en option", + "listTransfers": "Liste des Transfers", + "getTransfer": "Obtenez Transfer", + "createOnrampQuote": "Créer Onramp Quote", + "selectProvider": "Sélectionnez le provider", + "counterpartyIdPlaceholder": "ID Counterparty (par exemple, cpty_abc123)", + "selectFiatCurrency": "Sélectionnez la monnaie fiduciaire", + "onrampRedirectUrlPlaceholder": "https://app.example.com/payments/Zonramp/complete", + "createOfframpQuote": "Créer Offramp Quote", + "offrampRedirectUrlPlaceholder": "https://app.example.com/payments/Zofframp/complete" + }, + "totalSdpBalance": "Solde total du SDP", + "aggregatedAcrossWallets": "Agrégé sur {count} {walletLabel}.", + "wallet": "Wallet", + "wallets": "Wallets", + "noUsdValuedAssets": "Aucune ligne Asset évaluée en USD n'est encore disponible.", + "recentTransactions": "Opérations récentes", + "recentTransactionsDescription": "Dernière activité Transfer dans toute l'organisation Wallets.", + "refreshing": "Rafraîchissant...", + "refresh": "Actualiser", + "noTransactions": "Aucune transaction trouvée pour l'instant.", + "status": "Statut", + "transfer": "Transfert", + "asset": "Asset", + "direction": "Direction", + "counterpartyLabel": "Counterparty", + "signature": "Signature", + "createdLabel": "Créé", + "pending": "En attente", + "expired": "Expiré", + "unknown": "Inconnu", + "unavailable": "Indisponible", + "deposit": "Dépôt", + "pay": "Payer", + "transferDetails": { + "providerFee": "Frais du provider", + "networkFee": "Frais de réseau", + "exchangeRate": "Taux de change", + "fees": "Frais", + "provider": "provider", + "transactionId": "ID de transaction", + "providerReference": "Référence du provider", + "memo": "Memo", + "cashPickupCode": "Code de retrait d'espèces", + "moneygramTransactionId": "ID de transaction MoneyGram", + "payoutStatus": "Statut de paiement", + "payoutAmount": "Montant du paiement", + "cryptoTransferId": "Identifiant cryptographique Transfer", + "solanaSignature": "Solana signature", + "moneygramError": "Erreur MoneyGram", + "lastUpdated": "Dernière mise à jour", + "copy": "Copier {label}" + }, + "requestFailed": "La demande a échoué.", + "submitting": "Envoi...", + "sendTransfer": "Envoyer Transfer", + "sendBatch": "Envoyer Batch", + "reviewAction": "Examen", + "processing": "Traitement", + "verificationPending": "Vérification en attente", + "completeVerification": "Vérification complète", + "previous": "Précédent", + "goToTransaction": "Aller à la transaction", + "method": "Méthode", + "whoAreYouPaying": "Qui payez-vous ?", + "whoIsThisDepositFrom": "De qui provient ce dépôt ?", + "howWouldYouLikeToPay": "Comment souhaiteriez-vous payer ?", + "howWouldYouLikeToDeposit": "Comment souhaitez-vous effectuer un dépôt ?", + "poweredBy": "Alimenté par", + "playgroundProductName": "Paiements", + "recurring": { + "emptyResponse": "{request} a renvoyé une réponse vide.", + "counterpartyStepTitle": "À qui est destiné ce paiement Recurring ?", + "destination": "Destination", + "destinationStepTitle": "Où doivent aller les paiements ?", + "details": "Détails", + "detailsStepTitle": "Définir les détails du paiement", + "reviewStepTitle": "Vérifier le paiement Recurring", + "everyDay": "Chaque jour", + "collectDaily": "Collectez une fois par jour.", + "everyWeek": "Chaque semaine", + "collectWeekly": "Collectez une fois par semaine.", + "everyThirtyDays": "Tous les 30 jours", + "collectMonthly": "Collectez environ une fois par mois.", + "custom": "Personnalisé", + "customScheduleDescription": "Entrez un intervalle en heures.", + "notSet": "Non défini", + "customInterval": "Intervalle personnalisé", + "everyHour": "Toutes les heures", + "everyHours": "Toutes les heures {count}", + "notSelected": "Non sélectionné", + "destinationAccount": "Compte de destination", + "fundingWallet": "Financement Wallet", + "amount": "Montant", + "billingInterval": "Intervalle de facturation", + "firstPayment": "Premier paiement", + "afterActivation": "Après activation", + "metadata": "Métadonnées", + "creatingPayment": "Création du paiement Recurring.", + "paymentCreated": "Paiement Recurring créé.", + "pendingActivationDescription": "Il est en attente d'activation.", + "unableToCreate": "Impossible de créer le paiement Recurring.", + "paymentNotCreated": "Le paiement Recurring n'a pas été créé.", + "createPayment": "Créer un paiement Recurring", + "loadingAccounts": "Chargement des comptes", + "noSolanaAccounts": "Aucun compte Solana enregistré", + "selectDestinationAccount": "Sélectionnez un compte de destination", + "searchAccounts": "Rechercher des comptes", + "needsCryptoAccount": "Ce Counterparty nécessite un compte crypto Wallet Solana actif avant de pouvoir créer un paiement Recurring.", + "addSolanaAddress": "Ajouter l'adresse Solana", + "noDestinationWallet": "{name} n’a pas encore de destination Wallet dans ses fichiers.", + "attachDestinationWallet": "Attachez une autre destination Wallet pour ce Counterparty.", + "selectFundingWallet": "Sélectionnez un financement Wallet", + "searchWallets": "Rechercher Wallets", + "asset": "Asset", + "noTokenBalances": "Aucun solde Token pris en charge", + "selectAsset": "Sélectionnez un Asset", + "selectWalletFirst": "Sélectionnez d'abord un Wallet", + "searchAssets": "Rechercher des Assets", + "unresolvedTokenBalances": "Ce Wallet a des soldes Token, mais leurs symboles n'ont pas encore pu être résolus.", + "nativeSolUnsupported": "Les paiements Recurring nécessitent un solde Token. Le SOL natif n'est pas pris en charge.", + "invalidAmount": "Entrez un montant supérieur à zéro.", + "intervalHours": "Intervalle en heures", + "invalidInterval": "Saisissez un nombre entier d'heures compris entre 1 et 8760.", + "invalidFirstPayment": "Choisissez une date et une heure futures.", + "startAfterActivation": "Laissez vide pour démarrer après l'activation.", + "metadataUrl": "URL des métadonnées", + "metadataUrlPlaceholder": "https://example.com/metadata.json", + "invalidMetadataUrl": "Saisissez une URL valide de moins de 128 caractères.", + "optional": "Facultatif.", + "pendingRecordDescription": "Cela crée un enregistrement de paiement Recurring en attente. L'activation est une étape distincte.", + "pendingActivation": "En attente d'activation", + "activating": "Activation", + "active": "Actif", + "updating": "Mise à jour", + "canceling": "Annulation", + "resuming": "Reprise", + "paused": "En pause", + "canceled": "Annulé", + "expired": "Expiré", + "pending": "En attente", + "processing": "Traitement", + "collected": "Collecté", + "failed": "Échec", + "skipped": "Sauté", + "recurringPayments": "Paiements Recurring", + "recurringPaymentCount": "Paiements {count} Recurring", + "oneRecurringPayment": "1 paiement Recurring", + "unableToLoad": "Impossible de charger les paiements Recurring", + "noPayments": "Aucun paiement Recurring pour l’instant.", + "paymentsAppearHere": "Les enregistrements de paiement Recurring créés apparaîtront ici.", + "interval": "Intervalle", + "nextPayment": "Prochain paiement", + "counterpartyUnavailable": "Counterparty indisponible", + "payment": "Paiement Recurring", + "receivingWallet": "Réception de Wallet", + "starts": "Commence", + "currency": "Devise", + "paymentReference": "Référence de paiement", + "openMetadata": "Métadonnées ouvertes", + "created": "Créé", + "updated": "Mis à jour", + "edit": "Modifier", + "copyValue": "Copier la valeur", + "copied": "Copié", + "openSignature": "Ouvrir signature", + "collectionHistory": "Historique des collections", + "showingAttempts": "Affichage de {shown} sur {total} tentatives", + "oneAttempt": "1 tentative", + "attempts": "{count} tentatives", + "unableToLoadCollectionHistory": "Impossible de charger l'historique de collecte : {error}", + "noCollectionAttempts": "Aucune tentative de collecte pour l'instant. La prochaine collecte programmée est indiquée ci-dessus.", + "due": "Due", + "attempted": "Tentative", + "transfer": "Transfert", + "explorer": "Explorateur", + "everyWeeks": "Toutes les semaines {count}", + "everyDays": "Tous les jours {count}", + "paymentActivated": "Paiement Recurring activé.", + "collectionSubmitted": "Recouvrement de paiement Recurring soumis.", + "paymentCanceled": "Paiement Recurring annulé.", + "paymentResumed": "Le paiement Recurring a repris.", + "activationFailed": "L'activation a échoué", + "collectionFailed": "Échec de la collecte", + "cancellationFailed": "Échec de l'annulation", + "resumeFailed": "La reprise a échoué", + "retryActivation": "Réessayer l'activation", + "activate": "Activer", + "retryCollection": "Réessayer la collecte", + "collectNow": "Collectionnez maintenant", + "retryResume": "Réessayez de reprendre", + "resume": "CV", + "retryCancellation": "Réessayer l'annulation", + "cancel": "Annuler", + "actions": "Actions", + "editPayment": "Modifier le paiement", + "stopFutureCollections": "Arrêter les futures collectes", + "copyError": "Erreur de copie", + "readyToActivate": "Prêt à activer", + "readyToActivateDescription": "Crée l'abonnement et planifie le premier paiement.", + "lifecycleActionUnavailable": "Action de cycle de vie indisponible", + "lifecycleActionUnavailableDescription": "Ce paiement Recurring ne peut pas être modifié par rapport à son statut actuel.", + "updatingPayment": "Mise à jour du paiement Recurring.", + "actionFailed": "L'action de paiement Recurring a échoué.", + "alreadyFundingWallet": "{wallet} est déjà le financement Wallet.", + "updatingFundingWallet": "Mise à jour du financement Wallet.", + "fundingWalletUpdated": "Financement Wallet mis à jour.", + "fundingWalletUpdateFailed": "Échec de la mise à jour du financement de Wallet", + "paymentUpdateFailed": "Échec de la mise à jour du paiement Recurring.", + "selectReceivingWallet": "Sélectionnez un Wallet de réception.", + "alreadyReceivingWallet": "{wallet} est déjà le Wallet récepteur.", + "updatingReceivingWallet": "Mise à jour de la réception de Wallet.", + "receivingWalletUpdated": "Réception de Wallet mise à jour.", + "receivingWalletUpdateFailed": "Échec de la réception de la mise à jour Wallet", + "alreadySet": "{value} est déjà défini.", + "updatingBillingInterval": "Mise à jour de l'intervalle de facturation.", + "billingIntervalUpdated": "Intervalle de facturation mis à jour.", + "billingIntervalUpdateFailed": "Échec de la mise à jour de l'intervalle de facturation", + "selectCurrency": "Sélectionnez une devise.", + "alreadyCurrency": "{currency} est déjà la devise.", + "updatingCurrency": "Mise à jour de la devise.", + "currencyUpdated": "Devise mise à jour.", + "currencyUpdateFailed": "Échec de la mise à jour de la devise", + "updatingAmount": "Mise à jour du montant.", + "amountUpdated": "Montant mis à jour.", + "amountUpdateFailed": "Échec de la mise à jour du montant", + "editFundingWallet": "Modifier le financement Wallet", + "editFundingWalletDescription": "Choisissez le Wallet utilisé pour financer ce paiement Recurring.", + "editReceivingWallet": "Modifier la réception de Wallet", + "editReceivingWalletDescription": "Choisissez où ce paiement Recurring envoie les fonds.", + "editAmount": "Modifier le montant", + "editAmountDescription": "Définissez le montant collecté à chaque période de facturation.", + "editBillingInterval": "Modifier l'intervalle de facturation", + "editBillingIntervalDescription": "Choisissez la fréquence à laquelle ce paiement Recurring doit être collecté.", + "editCurrency": "Modifier la devise", + "editCurrencyDescription": "Choisissez un solde Token parmi le financement Wallet.", + "cancelPaymentTitle": "Annuler le paiement Recurring ?", + "cancelPaymentDescription": "Cela arrête les futures collectes pour {counterparty}. Vous pourrez reprendre le paiement ultérieurement depuis le menu Actions.", + "keepPayment": "Conserver le paiement", + "cancelPayment": "Annuler le paiement", + "save": "Enregistrer" + }, + "requests": { + "loadFailed": "Impossible de charger les demandes de paiement", + "awaitingPayment": "En attente de paiement", + "paid": "Payé", + "canceled": "Annulé", + "expired": "Expiré", + "paymentLinkCreated": "Lien de paiement créé", + "createPaymentRequest": "Créer une demande de paiement", + "createPaymentLink": "Créer un lien de paiement", + "createPaymentLinkDescription": "Demandez un paiement forfaitaire à l’un de vos Wallets.", + "amount": "Montant", + "token": "Token", + "selectToken": "Sélectionnez Token", + "destinationWallet": "Destination Wallet", + "selectWallet": "Sélectionnez Wallet", + "fromCounterparty": "De (Counterparty)", + "anyoneWithLink": "Quelqu'un ayant le lien", + "loadingCryptoAccount": "Chargement du compte crypto…", + "paysFrom": "Paye à partir de", + "noCryptoAccount": "Aucun compte crypto dans le dossier.", + "add": "Ajouter", + "linkExpires": "Le lien expire", + "noExpiry": "Pas d'expiration", + "oneHour": "1 heure", + "twentyFourHours": "24 heures", + "sevenDays": "7 jours", + "thirtyDays": "30 jours", + "cancel": "Annuler", + "creating": "Création…", + "createLink": "Créer un lien", + "paymentRequests": "Demandes de paiement", + "paymentRequestsDescription": "Liens partageables qui demandent un paiement fixe.", + "create": "Créer", + "noPaymentRequests": "Aucune demande de paiement pour l'instant", + "noPaymentRequestsDescription": "Créez un lien de paiement pour demander un paiement fixe.", + "from": "De", + "to": "À", + "paymentRequestDetails": "Détails de la demande de paiement", + "paymentRequest": "Demande de paiement", + "amountRequested": "Montant demandé", + "paymentLinkCopied": "Lien de paiement copié", + "copy": "Copier", + "reference": "Référence", + "expires": "Expire", + "destinationWalletId": "ID Wallet de destination", + "splMintAddress": "Adresse de SPL Mint", + "listRequests": "Liste des demandes de paiement", + "createRequest": "Créer une demande de paiement", + "playgroundProductName": "Demandes de paiement" + }, + "commandCenter": { + "moveMoney": "Transférer de l'argent", + "moveMoneyDescription": "Lancez le flux de paiement qui correspond à ce que vous devez faire.", + "payDescription": "Onchain ou fiduciaire", + "depositDescription": "Recevoir des crypto ou des devises", + "requestPayment": "Demander un paiement", + "requestPaymentDescription": "Partager un QR code ou un lien sponsorisé", + "schedule": "Planifier", + "scheduleDescription": "Créer un paiement récurrent", + "availableBalance": "Solde disponible", + "availableBalanceDescription": "Sur {count} {walletLabel}", + "balanceUnavailable": "Le solde est temporairement indisponible.", + "activity": "Activité", + "activityDescription": "Derniers transferts, lots, dépôts et versements.", + "activityUnavailable": "L'activité est temporairement indisponible.", + "transfers": "Transferts", + "batches": "Lots", + "typeDirection": "Type", + "amount": "Montant", + "upcomingOpen": "À venir et ouverts", + "upcomingOpenDescription": "Tâches pouvant nécessiter votre attention.", + "activeSchedules": "Plannings actifs", + "openRequests": "Demandes de paiement ouvertes", + "upcomingUnavailable": "Les paiements à venir sont temporairement indisponibles.", + "paymentNetwork": "Réseau de paiement", + "paymentNetworkDescription": "Contreparties enregistrées et destinations de versement.", + "counterpartiesReady": "{count} contreparties prêtes", + "counterparties": "contreparties", + "providersEnabled": "fournisseurs activés", + "networkUnavailable": "Le réseau de paiement est temporairement indisponible.", + "manageCounterparties": "Gérer les contreparties", + "viewRecurring": "Voir les paiements récurrents", + "viewRequests": "Voir les demandes de paiement" + }, + "viewAllTransactions": "Voir toutes les transactions", + "transactions": { + "searchPlaceholder": "Rechercher un ID, une signature, une adresse, une référence ou une contrepartie (3+ caractères)", + "clearSearch": "Effacer la recherche de transaction", + "filters": "Filtres", + "activeFilters": "{count} actif(s)", + "clearFilters": "Effacer les filtres", + "allStatuses": "Tous les statuts", + "allDirections": "Toutes les directions", + "allTypes": "Tous les types", + "allWallets": "Tous les portefeuilles", + "allCounterparties": "Toutes les contreparties", + "allProviders": "Tous les fournisseurs", + "assetPlaceholder": "Actif ou mint", + "fromDate": "Date de début", + "toDate": "Date de fin", + "sort": "Trier", + "newest": "Plus récents d'abord", + "oldest": "Plus anciens d'abord", + "amountHigh": "Montant : du plus élevé au plus bas", + "amountLow": "Montant : du plus bas au plus élevé", + "statusAscending": "Statut : de A à Z", + "inbound": "Entrant", + "outbound": "Sortant", + "transfer": "Virement", + "confidentialTransfer": "Virement confidentiel", + "batchTransfer": "Virement groupé", + "onramp": "Entrée", + "offramp": "Sortie", + "pending": "En attente", + "processing": "En cours", + "confirmed": "Confirmé", + "finalized": "Finalisé", + "failed": "Échoué", + "awaitingPayment": "En attente de paiement", + "settling": "Règlement", + "completed": "Terminé", + "canceled": "Annulé", + "expired": "Expiré", + "transaction": "Transaction", + "status": "Statut", + "amount": "Montant", + "direction": "Direction", + "counterparty": "Contrepartie", + "counterpartyId": "ID contrepartie", + "wallet": "Portefeuille", + "provider": "Fournisseur", + "created": "Créé", + "rowsPerPage": "Lignes par page", + "range": "{start}–{end} sur {total}", + "noMatches": "Aucune transaction ne correspond à ces filtres.", + "emptyProject": "Aucune transaction pour le moment.", + "loadError": "Les transactions n'ont pas pu être chargées.", + "retry": "Réessayer", + "viewDetails": "Voir la transaction {id}", + "details": "Détails de la transaction", + "loadingDetails": "Chargement des détails de la transaction", + "detailLoadError": "Les détails de la transaction n'ont pas pu être chargés.", + "transactionId": "ID de transaction", + "type": "Type", + "source": "Source", + "destination": "Destination", + "signature": "Signature", + "providerReference": "Référence fournisseur", + "memo": "Mémo", + "updated": "Mis à jour", + "viewOnExplorer": "Voir sur Solana Explorer", + "unavailable": "Indisponible", + "loadingOptions": "Chargement des options…" + } + } +} diff --git a/apps/sdp-web/messages/fr/dashboard-policies.json b/apps/sdp-web/messages/fr/dashboard-policies.json new file mode 100644 index 000000000..d927699c4 --- /dev/null +++ b/apps/sdp-web/messages/fr/dashboard-policies.json @@ -0,0 +1,51 @@ +{ + "DashboardPolicies": { + "all": "Tout", + "wallets": "Portefeuilles", + "apiKeys": "Clés API", + "searchPlaceholder": "Rechercher des portefeuilles ou des clés API", + "clearSearch": "Effacer la recherche", + "allStatuses": "Tous les statuts", + "defaultAllow": "Autorisation par défaut", + "draft": "Brouillon", + "active": "Actif", + "disabled": "Désactivé", + "configureControls": "Configurer les contrôles", + "walletControls": "Contrôles du portefeuille", + "apiKeyControls": "Contrôles des clés API", + "policySummary": "Résumé de la politique", + "summaryDescription": "Les contrôles sont attachés aux portefeuilles et aux clés API.", + "apiKeyBindings": "Liaisons de clés API", + "target": "Cible", + "status": "Statut", + "defaultAction": "Action par défaut", + "rules": "Règles", + "bindings": "Liaisons", + "lastUpdated": "Dernière mise à jour", + "actions": "Actions", + "wallet": "Portefeuille", + "apiKey": "Clé API", + "allow": "Autoriser", + "deny": "Refuser", + "approvalRequired": "Approbation requise", + "review": "Réviser", + "noRestrictions": "Aucune restriction", + "ruleCount": "{count} règles", + "singleRule": "1 règle", + "allWallets": "Tous les portefeuilles", + "selectedWalletCount": "{count} portefeuilles sélectionnés", + "singleSelectedWallet": "1 portefeuille sélectionné", + "configureWalletControls": "Configurer les contrôles", + "viewAudit": "Voir l'audit", + "viewRevisions": "Voir les révisions", + "configureScope": "Configurer la portée", + "viewBindings": "Voir les liaisons", + "noMatches": "Aucun contrôle ne correspond à ces filtres.", + "clearFilters": "Effacer les filtres", + "emptyProject": "Aucun contrôle de portefeuille ou de clé API n'est configuré.", + "loadError": "Impossible de charger les contrôles de politique.", + "retry": "Réessayer", + "rowsPerPage": "Lignes par page", + "range": "{start}–{end} sur {total}" + } +} diff --git a/apps/sdp-web/messages/fr/shared.json b/apps/sdp-web/messages/fr/shared.json new file mode 100644 index 000000000..a17d04431 --- /dev/null +++ b/apps/sdp-web/messages/fr/shared.json @@ -0,0 +1,215 @@ +{ + "tabs": { + "overview": "Aperçu", + "apiPlayground": "API Playground" + }, + "authTerms": { + "prefix": "En utilisant l’app, vous acceptez les", + "link": "Conditions d’utilisation Solana Foundation" + }, + "homeSignedIn": { + "loading": "Chargement...", + "selectOrganization": "Sélectionnez votre organisation", + "selectOrganizationDescription": "Choisissez ou créez une organisation pour continuer.", + "loadingDashboard": "Chargement du dashboard..." + }, + "allowlist": { + "comingSoon": "Bientôt disponible", + "description": "La gestion Allowlist arrivera dans une prochaine version." + }, + "members": { + "comingSoon": "Bientôt disponible", + "description": "La gestion des membres arrivera dans une prochaine version." + }, + "SharedComponents": { + "copied": "Copié", + "copy": "Copier", + "apiDebugLogs": "Logs debug API", + "pause": "Pause", + "resume": "Reprendre", + "requestSummary": "Méthode, durée, résumé à copier", + "query": "Query", + "requestBody": "Corps de la requête", + "response": "Réponse", + "createApiKey": "Créer une clé API", + "selectApiKey": "Sélectionner une clé API", + "selectOrganization": "Sélectionner une organisation", + "organizations": "Organisations", + "projects": "Projets", + "current": "Actuel", + "noOrganizations": "Aucune organisation.", + "noProjects": "Aucun projet.", + "locked": "Verrouillé", + "sandboxOnly": "Seul le mode Sandbox est pris en charge pour l’instant.", + "mainnetSoon": "Support Mainnet bientôt disponible.", + "createOrganization": "Créer une organisation", + "manageOrganization": "Gérer l’organisation", + "clear": "Effacer", + "disable": "Désactiver", + "collapse": "Réduire", + "close": "Fermer", + "closeModal": "Fermer la fenêtre", + "noRequests": "Aucune requête capturée.", + "noPayload": "Aucune query, corps ou réponse capturée.", + "selectApiEndpoint": "Sélectionner un endpoint API", + "request": "Requête", + "output": "Sortie", + "pathParameters": "Paramètres de chemin", + "noPathParameters": "Cet endpoint n’exige pas de paramètres de chemin.", + "selectValue": "Sélectionner une valeur", + "noRequestBody": "Cet endpoint n’exige pas de corps JSON.", + "status": "Statut :", + "apiKeyRequired": "Créez d’abord une clé API pour activer les requêtes live.", + "runRequest": "Exécuter", + "reset": "Réinitialiser", + "retry": "Réessayer", + "copyCode": "Copier le code", + "code": "Code", + "example": "Exemple", + "pending": "En attente", + "durationMilliseconds": "{duration}ms", + "networkDebugSummary": "{pending} en attente, {completed} terminées", + "aiInstructions": "Instructions IA", + "pageOf": "Page {page} sur {pageCount}", + "previousPage": "Page précédente", + "nextPage": "Page suivante", + "loading": "Chargement…", + "noOptionsAvailable": "Aucune option disponible.", + "noSearchMatches": "Aucun résultat pour votre recherche.", + "required": "(requis)", + "selectAnOption": "Sélectionner une option", + "search": "Rechercher…", + "fillBeforeSending": "à remplir avant l’envoi", + "noValue": "- aucun", + "aiInstructionIntro": "Utilisez l’endpoint API {productName} {method} {path}.", + "aiPathParameters": "Paramètres de chemin :", + "aiRequestBody": "Corps de la requête :", + "aiInstructionOutro": "Renvoyez le corps de réponse en JSON formaté et signalez toute erreur de validation ou d’auth.", + "runRequestToInspectOutput": "Exécutez la requête pour inspecter la sortie API live de cet endpoint.", + "requestFailed": "Échec de la requête", + "ready": "Prêt", + "completeRequiredFields": "Complétez les champs requis : {fields}", + "invalidApiKeyFormat": "Format de clé API invalide. Utilisez une clé brute comme sk_test_... ou sk_live_... avec un suffixe valide.", + "playgroundExecutionFailed": "Échec de l’exécution Playground.", + "requestExecutionFailed": "Échec de l’exécution de la requête." + }, + "dashboardShell": { + "openNavigation": "Ouvrir la navigation", + "closeNavigation": "Fermer la navigation", + "sandbox": "Sandbox", + "loadingDashboard": "Chargement du dashboard...", + "signInToContinue": "Connectez-vous pour continuer", + "signInDescription": "Accédez à votre espace organisation et aux contrôles Wallet.", + "signIn": "Se connecter", + "selectOrganization": "Sélectionner une organisation", + "selectOrganizationDescription": "Une organisation est requise pour continuer.", + "counterparty": "Counterparty", + "pay": "Payer", + "deposit": "Déposer", + "requests": "Demandes", + "recurring": "Récurrents", + "create": "Créer", + "manage": "Gérer", + "home": "Accueil", + "wallets": "Wallets", + "issuance": "Émission", + "payments": "Paiements", + "apiKeys": "Clés API", + "apiDocs": "Docs API", + "settings": "Paramètres", + "language": "Langue", + "chooseLanguage": "Choisir la langue", + "moreLanguagesHint": "D’autres langues apparaîtront ici dès qu’elles seront disponibles.", + "collapseSidebar": "Réduire la barre latérale", + "expandSidebar": "Étendre la barre latérale", + "closeNavigationOverlay": "Fermer la navigation", + "newCounterparty": "Nouveau Counterparty", + "manageCounterparty": "Gérer Counterparty", + "backToCounterparty": "Retour Counterparty", + "backToWallets": "Retour aux Wallets", + "backToWalletDetail": "Retour au détail Wallet", + "createWallet": "Créer un Wallet", + "activateProvider": "Activer le provider", + "newAsset": "Nouvel Asset", + "backToOverview": "Retour à l’aperçu", + "recurringPayments": "Paiements récurrents", + "recurringPayment": "Paiement récurrent", + "backToRecurringPayments": "Retour aux paiements récurrents", + "receive": "Recevoir", + "send": "Envoyer", + "backToPayments": "Retour aux paiements", + "members": "Membres", + "allowlist": "Allowlist", + "transactions": "Transactions", + "policies": "Politiques", + "newApiKey": "Nouvelle clé API", + "editApiKey": "Modifier la clé API", + "backToApiKeys": "Retour aux clés API", + "approvals": "Approbations", + "pendingApprovals": "{count} approbations en attente", + "colorTheme": "Thème de couleur", + "darkMode": "Mode sombre", + "expandPaymentsMenu": "Développer le menu Paiements", + "collapsePaymentsMenu": "Réduire le menu Paiements", + "backToWallet": "Retour au portefeuille", + "walletControls": "Contrôles du portefeuille", + "backToApprovals": "Retour aux approbations" + }, + "validation": { + "allowlistValueRequired": "La valeur Allowlist est requise", + "allowlistEntryIdRequired": "L’ID d’entrée Allowlist est requis", + "emailRequired": "L’e-mail est requis" + }, + "pay": { + "productName": "Solana Developer Platform", + "paymentReceived": "Paiement reçu", + "paymentReceivedDescription": "Cette demande a été payée. Rien d’autre à faire.", + "linkExpired": "Lien expiré", + "linkExpiredDescription": "Ce lien de paiement n’est plus valide. Demandez-en un nouveau à l’expéditeur.", + "requestCanceled": "Demande annulée", + "requestCanceledDescription": "Cette demande de paiement a été annulée par l’expéditeur.", + "paymentRequest": "Demande de paiement", + "scanWallet": "Scannez avec un Wallet Solana pour payer", + "openWallet": "Ouvrir dans le Wallet", + "to": "À", + "token": "Token", + "expires": "Expire", + "noExpiry": "Sans expiration", + "securedBySolanaPay": "Sécurisé par Solana Pay", + "qrCode": "QR code Solana Pay" + }, + "homeWorkspace": { + "unavailable": "Indisponible", + "createFirstWalletBalances": "Créez votre premier Wallet pour suivre les soldes.", + "noTrackedBalances": "Aucun solde suivi pour l’instant.", + "activityUnavailable": "L’activité est indisponible pour le moment.", + "paymentActivityAfterWallet": "L’activité de paiement apparaîtra après la création d’un Wallet.", + "noPaymentVolume": "Aucun volume de paiement enregistré.", + "loadingPaymentActivity": "Chargement de l’activité de paiement...", + "createFirstWalletActivity": "Créez votre premier Wallet pour suivre soldes et activité.", + "noRecentActivity": "Aucune activité récente.", + "loadingRecentActivity": "Chargement de l’activité récente...", + "createWallet": "Créer un Wallet", + "totalBalance": "Solde total", + "todaysVolume": "Volume du jour", + "recentTransactions": "Transactions récentes", + "activityDescription": "Dernière activité Wallet et émission dans l’organisation.", + "seeAllPayments": "Voir tous les paiements", + "time": "Heure", + "activity": "Activité", + "type": "Type", + "token": "Token", + "amount": "Montant", + "address": "Adresse", + "send": "Envoyer", + "receive": "Recevoir", + "transfer": "Transfert", + "untitledToken": "Token sans titre", + "unableToLoadIssuanceTokens": "Impossible de charger les Tokens d’émission", + "someIssuanceActivityUnavailable": "Une partie de l’activité d’émission n’a pas pu être chargée.", + "paymentsActivityUnavailable": "L’activité paiements est indisponible pour le moment.", + "issuanceActivityUnavailable": "L’activité d’émission est indisponible pour le moment.", + "failedToLoadActivity": "Échec du chargement de l’activité du dashboard", + "balanceDataUnavailable": "Les données de solde sont indisponibles pour le moment." + } +} diff --git a/apps/sdp-web/src/i18n/README.md b/apps/sdp-web/src/i18n/README.md index dcd385aae..af24067b5 100644 --- a/apps/sdp-web/src/i18n/README.md +++ b/apps/sdp-web/src/i18n/README.md @@ -2,6 +2,8 @@ The dashboard keeps its supported BCP-47 locales in `config.ts` and its English source catalog in `../../messages/en.json`. +Supported locales today: `en`, `fr`. French catalogs live under `../../messages/fr/` and must keep a 100% matching key inventory with English. + Use `await getTranslations()` in Server Components and `useTranslations()` in Client Components. Both accept only keys that exist in the English catalog. For dates, numbers, lists, and relative time, construct the native `Intl` formatter with the resolved locale rather than pinning it to `en-US`. To add a locale, add its BCP-47 tag to `supportedLocales`, add a same-shaped catalog, and register it in `messagesByLocale`. The request resolver gives a valid locale cookie priority, then uses `Accept-Language`, falling back to English. A future language picker should persist its selection in the `sdp-locale` cookie. diff --git a/apps/sdp-web/src/i18n/config.ts b/apps/sdp-web/src/i18n/config.ts index 73997bd0f..51ebd22df 100644 --- a/apps/sdp-web/src/i18n/config.ts +++ b/apps/sdp-web/src/i18n/config.ts @@ -1,4 +1,4 @@ -export const supportedLocales = ["en"] as const; +export const supportedLocales = ["en", "fr"] as const; export type AppLocale = (typeof supportedLocales)[number]; diff --git a/apps/sdp-web/src/i18n/messages.ts b/apps/sdp-web/src/i18n/messages.ts index b7ae50bde..1a1db8706 100644 --- a/apps/sdp-web/src/i18n/messages.ts +++ b/apps/sdp-web/src/i18n/messages.ts @@ -6,6 +6,13 @@ import dashboardPayments from "../../messages/en/dashboard-payments.json"; import dashboardPolicies from "../../messages/en/dashboard-policies.json"; import shared from "../../messages/en/shared.json"; import en from "../../messages/en.json"; +import frDashboardApprovals from "../../messages/fr/dashboard-approvals.json"; +import frDashboardCustody from "../../messages/fr/dashboard-custody.json"; +import frDashboardIssuance from "../../messages/fr/dashboard-issuance.json"; +import frDashboardPayments from "../../messages/fr/dashboard-payments.json"; +import frDashboardPolicies from "../../messages/fr/dashboard-policies.json"; +import frShared from "../../messages/fr/shared.json"; +import fr from "../../messages/fr.json"; const enMessages = { ...en, @@ -19,6 +26,16 @@ const enMessages = { export type Messages = typeof enMessages; +const frMessages = { + ...fr, + ...frDashboardApprovals, + ...frDashboardCustody, + ...frDashboardIssuance, + ...frDashboardPayments, + ...frDashboardPolicies, + Shared: frShared, +} satisfies Messages; + export type MessageKeyFor = TValue extends string ? "" : { @@ -30,7 +47,10 @@ export type MessageKeyFor = TValue extends string export type MessageKey = MessageKeyFor; export type TranslationValues = Record; -const messagesByLocale: Record = { en: enMessages }; +const messagesByLocale: Record = { + en: enMessages, + fr: frMessages, +}; export function getMessages(locale: AppLocale): Messages { return messagesByLocale[locale]; diff --git a/apps/sdp-web/src/i18n/messages.unit.test.ts b/apps/sdp-web/src/i18n/messages.unit.test.ts index c611f031f..1a5c67c55 100644 --- a/apps/sdp-web/src/i18n/messages.unit.test.ts +++ b/apps/sdp-web/src/i18n/messages.unit.test.ts @@ -1,15 +1,41 @@ import { describe, expect, it } from "vitest"; -import { isAppLocale } from "@/i18n/config"; +import { isAppLocale, supportedLocales } from "@/i18n/config"; import { getMessages, translate } from "@/i18n/messages"; +function flattenKeys(value: unknown, prefix = ""): string[] { + if (typeof value === "string") { + return [prefix]; + } + + if (!value || typeof value !== "object") { + return []; + } + + return Object.entries(value).flatMap(([key, nested]) => { + const next = prefix ? `${prefix}.${key}` : key; + return flattenKeys(nested, next); + }); +} + describe("i18n messages", () => { it("only accepts configured locales", () => { expect(isAppLocale("en")).toBe(true); - expect(isAppLocale("fr")).toBe(false); + expect(isAppLocale("fr")).toBe(true); + expect(isAppLocale("de")).toBe(false); }); it("resolves typed catalog entries", () => { expect(translate(getMessages("en"), "Home.joinWaitlist")).toBe("Join the waitlist"); + expect(translate(getMessages("fr"), "Home.joinWaitlist")).toBe("Rejoindre la liste d’attente"); + }); + + it("keeps non-English catalogs inventory-matched to English", () => { + const englishKeys = flattenKeys(getMessages("en")).sort(); + + for (const locale of supportedLocales) { + if (locale === "en") continue; + expect(flattenKeys(getMessages(locale)).sort()).toEqual(englishKeys); + } }); it("rejects missing interpolation values", () => {