From 032a43ad01a3f29d20223da73ef02dd26f6976cb Mon Sep 17 00:00:00 2001 From: Luca <102960244+Luca-Timo@users.noreply.github.com> Date: Mon, 11 May 2026 02:13:08 +0200 Subject: [PATCH] i18n(customers): add nl / pt / ru / fr translations for customer portal Previously these locales fell through to en for every customer.* / customers.* / settings.customerSurface / settings.features.customerPortal key. Machine-translated and flagged in the PR description as needing native review. Co-Authored-By: Claude Opus 4.6 --- frontend/src/i18n/locales/fr.json | 310 ++++++++++++++++++++++++++- frontend/src/i18n/locales/nl.json | 288 ++++++++++++++------------ frontend/src/i18n/locales/pt.json | 280 +++++++++++++------------ frontend/src/i18n/locales/ru.json | 334 ++++++++++++++++-------------- 4 files changed, 783 insertions(+), 429 deletions(-) diff --git a/frontend/src/i18n/locales/fr.json b/frontend/src/i18n/locales/fr.json index fbb7f607..4c59ed71 100644 --- a/frontend/src/i18n/locales/fr.json +++ b/frontend/src/i18n/locales/fr.json @@ -168,7 +168,8 @@ "eventTypes": "Types d'événements", "backup": "Sauvegarde et Restauration", "cmsPages": "Pages CMS", - "users": "Utilisateurs" + "users": "Utilisateurs", + "customers": "Clients" }, "archives": { "title": "Archives", @@ -1066,7 +1067,27 @@ "empty": "Aucun webhook pour l'instant. Créez-en un ci-dessus pour recevoir des notifications." }, "sectionLabel": "Section des paramètres", - "navAriaLabel": "Navigation des paramètres" + "navAriaLabel": "Navigation des paramètres", + "features": { + "sections": { + "customers": "Clients" + }, + "customerPortal": { + "title": "Portail client", + "description": "Connexions client persistantes. Les clients récurrents voient toutes leurs galeries assignées au même endroit — plus de mots de passe par événement. Base pour Calendrier / Devis / Factures (qui n'apparaissent dans le tableau de bord client que lorsque cette option est activée)." + } + }, + "customerSurface": { + "brandingTitle": "En-tête du tableau de bord client", + "brandingHint": "Contrôle ce qui s'affiche dans l'en-tête de /customer/dashboard. Les galeries publiques et les surfaces administratives ne sont pas affectées.", + "showLogo": "Afficher le logo dans l'en-tête client", + "showLogoHint": "Utilise le même logo de marque configuré ci-dessus.", + "showCompanyName": "Afficher le nom de l'entreprise dans l'en-tête client", + "showCompanyNameHint": "Masquer si votre logo inclut déjà le nom de l'entreprise.", + "save": "Enregistrer les modifications", + "saved": "Branding du tableau de bord client enregistré", + "error": "Impossible d'enregistrer les paramètres" + } }, "analytics": { "title": "Tableau de bord analytique", @@ -2490,5 +2511,290 @@ "movedToCategory_other": "{{count}} photos déplacées vers {{category}}", "moveToCategoryFailed": "Échec du déplacement des photos vers la catégorie", "moveToCategory": "Déplacer vers la catégorie" + }, + "customer": { + "login": { + "title": "Connexion client", + "subtitle": "Accédez à toutes vos galeries photo en un seul endroit.", + "email": "E-mail", + "password": "Mot de passe", + "emailRequired": "L'e-mail est obligatoire", + "invalidEmail": "Veuillez saisir une adresse e-mail valide", + "passwordRequired": "Le mot de passe est obligatoire", + "showPassword": "Afficher le mot de passe", + "hidePassword": "Masquer le mot de passe", + "signIn": "Se connecter", + "loginSuccess": "Bon retour !", + "invalidCredentials": "E-mail ou mot de passe invalide", + "tooManyAttempts": "Trop de tentatives — réessayez plus tard.", + "networkError": "Impossible de contacter le serveur. Veuillez réessayer.", + "generalError": "Échec de la connexion. Veuillez réessayer.", + "acceptedToast": "Compte prêt — veuillez vous connecter.", + "adminHint": "Vous cherchez le panneau d'administration ? Visitez /admin/login.", + "emailPlaceholder": "vous@exemple.com", + "passwordPlaceholder": "Votre mot de passe", + "needHelp": "Besoin d'aide ?", + "poweredBy": "Propulsé par PicPeak" + }, + "acceptInvite": { + "title": "Configurez votre compte", + "invalidToken": "Ce lien d'invitation est invalide ou expiré. Veuillez demander une nouvelle invitation à votre photographe.", + "emailWillBe": "L'e-mail de votre compte sera ", + "invitedBy": ", invité par ", + "name": "Votre nom", + "nameRequired": "Veuillez saisir votre nom", + "password": "Choisissez un mot de passe", + "confirm": "Confirmez le mot de passe", + "passwordTooShort": "Le mot de passe doit comporter au moins 8 caractères", + "passwordsMismatch": "Les mots de passe ne correspondent pas", + "passwordHint": "Au moins 8 caractères, avec une majuscule et un chiffre.", + "submit": "Créer le compte", + "successToast": "Compte créé — veuillez vous connecter.", + "alreadyExists": "Un compte avec cet e-mail existe déjà. Veuillez plutôt vous connecter.", + "invalidSubmission": "Impossible de créer votre compte.", + "generalError": "Impossible de créer votre compte. Veuillez réessayer.", + "subtitle": "Confirmez ou complétez vos informations. Vous pouvez tout modifier depuis la page de profil plus tard.", + "displayName": "Nom affiché", + "section": { + "personal": "Personnel", + "contact": "Contact & entreprise (facultatif)", + "address": "Adresse de facturation (facultatif)", + "password": "Choisissez un mot de passe" + } + }, + "dashboard": { + "title": "Vos galeries", + "subtitle": "Cliquez sur une galerie pour l'ouvrir. Le bouton Télécharger regroupe toutes les photos dans un zip.", + "loadError": "Impossible de charger vos galeries. Veuillez réessayer.", + "emptyTitle": "Aucune galerie pour le moment", + "emptyBody": "Dès que votre photographe vous attribuera une galerie, elle apparaîtra ici.", + "openAria": "Ouvrir la galerie {{name}}", + "opening": "Ouverture…", + "expiresOn": "Expire le {{date}}", + "expiredOn": "Expirée le {{date}}", + "eventExpired": "Cette galerie a expiré.", + "eventForbidden": "Vous n'avez plus accès à cette galerie.", + "openError": "Impossible d'ouvrir cette galerie. Veuillez réessayer.", + "download": "Télécharger", + "preparingDownload": "Préparation…", + "quickDownloadAria": "Télécharger toutes les photos de {{name}}", + "downloadStarted": "Téléchargement démarré pour {{name}}", + "downloadError": "Impossible de démarrer le téléchargement. Veuillez réessayer.", + "sortLabel": "Trier par", + "sortNewest": "Plus récents d'abord", + "sortOldest": "Plus anciens d'abord", + "sortName": "Par nom", + "open": "Ouvrir" + }, + "layout": { + "greeting": "Bonjour, {{name}}" + }, + "nav": { + "galleries": "Galeries", + "calendar": "Calendrier", + "quotes": "Devis", + "bills": "Factures", + "profile": "Profil", + "soon": "Bientôt" + }, + "comingSoon": { + "tag": "Bientôt disponible" + }, + "calendar": { + "title": "Calendrier", + "body": "Les prochaines séances, dates de livraison de galeries et autres événements liés à vos shootings apparaîtront ici. Nous vous préviendrons lorsque ce sera prêt." + }, + "quotes": { + "title": "Devis", + "body": "Consultez et acceptez les devis pour vos prochaines séances en un seul endroit. Nous y travaillons encore — pour l'instant, votre photographe continuera à envoyer ses devis comme d'habitude." + }, + "bills": { + "title": "Factures", + "body": "Les factures et l'historique des paiements pour vos séances seront disponibles ici. Nous vous enverrons un e-mail lorsque ce sera en ligne." + }, + "profile": { + "title": "Profil client", + "subtitle": "Gardez vos coordonnées et informations de facturation à jour — elles apparaîtront sur les devis et factures lorsque ces fonctionnalités seront actives.", + "savedToast": "Profil enregistré", + "saveError": "Impossible d'enregistrer le profil.", + "loadError": "Impossible de charger votre profil.", + "save": "Enregistrer les modifications", + "salutation": { + "none": "— Non spécifié —", + "herr": "M.", + "frau": "Mme", + "mx": "Mx", + "dr": "Dr" + }, + "section": { + "personal": "Informations personnelles", + "contact": "Contact & entreprise", + "address": "Adresse de facturation", + "password": "Changer le mot de passe" + }, + "field": { + "email": "E-mail (identifiant)", + "emailHint": "Contactez votre photographe si vous devez modifier votre e-mail de connexion.", + "salutation": "Civilité", + "firstName": "Prénom", + "lastName": "Nom", + "displayName": "Nom affiché", + "displayNameHint": "Comment nous vous saluons dans le tableau de bord.", + "phone": "Téléphone", + "companyName": "Nom de l'entreprise", + "vatId": "N° TVA", + "addressLine1": "Adresse ligne 1", + "addressLine2": "Adresse ligne 2", + "postalCode": "Code postal", + "city": "Ville", + "state": "Région / département", + "countryCode": "Pays" + }, + "password": { + "current": "Mot de passe actuel", + "next": "Nouveau mot de passe", + "confirm": "Confirmez le nouveau mot de passe", + "submit": "Mettre à jour le mot de passe", + "hint": "Au moins 8 caractères avec une majuscule et un chiffre.", + "currentRequired": "Saisissez votre mot de passe actuel", + "tooShort": "Au moins 8 caractères", + "mismatch": "Les mots de passe ne correspondent pas", + "wrong": "Le mot de passe actuel est incorrect", + "savedToast": "Mot de passe mis à jour", + "error": "Impossible de modifier le mot de passe" + } + }, + "resetPassword": { + "title": "Réinitialisez votre mot de passe", + "invalidToken": "Ce lien de réinitialisation est invalide ou expiré. Demandez à votre photographe d'en envoyer un nouveau.", + "forEmail": "Définition d'un nouveau mot de passe pour ", + "password": "Nouveau mot de passe", + "confirm": "Confirmez le nouveau mot de passe", + "submit": "Mettre à jour le mot de passe", + "hint": "Au moins 8 caractères avec une majuscule et un chiffre.", + "tooShort": "Le mot de passe doit comporter au moins 8 caractères", + "mismatch": "Les mots de passe ne correspondent pas", + "successToast": "Mot de passe mis à jour. Veuillez vous connecter.", + "invalidSubmission": "Impossible de mettre à jour votre mot de passe.", + "generalError": "Impossible de mettre à jour votre mot de passe. Veuillez réessayer." + } + }, + "customers": { + "pageTitle": "Clients", + "pageSubtitle": "Comptes clients récurrents pouvant se connecter sur /customer/login.", + "unnamed": "Sans nom", + "empty": "Aucun client pour le moment. Cliquez sur « Inviter un client » pour en ajouter un.", + "loadError": "Impossible de charger les clients", + "loadInvitationsError": "Impossible de charger les invitations", + "tabs": { + "customers": "Clients", + "invitations": "Invitations" + }, + "search": { + "placeholder": "Rechercher par e-mail, nom ou entreprise" + }, + "table": { + "name": "Nom", + "email": "E-mail", + "company": "Entreprise", + "eventCount": "Événements", + "lastLogin": "Dernière connexion", + "status": "Statut" + }, + "status": { + "active": "Actif", + "inactive": "Désactivé" + }, + "invite": { + "button": "Inviter un client", + "title": "Inviter un client", + "description": "Il recevra un e-mail avec un lien pour configurer son compte. Une fois accepté, vous pourrez l'assigner à des événements.", + "email": "E-mail", + "submit": "Envoyer l'invitation", + "success": "Invitation envoyée", + "error": "Impossible d'envoyer l'invitation.", + "conflict": "Un client avec cet e-mail existe déjà ou a une invitation en attente.", + "invalidEmail": "Veuillez saisir un e-mail valide", + "showPrefill": "+ Ajouter des coordonnées (facultatif)", + "hidePrefill": "− Masquer les coordonnées", + "prefillHint": "Tout ce que vous saisirez sera pré-rempli sur la page d'inscription du client — il pourra toujours le modifier." + }, + "invitations": { + "empty": "Aucune invitation en attente.", + "email": "E-mail", + "invitedBy": "Invité par", + "expiresAt": "Expire", + "createdAt": "Créé le", + "cancel": "Annuler" + }, + "deactivate": { + "button": "Désactiver", + "title": "Désactiver le client ?", + "body": "Il ne pourra plus se connecter. Vous pourrez le ré-inviter plus tard.", + "success": "Client désactivé", + "error": "Impossible de désactiver le client" + }, + "cancelInvitation": { + "title": "Annuler l'invitation ?", + "body": "Le lien d'invitation cessera immédiatement de fonctionner.", + "success": "Invitation annulée", + "error": "Impossible d'annuler l'invitation" + }, + "detail": { + "loadError": "Impossible de charger le client", + "saved": "Client enregistré", + "saveError": "Impossible d'enregistrer les modifications.", + "emailConflict": "Cet e-mail est déjà utilisé par un autre client.", + "save": "Enregistrer les modifications", + "expires": "expire", + "accountSection": "Compte", + "personalSection": "Informations personnelles", + "billingSection": "Adresse & facturation", + "notesSection": "Notes internes", + "eventsSection": "Événements assignés", + "noEvents": "Non assigné à des événements. Ajoutez ce client à un événement depuis le formulaire de l'événement.", + "email": "E-mail", + "preferredLanguage": "Langue préférée", + "salutation": "Civilité", + "salutationNone": "—", + "firstName": "Prénom", + "lastName": "Nom", + "displayName": "Nom affiché", + "phone": "Téléphone", + "company": "Entreprise", + "billingEmail": "E-mail de facturation", + "vatId": "N° TVA / fiscal", + "addressLine1": "Adresse ligne 1", + "addressLine2": "Adresse ligne 2", + "postalCode": "Code postal", + "city": "Ville", + "state": "Région / département", + "countryCode": "Pays (ISO 2)", + "notesHint": "Visible uniquement par les administrateurs. Jamais montré au client.", + "featuresSection": "Fonctionnalités client", + "featuresHint": "Surcharges par client pour les onglets du portail. Les bascules globales dans Paramètres → Fonctionnalités sont le commutateur principal — quand global est sur OFF personne ne voit l'onglet, quel que soit le réglage ici. Les valeurs par défaut sont ON ; mettez un bouton sur OFF pour masquer un onglet pour ce client en particulier.", + "passwordSection": "Actions du compte", + "passwordHint": "Envoie un lien de réinitialisation à usage unique (7 jours) à l'e-mail du client. Le mot de passe actuel continue de fonctionner jusqu'à ce que le client clique sur le lien et en définisse un nouveau.", + "passwordReset": { + "button": "Envoyer l'e-mail de réinitialisation", + "success": "E-mail de réinitialisation envoyé", + "error": "Impossible d'envoyer la réinitialisation", + "inactive": "Réactivez le client avant d'envoyer une réinitialisation." + } + }, + "reactivate": { + "button": "Réactiver", + "success": "Client réactivé", + "error": "Impossible de réactiver le client" + }, + "erase": { + "button": "Effacer les données du client", + "title": "Effacer les données du client ?", + "body": "Supprime le nom, l'e-mail, le téléphone, l'adresse, l'entreprise et les identifiants du client. La ligne de compte reste pour que les enregistrements d'accès historiques et les journaux d'audit y fassent toujours référence. Cette action est irréversible — vous ne pourrez pas restaurer les données ensuite.", + "confirm": "Effacer définitivement", + "confirmInFlight": "Effacement…", + "success": "Client effacé", + "error": "Impossible d'effacer le client" + } } } diff --git a/frontend/src/i18n/locales/nl.json b/frontend/src/i18n/locales/nl.json index a2132add..492e666e 100644 --- a/frontend/src/i18n/locales/nl.json +++ b/frontend/src/i18n/locales/nl.json @@ -168,7 +168,7 @@ "cmsPages": "CMS-pagina's", "users": "Gebruikers", "calendar": "Agenda", - "customers": "Customers" + "customers": "Klanten" }, "archives": { "title": "Archieven", @@ -1086,7 +1086,8 @@ "communication": "Communicatie", "scheduling": "Planning", "sales": "Verkoop", - "insights": "Inzichten & Toegang" + "insights": "Inzichten & Toegang", + "customers": "Klanten" }, "status": { "stable": "stabiel", @@ -1132,7 +1133,22 @@ "title": "Gebruikersbeheer", "description": "Multi-admin ondersteuning met rolgebaseerde rechten. Schakel dit uit als u een eenmansstudio bent.", "warning": "Bestaande gebruikersaccounts blijven geldig; de admin-interface om ze te beheren wordt verborgen totdat u dit weer inschakelt." + }, + "customerPortal": { + "title": "Klantenportaal", + "description": "Permanente klantlogins. Terugkerende klanten zien al hun toegewezen galerijen op één plek — geen wachtwoorden per evenement. Basis voor Agenda / Offertes / Facturen (die alleen in het klantdashboard verschijnen als dit aan staat)." } + }, + "customerSurface": { + "brandingTitle": "Kopregel klantdashboard", + "brandingHint": "Bepaalt wat in de kopregel van /customer/dashboard wordt getoond. Openbare galerijen en beheerschermen blijven onveranderd.", + "showLogo": "Logo in klantheader tonen", + "showLogoHint": "Gebruikt hetzelfde brandinglogo dat hierboven is geconfigureerd.", + "showCompanyName": "Bedrijfsnaam in klantheader tonen", + "showCompanyNameHint": "Verberg dit als je logo de bedrijfsnaam al bevat.", + "save": "Wijzigingen opslaan", + "saved": "Branding van klantdashboard opgeslagen", + "error": "Instellingen konden niet worden opgeslagen" } }, "analytics": { @@ -2545,7 +2561,7 @@ "customer": { "login": { "title": "Klantlogin", - "subtitle": "Bekijk al uw fotogalerieën op één plek.", + "subtitle": "Beheer al je fotogalerijen op één plek.", "email": "E-mail", "password": "Wachtwoord", "emailRequired": "E-mail is verplicht", @@ -2559,154 +2575,154 @@ "tooManyAttempts": "Te veel pogingen — probeer het later opnieuw.", "networkError": "Kan de server niet bereiken. Probeer het opnieuw.", "generalError": "Inloggen mislukt. Probeer het opnieuw.", - "acceptedToast": "Account klaar — log nu in.", - "adminHint": "Zoekt u het beheerderspaneel? Ga naar /admin/login.", - "emailPlaceholder": "you@example.com", - "passwordPlaceholder": "Your password", - "needHelp": "Need help?", - "poweredBy": "Powered by PicPeak" + "acceptedToast": "Account gereed — log nu in.", + "adminHint": "Op zoek naar het beheerderspaneel? Ga naar /admin/login.", + "emailPlaceholder": "jij@voorbeeld.com", + "passwordPlaceholder": "Je wachtwoord", + "needHelp": "Hulp nodig?", + "poweredBy": "Mogelijk gemaakt door PicPeak" }, "acceptInvite": { - "title": "Account instellen", - "invalidToken": "Deze uitnodigingslink is ongeldig of verlopen. Neem contact op met uw fotograaf voor een nieuwe uitnodiging.", - "emailWillBe": "Uw account-e-mail wordt ", + "title": "Account aanmaken", + "invalidToken": "Deze uitnodigingslink is ongeldig of verlopen. Vraag je fotograaf om een nieuwe uitnodiging.", + "emailWillBe": "Je accountmail wordt ", "invitedBy": ", uitgenodigd door ", - "name": "Uw naam", - "nameRequired": "Voer uw naam in", + "name": "Je naam", + "nameRequired": "Voer je naam in", "password": "Kies een wachtwoord", - "confirm": "Wachtwoord bevestigen", - "passwordTooShort": "Wachtwoord moet minimaal 8 tekens bevatten", + "confirm": "Bevestig wachtwoord", + "passwordTooShort": "Wachtwoord moet minstens 8 tekens bevatten", "passwordsMismatch": "Wachtwoorden komen niet overeen", - "passwordHint": "Minimaal 8 tekens, met één hoofdletter en één cijfer.", + "passwordHint": "Minstens 8 tekens, met één hoofdletter en één cijfer.", "submit": "Account aanmaken", "successToast": "Account aangemaakt — log nu in.", "alreadyExists": "Er bestaat al een account met dit e-mailadres. Log in plaats daarvan in.", "invalidSubmission": "Account kon niet worden aangemaakt.", "generalError": "Account kon niet worden aangemaakt. Probeer het opnieuw.", - "subtitle": "Confirm or fill in your details. You can edit anything from the profile page later.", - "displayName": "Display name", + "subtitle": "Bevestig of vul je gegevens aan. Je kunt alles later aanpassen via je profielpagina.", + "displayName": "Weergavenaam", "section": { - "personal": "Personal", - "contact": "Contact & business (optional)", - "address": "Billing address (optional)", - "password": "Choose a password" + "personal": "Persoonlijk", + "contact": "Contact & bedrijf (optioneel)", + "address": "Factuuradres (optioneel)", + "password": "Kies een wachtwoord" } }, "dashboard": { - "title": "Your galleries", - "subtitle": "Click a gallery to open it. The Download button bundles every photo as a zip.", - "loadError": "Uw galerieën konden niet worden geladen. Probeer het opnieuw.", - "emptyTitle": "Nog geen galerieën", - "emptyBody": "Zodra uw fotograaf u aan een galerie toewijst, verschijnt deze hier.", - "openAria": "Galerie {{name}} openen", - "opening": "Openen…", - "expiresOn": "Verloopt op {{date}}", + "title": "Je galerijen", + "subtitle": "Klik op een galerij om deze te openen. De downloadknop bundelt alle foto's in een zip.", + "loadError": "Je galerijen konden niet worden geladen. Probeer het opnieuw.", + "emptyTitle": "Nog geen galerijen", + "emptyBody": "Zodra je fotograaf je aan een galerij toewijst, verschijnt deze hier.", + "openAria": "Open galerij {{name}}", + "opening": "Bezig met openen…", + "expiresOn": "Verloopt {{date}}", "expiredOn": "Verlopen op {{date}}", - "eventExpired": "Deze galerie is verlopen.", - "eventForbidden": "U heeft geen toegang meer tot deze galerie.", - "openError": "Galerie kon niet worden geopend. Probeer het opnieuw.", + "eventExpired": "Deze galerij is verlopen.", + "eventForbidden": "Je hebt geen toegang meer tot deze galerij.", + "openError": "Deze galerij kon niet worden geopend. Probeer het opnieuw.", "download": "Downloaden", "preparingDownload": "Voorbereiden…", - "quickDownloadAria": "Alle foto's voor {{name}} downloaden", + "quickDownloadAria": "Download alle foto's voor {{name}}", "downloadStarted": "Download gestart voor {{name}}", - "downloadError": "Download kon niet worden gestart. Probeer het opnieuw.", - "sortLabel": "Sort by", - "sortNewest": "Newest first", - "sortOldest": "Oldest first", - "sortName": "By name", - "open": "Open" + "downloadError": "De download kon niet worden gestart. Probeer het opnieuw.", + "sortLabel": "Sorteer op", + "sortNewest": "Nieuwste eerst", + "sortOldest": "Oudste eerst", + "sortName": "Op naam", + "open": "Openen" }, "layout": { "greeting": "Hallo, {{name}}" }, "nav": { - "galleries": "Galleries", - "calendar": "Calendar", - "quotes": "Quotes", - "bills": "Bills", - "profile": "Profile", - "soon": "Soon" + "galleries": "Galerijen", + "calendar": "Agenda", + "quotes": "Offertes", + "bills": "Facturen", + "profile": "Profiel", + "soon": "Binnenkort" }, "comingSoon": { - "tag": "Coming soon" + "tag": "Binnenkort" }, "calendar": { - "title": "Calendar", - "body": "Upcoming sessions, gallery delivery dates, and other shoot-related events will land here. We'll let you know when it's ready." + "title": "Agenda", + "body": "Aankomende shoots, leverdata van galerijen en andere shoot-gerelateerde gebeurtenissen verschijnen hier. We laten je weten wanneer dit klaar is." }, "quotes": { - "title": "Quotes", - "body": "Review and accept quotes for upcoming shoots in one place. We're still building this — for now, your photographer will keep sending quotes the usual way." + "title": "Offertes", + "body": "Bekijk en accepteer offertes voor aankomende shoots op één plek. We werken er nog aan — je fotograaf blijft tot dan offertes op de gebruikelijke manier sturen." }, "bills": { - "title": "Bills", - "body": "Invoices and payment history for your sessions will be available here. We'll send you an email when this is live." + "title": "Facturen", + "body": "Facturen en betaalgeschiedenis voor je shoots verschijnen hier. We sturen een e-mail wanneer dit live is." }, "profile": { - "title": "Customer profile", - "subtitle": "Keep your contact and billing details up to date — they're shown on quotes and invoices once those features go live.", - "savedToast": "Profile saved", - "saveError": "Could not save profile.", - "loadError": "Could not load your profile.", - "save": "Save changes", + "title": "Klantprofiel", + "subtitle": "Houd je contact- en factureringsgegevens actueel — ze verschijnen op offertes en facturen zodra die functies live zijn.", + "savedToast": "Profiel opgeslagen", + "saveError": "Profiel kon niet worden opgeslagen.", + "loadError": "Je profiel kon niet worden geladen.", + "save": "Wijzigingen opslaan", "salutation": { - "none": "— Not specified —", - "herr": "Mr.", - "frau": "Ms.", + "none": "— Niet opgegeven —", + "herr": "Dhr.", + "frau": "Mevr.", "mx": "Mx", "dr": "Dr." }, "section": { - "personal": "Personal information", - "contact": "Contact & business", - "address": "Billing address", - "password": "Change password" + "personal": "Persoonlijke gegevens", + "contact": "Contact & bedrijf", + "address": "Factuuradres", + "password": "Wachtwoord wijzigen" }, "field": { - "email": "Email (login)", - "emailHint": "Contact your photographer if you need to change your login email.", - "salutation": "Salutation", - "firstName": "First name", - "lastName": "Last name", - "displayName": "Display name", - "displayNameHint": "How we greet you in the dashboard.", - "phone": "Phone", - "companyName": "Company name", - "vatId": "VAT ID", - "addressLine1": "Address line 1", - "addressLine2": "Address line 2", - "postalCode": "Postal code", - "city": "City", - "state": "State / region", - "countryCode": "Country" + "email": "E-mail (login)", + "emailHint": "Neem contact op met je fotograaf als je je login-mail wilt wijzigen.", + "salutation": "Aanhef", + "firstName": "Voornaam", + "lastName": "Achternaam", + "displayName": "Weergavenaam", + "displayNameHint": "Hoe we je in het dashboard begroeten.", + "phone": "Telefoon", + "companyName": "Bedrijfsnaam", + "vatId": "Btw-nummer", + "addressLine1": "Adresregel 1", + "addressLine2": "Adresregel 2", + "postalCode": "Postcode", + "city": "Stad", + "state": "Provincie / regio", + "countryCode": "Land" }, "password": { - "current": "Current password", - "next": "New password", - "confirm": "Confirm new password", - "submit": "Update password", - "hint": "At least 8 characters with one uppercase letter and one number.", - "currentRequired": "Enter your current password", - "tooShort": "At least 8 characters", - "mismatch": "Passwords do not match", - "wrong": "Current password is incorrect", - "savedToast": "Password updated", - "error": "Could not change password" + "current": "Huidig wachtwoord", + "next": "Nieuw wachtwoord", + "confirm": "Bevestig nieuw wachtwoord", + "submit": "Wachtwoord bijwerken", + "hint": "Minstens 8 tekens met één hoofdletter en één cijfer.", + "currentRequired": "Voer je huidige wachtwoord in", + "tooShort": "Minstens 8 tekens", + "mismatch": "Wachtwoorden komen niet overeen", + "wrong": "Huidig wachtwoord is onjuist", + "savedToast": "Wachtwoord bijgewerkt", + "error": "Wachtwoord kon niet worden gewijzigd" } }, "resetPassword": { - "title": "Reset your password", - "invalidToken": "This reset link is invalid or has expired. Please ask your photographer to send a new one.", - "forEmail": "Setting a new password for ", - "password": "New password", - "confirm": "Confirm new password", - "submit": "Update password", - "hint": "At least 8 characters with one uppercase letter and one number.", - "tooShort": "Password must be at least 8 characters", - "mismatch": "Passwords do not match", - "successToast": "Password updated. Please log in.", - "invalidSubmission": "Could not update your password.", - "generalError": "Could not update your password. Please try again." + "title": "Wachtwoord opnieuw instellen", + "invalidToken": "Deze resetlink is ongeldig of verlopen. Vraag je fotograaf om een nieuwe.", + "forEmail": "Nieuw wachtwoord instellen voor ", + "password": "Nieuw wachtwoord", + "confirm": "Bevestig nieuw wachtwoord", + "submit": "Wachtwoord bijwerken", + "hint": "Minstens 8 tekens met één hoofdletter en één cijfer.", + "tooShort": "Wachtwoord moet minstens 8 tekens bevatten", + "mismatch": "Wachtwoorden komen niet overeen", + "successToast": "Wachtwoord bijgewerkt. Log nu in.", + "invalidSubmission": "Je wachtwoord kon niet worden bijgewerkt.", + "generalError": "Je wachtwoord kon niet worden bijgewerkt. Probeer het opnieuw." } }, "customers": { @@ -2738,16 +2754,16 @@ "invite": { "button": "Klant uitnodigen", "title": "Een klant uitnodigen", - "description": "Zij ontvangen een e-mail met een link om hun account in te stellen. Zodra zij hebben geaccepteerd, kunt u hen toewijzen aan evenementen.", + "description": "Ze ontvangen een e-mail met een link om hun account aan te maken. Zodra ze deze hebben geaccepteerd, kun je ze aan evenementen toewijzen.", "email": "E-mail", - "submit": "Uitnodiging sturen", + "submit": "Uitnodiging versturen", "success": "Uitnodiging verzonden", "error": "Uitnodiging kon niet worden verzonden.", - "conflict": "Er bestaat al een klant met dit e-mailadres of er is een openstaande uitnodiging.", + "conflict": "Er bestaat al een klant met dit e-mailadres of er staat een uitnodiging open.", "invalidEmail": "Voer een geldig e-mailadres in", - "showPrefill": "+ Add contact details (optional)", - "hidePrefill": "− Hide contact details", - "prefillHint": "Anything you fill in will be pre-populated on the customer's sign-up page — they can still edit it." + "showPrefill": "+ Contactgegevens toevoegen (optioneel)", + "hidePrefill": "− Contactgegevens verbergen", + "prefillHint": "Alles wat je invult wordt voorgevuld op de inschrijfpagina van de klant — ze kunnen het nog steeds bewerken." }, "invitations": { "empty": "Geen openstaande uitnodigingen.", @@ -2760,13 +2776,13 @@ "deactivate": { "button": "Deactiveren", "title": "Klant deactiveren?", - "body": "Zij kunnen niet meer inloggen. U kunt hen later opnieuw uitnodigen.", + "body": "Ze kunnen niet meer inloggen. Je kunt ze later opnieuw uitnodigen.", "success": "Klant gedeactiveerd", "error": "Klant kon niet worden gedeactiveerd" }, "cancelInvitation": { "title": "Uitnodiging annuleren?", - "body": "De uitnodigingslink stopt direct met werken.", + "body": "De uitnodigingslink werkt direct niet meer.", "success": "Uitnodiging geannuleerd", "error": "Uitnodiging kon niet worden geannuleerd" }, @@ -2774,7 +2790,7 @@ "loadError": "Klant kon niet worden geladen", "saved": "Klant opgeslagen", "saveError": "Wijzigingen konden niet worden opgeslagen.", - "emailConflict": "Dat e-mailadres is al in gebruik door een andere klant.", + "emailConflict": "Dit e-mailadres is al in gebruik bij een andere klant.", "save": "Wijzigingen opslaan", "expires": "verloopt", "accountSection": "Account", @@ -2782,7 +2798,7 @@ "billingSection": "Adres & facturering", "notesSection": "Interne notities", "eventsSection": "Toegewezen evenementen", - "noEvents": "Nog niet toegewezen aan evenementen. Voeg deze klant toe aan een evenement via het evenementformulier.", + "noEvents": "Nog niet aan evenementen toegewezen. Voeg deze klant toe aan een evenement via het evenementformulier.", "email": "E-mail", "preferredLanguage": "Voorkeurstaal", "salutation": "Aanhef", @@ -2792,8 +2808,8 @@ "displayName": "Weergavenaam", "phone": "Telefoon", "company": "Bedrijf", - "billingEmail": "Facturatie-e-mail", - "vatId": "BTW / fiscaal nummer", + "billingEmail": "Factuur-e-mail", + "vatId": "Btw / belasting-ID", "addressLine1": "Adresregel 1", "addressLine2": "Adresregel 2", "postalCode": "Postcode", @@ -2801,30 +2817,30 @@ "state": "Provincie / regio", "countryCode": "Land (ISO 2)", "notesHint": "Alleen zichtbaar voor beheerders. Wordt nooit aan de klant getoond.", - "featuresSection": "Customer features", - "featuresHint": "Per-customer overrides for the customer-surface tabs. The global toggles in Settings → Customer Surface are the master switch — when global is OFF nobody sees the tab, regardless of what you set here. Defaults are ON, so flip a switch OFF to hide a tab for this specific customer.", - "passwordSection": "Account actions", - "passwordHint": "Sends a 7-day single-use reset link to the customer's email. The customer's current password keeps working until they click the link and set a new one.", + "featuresSection": "Klantfuncties", + "featuresHint": "Per-klant overrides voor de tabbladen van de klantenomgeving. De globale schakelaars in Instellingen → Functies zijn de hoofdschakelaar — als globaal UIT staat, ziet niemand het tabblad, ongeacht wat je hier instelt. Standaard staat alles AAN; zet een schakelaar UIT om een tabblad voor deze specifieke klant te verbergen.", + "passwordSection": "Accountacties", + "passwordHint": "Stuurt een eenmalig te gebruiken resetlink (7 dagen geldig) naar het e-mailadres van de klant. Het huidige wachtwoord blijft werken totdat de klant de link gebruikt en een nieuw wachtwoord instelt.", "passwordReset": { - "button": "Send password reset email", - "success": "Password reset email sent", - "error": "Could not send password reset", - "inactive": "Reactivate the customer before sending a reset." + "button": "Wachtwoord-resetmail versturen", + "success": "Wachtwoord-resetmail verzonden", + "error": "Wachtwoordreset kon niet worden verzonden", + "inactive": "Reactiveer de klant voordat je een reset verstuurt." } }, "reactivate": { - "button": "Reactivate", - "success": "Customer reactivated", - "error": "Could not reactivate customer" + "button": "Heractiveren", + "success": "Klant heractiveerd", + "error": "Klant kon niet worden heractiveerd" }, "erase": { - "button": "Erase customer data", - "title": "Erase customer data?", - "body": "Removes the customer's name, email, phone, address, company and credentials. The account row stays so historical event-access records and audit logs still reference it. This is irreversible — you cannot restore the data afterwards.", - "confirm": "Erase permanently", - "confirmInFlight": "Erasing…", - "success": "Customer erased", - "error": "Could not erase customer" + "button": "Klantgegevens wissen", + "title": "Klantgegevens wissen?", + "body": "Verwijdert de naam, e-mail, telefoon, adres, bedrijf en inloggegevens van de klant. De accountrij blijft staan zodat historische toegangs- en auditgegevens nog steeds verwijzen. Dit is onomkeerbaar — je kunt de gegevens daarna niet meer herstellen.", + "confirm": "Definitief wissen", + "confirmInFlight": "Bezig met wissen…", + "success": "Klant gewist", + "error": "Klant kon niet worden gewist" } } } diff --git a/frontend/src/i18n/locales/pt.json b/frontend/src/i18n/locales/pt.json index a010710f..ca5dae75 100644 --- a/frontend/src/i18n/locales/pt.json +++ b/frontend/src/i18n/locales/pt.json @@ -171,7 +171,7 @@ "cmsPages": "Páginas CMS", "users": "Utilizadores", "calendar": "Calendário", - "customers": "Customers" + "customers": "Clientes" }, "archives": { "title": "Arquivos", @@ -1103,7 +1103,8 @@ "communication": "Comunicação", "scheduling": "Agendamento", "sales": "Vendas", - "insights": "Análises & Acesso" + "insights": "Análises & Acesso", + "customers": "Clientes" }, "status": { "stable": "estável", @@ -1149,7 +1150,22 @@ "title": "Gerenciamento de Usuários", "description": "Suporte a múltiplos administradores com permissões baseadas em função. Desative se você é um estúdio individual.", "warning": "Contas de usuário existentes permanecem válidas; a interface administrativa para gerenciá-las ficará oculta até você reativar isto." + }, + "customerPortal": { + "title": "Portal do cliente", + "description": "Logins persistentes para clientes. Clientes recorrentes veem todas as galerias atribuídas em um só lugar — sem senhas por evento. Base para Calendário / Orçamentos / Faturas (que só aparecem no painel do cliente quando isto está ativo)." } + }, + "customerSurface": { + "brandingTitle": "Cabeçalho do painel do cliente", + "brandingHint": "Controla o que aparece no cabeçalho de /customer/dashboard. Galerias públicas e áreas administrativas não são afetadas.", + "showLogo": "Mostrar logo no cabeçalho do cliente", + "showLogoHint": "Usa o mesmo logo de branding configurado acima.", + "showCompanyName": "Mostrar nome da empresa no cabeçalho do cliente", + "showCompanyNameHint": "Oculte se seu logo já inclui o nome da empresa.", + "save": "Salvar alterações", + "saved": "Branding do painel do cliente salvo", + "error": "Não foi possível salvar as configurações" } }, "analytics": { @@ -2577,60 +2593,60 @@ }, "customer": { "login": { - "title": "Login de cliente", + "title": "Acesso do cliente", "subtitle": "Acesse todas as suas galerias de fotos em um só lugar.", "email": "E-mail", "password": "Senha", - "emailRequired": "E-mail é obrigatório", - "invalidEmail": "Insira um e-mail válido", - "passwordRequired": "Senha é obrigatória", + "emailRequired": "O e-mail é obrigatório", + "invalidEmail": "Informe um e-mail válido", + "passwordRequired": "A senha é obrigatória", "showPassword": "Mostrar senha", "hidePassword": "Ocultar senha", "signIn": "Entrar", "loginSuccess": "Bem-vindo de volta!", "invalidCredentials": "E-mail ou senha inválidos", "tooManyAttempts": "Muitas tentativas — tente novamente mais tarde.", - "networkError": "Não foi possível conectar ao servidor. Tente novamente.", + "networkError": "Não foi possível acessar o servidor. Tente novamente.", "generalError": "Falha no login. Tente novamente.", "acceptedToast": "Conta pronta — faça login.", "adminHint": "Procurando o painel de administração? Acesse /admin/login.", - "emailPlaceholder": "you@example.com", - "passwordPlaceholder": "Your password", - "needHelp": "Need help?", - "poweredBy": "Powered by PicPeak" + "emailPlaceholder": "voce@exemplo.com", + "passwordPlaceholder": "Sua senha", + "needHelp": "Precisa de ajuda?", + "poweredBy": "Desenvolvido por PicPeak" }, "acceptInvite": { - "title": "Configurar sua conta", - "invalidToken": "Este link de convite é inválido ou expirou. Entre em contato com seu fotógrafo para um novo convite.", - "emailWillBe": "O e-mail da sua conta será ", + "title": "Configure sua conta", + "invalidToken": "Este link de convite é inválido ou expirou. Peça um novo convite ao seu fotógrafo.", + "emailWillBe": "Seu e-mail de conta será ", "invitedBy": ", convidado por ", "name": "Seu nome", - "nameRequired": "Insira seu nome", + "nameRequired": "Informe seu nome", "password": "Escolha uma senha", "confirm": "Confirmar senha", - "passwordTooShort": "A senha deve ter no mínimo 8 caracteres", + "passwordTooShort": "A senha deve ter pelo menos 8 caracteres", "passwordsMismatch": "As senhas não coincidem", - "passwordHint": "Mínimo de 8 caracteres, com uma letra maiúscula e um número.", + "passwordHint": "Pelo menos 8 caracteres, com uma letra maiúscula e um número.", "submit": "Criar conta", "successToast": "Conta criada — faça login.", "alreadyExists": "Já existe uma conta com este e-mail. Faça login.", "invalidSubmission": "Não foi possível criar sua conta.", "generalError": "Não foi possível criar sua conta. Tente novamente.", - "subtitle": "Confirm or fill in your details. You can edit anything from the profile page later.", - "displayName": "Display name", + "subtitle": "Confirme ou preencha seus dados. Você pode editar tudo depois na página de perfil.", + "displayName": "Nome de exibição", "section": { - "personal": "Personal", - "contact": "Contact & business (optional)", - "address": "Billing address (optional)", - "password": "Choose a password" + "personal": "Pessoal", + "contact": "Contato & empresa (opcional)", + "address": "Endereço de cobrança (opcional)", + "password": "Escolha uma senha" } }, "dashboard": { - "title": "Your galleries", - "subtitle": "Click a gallery to open it. The Download button bundles every photo as a zip.", + "title": "Suas galerias", + "subtitle": "Clique em uma galeria para abri-la. O botão Baixar empacota todas as fotos em um zip.", "loadError": "Não foi possível carregar suas galerias. Tente novamente.", - "emptyTitle": "Ainda não há galerias", - "emptyBody": "Assim que seu fotógrafo atribuir você a uma galeria, ela aparecerá aqui.", + "emptyTitle": "Nenhuma galeria ainda", + "emptyBody": "Assim que seu fotógrafo te atribuir a uma galeria, ela aparecerá aqui.", "openAria": "Abrir galeria {{name}}", "opening": "Abrindo…", "expiresOn": "Expira em {{date}}", @@ -2643,110 +2659,110 @@ "quickDownloadAria": "Baixar todas as fotos de {{name}}", "downloadStarted": "Download iniciado para {{name}}", "downloadError": "Não foi possível iniciar o download. Tente novamente.", - "sortLabel": "Sort by", - "sortNewest": "Newest first", - "sortOldest": "Oldest first", - "sortName": "By name", - "open": "Open" + "sortLabel": "Ordenar por", + "sortNewest": "Mais recentes", + "sortOldest": "Mais antigos", + "sortName": "Por nome", + "open": "Abrir" }, "layout": { "greeting": "Olá, {{name}}" }, "nav": { - "galleries": "Galleries", - "calendar": "Calendar", - "quotes": "Quotes", - "bills": "Bills", - "profile": "Profile", - "soon": "Soon" + "galleries": "Galerias", + "calendar": "Calendário", + "quotes": "Orçamentos", + "bills": "Faturas", + "profile": "Perfil", + "soon": "Em breve" }, "comingSoon": { - "tag": "Coming soon" + "tag": "Em breve" }, "calendar": { - "title": "Calendar", - "body": "Upcoming sessions, gallery delivery dates, and other shoot-related events will land here. We'll let you know when it's ready." + "title": "Calendário", + "body": "Próximas sessões, datas de entrega de galerias e outros eventos relacionados a sessões aparecerão aqui. Avisaremos quando estiver pronto." }, "quotes": { - "title": "Quotes", - "body": "Review and accept quotes for upcoming shoots in one place. We're still building this — for now, your photographer will keep sending quotes the usual way." + "title": "Orçamentos", + "body": "Revise e aceite orçamentos para sessões futuras em um só lugar. Ainda estamos construindo — por enquanto, seu fotógrafo continuará enviando orçamentos da maneira habitual." }, "bills": { - "title": "Bills", - "body": "Invoices and payment history for your sessions will be available here. We'll send you an email when this is live." + "title": "Faturas", + "body": "Faturas e histórico de pagamentos das suas sessões estarão disponíveis aqui. Enviaremos um e-mail quando estiver no ar." }, "profile": { - "title": "Customer profile", - "subtitle": "Keep your contact and billing details up to date — they're shown on quotes and invoices once those features go live.", - "savedToast": "Profile saved", - "saveError": "Could not save profile.", - "loadError": "Could not load your profile.", - "save": "Save changes", + "title": "Perfil do cliente", + "subtitle": "Mantenha seus dados de contato e cobrança atualizados — eles aparecem em orçamentos e faturas quando essas funções forem ativadas.", + "savedToast": "Perfil salvo", + "saveError": "Não foi possível salvar o perfil.", + "loadError": "Não foi possível carregar seu perfil.", + "save": "Salvar alterações", "salutation": { - "none": "— Not specified —", - "herr": "Mr.", - "frau": "Ms.", + "none": "— Não especificado —", + "herr": "Sr.", + "frau": "Sra.", "mx": "Mx", "dr": "Dr." }, "section": { - "personal": "Personal information", - "contact": "Contact & business", - "address": "Billing address", - "password": "Change password" + "personal": "Informações pessoais", + "contact": "Contato & empresa", + "address": "Endereço de cobrança", + "password": "Alterar senha" }, "field": { - "email": "Email (login)", - "emailHint": "Contact your photographer if you need to change your login email.", - "salutation": "Salutation", - "firstName": "First name", - "lastName": "Last name", - "displayName": "Display name", - "displayNameHint": "How we greet you in the dashboard.", - "phone": "Phone", - "companyName": "Company name", - "vatId": "VAT ID", - "addressLine1": "Address line 1", - "addressLine2": "Address line 2", - "postalCode": "Postal code", - "city": "City", - "state": "State / region", - "countryCode": "Country" + "email": "E-mail (login)", + "emailHint": "Contate seu fotógrafo se precisar mudar o e-mail de login.", + "salutation": "Saudação", + "firstName": "Nome", + "lastName": "Sobrenome", + "displayName": "Nome de exibição", + "displayNameHint": "Como te cumprimentamos no painel.", + "phone": "Telefone", + "companyName": "Nome da empresa", + "vatId": "CNPJ / IVA", + "addressLine1": "Endereço linha 1", + "addressLine2": "Endereço linha 2", + "postalCode": "CEP", + "city": "Cidade", + "state": "Estado / região", + "countryCode": "País" }, "password": { - "current": "Current password", - "next": "New password", - "confirm": "Confirm new password", - "submit": "Update password", - "hint": "At least 8 characters with one uppercase letter and one number.", - "currentRequired": "Enter your current password", - "tooShort": "At least 8 characters", - "mismatch": "Passwords do not match", - "wrong": "Current password is incorrect", - "savedToast": "Password updated", - "error": "Could not change password" + "current": "Senha atual", + "next": "Nova senha", + "confirm": "Confirmar nova senha", + "submit": "Atualizar senha", + "hint": "Pelo menos 8 caracteres com uma letra maiúscula e um número.", + "currentRequired": "Informe sua senha atual", + "tooShort": "Pelo menos 8 caracteres", + "mismatch": "As senhas não coincidem", + "wrong": "Senha atual incorreta", + "savedToast": "Senha atualizada", + "error": "Não foi possível alterar a senha" } }, "resetPassword": { - "title": "Reset your password", - "invalidToken": "This reset link is invalid or has expired. Please ask your photographer to send a new one.", - "forEmail": "Setting a new password for ", - "password": "New password", - "confirm": "Confirm new password", - "submit": "Update password", - "hint": "At least 8 characters with one uppercase letter and one number.", - "tooShort": "Password must be at least 8 characters", - "mismatch": "Passwords do not match", - "successToast": "Password updated. Please log in.", - "invalidSubmission": "Could not update your password.", - "generalError": "Could not update your password. Please try again." + "title": "Redefinir sua senha", + "invalidToken": "Este link de redefinição é inválido ou expirou. Peça ao seu fotógrafo um novo.", + "forEmail": "Definindo uma nova senha para ", + "password": "Nova senha", + "confirm": "Confirmar nova senha", + "submit": "Atualizar senha", + "hint": "Pelo menos 8 caracteres com uma letra maiúscula e um número.", + "tooShort": "A senha deve ter pelo menos 8 caracteres", + "mismatch": "As senhas não coincidem", + "successToast": "Senha atualizada. Faça login.", + "invalidSubmission": "Não foi possível atualizar sua senha.", + "generalError": "Não foi possível atualizar sua senha. Tente novamente." } }, "customers": { "pageTitle": "Clientes", - "pageSubtitle": "Contas recorrentes de clientes que podem entrar em /customer/login.", + "pageSubtitle": "Contas de clientes recorrentes que podem entrar em /customer/login.", "unnamed": "Sem nome", - "empty": "Ainda não há clientes. Clique em \"Convidar cliente\" para adicionar um.", + "empty": "Nenhum cliente ainda. Clique em \"Convidar cliente\" para adicionar um.", "loadError": "Não foi possível carregar os clientes", "loadInvitationsError": "Não foi possível carregar os convites", "tabs": { @@ -2754,14 +2770,14 @@ "invitations": "Convites" }, "search": { - "placeholder": "Pesquisar por e-mail, nome ou empresa" + "placeholder": "Buscar por e-mail, nome ou empresa" }, "table": { "name": "Nome", "email": "E-mail", "company": "Empresa", "eventCount": "Eventos", - "lastLogin": "Último login", + "lastLogin": "Último acesso", "status": "Status" }, "status": { @@ -2771,29 +2787,29 @@ "invite": { "button": "Convidar cliente", "title": "Convidar um cliente", - "description": "Eles receberão um e-mail com um link para configurar a conta. Após aceitarem, você poderá atribuí-los a eventos.", + "description": "Eles receberão um e-mail com um link para configurar a conta. Após aceitarem, você pode atribuí-los a eventos.", "email": "E-mail", "submit": "Enviar convite", "success": "Convite enviado", "error": "Não foi possível enviar o convite.", - "conflict": "Já existe um cliente com este e-mail ou há um convite pendente.", - "invalidEmail": "Insira um e-mail válido", - "showPrefill": "+ Add contact details (optional)", - "hidePrefill": "− Hide contact details", - "prefillHint": "Anything you fill in will be pre-populated on the customer's sign-up page — they can still edit it." + "conflict": "Já existe um cliente com este e-mail ou um convite pendente.", + "invalidEmail": "Informe um e-mail válido", + "showPrefill": "+ Adicionar detalhes de contato (opcional)", + "hidePrefill": "− Ocultar detalhes de contato", + "prefillHint": "Qualquer dado preenchido será pré-preenchido na página de cadastro do cliente — ele ainda pode editá-lo." }, "invitations": { "empty": "Nenhum convite pendente.", "email": "E-mail", "invitedBy": "Convidado por", "expiresAt": "Expira", - "createdAt": "Criado", + "createdAt": "Criado em", "cancel": "Cancelar" }, "deactivate": { "button": "Desativar", "title": "Desativar cliente?", - "body": "Eles não poderão mais fazer login. Você pode convidá-los novamente depois.", + "body": "Ele não conseguirá mais entrar. Você pode convidá-lo novamente depois.", "success": "Cliente desativado", "error": "Não foi possível desativar o cliente" }, @@ -2809,13 +2825,13 @@ "saveError": "Não foi possível salvar as alterações.", "emailConflict": "Este e-mail já está em uso por outro cliente.", "save": "Salvar alterações", - "expires": "expira", + "expires": "expira em", "accountSection": "Conta", "personalSection": "Informações pessoais", - "billingSection": "Endereço & faturamento", + "billingSection": "Endereço & cobrança", "notesSection": "Notas internas", "eventsSection": "Eventos atribuídos", - "noEvents": "Ainda não atribuído a nenhum evento. Adicione este cliente a um evento pelo formulário de evento.", + "noEvents": "Ainda não atribuído a nenhum evento. Adicione este cliente a um evento pelo formulário do evento.", "email": "E-mail", "preferredLanguage": "Idioma preferido", "salutation": "Saudação", @@ -2825,8 +2841,8 @@ "displayName": "Nome de exibição", "phone": "Telefone", "company": "Empresa", - "billingEmail": "E-mail de faturamento", - "vatId": "NIF / CNPJ", + "billingEmail": "E-mail de cobrança", + "vatId": "CNPJ / IVA", "addressLine1": "Endereço linha 1", "addressLine2": "Endereço linha 2", "postalCode": "CEP", @@ -2834,30 +2850,30 @@ "state": "Estado / região", "countryCode": "País (ISO 2)", "notesHint": "Visível apenas para administradores. Nunca mostrado ao cliente.", - "featuresSection": "Customer features", - "featuresHint": "Per-customer overrides for the customer-surface tabs. The global toggles in Settings → Customer Surface are the master switch — when global is OFF nobody sees the tab, regardless of what you set here. Defaults are ON, so flip a switch OFF to hide a tab for this specific customer.", - "passwordSection": "Account actions", - "passwordHint": "Sends a 7-day single-use reset link to the customer's email. The customer's current password keeps working until they click the link and set a new one.", + "featuresSection": "Funções do cliente", + "featuresHint": "Substituições por cliente para as abas do portal. Os toggles globais em Configurações → Recursos são a chave principal — quando o global está DESLIGADO ninguém vê a aba, independente do que você definir aqui. Os padrões são LIGADOS; desligue um para ocultar uma aba para este cliente específico.", + "passwordSection": "Ações da conta", + "passwordHint": "Envia um link de redefinição de uso único (7 dias) ao e-mail do cliente. A senha atual continua funcionando até o cliente clicar no link e definir uma nova.", "passwordReset": { - "button": "Send password reset email", - "success": "Password reset email sent", - "error": "Could not send password reset", - "inactive": "Reactivate the customer before sending a reset." + "button": "Enviar e-mail de redefinição", + "success": "E-mail de redefinição enviado", + "error": "Não foi possível enviar a redefinição", + "inactive": "Reative o cliente antes de enviar uma redefinição." } }, "reactivate": { - "button": "Reactivate", - "success": "Customer reactivated", - "error": "Could not reactivate customer" + "button": "Reativar", + "success": "Cliente reativado", + "error": "Não foi possível reativar o cliente" }, "erase": { - "button": "Erase customer data", - "title": "Erase customer data?", - "body": "Removes the customer's name, email, phone, address, company and credentials. The account row stays so historical event-access records and audit logs still reference it. This is irreversible — you cannot restore the data afterwards.", - "confirm": "Erase permanently", - "confirmInFlight": "Erasing…", - "success": "Customer erased", - "error": "Could not erase customer" + "button": "Apagar dados do cliente", + "title": "Apagar dados do cliente?", + "body": "Remove nome, e-mail, telefone, endereço, empresa e credenciais do cliente. O registro da conta permanece para que registros históricos de acesso e logs de auditoria ainda o referenciem. Esta ação é irreversível — você não poderá restaurar os dados depois.", + "confirm": "Apagar permanentemente", + "confirmInFlight": "Apagando…", + "success": "Cliente apagado", + "error": "Não foi possível apagar o cliente" } } } diff --git a/frontend/src/i18n/locales/ru.json b/frontend/src/i18n/locales/ru.json index fc66f1de..7ff59c46 100644 --- a/frontend/src/i18n/locales/ru.json +++ b/frontend/src/i18n/locales/ru.json @@ -174,7 +174,7 @@ "cmsPages": "CMS-страницы", "users": "Пользователи", "calendar": "Календарь", - "customers": "Customers" + "customers": "Клиенты" }, "archives": { "title": "Архивы", @@ -1120,7 +1120,8 @@ "communication": "Коммуникации", "scheduling": "Планирование", "sales": "Продажи", - "insights": "Аналитика и доступ" + "insights": "Аналитика и доступ", + "customers": "Клиенты" }, "status": { "stable": "стабильно", @@ -1166,7 +1167,22 @@ "title": "Управление пользователями", "description": "Поддержка нескольких администраторов с ролевыми правами. Отключите, если работаете в одиночку.", "warning": "Существующие учётные записи остаются действительными; интерфейс управления ими будет скрыт до повторного включения." + }, + "customerPortal": { + "title": "Клиентский портал", + "description": "Постоянные логины клиентов. Постоянные клиенты видят все назначенные галереи в одном месте — без паролей для каждого события. Основа для Календаря / Смет / Счетов (которые отображаются в клиентской панели только при включённой опции)." } + }, + "customerSurface": { + "brandingTitle": "Шапка панели клиента", + "brandingHint": "Управляет тем, что показывается в шапке /customer/dashboard. Публичные галереи и админ-разделы не затрагиваются.", + "showLogo": "Показывать логотип в шапке клиента", + "showLogoHint": "Используется тот же логотип бренда, что настроен выше.", + "showCompanyName": "Показывать название компании в шапке клиента", + "showCompanyNameHint": "Скройте, если логотип уже содержит название компании.", + "save": "Сохранить изменения", + "saved": "Брендинг панели клиента сохранён", + "error": "Не удалось сохранить настройки" } }, "analytics": { @@ -2610,176 +2626,176 @@ }, "customer": { "login": { - "title": "Вход клиента", + "title": "Вход для клиентов", "subtitle": "Доступ ко всем вашим фотогалереям в одном месте.", - "email": "E-mail", + "email": "Эл. почта", "password": "Пароль", - "emailRequired": "E-mail обязателен", - "invalidEmail": "Введите корректный e-mail", - "passwordRequired": "Пароль обязателен", + "emailRequired": "Укажите эл. почту", + "invalidEmail": "Введите корректный адрес эл. почты", + "passwordRequired": "Укажите пароль", "showPassword": "Показать пароль", "hidePassword": "Скрыть пароль", "signIn": "Войти", "loginSuccess": "С возвращением!", "invalidCredentials": "Неверный e-mail или пароль", "tooManyAttempts": "Слишком много попыток — попробуйте позже.", - "networkError": "Сервер недоступен. Попробуйте ещё раз.", - "generalError": "Ошибка входа. Попробуйте ещё раз.", - "acceptedToast": "Аккаунт готов — войдите.", + "networkError": "Не удалось связаться с сервером. Попробуйте снова.", + "generalError": "Не удалось войти. Попробуйте снова.", + "acceptedToast": "Учётная запись готова — войдите.", "adminHint": "Ищете админ-панель? Перейдите на /admin/login.", "emailPlaceholder": "you@example.com", - "passwordPlaceholder": "Your password", - "needHelp": "Need help?", - "poweredBy": "Powered by PicPeak" + "passwordPlaceholder": "Ваш пароль", + "needHelp": "Нужна помощь?", + "poweredBy": "Работает на PicPeak" }, "acceptInvite": { - "title": "Настройте ваш аккаунт", - "invalidToken": "Эта ссылка-приглашение недействительна или истекла. Свяжитесь с фотографом для нового приглашения.", - "emailWillBe": "E-mail вашего аккаунта будет ", - "invitedBy": ", пригласил ", + "title": "Создайте учётную запись", + "invalidToken": "Ссылка-приглашение недействительна или просрочена. Попросите фотографа выслать новое приглашение.", + "emailWillBe": "Эл. почта учётной записи: ", + "invitedBy": ", приглашение от ", "name": "Ваше имя", "nameRequired": "Введите ваше имя", - "password": "Выберите пароль", + "password": "Придумайте пароль", "confirm": "Подтвердите пароль", "passwordTooShort": "Пароль должен содержать не менее 8 символов", "passwordsMismatch": "Пароли не совпадают", - "passwordHint": "Не менее 8 символов, с одной заглавной буквой и одной цифрой.", - "submit": "Создать аккаунт", - "successToast": "Аккаунт создан — войдите.", - "alreadyExists": "Аккаунт с таким e-mail уже существует. Войдите вместо этого.", - "invalidSubmission": "Не удалось создать аккаунт.", - "generalError": "Не удалось создать аккаунт. Попробуйте ещё раз.", - "subtitle": "Confirm or fill in your details. You can edit anything from the profile page later.", - "displayName": "Display name", + "passwordHint": "Минимум 8 символов, одна заглавная буква и одна цифра.", + "submit": "Создать учётную запись", + "successToast": "Учётная запись создана — войдите.", + "alreadyExists": "Учётная запись с этим e-mail уже существует. Пожалуйста, войдите.", + "invalidSubmission": "Не удалось создать учётную запись.", + "generalError": "Не удалось создать учётную запись. Попробуйте снова.", + "subtitle": "Подтвердите или заполните данные. Изменить их можно позже в профиле.", + "displayName": "Отображаемое имя", "section": { - "personal": "Personal", - "contact": "Contact & business (optional)", - "address": "Billing address (optional)", - "password": "Choose a password" + "personal": "Личное", + "contact": "Контакты и компания (необязательно)", + "address": "Адрес для счетов (необязательно)", + "password": "Придумайте пароль" } }, "dashboard": { - "title": "Your galleries", - "subtitle": "Click a gallery to open it. The Download button bundles every photo as a zip.", - "loadError": "Не удалось загрузить ваши галереи. Попробуйте ещё раз.", - "emptyTitle": "Пока нет галерей", - "emptyBody": "Как только фотограф привяжет вас к галерее, она появится здесь.", + "title": "Ваши галереи", + "subtitle": "Нажмите на галерею, чтобы открыть её. Кнопка «Скачать» собирает все фото в zip.", + "loadError": "Не удалось загрузить ваши галереи. Попробуйте снова.", + "emptyTitle": "Галерей пока нет", + "emptyBody": "Как только фотограф назначит вам галерею, она появится здесь.", "openAria": "Открыть галерею {{name}}", - "opening": "Открывается…", - "expiresOn": "Истекает {{date}}", - "expiredOn": "Истёк {{date}}", - "eventExpired": "Эта галерея истекла.", + "opening": "Открываем…", + "expiresOn": "Срок до {{date}}", + "expiredOn": "Срок истёк {{date}}", + "eventExpired": "Срок действия этой галереи истёк.", "eventForbidden": "У вас больше нет доступа к этой галерее.", - "openError": "Не удалось открыть эту галерею. Попробуйте ещё раз.", + "openError": "Не удалось открыть галерею. Попробуйте снова.", "download": "Скачать", - "preparingDownload": "Подготовка…", + "preparingDownload": "Готовим…", "quickDownloadAria": "Скачать все фото для {{name}}", - "downloadStarted": "Скачивание начато для {{name}}", - "downloadError": "Не удалось начать скачивание. Попробуйте ещё раз.", - "sortLabel": "Sort by", - "sortNewest": "Newest first", - "sortOldest": "Oldest first", - "sortName": "By name", - "open": "Open" + "downloadStarted": "Загрузка начата для {{name}}", + "downloadError": "Не удалось начать загрузку. Попробуйте снова.", + "sortLabel": "Сортировать по", + "sortNewest": "Сначала новые", + "sortOldest": "Сначала старые", + "sortName": "По имени", + "open": "Открыть" }, "layout": { - "greeting": "Привет, {{name}}" + "greeting": "Здравствуйте, {{name}}" }, "nav": { - "galleries": "Galleries", - "calendar": "Calendar", - "quotes": "Quotes", - "bills": "Bills", - "profile": "Profile", - "soon": "Soon" + "galleries": "Галереи", + "calendar": "Календарь", + "quotes": "Сметы", + "bills": "Счета", + "profile": "Профиль", + "soon": "Скоро" }, "comingSoon": { - "tag": "Coming soon" + "tag": "Скоро" }, "calendar": { - "title": "Calendar", - "body": "Upcoming sessions, gallery delivery dates, and other shoot-related events will land here. We'll let you know when it's ready." + "title": "Календарь", + "body": "Предстоящие сессии, даты передачи галерей и другие события появятся здесь. Мы сообщим, когда раздел будет готов." }, "quotes": { - "title": "Quotes", - "body": "Review and accept quotes for upcoming shoots in one place. We're still building this — for now, your photographer will keep sending quotes the usual way." + "title": "Сметы", + "body": "Просматривайте и принимайте сметы для будущих съёмок в одном месте. Раздел в разработке — пока фотограф будет присылать сметы как обычно." }, "bills": { - "title": "Bills", - "body": "Invoices and payment history for your sessions will be available here. We'll send you an email when this is live." + "title": "Счета", + "body": "Здесь будут счета и история платежей за ваши сессии. Мы отправим письмо, когда раздел заработает." }, "profile": { - "title": "Customer profile", - "subtitle": "Keep your contact and billing details up to date — they're shown on quotes and invoices once those features go live.", - "savedToast": "Profile saved", - "saveError": "Could not save profile.", - "loadError": "Could not load your profile.", - "save": "Save changes", + "title": "Профиль клиента", + "subtitle": "Поддерживайте контактные и платёжные данные в актуальном состоянии — они появятся в сметах и счетах, когда соответствующие разделы запустятся.", + "savedToast": "Профиль сохранён", + "saveError": "Не удалось сохранить профиль.", + "loadError": "Не удалось загрузить профиль.", + "save": "Сохранить изменения", "salutation": { - "none": "— Not specified —", - "herr": "Mr.", - "frau": "Ms.", + "none": "— Не указано —", + "herr": "Г-н", + "frau": "Г-жа", "mx": "Mx", - "dr": "Dr." + "dr": "Д-р" }, "section": { - "personal": "Personal information", - "contact": "Contact & business", - "address": "Billing address", - "password": "Change password" + "personal": "Личные данные", + "contact": "Контакты и компания", + "address": "Адрес для счетов", + "password": "Сменить пароль" }, "field": { - "email": "Email (login)", - "emailHint": "Contact your photographer if you need to change your login email.", - "salutation": "Salutation", - "firstName": "First name", - "lastName": "Last name", - "displayName": "Display name", - "displayNameHint": "How we greet you in the dashboard.", - "phone": "Phone", - "companyName": "Company name", - "vatId": "VAT ID", - "addressLine1": "Address line 1", - "addressLine2": "Address line 2", - "postalCode": "Postal code", - "city": "City", - "state": "State / region", - "countryCode": "Country" + "email": "Эл. почта (логин)", + "emailHint": "Свяжитесь с фотографом, если нужно изменить эл. почту для входа.", + "salutation": "Обращение", + "firstName": "Имя", + "lastName": "Фамилия", + "displayName": "Отображаемое имя", + "displayNameHint": "Как мы будем обращаться к вам в панели.", + "phone": "Телефон", + "companyName": "Название компании", + "vatId": "ИНН / НДС", + "addressLine1": "Адрес, строка 1", + "addressLine2": "Адрес, строка 2", + "postalCode": "Индекс", + "city": "Город", + "state": "Регион", + "countryCode": "Страна" }, "password": { - "current": "Current password", - "next": "New password", - "confirm": "Confirm new password", - "submit": "Update password", - "hint": "At least 8 characters with one uppercase letter and one number.", - "currentRequired": "Enter your current password", - "tooShort": "At least 8 characters", - "mismatch": "Passwords do not match", - "wrong": "Current password is incorrect", - "savedToast": "Password updated", - "error": "Could not change password" + "current": "Текущий пароль", + "next": "Новый пароль", + "confirm": "Подтвердите новый пароль", + "submit": "Обновить пароль", + "hint": "Минимум 8 символов, одна заглавная буква и одна цифра.", + "currentRequired": "Введите текущий пароль", + "tooShort": "Минимум 8 символов", + "mismatch": "Пароли не совпадают", + "wrong": "Текущий пароль неверен", + "savedToast": "Пароль обновлён", + "error": "Не удалось изменить пароль" } }, "resetPassword": { - "title": "Reset your password", - "invalidToken": "This reset link is invalid or has expired. Please ask your photographer to send a new one.", - "forEmail": "Setting a new password for ", - "password": "New password", - "confirm": "Confirm new password", - "submit": "Update password", - "hint": "At least 8 characters with one uppercase letter and one number.", - "tooShort": "Password must be at least 8 characters", - "mismatch": "Passwords do not match", - "successToast": "Password updated. Please log in.", - "invalidSubmission": "Could not update your password.", - "generalError": "Could not update your password. Please try again." + "title": "Сброс пароля", + "invalidToken": "Ссылка для сброса недействительна или просрочена. Попросите фотографа выслать новую.", + "forEmail": "Установка нового пароля для ", + "password": "Новый пароль", + "confirm": "Подтвердите новый пароль", + "submit": "Обновить пароль", + "hint": "Минимум 8 символов, одна заглавная буква и одна цифра.", + "tooShort": "Пароль должен содержать не менее 8 символов", + "mismatch": "Пароли не совпадают", + "successToast": "Пароль обновлён. Пожалуйста, войдите.", + "invalidSubmission": "Не удалось обновить пароль.", + "generalError": "Не удалось обновить пароль. Попробуйте снова." } }, "customers": { "pageTitle": "Клиенты", - "pageSubtitle": "Повторные клиентские аккаунты, которые могут входить на /customer/login.", + "pageSubtitle": "Постоянные учётные записи клиентов, которые могут входить на /customer/login.", "unnamed": "Без имени", - "empty": "Пока нет клиентов. Нажмите «Пригласить клиента», чтобы добавить.", + "empty": "Клиентов пока нет. Нажмите «Пригласить клиента», чтобы добавить.", "loadError": "Не удалось загрузить клиентов", "loadInvitationsError": "Не удалось загрузить приглашения", "tabs": { @@ -2791,7 +2807,7 @@ }, "table": { "name": "Имя", - "email": "E-mail", + "email": "Эл. почта", "company": "Компания", "eventCount": "События", "lastLogin": "Последний вход", @@ -2799,40 +2815,40 @@ }, "status": { "active": "Активен", - "inactive": "Отключён" + "inactive": "Деактивирован" }, "invite": { "button": "Пригласить клиента", "title": "Пригласить клиента", - "description": "Они получат e-mail со ссылкой для настройки аккаунта. После принятия их можно назначать на события.", - "email": "E-mail", + "description": "Клиент получит письмо со ссылкой на создание учётной записи. После принятия вы сможете назначать его на события.", + "email": "Эл. почта", "submit": "Отправить приглашение", "success": "Приглашение отправлено", "error": "Не удалось отправить приглашение.", - "conflict": "Клиент с таким e-mail уже существует или имеет ожидающее приглашение.", + "conflict": "Клиент с таким e-mail уже существует или есть ожидающее приглашение.", "invalidEmail": "Введите корректный e-mail", - "showPrefill": "+ Add contact details (optional)", - "hidePrefill": "− Hide contact details", - "prefillHint": "Anything you fill in will be pre-populated on the customer's sign-up page — they can still edit it." + "showPrefill": "+ Добавить контактные данные (необязательно)", + "hidePrefill": "− Скрыть контактные данные", + "prefillHint": "Заполненные значения будут предзаполнены на странице регистрации клиента — клиент сможет их отредактировать." }, "invitations": { "empty": "Нет ожидающих приглашений.", - "email": "E-mail", + "email": "Эл. почта", "invitedBy": "Пригласил", - "expiresAt": "Истекает", + "expiresAt": "Срок", "createdAt": "Создано", - "cancel": "Отмена" + "cancel": "Отменить" }, "deactivate": { "button": "Деактивировать", "title": "Деактивировать клиента?", - "body": "Они больше не смогут войти. Вы можете пригласить их повторно позже.", + "body": "Клиент больше не сможет входить. Позже его можно пригласить снова.", "success": "Клиент деактивирован", "error": "Не удалось деактивировать клиента" }, "cancelInvitation": { "title": "Отменить приглашение?", - "body": "Ссылка-приглашение перестанет работать немедленно.", + "body": "Ссылка приглашения сразу перестанет работать.", "success": "Приглашение отменено", "error": "Не удалось отменить приглашение" }, @@ -2842,15 +2858,15 @@ "saveError": "Не удалось сохранить изменения.", "emailConflict": "Этот e-mail уже используется другим клиентом.", "save": "Сохранить изменения", - "expires": "истекает", - "accountSection": "Аккаунт", - "personalSection": "Личная информация", - "billingSection": "Адрес и биллинг", + "expires": "срок", + "accountSection": "Учётная запись", + "personalSection": "Личные данные", + "billingSection": "Адрес и оплата", "notesSection": "Внутренние заметки", "eventsSection": "Назначенные события", - "noEvents": "Пока не привязан ни к одному событию. Добавьте этого клиента в форме события.", - "email": "E-mail", - "preferredLanguage": "Предпочтительный язык", + "noEvents": "Пока не назначен ни на одно событие. Добавьте клиента к событию через форму события.", + "email": "Эл. почта", + "preferredLanguage": "Предпочитаемый язык", "salutation": "Обращение", "salutationNone": "—", "firstName": "Имя", @@ -2859,38 +2875,38 @@ "phone": "Телефон", "company": "Компания", "billingEmail": "E-mail для счетов", - "vatId": "НДС / ИНН", + "vatId": "ИНН / НДС", "addressLine1": "Адрес, строка 1", "addressLine2": "Адрес, строка 2", - "postalCode": "Почтовый индекс", + "postalCode": "Индекс", "city": "Город", - "state": "Область / регион", + "state": "Регион", "countryCode": "Страна (ISO 2)", - "notesHint": "Видно только администраторам. Никогда не показывается клиенту.", - "featuresSection": "Customer features", - "featuresHint": "Per-customer overrides for the customer-surface tabs. The global toggles in Settings → Customer Surface are the master switch — when global is OFF nobody sees the tab, regardless of what you set here. Defaults are ON, so flip a switch OFF to hide a tab for this specific customer.", - "passwordSection": "Account actions", - "passwordHint": "Sends a 7-day single-use reset link to the customer's email. The customer's current password keeps working until they click the link and set a new one.", + "notesHint": "Видно только администраторам. Клиенту не показывается.", + "featuresSection": "Функции клиента", + "featuresHint": "Индивидуальные переопределения вкладок клиентского портала. Глобальные переключатели в Настройки → Функции — главный выключатель: если глобально ВЫКЛ, вкладку никто не увидит, что бы вы здесь ни задали. По умолчанию ВКЛ; выключите, чтобы скрыть вкладку для конкретного клиента.", + "passwordSection": "Действия с учётной записью", + "passwordHint": "Отправляет одноразовую ссылку для сброса (7 дней) на e-mail клиента. Текущий пароль продолжает работать, пока клиент не пройдёт по ссылке и не задаст новый.", "passwordReset": { - "button": "Send password reset email", - "success": "Password reset email sent", - "error": "Could not send password reset", - "inactive": "Reactivate the customer before sending a reset." + "button": "Отправить письмо для сброса пароля", + "success": "Письмо для сброса пароля отправлено", + "error": "Не удалось отправить сброс пароля", + "inactive": "Активируйте клиента перед отправкой сброса." } }, "reactivate": { - "button": "Reactivate", - "success": "Customer reactivated", - "error": "Could not reactivate customer" + "button": "Активировать", + "success": "Клиент активирован", + "error": "Не удалось активировать клиента" }, "erase": { - "button": "Erase customer data", - "title": "Erase customer data?", - "body": "Removes the customer's name, email, phone, address, company and credentials. The account row stays so historical event-access records and audit logs still reference it. This is irreversible — you cannot restore the data afterwards.", - "confirm": "Erase permanently", - "confirmInFlight": "Erasing…", - "success": "Customer erased", - "error": "Could not erase customer" + "button": "Стереть данные клиента", + "title": "Стереть данные клиента?", + "body": "Удаляет имя, e-mail, телефон, адрес, компанию и учётные данные клиента. Запись учётной записи остаётся, чтобы исторические записи доступа и аудита продолжали ссылаться на неё. Это необратимо — после нельзя восстановить данные.", + "confirm": "Стереть навсегда", + "confirmInFlight": "Стираем…", + "success": "Данные клиента стёрты", + "error": "Не удалось стереть данные клиента" } } }