mirror of
https://github.com/btouchard/ackify.git
synced 2026-02-09 23:38:30 -06:00
feat(webapp): complete i18n implementation and admin document input enhancement
- feat(admin): accept URLs, file paths, and IDs in document creation form
- Modified AdminDashboard to use findOrCreateDocument service
- Now matches user UI functionality for flexible document references
- feat(i18n): replace all hardcoded French texts with translation keys
- Added 50+ new translation keys across admin and user interfaces
- Updated 7 Vue components: AdminDashboard, AdminDocumentDetail,
DocumentForm, SignButton, SignatureList, SignaturesPage, EmbedPage
- Synchronized all new keys to 5 languages (fr, en, es, de, it)
- All templates now use vue-i18n with proper parameterized translations
- Zero hardcoded texts remaining in HTML templates
This commit is contained in:
@@ -64,7 +64,7 @@ const handleSubmit = async () => {
|
||||
<Input
|
||||
v-model="documentUrl"
|
||||
type="text"
|
||||
placeholder="URL, PATH ou RÉFÉRENCE du document à lire (optionnel)"
|
||||
:placeholder="$t('admin.documentForm.placeholder')"
|
||||
class="flex-1 h-11"
|
||||
:disabled="isSubmitting"
|
||||
@keyup.enter="handleSubmit"
|
||||
@@ -75,8 +75,8 @@ const handleSubmit = async () => {
|
||||
class="group whitespace-nowrap"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span v-if="isSubmitting">Chargement...</span>
|
||||
<span v-else>Commencer</span>
|
||||
<span v-if="isSubmitting">{{ $t('admin.documentForm.submitting') }}</span>
|
||||
<span v-else>{{ $t('admin.documentForm.submit') }}</span>
|
||||
<ArrowRight v-if="!isSubmitting" :size="16" class="ml-2 transition-transform group-hover:translate-x-1" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"
|
||||
/>
|
||||
</svg>
|
||||
{{ loading ? 'Confirmation en cours...' : 'Confirmer la lecture' }}
|
||||
{{ loading ? $t('signButton.signing') : $t('signButton.confirmAction') }}
|
||||
</button>
|
||||
|
||||
<div v-else class="signed-status">
|
||||
@@ -63,10 +63,10 @@
|
||||
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="font-semibold">Lecture confirmée</span>
|
||||
<span class="font-semibold">{{ $t('signButton.confirmed') }}</span>
|
||||
</div>
|
||||
<p v-if="signedAt" class="mt-2 text-sm text-muted-foreground text-center">
|
||||
Le {{ formatDate(signedAt) }}
|
||||
{{ $t('signButton.on') }} {{ formatDate(signedAt) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useSignatureStore } from '@/stores/signatures'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
@@ -100,6 +101,7 @@ const emit = defineEmits<{
|
||||
error: [error: string]
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
const authStore = useAuthStore()
|
||||
const signatureStore = useSignatureStore()
|
||||
const loading = ref(false)
|
||||
@@ -146,7 +148,7 @@ const buttonClasses = computed(() => {
|
||||
|
||||
async function handleSign() {
|
||||
if (!props.docId) {
|
||||
error.value = 'Document ID manquant'
|
||||
error.value = t('signButton.error.missingDocId')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -164,7 +166,7 @@ async function handleSign() {
|
||||
try {
|
||||
await authStore.startOAuthLogin(window.location.pathname + window.location.search)
|
||||
} catch (err: any) {
|
||||
error.value = 'Impossible de démarrer l\'authentification'
|
||||
error.value = t('signButton.error.authFailed')
|
||||
emit('error', error.value)
|
||||
}
|
||||
return
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
/>
|
||||
</svg>
|
||||
<p class="mt-2 text-muted-foreground">{{ emptyMessage || 'Aucune confirmation trouvée' }}</p>
|
||||
<p class="mt-2 text-muted-foreground">{{ emptyMessage || $t('signatureList.empty') }}</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="space-y-4">
|
||||
@@ -75,7 +75,7 @@
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
Confirmé
|
||||
{{ $t('signatureList.confirmed') }}
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
@@ -95,28 +95,28 @@
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
Document supprimé{{ signature.docDeletedAt ? ` le ${formatDate(signature.docDeletedAt)}` : '' }}
|
||||
{{ $t('signatureList.documentDeleted') }}{{ signature.docDeletedAt ? ` ${formatDate(signature.docDeletedAt)}` : '' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-2 space-y-1 text-sm text-muted-foreground">
|
||||
<p v-if="signature.docTitle">
|
||||
<span class="font-medium">ID:</span> {{ signature.docId }}
|
||||
<span class="font-medium">{{ $t('signatureList.fields.id') }}</span> {{ signature.docId }}
|
||||
</p>
|
||||
<p v-if="signature.docUrl">
|
||||
<span class="font-medium">Document:</span>
|
||||
<span class="font-medium">{{ $t('signatureList.fields.document') }}</span>
|
||||
<a :href="signature.docUrl" target="_blank" rel="noopener noreferrer" class="text-primary hover:text-primary/80 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded">
|
||||
{{ signature.docUrl }}
|
||||
</a>
|
||||
</p>
|
||||
<p v-if="showUserInfo">
|
||||
<span class="font-medium">Lecteur:</span> {{ signature.userName || signature.userEmail }}
|
||||
<span class="font-medium">{{ $t('signatureList.fields.reader') }}</span> {{ signature.userName || signature.userEmail }}
|
||||
</p>
|
||||
<p>
|
||||
<span class="font-medium">Date:</span> {{ formatDate(signature.signedAt) }}
|
||||
<span class="font-medium">{{ $t('signatureList.fields.date') }}</span> {{ formatDate(signature.signedAt) }}
|
||||
</p>
|
||||
<p v-if="signature.serviceInfo" class="flex items-center">
|
||||
<span class="font-medium mr-2">Origine:</span>
|
||||
<span class="font-medium mr-2">{{ $t('signatureList.fields.source') }}</span>
|
||||
<span class="inline-flex items-center space-x-1">
|
||||
<span v-html="signature.serviceInfo.icon"></span>
|
||||
<span>{{ signature.serviceInfo.name }}</span>
|
||||
@@ -127,20 +127,20 @@
|
||||
<div v-if="showDetails" class="mt-3 pt-3 border-t border-border">
|
||||
<details class="text-xs text-muted-foreground">
|
||||
<summary class="cursor-pointer hover:text-foreground font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded">
|
||||
Détails de vérification
|
||||
{{ $t('signatureList.verificationDetails') }}
|
||||
</summary>
|
||||
<div class="mt-2 space-y-1 font-mono bg-muted p-2 rounded border border-border">
|
||||
<p><span class="font-semibold">ID:</span> {{ signature.id }}</p>
|
||||
<p><span class="font-semibold">Nonce:</span> {{ signature.nonce }}</p>
|
||||
<p><span class="font-semibold">{{ $t('signatureList.fields.id') }}</span> {{ signature.id }}</p>
|
||||
<p><span class="font-semibold">{{ $t('signatureList.fields.nonce') }}</span> {{ signature.nonce }}</p>
|
||||
<p class="break-all">
|
||||
<span class="font-semibold">Hash:</span> {{ signature.payloadHash }}
|
||||
<span class="font-semibold">{{ $t('signatureList.fields.hash') }}</span> {{ signature.payloadHash }}
|
||||
</p>
|
||||
<p class="break-all">
|
||||
<span class="font-semibold">Confirmation:</span>
|
||||
<span class="font-semibold">{{ $t('signatureList.confirmation') }}</span>
|
||||
{{ signature.signature.substring(0, 64) }}...
|
||||
</p>
|
||||
<p v-if="signature.prevHash" class="break-all">
|
||||
<span class="font-semibold">Hash précédent:</span> {{ signature.prevHash }}
|
||||
<span class="font-semibold">{{ $t('signatureList.previousHash') }}</span> {{ signature.prevHash }}
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
@@ -152,7 +152,7 @@
|
||||
@click="$emit('view-details', signature)"
|
||||
class="text-primary hover:text-primary/80 text-sm font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded px-2 py-1"
|
||||
>
|
||||
Voir détails
|
||||
{{ $t('signatureList.viewDetails') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
"connectedAs": "Angemeldet als"
|
||||
},
|
||||
"choice": {
|
||||
"title": "Bei Ackify anmelden",
|
||||
"title": "Anmeldung bei Ackify",
|
||||
"subtitle": "Wählen Sie Ihre bevorzugte Authentifizierungsmethode",
|
||||
"privacy": "Ihre Authentifizierung ist sicher und verschlüsselt"
|
||||
},
|
||||
"oauth": {
|
||||
"title": "Anmeldung mit OAuth",
|
||||
"description": "Verwenden Sie Ihr bestehendes Konto",
|
||||
"description": "Verwenden Sie Ihr Unternehmenskonto",
|
||||
"button": "Mit OAuth fortfahren",
|
||||
"error": "OAuth-Anmeldung fehlgeschlagen"
|
||||
},
|
||||
@@ -42,11 +42,11 @@
|
||||
"title": "Anmeldung per E-Mail",
|
||||
"description": "Wir senden Ihnen einen magischen Link",
|
||||
"email_label": "E-Mail-Adresse",
|
||||
"email_placeholder": "sie{'@'}beispiel.de",
|
||||
"email_placeholder": "sie{'@'}beispiel.com",
|
||||
"button": "Magischen Link senden",
|
||||
"sent": {
|
||||
"title": "Überprüfen Sie Ihre E-Mail",
|
||||
"message": "Wir haben Ihnen einen magischen Link geschickt. Klicken Sie darauf, um sich anzumelden.",
|
||||
"title": "Überprüfen Sie Ihre E-Mails",
|
||||
"message": "Wir haben Ihnen einen magischen Link gesendet. Klicken Sie darauf, um sich anzumelden.",
|
||||
"expire": "Der Link läuft in 15 Minuten ab."
|
||||
},
|
||||
"error_invalid_email": "Bitte geben Sie eine gültige E-Mail-Adresse ein",
|
||||
@@ -55,10 +55,10 @@
|
||||
},
|
||||
"sign": {
|
||||
"title": "Lesebestätigung",
|
||||
"subtitle": "Bestätigen Sie Ihre Lesung mit einer kryptographischen Ed25519-Bestätigung",
|
||||
"subtitle": "Bestätigen Sie Ihre Lektüre mit einer kryptografischen Ed25519-Bestätigung",
|
||||
"loading": {
|
||||
"title": "Dokument wird geladen...",
|
||||
"description": "Bitte warten Sie, während wir das Dokument zur Signierung vorbereiten."
|
||||
"description": "Bitte warten Sie, während wir das Dokument zur Signatur vorbereiten."
|
||||
},
|
||||
"noDocument": {
|
||||
"title": "Kein Dokument angegeben",
|
||||
@@ -66,8 +66,8 @@
|
||||
"examples": "Beispiele:"
|
||||
},
|
||||
"success": {
|
||||
"title": "Lesung erfolgreich bestätigt!",
|
||||
"description": "Ihre Bestätigung wurde kryptographisch und sicher gespeichert."
|
||||
"title": "Lektüre erfolgreich bestätigt!",
|
||||
"description": "Ihre Bestätigung wurde kryptografisch und sicher aufgezeichnet."
|
||||
},
|
||||
"error": {
|
||||
"title": "Ein Fehler ist aufgetreten",
|
||||
@@ -80,64 +80,69 @@
|
||||
"id": "ID"
|
||||
},
|
||||
"info": {
|
||||
"description": "Durch die Bestätigung der Lesung dieses Dokuments bestätigen Sie, dass Sie dessen Inhalt gelesen haben und akzeptieren, es kryptographisch und unwiderruflich zu validieren.",
|
||||
"recorded": "Ihre Bestätigung wird mit den folgenden Informationen gespeichert:",
|
||||
"description": "Indem Sie die Lektüre dieses Dokuments bestätigen, bestätigen Sie, dass Sie dessen Inhalt zur Kenntnis genommen haben und akzeptieren, es auf kryptografische und unwiderrufliche Weise zu validieren.",
|
||||
"recorded": "Ihre Bestätigung wird mit den folgenden Informationen aufgezeichnet:",
|
||||
"email": "Ihre E-Mail-Adresse",
|
||||
"timestamp": "Präziser Zeitstempel der Bestätigung",
|
||||
"signature": "Kryptographische Ed25519-Bestätigung",
|
||||
"signature": "Kryptografische Ed25519-Bestätigung",
|
||||
"hash": "SHA-256-Hash des Inhalts"
|
||||
},
|
||||
"confirmations": {
|
||||
"title": "Bestehende Bestätigungen",
|
||||
"title": "Vorhandene Bestätigungen",
|
||||
"count": "{count} Bestätigung | {count} Bestätigungen",
|
||||
"recorded": "gespeichert"
|
||||
"recorded": "aufgezeichnet | aufgezeichnet"
|
||||
},
|
||||
"empty": {
|
||||
"title": "Noch keine Bestätigungen",
|
||||
"description": "Seien Sie der Erste, der die Lesung dieses Dokuments bestätigt"
|
||||
"title": "Noch keine Bestätigung",
|
||||
"description": "Seien Sie der Erste, der die Lektüre dieses Dokuments bestätigt"
|
||||
},
|
||||
"howItWorks": {
|
||||
"title": "Wie funktioniert es?",
|
||||
"subtitle": "Ackify ermöglicht es Ihnen, kryptographisch zu beweisen, dass Sie ein Dokument gelesen haben",
|
||||
"subtitle": "Ackify ermöglicht es Ihnen, kryptografisch zu beweisen, dass Sie ein Dokument gelesen haben",
|
||||
"step1": {
|
||||
"title": "1. Greifen Sie auf das Dokument zu",
|
||||
"title": "1. Auf das Dokument zugreifen",
|
||||
"description": "Fügen Sie {code} zur Adresse dieser Seite hinzu"
|
||||
},
|
||||
"step2": {
|
||||
"title": "2. Authentifizieren Sie sich",
|
||||
"title": "2. Authentifizieren",
|
||||
"description": "Melden Sie sich über OAuth2 an, um Ihre Identität zu bestätigen"
|
||||
},
|
||||
"step3": {
|
||||
"title": "3. Bestätigen Sie die Lesung",
|
||||
"description": "Ihre Bestätigung wird mit einer Ed25519-Signatur gespeichert"
|
||||
"title": "3. Lektüre bestätigen",
|
||||
"description": "Ihre Bestätigung wird mit einer Ed25519-Signatur aufgezeichnet"
|
||||
},
|
||||
"features": {
|
||||
"crypto": {
|
||||
"title": "Kryptographische Sicherheit",
|
||||
"description": "Unwiderrufliche Ed25519-Signaturen garantieren Authentizität"
|
||||
"title": "Kryptografische Sicherheit",
|
||||
"description": "Unwiderrufliche Ed25519-Signaturen garantieren die Authentizität"
|
||||
},
|
||||
"instant": {
|
||||
"title": "Sofort",
|
||||
"description": "Bestätigung mit zwei Klicks und sofortiger kryptographischer Verifizierung"
|
||||
"description": "Bestätigung mit zwei Klicks und sofortiger kryptografischer Überprüfung"
|
||||
},
|
||||
"timestamp": {
|
||||
"title": "Präziser Zeitstempel",
|
||||
"description": "Jede Bestätigung wird zeitgestempelt und verkettet, um Integrität zu gewährleisten"
|
||||
"description": "Jede Bestätigung wird mit Zeitstempel versehen und verkettet, um Integrität zu gewährleisten"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"signButton": {
|
||||
"confirm": "Meine Lesung bestätigen",
|
||||
"confirm": "Meine Lektüre bestätigen",
|
||||
"confirmAction": "Lektüre bestätigen",
|
||||
"alreadySigned": "Bereits bestätigt",
|
||||
"confirmed": "Lektüre bestätigt",
|
||||
"mustLogin": "Anmelden zum Bestätigen",
|
||||
"signing": "Bestätigung läuft...",
|
||||
"verified": "Verifiziert",
|
||||
"on": "Am",
|
||||
"error": {
|
||||
"title": "Bestätigung fehlgeschlagen",
|
||||
"notAuthenticated": "Sie müssen angemeldet sein, um ein Dokument zu bestätigen.",
|
||||
"alreadySigned": "Sie haben dieses Dokument bereits bestätigt.",
|
||||
"generic": "Bei der Bestätigung ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut."
|
||||
"generic": "Bei der Bestätigung ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut.",
|
||||
"missingDocId": "Dokument-ID fehlt",
|
||||
"authFailed": "Authentifizierung kann nicht gestartet werden"
|
||||
}
|
||||
},
|
||||
"signatureList": {
|
||||
@@ -145,42 +150,60 @@
|
||||
"email": "E-Mail",
|
||||
"date": "Datum",
|
||||
"signature": "Signatur",
|
||||
"confirmation": "Bestätigung:",
|
||||
"hash": "Hash",
|
||||
"nonce": "Nonce",
|
||||
"verificationStatus": "Verifizierungsstatus",
|
||||
"verificationStatus": "Überprüfungsstatus",
|
||||
"verified": "Verifiziert",
|
||||
"confirmed": "Bestätigt",
|
||||
"notVerified": "Nicht verifiziert",
|
||||
"showDetails": "Details anzeigen",
|
||||
"hideDetails": "Details verbergen",
|
||||
"hideDetails": "Details ausblenden",
|
||||
"viewDetails": "Details ansehen",
|
||||
"verificationDetails": "Überprüfungsdetails",
|
||||
"copy": "Kopieren",
|
||||
"copied": "Kopiert!",
|
||||
"previousHash": "Vorheriger Hash"
|
||||
"previousHash": "Vorheriger Hash:",
|
||||
"empty": "Keine Bestätigung gefunden",
|
||||
"documentDeleted": "Dokument gelöscht",
|
||||
"fields": {
|
||||
"id": "ID:",
|
||||
"document": "Dokument:",
|
||||
"reader": "Leser:",
|
||||
"date": "Datum:",
|
||||
"source": "Herkunft:",
|
||||
"nonce": "Nonce:",
|
||||
"hash": "Hash:"
|
||||
}
|
||||
},
|
||||
"signatures": {
|
||||
"title": "Meine Lesebestätigungen",
|
||||
"subtitle": "Liste aller Dokumente, deren Lesung Sie kryptographisch bestätigt haben",
|
||||
"subtitle": "Liste aller Dokumente, deren Lektüre Sie kryptografisch bestätigt haben",
|
||||
"loading": "Ihre Bestätigungen werden geladen...",
|
||||
"empty": {
|
||||
"title": "Noch keine Bestätigungen",
|
||||
"description": "Sie haben noch keine Dokumente bestätigt. Beginnen Sie mit der Bestätigung eines Dokuments, um es hier anzuzeigen."
|
||||
"title": "Noch keine Bestätigung",
|
||||
"description": "Sie haben noch kein Dokument bestätigt. Beginnen Sie mit der Bestätigung eines Dokuments, um es hier zu sehen.",
|
||||
"alternative": "Sie haben noch keine Dokumentlektüre bestätigt"
|
||||
},
|
||||
"count": "{count} Bestätigung | {count} Bestätigungen",
|
||||
"results": "{count} Ergebnis | {count} Ergebnisse",
|
||||
"document": "Dokument",
|
||||
"signedAt": "Bestätigt am",
|
||||
"viewDetails": "Details anzeigen",
|
||||
"viewDetails": "Details ansehen",
|
||||
"deletedDocuments": "Gelöschte Dokumente",
|
||||
"stats": {
|
||||
"total": "Gesamt",
|
||||
"totalConfirmations": "Gesamtbestätigungen",
|
||||
"unique": "Eindeutige",
|
||||
"uniqueDocuments": "Eindeutige Dokumente",
|
||||
"unique": "Einzigartig",
|
||||
"uniqueDocuments": "Einzigartige Dokumente",
|
||||
"last": "Letzte",
|
||||
"lastConfirmation": "Letzte Bestätigung"
|
||||
"lastConfirmation": "Letzte Bestätigung",
|
||||
"notAvailable": "N/V"
|
||||
},
|
||||
"allConfirmations": "Alle meine Bestätigungen",
|
||||
"about": {
|
||||
"title": "Über Bestätigungen",
|
||||
"description": "Jede Bestätigung wird kryptographisch mit Ed25519 aufgezeichnet und verkettet, um Integrität zu gewährleisten. Bestätigungen sind unwiderruflich und präzise zeitgestempelt."
|
||||
"description": "Jede Bestätigung wird kryptografisch mit Ed25519 aufgezeichnet und verkettet, um die Integrität zu gewährleisten. Bestätigungen sind unwiderruflich und präzise mit Zeitstempel versehen."
|
||||
},
|
||||
"search": "Suchen...",
|
||||
"error": {
|
||||
@@ -189,7 +212,7 @@
|
||||
}
|
||||
},
|
||||
"admin": {
|
||||
"title": "Verwaltung",
|
||||
"title": "Administration",
|
||||
"subtitle": "Dokumente und erwartete Leser verwalten",
|
||||
"loading": "Daten werden geladen...",
|
||||
"dashboard": {
|
||||
@@ -197,6 +220,7 @@
|
||||
"totalDocuments": "Gesamtdokumente",
|
||||
"totalSignatures": "Gesamtbestätigungen",
|
||||
"recentActivity": "Letzte Aktivität",
|
||||
"backToDashboard": "Zurück zum Dashboard",
|
||||
"stats": {
|
||||
"documents": "Dokumente",
|
||||
"readers": "Leser",
|
||||
@@ -204,19 +228,20 @@
|
||||
"expected": "Erwartet",
|
||||
"signed": "Signiert",
|
||||
"pending": "Ausstehend",
|
||||
"completion": "Fertigstellung"
|
||||
"completion": "Vollständigkeit"
|
||||
}
|
||||
},
|
||||
"documents": {
|
||||
"title": "Alle Dokumente",
|
||||
"new": "Neues Dokument erstellen",
|
||||
"newDescription": "Eine Dokumentreferenz vorbereiten, um Lesebestätigungen zu verfolgen",
|
||||
"newDescription": "Dokumentreferenz vorbereiten, um Lesebestätigungen zu verfolgen",
|
||||
"search": "Suchen...",
|
||||
"searchPlaceholder": "Nach ID, Titel oder URL suchen...",
|
||||
"id": "Dokument-ID",
|
||||
"idLabel": "Dokument-ID",
|
||||
"idHelper": "Nur Buchstaben, Zahlen, Bindestriche und Unterstriche",
|
||||
"idPlaceholder": "z.B.: sicherheitsrichtlinie-2025",
|
||||
"idLabel": "Dokument",
|
||||
"idHelper": "Akzeptiert URLs, Dateipfade oder einfache Kennungen",
|
||||
"idHelperShort": "Akzeptiert URLs, Pfade oder Kennungen",
|
||||
"idPlaceholder": "URL, PFAD oder ID des Dokuments",
|
||||
"signatures": "Bestätigungen",
|
||||
"created": "Erstellt",
|
||||
"createdOn": "Erstellt am",
|
||||
@@ -228,11 +253,75 @@
|
||||
"manage": "Verwalten",
|
||||
"edit": "Bearbeiten",
|
||||
"delete": "Löschen",
|
||||
"empty": "Keine Dokumente gefunden"
|
||||
"empty": "Kein Dokument gefunden",
|
||||
"noResults": "Keine Ergebnisse",
|
||||
"noDocuments": "Keine Dokumente",
|
||||
"tryAnotherSearch": "Versuchen Sie eine andere Suche",
|
||||
"willAppear": "Dokumente werden hier angezeigt, sobald sie erstellt wurden",
|
||||
"totalCount": "{count} Dokument insgesamt | {count} Dokumente insgesamt",
|
||||
"pagination": {
|
||||
"page": "Seite {current}/{total}",
|
||||
"pageOf": "Seite {current} von {total}"
|
||||
}
|
||||
},
|
||||
"webhooks": {
|
||||
"title": "Webhooks",
|
||||
"subtitle": "Benachrichtigungen an Drittanwendungen konfigurieren",
|
||||
"manage": "Webhooks verwalten",
|
||||
"new": "Neuer Webhook",
|
||||
"edit": "Bearbeiten",
|
||||
"delete": "Löschen",
|
||||
"enable": "Aktivieren",
|
||||
"disable": "Deaktivieren",
|
||||
"status": {
|
||||
"enabled": "Aktiv",
|
||||
"disabled": "Inaktiv"
|
||||
},
|
||||
"confirmDelete": "Diesen Webhook löschen?",
|
||||
"empty": "Kein Webhook",
|
||||
"listTitle": "Liste der Webhooks",
|
||||
"listSubtitle": "Ein Webhook kann mehrere Ereignisse abhören",
|
||||
"columns": {
|
||||
"title": "Name",
|
||||
"url": "URL",
|
||||
"events": "Ereignisse",
|
||||
"status": "Status",
|
||||
"actions": "Aktionen"
|
||||
},
|
||||
"form": {
|
||||
"title": "Webhook-Einstellungen",
|
||||
"subtitle": "Geben Sie URL, Geheimnis und Ereignisse an",
|
||||
"nameLabel": "Webhook-Name",
|
||||
"namePlaceholder": "CRM-Webhook",
|
||||
"urlLabel": "Ziel-URL",
|
||||
"secretLabel": "HMAC-Geheimnis",
|
||||
"secretPlaceholder": "Geben Sie ein Geheimnis ein (erforderlich)",
|
||||
"secretKeep": "Leer lassen zum Beibehalten",
|
||||
"eventsLabel": "Zu abhörende Ereignisse",
|
||||
"descriptionLabel": "Beschreibung (optional)",
|
||||
"descriptionPlaceholder": "Interne Notiz…",
|
||||
"validation": "Bitte füllen Sie Name, URL, Geheimnis und mindestens ein Ereignis aus."
|
||||
},
|
||||
"editTitle": "Webhook bearbeiten",
|
||||
"events": {
|
||||
"documentCreated": "Dokument erstellt",
|
||||
"signatureCreated": "Signatur erstellt",
|
||||
"documentCompleted": "Dokument abgeschlossen",
|
||||
"reminderSent": "Erinnerung gesendet",
|
||||
"reminderFailed": "Erinnerung fehlgeschlagen"
|
||||
},
|
||||
"eventsMap": {
|
||||
"document.created": "Dokument erstellt",
|
||||
"signature.created": "Signatur erstellt",
|
||||
"document.completed": "Dokument abgeschlossen",
|
||||
"reminder.sent": "Erinnerung gesendet",
|
||||
"reminder.failed": "Erinnerung fehlgeschlagen"
|
||||
}
|
||||
},
|
||||
"documentDetail": {
|
||||
"title": "Dokumentdetails",
|
||||
"metadata": "Dokumentmetadaten und Prüfsumme",
|
||||
"title": "Dokument",
|
||||
"metadata": "📄 Dokumentinformationen",
|
||||
"metadataDescription": "Dokumentmetadaten und Prüfsumme",
|
||||
"checksum": "Prüfsumme",
|
||||
"algorithm": "Algorithmus",
|
||||
"titleLabel": "Titel",
|
||||
@@ -245,69 +334,110 @@
|
||||
"descriptionLabel": "Beschreibung",
|
||||
"descriptionPlaceholder": "Dokumentbeschreibung...",
|
||||
"signatures": "Bestätigungen",
|
||||
"back": "Zurück zur Liste",
|
||||
"back": "Zurück",
|
||||
"expectedSigners": "Erwartete Unterzeichner",
|
||||
"addExpectedSigner": "Erwarteten Unterzeichner hinzufügen",
|
||||
"addSigners": "Erwartete Leser hinzufügen",
|
||||
"addButton": "Hinzufügen",
|
||||
"adding": "Wird hinzugefügt...",
|
||||
"emailsLabel": "E-Mails (eine pro Zeile)",
|
||||
"emailsPlaceholder": "Maria Schmidt <maria.schmidt{'@'}example.com>\njohn.mueller{'@'}example.com\nSophie Weber <sophie{'@'}example.com>",
|
||||
"emailsPlaceholder": "Marie Dupont <marie.dupont{'@'}example.com>\njean.martin{'@'}example.com\nSophie Bernard <sophie{'@'}example.com>",
|
||||
"emailsHelper": "Akzeptierte Formate: \"Vorname Nachname <email{'@'}example.com>\" oder \"email{'@'}example.com\"",
|
||||
"emailLabel": "E-Mail *",
|
||||
"emailPlaceholder": "email{'@'}example.com",
|
||||
"nameLabel": "Name",
|
||||
"namePlaceholder": "Vollständiger Name",
|
||||
"reader": "Leser",
|
||||
"readers": "✓ Erwartete Leser",
|
||||
"user": "Benutzer",
|
||||
"status": "Status",
|
||||
"statusConfirmed": "✓ Bestätigt",
|
||||
"statusPending": "⏳ Ausstehend",
|
||||
"confirmedOn": "Bestätigt am",
|
||||
"noExpectedSigners": "Keine erwarteten Leser",
|
||||
"noSignatures": "Keine Bestätigungen",
|
||||
"reminders": "E-Mail-Erinnerungen",
|
||||
"reminders": "📧 E-Mail-Erinnerungen",
|
||||
"remindersDescription": "Erinnerungen an Leser senden, die auf Bestätigung warten",
|
||||
"remindersSent": "Gesendete Erinnerungen",
|
||||
"toRemind": "Zu erinnern",
|
||||
"lastReminder": "Letzte Erinnerung",
|
||||
"sendReminder": "Erinnerung senden",
|
||||
"sending": "Wird gesendet...",
|
||||
"sendReminders": "Erinnerungen senden",
|
||||
"sendToAll": "An alle wartenden Leser senden ({count})",
|
||||
"sendToSelected": "Nur an Ausgewählte senden ({count})",
|
||||
"allContacted": "✓ Alle erwarteten Leser wurden kontaktiert oder haben bestätigt",
|
||||
"unexpectedSignatures": "⚠ Zusätzliche Lesebestätigungen",
|
||||
"unexpectedDescription": "Benutzer, die bestätigt haben, aber nicht in der Liste der erwarteten Leser stehen",
|
||||
"createdBy": "Erstellt von {by} am {date}",
|
||||
"saving": "Wird gespeichert...",
|
||||
"deleting": "Wird gelöscht...",
|
||||
"copiedToClipboard": "In die Zwischenablage kopiert",
|
||||
"metadataSaved": "Metadaten erfolgreich gespeichert",
|
||||
"signersAdded": "{count} Leser erfolgreich hinzugefügt",
|
||||
"signerRemoved": "{email} erfolgreich entfernt",
|
||||
"remindersSentSuccess": "{count} Erinnerung(en) erfolgreich gesendet",
|
||||
"remindersSentPartial": "{sent} Erinnerung(en) gesendet, {failed} fehlgeschlagen",
|
||||
"remindersSentGeneric": "Erinnerungen erfolgreich gesendet",
|
||||
"confirmSendReminders": "Erinnerungen an {count} Leser senden, die auf Bestätigung warten?",
|
||||
"confirmSendRemindersSelected": "Erinnerungen an {count} ausgewählte(n) Leser senden?",
|
||||
"confirmSendRemindersTitle": "📧 Erinnerungen senden",
|
||||
"removeSignerTitle": "⚠️ Erwarteten Leser entfernen",
|
||||
"removeSignerMessage": "{email} aus der Liste der erwarteten Leser entfernen?",
|
||||
"metadataWarning": {
|
||||
"title": "⚠️ Warnung: Signaturungültigkeit",
|
||||
"description": "Sie sind dabei, kritische Dokumentinformationen (URL, Prüfsumme, Algorithmus oder Beschreibung) zu ändern.",
|
||||
"warning": "Diese Änderung führt zur Ungültigkeit aller bestehenden Signaturen, da sie kryptographisch mit dem aktuellen Dokumentinhalt verknüpft sind.",
|
||||
"title": "⚠️ Achtung: Ungültigmachung der Signaturen",
|
||||
"description": "Sie sind dabei, kritische Informationen des Dokuments zu ändern (URL, Prüfsumme, Algorithmus oder Beschreibung).",
|
||||
"warning": "Diese Änderung führt zur Ungültigmachung aller vorhandenen Signaturen, da sie kryptografisch mit dem aktuellen Inhalt des Dokuments verbunden sind.",
|
||||
"currentSignatures": "Aktuelle Signaturen, die ungültig werden:",
|
||||
"confirm": "Ich verstehe, fortfahren",
|
||||
"cancel": "Abbrechen"
|
||||
},
|
||||
"dangerZone": "Gefahrenbereich",
|
||||
"dangerZone": "⚠️ Gefahrenzone",
|
||||
"dangerZoneDescription": "Irreversible Aktionen für dieses Dokument",
|
||||
"deleteDocument": "Dieses Dokument löschen",
|
||||
"deleteDocumentDescription": "Diese Aktion löscht dauerhaft das Dokument, seine Metadaten, die erwarteten Leser und alle zugehörigen Bestätigungen.\nDiese Aktion ist irreversibel.",
|
||||
"deleteWarning": "Diese Aktion ist irreversibel!",
|
||||
"deleteWillRemove": "Diese Aktion wird dauerhaft entfernen:",
|
||||
"deleteWillRemove": "Das Löschen dieses Dokuments führt zum endgültigen Verlust von:",
|
||||
"deleteItem1": "Alle Dokumentmetadaten",
|
||||
"deleteItem2": "Die Liste der erwarteten Leser",
|
||||
"deleteItem3": "Alle kryptographischen Bestätigungen",
|
||||
"deleteItem4": "Den Erinnerungsverlauf"
|
||||
"deleteItem3": "Alle kryptografischen Bestätigungen",
|
||||
"deleteItem4": "Der Erinnerungsverlauf",
|
||||
"deleteConfirmTitle": "⚠️ Löschen bestätigen",
|
||||
"deleteConfirmButton": "Endgültig löschen",
|
||||
"documentId": "Dokument-ID:"
|
||||
},
|
||||
"documentForm": {
|
||||
"title": "Dokumentreferenz",
|
||||
"label": "Referenz (URL, Pfad oder ID)",
|
||||
"placeholder": "https://example.com/doc.pdf oder /pfad/zum/doc",
|
||||
"submit": "Bestätigen",
|
||||
"placeholder": "URL, PFAD oder REFERENZ des zu lesenden Dokuments (optional)",
|
||||
"submit": "Beginnen",
|
||||
"submitting": "Wird geladen...",
|
||||
"creating": "Wird erstellt..."
|
||||
}
|
||||
},
|
||||
"embed": {
|
||||
"loading": "Signaturinformationen werden geladen...",
|
||||
"title": "Signatur für",
|
||||
"document": "Dokument:",
|
||||
"signedBy": "Signiert von",
|
||||
"on": "am",
|
||||
"verified": "Verifiziert",
|
||||
"viewAll": "Alle Bestätigungen anzeigen",
|
||||
"error": "Signaturinformationen können nicht geladen werden"
|
||||
"viewAll": "Alle Bestätigungen ansehen",
|
||||
"error": "Signaturinformationen können nicht geladen werden",
|
||||
"sign": "Signieren",
|
||||
"signDocument": "Dieses Dokument signieren",
|
||||
"noSignatures": "Keine Signatur für dieses Dokument",
|
||||
"confirmationsCount": "{count} Bestätigung(en)",
|
||||
"poweredBy": "Powered by Ackify",
|
||||
"missingDocId": "Dokument-ID fehlt"
|
||||
},
|
||||
"notFound": {
|
||||
"title": "Seite nicht gefunden",
|
||||
"description": "Die Seite, die Sie suchen, existiert nicht oder wurde verschoben.",
|
||||
"description": "Die von Ihnen gesuchte Seite existiert nicht oder wurde verschoben.",
|
||||
"home": "Zurück zur Startseite"
|
||||
},
|
||||
"footer": {
|
||||
"description": "Open-Source-Lösung für kryptographische Dokumentenlesebestätigung mit unwiderruflichen Ed25519-Signaturen.",
|
||||
"description": "Open-Source-Lösung für kryptografische Dokumentlesebestätigung mit unwiderruflichen Ed25519-Signaturen.",
|
||||
"navigation": {
|
||||
"title": "Navigation"
|
||||
},
|
||||
@@ -320,12 +450,12 @@
|
||||
"legal": {
|
||||
"title": "Rechtliches",
|
||||
"terms": "Nutzungsbedingungen",
|
||||
"privacy": "Datenschutzerklärung",
|
||||
"privacy": "Datenschutzrichtlinie",
|
||||
"contact": "Kontakt"
|
||||
},
|
||||
"copyright": "Alle Rechte vorbehalten.",
|
||||
"license": "Lizenziert unter AGPL-3.0-or-later",
|
||||
"madeWith": "Erstellt mit",
|
||||
"license": "Lizenz AGPL-3.0-or-later",
|
||||
"madeWith": "Gemacht mit",
|
||||
"by": "von",
|
||||
"links": {
|
||||
"privacy": "Datenschutz",
|
||||
@@ -340,7 +470,7 @@
|
||||
"warning": "Warnung"
|
||||
},
|
||||
"common": {
|
||||
"loading": "Wird geladen...",
|
||||
"loading": "Laden...",
|
||||
"save": "Speichern",
|
||||
"cancel": "Abbrechen",
|
||||
"delete": "Löschen",
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
"myConfirmations": "My confirmations",
|
||||
"admin": "Admin",
|
||||
"administration": "Administration",
|
||||
"login": "Log in",
|
||||
"logout": "Log out",
|
||||
"login": "Sign in",
|
||||
"logout": "Sign out",
|
||||
"mobileMenu": "Mobile menu",
|
||||
"mainNavigation": "Main navigation"
|
||||
},
|
||||
@@ -34,19 +34,19 @@
|
||||
},
|
||||
"oauth": {
|
||||
"title": "Sign in with OAuth",
|
||||
"description": "Use your entreprise account",
|
||||
"description": "Use your company account",
|
||||
"button": "Continue with OAuth",
|
||||
"error": "OAuth login failed"
|
||||
"error": "OAuth sign in failed"
|
||||
},
|
||||
"magiclink": {
|
||||
"title": "Sign in with Email",
|
||||
"title": "Sign in by Email",
|
||||
"description": "We'll send you a magic link",
|
||||
"email_label": "Email address",
|
||||
"email_placeholder": "you{'@'}example.com",
|
||||
"button": "Send Magic Link",
|
||||
"button": "Send magic link",
|
||||
"sent": {
|
||||
"title": "Check your email",
|
||||
"message": "We sent you a magic link. Click on it to sign in.",
|
||||
"message": "We've sent you a magic link. Click on it to sign in.",
|
||||
"expire": "The link expires in 15 minutes."
|
||||
},
|
||||
"error_invalid_email": "Please enter a valid email address",
|
||||
@@ -67,13 +67,13 @@
|
||||
},
|
||||
"success": {
|
||||
"title": "Reading confirmed successfully!",
|
||||
"description": "Your confirmation has been recorded cryptographically and securely."
|
||||
"description": "Your confirmation has been cryptographically and securely recorded."
|
||||
},
|
||||
"error": {
|
||||
"title": "An error occurred",
|
||||
"authRequired": "You must be logged in to create a document.",
|
||||
"authRequired": "You must be signed in to create a document.",
|
||||
"loadFailed": "Failed to load document",
|
||||
"loginButton": "Log in"
|
||||
"loginButton": "Sign in"
|
||||
},
|
||||
"document": {
|
||||
"title": "Document to confirm",
|
||||
@@ -83,7 +83,7 @@
|
||||
"description": "By confirming the reading of this document, you certify that you have read its content and agree to validate it cryptographically and non-repudiably.",
|
||||
"recorded": "Your confirmation will be recorded with the following information:",
|
||||
"email": "Your email address",
|
||||
"timestamp": "Precise timestamp of the confirmation",
|
||||
"timestamp": "Precise confirmation timestamp",
|
||||
"signature": "Ed25519 cryptographic confirmation",
|
||||
"hash": "SHA-256 hash of the content"
|
||||
},
|
||||
@@ -98,14 +98,14 @@
|
||||
},
|
||||
"howItWorks": {
|
||||
"title": "How does it work?",
|
||||
"subtitle": "Ackify allows you to cryptographically prove that you have read a document",
|
||||
"subtitle": "Ackify allows you to cryptographically prove that you've read a document",
|
||||
"step1": {
|
||||
"title": "1. Access the document",
|
||||
"description": "Add {code} to this page's address"
|
||||
},
|
||||
"step2": {
|
||||
"title": "2. Authenticate",
|
||||
"description": "Log in via OAuth2 to confirm your identity"
|
||||
"description": "Sign in via OAuth2 to confirm your identity"
|
||||
},
|
||||
"step3": {
|
||||
"title": "3. Confirm reading",
|
||||
@@ -121,7 +121,7 @@
|
||||
"description": "Two-click confirmation with immediate cryptographic verification"
|
||||
},
|
||||
"timestamp": {
|
||||
"title": "Precise timestamp",
|
||||
"title": "Precise timestamping",
|
||||
"description": "Each confirmation is timestamped and chained to ensure integrity"
|
||||
}
|
||||
}
|
||||
@@ -129,15 +129,20 @@
|
||||
},
|
||||
"signButton": {
|
||||
"confirm": "Confirm my reading",
|
||||
"confirmAction": "Confirm reading",
|
||||
"alreadySigned": "Already confirmed",
|
||||
"mustLogin": "Log in to confirm",
|
||||
"confirmed": "Reading confirmed",
|
||||
"mustLogin": "Sign in to confirm",
|
||||
"signing": "Confirming...",
|
||||
"verified": "Verified",
|
||||
"on": "On",
|
||||
"error": {
|
||||
"title": "Confirmation failed",
|
||||
"notAuthenticated": "You must be logged in to confirm a document.",
|
||||
"notAuthenticated": "You must be signed in to confirm a document.",
|
||||
"alreadySigned": "You have already confirmed this document.",
|
||||
"generic": "An error occurred during confirmation. Please try again."
|
||||
"generic": "An error occurred during confirmation. Please try again.",
|
||||
"missingDocId": "Document ID missing",
|
||||
"authFailed": "Unable to start authentication"
|
||||
}
|
||||
},
|
||||
"signatureList": {
|
||||
@@ -145,16 +150,31 @@
|
||||
"email": "Email",
|
||||
"date": "Date",
|
||||
"signature": "Signature",
|
||||
"confirmation": "Confirmation:",
|
||||
"hash": "Hash",
|
||||
"nonce": "Nonce",
|
||||
"verificationStatus": "Verification status",
|
||||
"verified": "Verified",
|
||||
"confirmed": "Confirmed",
|
||||
"notVerified": "Not verified",
|
||||
"showDetails": "Show details",
|
||||
"hideDetails": "Hide details",
|
||||
"viewDetails": "View details",
|
||||
"verificationDetails": "Verification details",
|
||||
"copy": "Copy",
|
||||
"copied": "Copied!",
|
||||
"previousHash": "Previous hash"
|
||||
"previousHash": "Previous hash:",
|
||||
"empty": "No confirmations found",
|
||||
"documentDeleted": "Document deleted",
|
||||
"fields": {
|
||||
"id": "ID:",
|
||||
"document": "Document:",
|
||||
"reader": "Reader:",
|
||||
"date": "Date:",
|
||||
"source": "Source:",
|
||||
"nonce": "Nonce:",
|
||||
"hash": "Hash:"
|
||||
}
|
||||
},
|
||||
"signatures": {
|
||||
"title": "My reading confirmations",
|
||||
@@ -162,20 +182,23 @@
|
||||
"loading": "Loading your confirmations...",
|
||||
"empty": {
|
||||
"title": "No confirmations yet",
|
||||
"description": "You haven't confirmed any documents yet. Start by confirming a document to see it appear here."
|
||||
"description": "You haven't confirmed any documents yet. Start by confirming a document to see it appear here.",
|
||||
"alternative": "You haven't confirmed reading any documents yet"
|
||||
},
|
||||
"count": "{count} confirmation | {count} confirmations",
|
||||
"results": "{count} result | {count} results",
|
||||
"document": "Document",
|
||||
"signedAt": "Confirmed on",
|
||||
"viewDetails": "View details",
|
||||
"deletedDocuments": "Deleted documents",
|
||||
"stats": {
|
||||
"total": "Total",
|
||||
"totalConfirmations": "Total confirmations",
|
||||
"unique": "Unique",
|
||||
"uniqueDocuments": "Unique documents",
|
||||
"last": "Last",
|
||||
"lastConfirmation": "Last confirmation"
|
||||
"lastConfirmation": "Last confirmation",
|
||||
"notAvailable": "N/A"
|
||||
},
|
||||
"allConfirmations": "All my confirmations",
|
||||
"about": {
|
||||
@@ -197,6 +220,7 @@
|
||||
"totalDocuments": "Total documents",
|
||||
"totalSignatures": "Total confirmations",
|
||||
"recentActivity": "Recent activity",
|
||||
"backToDashboard": "Back to dashboard",
|
||||
"stats": {
|
||||
"documents": "Documents",
|
||||
"readers": "Readers",
|
||||
@@ -212,11 +236,12 @@
|
||||
"new": "Create new document",
|
||||
"newDescription": "Prepare a document reference to track reading confirmations",
|
||||
"search": "Search...",
|
||||
"searchPlaceholder": "Search by ID, title, or URL...",
|
||||
"searchPlaceholder": "Search by ID, title or URL...",
|
||||
"id": "Document ID",
|
||||
"idLabel": "Document ID",
|
||||
"idHelper": "Letters, numbers, dashes and underscores only",
|
||||
"idPlaceholder": "e.g: security-policy-2025",
|
||||
"idLabel": "Document",
|
||||
"idHelper": "Accepts URLs, file paths or simple identifiers",
|
||||
"idHelperShort": "Accepts URLs, paths or identifiers",
|
||||
"idPlaceholder": "URL, PATH or document ID",
|
||||
"signatures": "Confirmations",
|
||||
"created": "Created",
|
||||
"createdOn": "Created on",
|
||||
@@ -228,22 +253,34 @@
|
||||
"manage": "Manage",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"empty": "No documents found"
|
||||
"empty": "No documents found",
|
||||
"noResults": "No results",
|
||||
"noDocuments": "No documents",
|
||||
"tryAnotherSearch": "Try another search",
|
||||
"willAppear": "Documents will appear here once created",
|
||||
"totalCount": "{count} document in total | {count} documents in total",
|
||||
"pagination": {
|
||||
"page": "Page {current}/{total}",
|
||||
"pageOf": "Page {current} of {total}"
|
||||
}
|
||||
},
|
||||
"webhooks": {
|
||||
"title": "Webhooks",
|
||||
"subtitle": "Notify third-party apps of events",
|
||||
"subtitle": "Configure notifications to third-party applications",
|
||||
"manage": "Manage webhooks",
|
||||
"new": "New webhook",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"enable": "Enable",
|
||||
"disable": "Disable",
|
||||
"status": { "enabled": "Enabled", "disabled": "Disabled" },
|
||||
"status": {
|
||||
"enabled": "Active",
|
||||
"disabled": "Inactive"
|
||||
},
|
||||
"confirmDelete": "Delete this webhook?",
|
||||
"empty": "No webhooks",
|
||||
"listTitle": "Webhooks list",
|
||||
"listSubtitle": "A webhook can subscribe to several events",
|
||||
"listSubtitle": "A webhook can listen to multiple events",
|
||||
"columns": {
|
||||
"title": "Name",
|
||||
"url": "URL",
|
||||
@@ -253,17 +290,17 @@
|
||||
},
|
||||
"form": {
|
||||
"title": "Webhook settings",
|
||||
"subtitle": "Provide URL, secret and events",
|
||||
"subtitle": "Fill in the URL, secret and events",
|
||||
"nameLabel": "Webhook name",
|
||||
"namePlaceholder": "CRM webhook",
|
||||
"urlLabel": "Target URL",
|
||||
"secretLabel": "HMAC secret",
|
||||
"namePlaceholder": "CRM Webhook",
|
||||
"urlLabel": "Destination URL",
|
||||
"secretLabel": "HMAC Secret",
|
||||
"secretPlaceholder": "Enter a secret (required)",
|
||||
"secretKeep": "Leave empty to keep current",
|
||||
"eventsLabel": "Events to subscribe",
|
||||
"secretKeep": "Leave empty to keep",
|
||||
"eventsLabel": "Events to listen to",
|
||||
"descriptionLabel": "Description (optional)",
|
||||
"descriptionPlaceholder": "Internal note…",
|
||||
"validation": "Please fill name, URL, secret and at least one event."
|
||||
"validation": "Please complete the name, URL, secret and at least one event."
|
||||
},
|
||||
"editTitle": "Edit webhook",
|
||||
"events": {
|
||||
@@ -282,8 +319,9 @@
|
||||
}
|
||||
},
|
||||
"documentDetail": {
|
||||
"title": "Document details",
|
||||
"metadata": "Document metadata and checksum",
|
||||
"title": "Document",
|
||||
"metadata": "📄 Document information",
|
||||
"metadataDescription": "Document metadata and checksum",
|
||||
"checksum": "Checksum",
|
||||
"algorithm": "Algorithm",
|
||||
"titleLabel": "Title",
|
||||
@@ -296,61 +334,102 @@
|
||||
"descriptionLabel": "Description",
|
||||
"descriptionPlaceholder": "Document description...",
|
||||
"signatures": "Confirmations",
|
||||
"back": "Back to list",
|
||||
"back": "Back",
|
||||
"expectedSigners": "Expected signers",
|
||||
"addExpectedSigner": "Add expected signer",
|
||||
"addSigners": "Add expected readers",
|
||||
"addButton": "Add",
|
||||
"adding": "Adding...",
|
||||
"emailsLabel": "Emails (one per line)",
|
||||
"emailsPlaceholder": "Mary Smith <mary.smith{'@'}example.com>\njohn.doe{'@'}example.com\nSophie Johnson <sophie{'@'}example.com>",
|
||||
"emailsPlaceholder": "Jane Doe <jane.doe{'@'}example.com>\njohn.smith{'@'}example.com\nSarah Johnson <sarah{'@'}example.com>",
|
||||
"emailsHelper": "Accepted formats: \"First Last <email{'@'}example.com>\" or \"email{'@'}example.com\"",
|
||||
"emailLabel": "Email *",
|
||||
"emailPlaceholder": "email{'@'}example.com",
|
||||
"nameLabel": "Name",
|
||||
"namePlaceholder": "Full name",
|
||||
"reader": "Reader",
|
||||
"readers": "✓ Expected readers",
|
||||
"user": "User",
|
||||
"status": "Status",
|
||||
"statusConfirmed": "✓ Confirmed",
|
||||
"statusPending": "⏳ Pending",
|
||||
"confirmedOn": "Confirmed on",
|
||||
"noExpectedSigners": "No expected readers",
|
||||
"noSignatures": "No confirmations",
|
||||
"reminders": "Email reminders",
|
||||
"reminders": "📧 Email reminders",
|
||||
"remindersDescription": "Send reminders to readers awaiting confirmation",
|
||||
"remindersSent": "Reminders sent",
|
||||
"toRemind": "To remind",
|
||||
"lastReminder": "Last reminder",
|
||||
"sendReminder": "Send reminder",
|
||||
"sending": "Sending...",
|
||||
"sendReminders": "Send reminders",
|
||||
"sendToAll": "Send to all pending readers ({count})",
|
||||
"sendToSelected": "Send to selected only ({count})",
|
||||
"allContacted": "✓ All expected readers have been contacted or confirmed",
|
||||
"unexpectedSignatures": "⚠ Additional reading confirmations",
|
||||
"unexpectedDescription": "Users who confirmed but are not on the expected readers list",
|
||||
"createdBy": "Created by {by} on {date}",
|
||||
"saving": "Saving...",
|
||||
"deleting": "Deleting...",
|
||||
"copiedToClipboard": "Copied to clipboard",
|
||||
"metadataSaved": "Metadata saved successfully",
|
||||
"signersAdded": "{count} reader(s) added successfully",
|
||||
"signerRemoved": "{email} removed successfully",
|
||||
"remindersSentSuccess": "{count} reminder(s) sent successfully",
|
||||
"remindersSentPartial": "{sent} reminder(s) sent, {failed} failed",
|
||||
"remindersSentGeneric": "Reminders sent successfully",
|
||||
"confirmSendReminders": "Send reminders to {count} reader(s) awaiting confirmation?",
|
||||
"confirmSendRemindersSelected": "Send reminders to {count} selected reader(s)?",
|
||||
"confirmSendRemindersTitle": "📧 Send reminders",
|
||||
"removeSignerTitle": "⚠️ Remove expected reader",
|
||||
"removeSignerMessage": "Remove {email} from the expected readers list?",
|
||||
"metadataWarning": {
|
||||
"title": "⚠️ Warning: Signature invalidation",
|
||||
"description": "You are about to modify critical document information (URL, checksum, algorithm, or description).",
|
||||
"description": "You are about to modify critical document information (URL, checksum, algorithm or description).",
|
||||
"warning": "This modification will invalidate all existing signatures, as they are cryptographically linked to the current document content.",
|
||||
"currentSignatures": "Current signatures that will be invalidated:",
|
||||
"confirm": "I understand, continue",
|
||||
"cancel": "Cancel"
|
||||
},
|
||||
"dangerZone": "Danger zone",
|
||||
"dangerZone": "⚠️ Danger zone",
|
||||
"dangerZoneDescription": "Irreversible actions on this document",
|
||||
"deleteDocument": "Delete this document",
|
||||
"deleteDocumentDescription": "This action will permanently delete the document, its metadata, expected readers and all associated confirmations.\nThis action is irreversible.",
|
||||
"deleteWarning": "This action is irreversible!",
|
||||
"deleteWillRemove": "This action will permanently remove:",
|
||||
"deleteWillRemove": "Deleting this document will result in the permanent loss of:",
|
||||
"deleteItem1": "All document metadata",
|
||||
"deleteItem2": "The list of expected readers",
|
||||
"deleteItem3": "All cryptographic confirmations",
|
||||
"deleteItem4": "The reminder history"
|
||||
"deleteItem4": "The reminder history",
|
||||
"deleteConfirmTitle": "⚠️ Confirm deletion",
|
||||
"deleteConfirmButton": "Delete permanently",
|
||||
"documentId": "Document ID:"
|
||||
},
|
||||
"documentForm": {
|
||||
"title": "Document reference",
|
||||
"label": "Reference (URL, path or ID)",
|
||||
"placeholder": "https://example.com/doc.pdf or /path/to/doc",
|
||||
"submit": "Confirm",
|
||||
"placeholder": "URL, PATH or REFERENCE of the document to read (optional)",
|
||||
"submit": "Start",
|
||||
"submitting": "Loading...",
|
||||
"creating": "Creating..."
|
||||
}
|
||||
},
|
||||
"embed": {
|
||||
"loading": "Loading signature information...",
|
||||
"title": "Signature for",
|
||||
"document": "Document:",
|
||||
"signedBy": "Signed by",
|
||||
"on": "on",
|
||||
"verified": "Verified",
|
||||
"viewAll": "View all confirmations",
|
||||
"error": "Unable to load signature information"
|
||||
"error": "Unable to load signature information",
|
||||
"sign": "Sign",
|
||||
"signDocument": "Sign this document",
|
||||
"noSignatures": "No signatures for this document",
|
||||
"confirmationsCount": "{count} confirmation(s)",
|
||||
"poweredBy": "Powered by Ackify",
|
||||
"missingDocId": "Document ID missing"
|
||||
},
|
||||
"notFound": {
|
||||
"title": "Page not found",
|
||||
@@ -358,7 +437,7 @@
|
||||
"home": "Back to home"
|
||||
},
|
||||
"footer": {
|
||||
"description": "Open-source cryptographic document reading confirmation solution with non-repudiable Ed25519 signatures.",
|
||||
"description": "Open-source solution for cryptographic confirmation of document reading with non-repudiable Ed25519 signatures.",
|
||||
"navigation": {
|
||||
"title": "Navigation"
|
||||
},
|
||||
@@ -370,12 +449,12 @@
|
||||
},
|
||||
"legal": {
|
||||
"title": "Legal",
|
||||
"terms": "Terms of Service",
|
||||
"privacy": "Privacy Policy",
|
||||
"terms": "Terms of use",
|
||||
"privacy": "Privacy policy",
|
||||
"contact": "Contact"
|
||||
},
|
||||
"copyright": "All rights reserved.",
|
||||
"license": "Licensed under AGPL-3.0-or-later",
|
||||
"license": "AGPL-3.0-or-later License",
|
||||
"madeWith": "Made with",
|
||||
"by": "by",
|
||||
"links": {
|
||||
|
||||
@@ -30,26 +30,26 @@
|
||||
"choice": {
|
||||
"title": "Iniciar sesión en Ackify",
|
||||
"subtitle": "Elija su método de autenticación preferido",
|
||||
"privacy": "Su autenticación es segura y cifrada"
|
||||
"privacy": "Su autenticación está asegurada y cifrada"
|
||||
},
|
||||
"oauth": {
|
||||
"title": "Iniciar sesión con OAuth",
|
||||
"description": "Use su cuenta existente",
|
||||
"description": "Use su cuenta empresarial",
|
||||
"button": "Continuar con OAuth",
|
||||
"error": "Error de inicio de sesión OAuth"
|
||||
"error": "Error en el inicio de sesión OAuth"
|
||||
},
|
||||
"magiclink": {
|
||||
"title": "Iniciar sesión por correo electrónico",
|
||||
"title": "Iniciar sesión por Email",
|
||||
"description": "Le enviaremos un enlace mágico",
|
||||
"email_label": "Dirección de correo electrónico",
|
||||
"email_label": "Dirección de email",
|
||||
"email_placeholder": "usted{'@'}ejemplo.com",
|
||||
"button": "Enviar enlace mágico",
|
||||
"sent": {
|
||||
"title": "Revise su correo electrónico",
|
||||
"title": "Consulte sus emails",
|
||||
"message": "Le hemos enviado un enlace mágico. Haga clic en él para iniciar sesión.",
|
||||
"expire": "El enlace caduca en 15 minutos."
|
||||
"expire": "El enlace expira en 15 minutos."
|
||||
},
|
||||
"error_invalid_email": "Por favor ingrese una dirección de correo electrónico válida",
|
||||
"error_invalid_email": "Por favor, ingrese una dirección de email válida",
|
||||
"error_send": "Error al enviar el enlace mágico"
|
||||
}
|
||||
},
|
||||
@@ -57,21 +57,21 @@
|
||||
"title": "Confirmación de Lectura",
|
||||
"subtitle": "Certifique su lectura con una confirmación criptográfica Ed25519",
|
||||
"loading": {
|
||||
"title": "Cargando documento...",
|
||||
"description": "Por favor espere mientras preparamos el documento para la firma."
|
||||
"title": "Cargando el documento...",
|
||||
"description": "Por favor, espere mientras preparamos el documento para la firma."
|
||||
},
|
||||
"noDocument": {
|
||||
"title": "Ningún documento especificado",
|
||||
"description": "Para firmar un documento, agregue el parámetro {code} a la URL",
|
||||
"description": "Para firmar un documento, añada el parámetro {code} a la URL",
|
||||
"examples": "Ejemplos:"
|
||||
},
|
||||
"success": {
|
||||
"title": "¡Lectura confirmada con éxito!",
|
||||
"description": "Su confirmación ha sido registrada de manera criptográfica y segura."
|
||||
"description": "Su confirmación ha sido registrada de forma criptográfica y segura."
|
||||
},
|
||||
"error": {
|
||||
"title": "Ha ocurrido un error",
|
||||
"authRequired": "Debe iniciar sesión para crear un documento.",
|
||||
"authRequired": "Debe estar conectado para crear un documento.",
|
||||
"loadFailed": "Error al cargar el documento",
|
||||
"loginButton": "Iniciar sesión"
|
||||
},
|
||||
@@ -80,9 +80,9 @@
|
||||
"id": "ID"
|
||||
},
|
||||
"info": {
|
||||
"description": "Al confirmar la lectura de este documento, usted certifica haber leído su contenido y acepta validarlo de manera criptográfica y no repudiable.",
|
||||
"description": "Al confirmar la lectura de este documento, usted certifica haber tomado conocimiento de su contenido y acepta validarlo de manera criptográfica e irrefutable.",
|
||||
"recorded": "Su confirmación será registrada con la siguiente información:",
|
||||
"email": "Su dirección de correo electrónico",
|
||||
"email": "Su dirección de email",
|
||||
"timestamp": "Marca de tiempo precisa de la confirmación",
|
||||
"signature": "Confirmación criptográfica Ed25519",
|
||||
"hash": "Hash SHA-256 del contenido"
|
||||
@@ -98,14 +98,14 @@
|
||||
},
|
||||
"howItWorks": {
|
||||
"title": "¿Cómo funciona?",
|
||||
"subtitle": "Ackify le permite demostrar criptográficamente que ha leído un documento",
|
||||
"subtitle": "Ackify le permite probar criptográficamente que ha leído un documento",
|
||||
"step1": {
|
||||
"title": "1. Acceda al documento",
|
||||
"description": "Agregue {code} a la dirección de esta página"
|
||||
"description": "Añada {code} a la dirección de esta página"
|
||||
},
|
||||
"step2": {
|
||||
"title": "2. Autentíquese",
|
||||
"description": "Inicie sesión a través de OAuth2 para confirmar su identidad"
|
||||
"description": "Inicie sesión vía OAuth2 para confirmar su identidad"
|
||||
},
|
||||
"step3": {
|
||||
"title": "3. Confirme la lectura",
|
||||
@@ -114,7 +114,7 @@
|
||||
"features": {
|
||||
"crypto": {
|
||||
"title": "Seguridad criptográfica",
|
||||
"description": "Firmas Ed25519 no repudiables que garantizan la autenticidad"
|
||||
"description": "Firmas Ed25519 irrefutables que garantizan la autenticidad"
|
||||
},
|
||||
"instant": {
|
||||
"title": "Instantáneo",
|
||||
@@ -122,70 +122,93 @@
|
||||
},
|
||||
"timestamp": {
|
||||
"title": "Marca de tiempo precisa",
|
||||
"description": "Cada confirmación está marcada temporalmente y encadenada para garantizar la integridad"
|
||||
"description": "Cada confirmación tiene marca de tiempo y está encadenada para garantizar la integridad"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"signButton": {
|
||||
"confirm": "Confirmar mi lectura",
|
||||
"confirmAction": "Confirmar la lectura",
|
||||
"alreadySigned": "Ya confirmado",
|
||||
"confirmed": "Lectura confirmada",
|
||||
"mustLogin": "Iniciar sesión para confirmar",
|
||||
"signing": "Confirmando...",
|
||||
"signing": "Confirmación en curso...",
|
||||
"verified": "Verificado",
|
||||
"on": "El",
|
||||
"error": {
|
||||
"title": "Error en la confirmación",
|
||||
"notAuthenticated": "Debe iniciar sesión para confirmar un documento.",
|
||||
"notAuthenticated": "Debe estar conectado para confirmar un documento.",
|
||||
"alreadySigned": "Ya ha confirmado este documento.",
|
||||
"generic": "Ha ocurrido un error durante la confirmación. Por favor, inténtelo de nuevo."
|
||||
"generic": "Ha ocurrido un error durante la confirmación. Por favor, inténtelo de nuevo.",
|
||||
"missingDocId": "ID de documento faltante",
|
||||
"authFailed": "Imposible iniciar la autenticación"
|
||||
}
|
||||
},
|
||||
"signatureList": {
|
||||
"loading": "Cargando confirmaciones...",
|
||||
"email": "Correo electrónico",
|
||||
"loading": "Cargando las confirmaciones...",
|
||||
"email": "Email",
|
||||
"date": "Fecha",
|
||||
"signature": "Firma",
|
||||
"confirmation": "Confirmación:",
|
||||
"hash": "Hash",
|
||||
"nonce": "Nonce",
|
||||
"verificationStatus": "Estado de verificación",
|
||||
"verified": "Verificado",
|
||||
"confirmed": "Confirmado",
|
||||
"notVerified": "No verificado",
|
||||
"showDetails": "Mostrar detalles",
|
||||
"hideDetails": "Ocultar detalles",
|
||||
"viewDetails": "Ver detalles",
|
||||
"verificationDetails": "Detalles de verificación",
|
||||
"copy": "Copiar",
|
||||
"copied": "¡Copiado!",
|
||||
"previousHash": "Hash anterior"
|
||||
"previousHash": "Hash anterior:",
|
||||
"empty": "Ninguna confirmación encontrada",
|
||||
"documentDeleted": "Documento eliminado",
|
||||
"fields": {
|
||||
"id": "ID:",
|
||||
"document": "Documento:",
|
||||
"reader": "Lector:",
|
||||
"date": "Fecha:",
|
||||
"source": "Origen:",
|
||||
"nonce": "Nonce:",
|
||||
"hash": "Hash:"
|
||||
}
|
||||
},
|
||||
"signatures": {
|
||||
"title": "Mis confirmaciones de lectura",
|
||||
"subtitle": "Lista de todos los documentos cuya lectura ha confirmado criptográficamente",
|
||||
"subtitle": "Lista de todos los documentos cuya lectura has confirmado criptográficamente",
|
||||
"loading": "Cargando sus confirmaciones...",
|
||||
"empty": {
|
||||
"title": "Ninguna confirmación por el momento",
|
||||
"description": "Aún no ha confirmado ningún documento. Comience confirmando un documento para verlo aparecer aquí."
|
||||
"description": "Aún no ha confirmado ningún documento. Comience confirmando un documento para verlo aparecer aquí.",
|
||||
"alternative": "Aún no ha confirmado la lectura de documentos"
|
||||
},
|
||||
"count": "{count} confirmación | {count} confirmaciones",
|
||||
"results": "{count} resultado | {count} resultados",
|
||||
"document": "Documento",
|
||||
"signedAt": "Confirmado el",
|
||||
"viewDetails": "Ver detalles",
|
||||
"deletedDocuments": "Documentos eliminados",
|
||||
"stats": {
|
||||
"total": "Total",
|
||||
"totalConfirmations": "Total confirmaciones",
|
||||
"unique": "Únicos",
|
||||
"uniqueDocuments": "Documentos únicos",
|
||||
"last": "Último",
|
||||
"lastConfirmation": "Última confirmación"
|
||||
"lastConfirmation": "Última confirmación",
|
||||
"notAvailable": "N/A"
|
||||
},
|
||||
"allConfirmations": "Todas mis confirmaciones",
|
||||
"about": {
|
||||
"title": "Acerca de las confirmaciones",
|
||||
"description": "Cada confirmación se registra criptográficamente con Ed25519 y se encadena para garantizar la integridad. Las confirmaciones son no repudiables y están marcadas temporalmente con precisión."
|
||||
"description": "Cada confirmación se registra criptográficamente con Ed25519 y se encadena para garantizar la integridad. Las confirmaciones son irrefutables y tienen una marca de tiempo precisa."
|
||||
},
|
||||
"search": "Buscar...",
|
||||
"error": {
|
||||
"title": "Error al cargar las confirmaciones",
|
||||
"description": "No se pueden cargar sus confirmaciones. Por favor, inténtelo de nuevo."
|
||||
"description": "Imposible cargar sus confirmaciones. Por favor, inténtelo de nuevo."
|
||||
}
|
||||
},
|
||||
"admin": {
|
||||
@@ -197,6 +220,7 @@
|
||||
"totalDocuments": "Documentos totales",
|
||||
"totalSignatures": "Confirmaciones totales",
|
||||
"recentActivity": "Actividad reciente",
|
||||
"backToDashboard": "Volver al panel de control",
|
||||
"stats": {
|
||||
"documents": "Documentos",
|
||||
"readers": "Lectores",
|
||||
@@ -204,19 +228,20 @@
|
||||
"expected": "Esperados",
|
||||
"signed": "Firmados",
|
||||
"pending": "Pendientes",
|
||||
"completion": "Finalización"
|
||||
"completion": "Completitud"
|
||||
}
|
||||
},
|
||||
"documents": {
|
||||
"title": "Todos los documentos",
|
||||
"new": "Crear nuevo documento",
|
||||
"newDescription": "Preparar la referencia de un documento para rastrear las confirmaciones de lectura",
|
||||
"newDescription": "Preparar una referencia de documento para seguir las confirmaciones de lectura",
|
||||
"search": "Buscar...",
|
||||
"searchPlaceholder": "Buscar por ID, título o URL...",
|
||||
"id": "ID del documento",
|
||||
"idLabel": "ID del documento",
|
||||
"idHelper": "Solo letras, números, guiones y guiones bajos",
|
||||
"idPlaceholder": "ej: politica-seguridad-2025",
|
||||
"idLabel": "Documento",
|
||||
"idHelper": "Acepta URLs, rutas de archivos o identificadores simples",
|
||||
"idHelperShort": "Acepta URLs, rutas o identificadores",
|
||||
"idPlaceholder": "URL, PATH o ID del documento",
|
||||
"signatures": "Confirmaciones",
|
||||
"created": "Creado",
|
||||
"createdOn": "Creado el",
|
||||
@@ -228,15 +253,79 @@
|
||||
"manage": "Gestionar",
|
||||
"edit": "Editar",
|
||||
"delete": "Eliminar",
|
||||
"empty": "No se encontraron documentos"
|
||||
"empty": "Ningún documento encontrado",
|
||||
"noResults": "Ningún resultado",
|
||||
"noDocuments": "Ningún documento",
|
||||
"tryAnotherSearch": "Pruebe otra búsqueda",
|
||||
"willAppear": "Los documentos aparecerán aquí una vez creados",
|
||||
"totalCount": "{count} documento en total | {count} documentos en total",
|
||||
"pagination": {
|
||||
"page": "Página {current}/{total}",
|
||||
"pageOf": "Página {current} de {total}"
|
||||
}
|
||||
},
|
||||
"webhooks": {
|
||||
"title": "Webhooks",
|
||||
"subtitle": "Configurar notificaciones hacia aplicaciones de terceros",
|
||||
"manage": "Gestionar webhooks",
|
||||
"new": "Nuevo webhook",
|
||||
"edit": "Editar",
|
||||
"delete": "Eliminar",
|
||||
"enable": "Activar",
|
||||
"disable": "Desactivar",
|
||||
"status": {
|
||||
"enabled": "Activo",
|
||||
"disabled": "Inactivo"
|
||||
},
|
||||
"confirmDelete": "¿Eliminar este webhook?",
|
||||
"empty": "Ningún webhook",
|
||||
"listTitle": "Lista de webhooks",
|
||||
"listSubtitle": "Un webhook puede escuchar varios eventos",
|
||||
"columns": {
|
||||
"title": "Nombre",
|
||||
"url": "URL",
|
||||
"events": "Eventos",
|
||||
"status": "Estado",
|
||||
"actions": "Acciones"
|
||||
},
|
||||
"form": {
|
||||
"title": "Parámetros del webhook",
|
||||
"subtitle": "Complete la URL, el secreto y los eventos",
|
||||
"nameLabel": "Nombre del webhook",
|
||||
"namePlaceholder": "Webhook CRM",
|
||||
"urlLabel": "URL de destino",
|
||||
"secretLabel": "Secreto HMAC",
|
||||
"secretPlaceholder": "Ingrese un secreto (requerido)",
|
||||
"secretKeep": "Dejar vacío para conservar",
|
||||
"eventsLabel": "Eventos a escuchar",
|
||||
"descriptionLabel": "Descripción (opcional)",
|
||||
"descriptionPlaceholder": "Nota interna…",
|
||||
"validation": "Por favor, complete el nombre, la URL, el secreto y al menos un evento."
|
||||
},
|
||||
"editTitle": "Editar el webhook",
|
||||
"events": {
|
||||
"documentCreated": "Documento creado",
|
||||
"signatureCreated": "Firma creada",
|
||||
"documentCompleted": "Documento completado",
|
||||
"reminderSent": "Recordatorio enviado",
|
||||
"reminderFailed": "Recordatorio fallido"
|
||||
},
|
||||
"eventsMap": {
|
||||
"document.created": "Documento creado",
|
||||
"signature.created": "Firma creada",
|
||||
"document.completed": "Documento completado",
|
||||
"reminder.sent": "Recordatorio enviado",
|
||||
"reminder.failed": "Recordatorio fallido"
|
||||
}
|
||||
},
|
||||
"documentDetail": {
|
||||
"title": "Detalles del documento",
|
||||
"metadata": "Metadatos y checksum del documento",
|
||||
"title": "Documento",
|
||||
"metadata": "📄 Información del documento",
|
||||
"metadataDescription": "Metadatos y checksum del documento",
|
||||
"checksum": "Checksum",
|
||||
"algorithm": "Algoritmo",
|
||||
"titleLabel": "Título",
|
||||
"titlePlaceholder": "Política de Seguridad 2025",
|
||||
"titlePlaceholder": "Política de seguridad 2025",
|
||||
"urlLabel": "URL",
|
||||
"urlPlaceholder": "https://example.com/doc.pdf",
|
||||
"checksumLabel": "Checksum",
|
||||
@@ -245,61 +334,102 @@
|
||||
"descriptionLabel": "Descripción",
|
||||
"descriptionPlaceholder": "Descripción del documento...",
|
||||
"signatures": "Confirmaciones",
|
||||
"back": "Volver a la lista",
|
||||
"back": "Volver",
|
||||
"expectedSigners": "Firmantes esperados",
|
||||
"addExpectedSigner": "Agregar firmante esperado",
|
||||
"addSigners": "Agregar lectores esperados",
|
||||
"emailsLabel": "Correos electrónicos (uno por línea)",
|
||||
"emailsPlaceholder": "María García <maria.garcia{'@'}example.com>\njuan.martinez{'@'}example.com\nSofía Rodríguez <sofia{'@'}example.com>",
|
||||
"emailLabel": "Correo electrónico *",
|
||||
"addExpectedSigner": "Añadir firmante esperado",
|
||||
"addSigners": "Añadir lectores esperados",
|
||||
"addButton": "Añadir",
|
||||
"adding": "Añadiendo...",
|
||||
"emailsLabel": "Emails (uno por línea)",
|
||||
"emailsPlaceholder": "María López <maria.lopez{'@'}example.com>\njuan.martin{'@'}example.com>\nSofía García <sofia{'@'}example.com>",
|
||||
"emailsHelper": "Formatos aceptados: \"Nombre Apellido <email{'@'}example.com>\" o \"email{'@'}example.com\"",
|
||||
"emailLabel": "Email *",
|
||||
"emailPlaceholder": "email{'@'}example.com",
|
||||
"nameLabel": "Nombre",
|
||||
"namePlaceholder": "Nombre completo",
|
||||
"reader": "Lector",
|
||||
"readers": "✓ Lectores esperados",
|
||||
"user": "Usuario",
|
||||
"status": "Estado",
|
||||
"statusConfirmed": "✓ Confirmado",
|
||||
"statusPending": "⏳ En espera",
|
||||
"confirmedOn": "Confirmado el",
|
||||
"noExpectedSigners": "Ningún lector esperado",
|
||||
"noSignatures": "Ninguna confirmación",
|
||||
"reminders": "Recordatorios por correo electrónico",
|
||||
"reminders": "📧 Recordatorios por email",
|
||||
"remindersDescription": "Enviar recordatorios a los lectores en espera de confirmación",
|
||||
"remindersSent": "Recordatorios enviados",
|
||||
"toRemind": "Por recordar",
|
||||
"toRemind": "Para recordar",
|
||||
"lastReminder": "Último recordatorio",
|
||||
"sendReminder": "Enviar recordatorio",
|
||||
"sending": "Enviando...",
|
||||
"sendReminders": "Enviar recordatorios",
|
||||
"sendToAll": "Enviar a todos los lectores en espera ({count})",
|
||||
"sendToSelected": "Enviar solo a los seleccionados ({count})",
|
||||
"allContacted": "✓ Todos los lectores esperados han sido contactados o han confirmado",
|
||||
"unexpectedSignatures": "⚠ Confirmaciones de lectura complementarias",
|
||||
"unexpectedDescription": "Usuarios que han confirmado pero no están presentes en la lista de lectores esperados",
|
||||
"createdBy": "Creado por {by} el {date}",
|
||||
"saving": "Guardando...",
|
||||
"deleting": "Eliminando...",
|
||||
"copiedToClipboard": "Copiado al portapapeles",
|
||||
"metadataSaved": "Metadatos guardados con éxito",
|
||||
"signersAdded": "{count} lector(es) añadido(s) con éxito",
|
||||
"signerRemoved": "{email} eliminado con éxito",
|
||||
"remindersSentSuccess": "{count} recordatorio(s) enviado(s) con éxito",
|
||||
"remindersSentPartial": "{sent} recordatorio(s) enviado(s), {failed} fallo(s)",
|
||||
"remindersSentGeneric": "Recordatorios enviados con éxito",
|
||||
"confirmSendReminders": "¿Enviar recordatorios a {count} lector(es) en espera de confirmación?",
|
||||
"confirmSendRemindersSelected": "¿Enviar recordatorios a {count} lector(es) seleccionado(s)?",
|
||||
"confirmSendRemindersTitle": "📧 Enviar recordatorios",
|
||||
"removeSignerTitle": "⚠️ Eliminar el lector esperado",
|
||||
"removeSignerMessage": "¿Eliminar {email} de la lista de lectores esperados?",
|
||||
"metadataWarning": {
|
||||
"title": "⚠️ Atención: Invalidación de firmas",
|
||||
"description": "Está a punto de modificar información crítica del documento (URL, checksum, algoritmo o descripción).",
|
||||
"warning": "Esta modificación resultará en la invalidación de todas las firmas existentes, ya que están vinculadas criptográficamente al contenido actual del documento.",
|
||||
"warning": "Esta modificación provocará la invalidación de todas las firmas existentes, ya que están vinculadas criptográficamente al contenido actual del documento.",
|
||||
"currentSignatures": "Firmas actuales que serán invalidadas:",
|
||||
"confirm": "Entiendo, continuar",
|
||||
"cancel": "Cancelar"
|
||||
},
|
||||
"dangerZone": "Zona de peligro",
|
||||
"dangerZoneDescription": "Acciones irreversibles en este documento",
|
||||
"dangerZone": "⚠️ Zona de peligro",
|
||||
"dangerZoneDescription": "Acciones irreversibles sobre este documento",
|
||||
"deleteDocument": "Eliminar este documento",
|
||||
"deleteDocumentDescription": "Esta acción eliminará definitivamente el documento, sus metadatos, los lectores esperados y todas las confirmaciones asociadas.\nEsta acción es irreversible.",
|
||||
"deleteWarning": "¡Esta acción es irreversible!",
|
||||
"deleteWillRemove": "Esta acción eliminará permanentemente:",
|
||||
"deleteWillRemove": "La eliminación de este documento provocará la pérdida definitiva de:",
|
||||
"deleteItem1": "Todos los metadatos del documento",
|
||||
"deleteItem2": "La lista de lectores esperados",
|
||||
"deleteItem3": "Todas las confirmaciones criptográficas",
|
||||
"deleteItem4": "El historial de recordatorios"
|
||||
"deleteItem4": "El historial de recordatorios",
|
||||
"deleteConfirmTitle": "⚠️ Confirmar la eliminación",
|
||||
"deleteConfirmButton": "Eliminar definitivamente",
|
||||
"documentId": "ID del documento:"
|
||||
},
|
||||
"documentForm": {
|
||||
"title": "Referencia del documento",
|
||||
"label": "Referencia (URL, ruta o ID)",
|
||||
"placeholder": "https://example.com/doc.pdf o /ruta/al/doc",
|
||||
"submit": "Confirmar",
|
||||
"creating": "Creando..."
|
||||
"placeholder": "URL, PATH o REFERENCIA del documento a leer (opcional)",
|
||||
"submit": "Comenzar",
|
||||
"submitting": "Cargando...",
|
||||
"creating": "Creación en curso..."
|
||||
}
|
||||
},
|
||||
"embed": {
|
||||
"loading": "Cargando información de firma...",
|
||||
"loading": "Cargando información de la firma...",
|
||||
"title": "Firma para",
|
||||
"document": "Documento:",
|
||||
"signedBy": "Firmado por",
|
||||
"on": "el",
|
||||
"verified": "Verificado",
|
||||
"viewAll": "Ver todas las confirmaciones",
|
||||
"error": "No se puede cargar la información de firma"
|
||||
"error": "Imposible cargar la información de la firma",
|
||||
"sign": "Firmar",
|
||||
"signDocument": "Firmar este documento",
|
||||
"noSignatures": "Ninguna firma para este documento",
|
||||
"confirmationsCount": "{count} confirmación(es)",
|
||||
"poweredBy": "Desarrollado por Ackify",
|
||||
"missingDocId": "ID de documento faltante"
|
||||
},
|
||||
"notFound": {
|
||||
"title": "Página no encontrada",
|
||||
@@ -307,7 +437,7 @@
|
||||
"home": "Volver al inicio"
|
||||
},
|
||||
"footer": {
|
||||
"description": "Solución de código abierto de confirmación criptográfica de lectura de documentos con firmas Ed25519 no repudiables.",
|
||||
"description": "Solución de código abierto de confirmación criptográfica de lectura de documentos con firmas Ed25519 irrefutables.",
|
||||
"navigation": {
|
||||
"title": "Navegación"
|
||||
},
|
||||
@@ -319,7 +449,7 @@
|
||||
},
|
||||
"legal": {
|
||||
"title": "Legal",
|
||||
"terms": "Términos de uso",
|
||||
"terms": "Condiciones de uso",
|
||||
"privacy": "Política de privacidad",
|
||||
"contact": "Contacto"
|
||||
},
|
||||
@@ -329,7 +459,7 @@
|
||||
"by": "por",
|
||||
"links": {
|
||||
"privacy": "Privacidad",
|
||||
"terms": "Términos",
|
||||
"terms": "Condiciones",
|
||||
"contact": "Contacto"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -129,15 +129,20 @@
|
||||
},
|
||||
"signButton": {
|
||||
"confirm": "Confirmer ma lecture",
|
||||
"confirmAction": "Confirmer la lecture",
|
||||
"alreadySigned": "Déjà confirmé",
|
||||
"confirmed": "Lecture confirmée",
|
||||
"mustLogin": "Se connecter pour confirmer",
|
||||
"signing": "Confirmation en cours...",
|
||||
"verified": "Vérifié",
|
||||
"on": "Le",
|
||||
"error": {
|
||||
"title": "Échec de la confirmation",
|
||||
"notAuthenticated": "Vous devez être connecté pour confirmer un document.",
|
||||
"alreadySigned": "Vous avez déjà confirmé ce document.",
|
||||
"generic": "Une erreur est survenue lors de la confirmation. Veuillez réessayer."
|
||||
"generic": "Une erreur est survenue lors de la confirmation. Veuillez réessayer.",
|
||||
"missingDocId": "Document ID manquant",
|
||||
"authFailed": "Impossible de démarrer l'authentification"
|
||||
}
|
||||
},
|
||||
"signatureList": {
|
||||
@@ -145,16 +150,31 @@
|
||||
"email": "Email",
|
||||
"date": "Date",
|
||||
"signature": "Signature",
|
||||
"confirmation": "Confirmation:",
|
||||
"hash": "Hash",
|
||||
"nonce": "Nonce",
|
||||
"verificationStatus": "Statut de vérification",
|
||||
"verified": "Vérifié",
|
||||
"confirmed": "Confirmé",
|
||||
"notVerified": "Non vérifié",
|
||||
"showDetails": "Afficher les détails",
|
||||
"hideDetails": "Masquer les détails",
|
||||
"viewDetails": "Voir détails",
|
||||
"verificationDetails": "Détails de vérification",
|
||||
"copy": "Copier",
|
||||
"copied": "Copié !",
|
||||
"previousHash": "Hash précédent"
|
||||
"previousHash": "Hash précédent:",
|
||||
"empty": "Aucune confirmation trouvée",
|
||||
"documentDeleted": "Document supprimé",
|
||||
"fields": {
|
||||
"id": "ID:",
|
||||
"document": "Document:",
|
||||
"reader": "Lecteur:",
|
||||
"date": "Date:",
|
||||
"source": "Origine:",
|
||||
"nonce": "Nonce:",
|
||||
"hash": "Hash:"
|
||||
}
|
||||
},
|
||||
"signatures": {
|
||||
"title": "Mes confirmations de lecture",
|
||||
@@ -162,20 +182,23 @@
|
||||
"loading": "Chargement de vos confirmations...",
|
||||
"empty": {
|
||||
"title": "Aucune confirmation pour le moment",
|
||||
"description": "Vous n'avez pas encore confirmé de document. Commencez par confirmer un document pour le voir apparaître ici."
|
||||
"description": "Vous n'avez pas encore confirmé de document. Commencez par confirmer un document pour le voir apparaître ici.",
|
||||
"alternative": "Vous n'avez pas encore confirmé la lecture de documents"
|
||||
},
|
||||
"count": "{count} confirmation | {count} confirmations",
|
||||
"results": "{count} résultat | {count} résultats",
|
||||
"document": "Document",
|
||||
"signedAt": "Confirmé le",
|
||||
"viewDetails": "Voir les détails",
|
||||
"deletedDocuments": "Documents supprimés",
|
||||
"stats": {
|
||||
"total": "Total",
|
||||
"totalConfirmations": "Total confirmations",
|
||||
"unique": "Uniques",
|
||||
"uniqueDocuments": "Documents uniques",
|
||||
"last": "Dernier",
|
||||
"lastConfirmation": "Dernière confirmation"
|
||||
"lastConfirmation": "Dernière confirmation",
|
||||
"notAvailable": "N/A"
|
||||
},
|
||||
"allConfirmations": "Toutes mes confirmations",
|
||||
"about": {
|
||||
@@ -197,6 +220,7 @@
|
||||
"totalDocuments": "Documents totaux",
|
||||
"totalSignatures": "Confirmations totales",
|
||||
"recentActivity": "Activité récente",
|
||||
"backToDashboard": "Retour au tableau de bord",
|
||||
"stats": {
|
||||
"documents": "Documents",
|
||||
"readers": "Lecteurs",
|
||||
@@ -214,9 +238,10 @@
|
||||
"search": "Rechercher...",
|
||||
"searchPlaceholder": "Rechercher par ID, titre ou URL...",
|
||||
"id": "ID du document",
|
||||
"idLabel": "ID du document",
|
||||
"idHelper": "Lettres, chiffres, tirets et underscores uniquement",
|
||||
"idPlaceholder": "ex: politique-securite-2025",
|
||||
"idLabel": "Document",
|
||||
"idHelper": "Accepte les URLs, les chemins de fichiers ou les identifiants simples",
|
||||
"idHelperShort": "Accepte les URLs, chemins ou identifiants",
|
||||
"idPlaceholder": "URL, PATH ou ID du document",
|
||||
"signatures": "Confirmations",
|
||||
"created": "Créé",
|
||||
"createdOn": "Créé le",
|
||||
@@ -228,7 +253,16 @@
|
||||
"manage": "Gérer",
|
||||
"edit": "Modifier",
|
||||
"delete": "Supprimer",
|
||||
"empty": "Aucun document trouvé"
|
||||
"empty": "Aucun document trouvé",
|
||||
"noResults": "Aucun résultat",
|
||||
"noDocuments": "Aucun document",
|
||||
"tryAnotherSearch": "Essayez une autre recherche",
|
||||
"willAppear": "Les documents apparaîtront ici une fois créés",
|
||||
"totalCount": "{count} document au total | {count} documents au total",
|
||||
"pagination": {
|
||||
"page": "Page {current}/{total}",
|
||||
"pageOf": "Page {current} sur {total}"
|
||||
}
|
||||
},
|
||||
"webhooks": {
|
||||
"title": "Webhooks",
|
||||
@@ -282,8 +316,9 @@
|
||||
}
|
||||
},
|
||||
"documentDetail": {
|
||||
"title": "Détails du document",
|
||||
"metadata": "Métadonnées et checksum du document",
|
||||
"title": "Document",
|
||||
"metadata": "📄 Informations sur le document",
|
||||
"metadataDescription": "Métadonnées et checksum du document",
|
||||
"checksum": "Checksum",
|
||||
"algorithm": "Algorithme",
|
||||
"titleLabel": "Titre",
|
||||
@@ -296,27 +331,56 @@
|
||||
"descriptionLabel": "Description",
|
||||
"descriptionPlaceholder": "Description du document...",
|
||||
"signatures": "Confirmations",
|
||||
"back": "Retour à la liste",
|
||||
"back": "Retour",
|
||||
"expectedSigners": "Signataires attendus",
|
||||
"addExpectedSigner": "Ajouter un signataire attendu",
|
||||
"addSigners": "Ajouter des lecteurs attendus",
|
||||
"addButton": "Ajouter",
|
||||
"adding": "Ajout...",
|
||||
"emailsLabel": "Emails (un par ligne)",
|
||||
"emailsPlaceholder": "Marie Dupont <marie.dupont{'@'}example.com>\njean.martin{'@'}example.com\nSophie Bernard <sophie{'@'}example.com>",
|
||||
"emailsHelper": "Formats acceptés : \"Nom Prénom <email{'@'}example.com>\" ou \"email{'@'}example.com\"",
|
||||
"emailLabel": "Email *",
|
||||
"emailPlaceholder": "email{'@'}example.com",
|
||||
"nameLabel": "Nom",
|
||||
"namePlaceholder": "Nom complet",
|
||||
"reader": "Lecteur",
|
||||
"readers": "✓ Lecteurs attendus",
|
||||
"user": "Utilisateur",
|
||||
"status": "Statut",
|
||||
"statusConfirmed": "✓ Confirmé",
|
||||
"statusPending": "⏳ En attente",
|
||||
"confirmedOn": "Confirmé le",
|
||||
"noExpectedSigners": "Aucun lecteur attendu",
|
||||
"noSignatures": "Aucune confirmation",
|
||||
"reminders": "Relances email",
|
||||
"reminders": "📧 Relances par email",
|
||||
"remindersDescription": "Envoyer des rappels aux lecteurs en attente de confirmation",
|
||||
"remindersSent": "Relances envoyées",
|
||||
"toRemind": "À relancer",
|
||||
"lastReminder": "Dernière relance",
|
||||
"sendReminder": "Envoyer une relance",
|
||||
"sending": "Envoi...",
|
||||
"sendReminders": "Envoyer les relances",
|
||||
"sendToAll": "Envoyer à tous les lecteurs en attente ({count})",
|
||||
"sendToSelected": "Envoyer uniquement aux sélectionnés ({count})",
|
||||
"allContacted": "✓ Tous les lecteurs attendus ont été contactés ou ont confirmé",
|
||||
"unexpectedSignatures": "⚠ Confirmations de lecture complémentaires",
|
||||
"unexpectedDescription": "Utilisateurs ayant confirmé mais non présents dans la liste des lecteurs attendus",
|
||||
"createdBy": "Créé par {by} le {date}",
|
||||
"saving": "Enregistrement...",
|
||||
"deleting": "Suppression...",
|
||||
"copiedToClipboard": "Copié dans le presse-papiers",
|
||||
"metadataSaved": "Métadonnées enregistrées avec succès",
|
||||
"signersAdded": "{count} lecteur(s) ajouté(s) avec succès",
|
||||
"signerRemoved": "{email} retiré avec succès",
|
||||
"remindersSentSuccess": "{count} relance(s) envoyée(s) avec succès",
|
||||
"remindersSentPartial": "{sent} relance(s) envoyée(s), {failed} échec(s)",
|
||||
"remindersSentGeneric": "Relances envoyées avec succès",
|
||||
"confirmSendReminders": "Envoyer des relances à {count} lecteur(s) en attente de confirmation ?",
|
||||
"confirmSendRemindersSelected": "Envoyer des relances à {count} lecteur(s) sélectionné(s) ?",
|
||||
"confirmSendRemindersTitle": "📧 Envoyer des relances",
|
||||
"removeSignerTitle": "⚠️ Retirer le lecteur attendu",
|
||||
"removeSignerMessage": "Retirer {email} de la liste des lecteurs attendus ?",
|
||||
"metadataWarning": {
|
||||
"title": "⚠️ Attention : Invalidation des signatures",
|
||||
"description": "Vous êtes sur le point de modifier des informations critiques du document (URL, checksum, algorithme ou description).",
|
||||
@@ -325,32 +389,44 @@
|
||||
"confirm": "Je comprends, continuer",
|
||||
"cancel": "Annuler"
|
||||
},
|
||||
"dangerZone": "Zone de danger",
|
||||
"dangerZone": "⚠️ Zone de danger",
|
||||
"dangerZoneDescription": "Actions irréversibles sur ce document",
|
||||
"deleteDocument": "Supprimer ce document",
|
||||
"deleteDocumentDescription": "Cette action supprimera définitivement le document, ses métadonnées, les lecteurs attendus et toutes les confirmations associées.\nCette action est irréversible.",
|
||||
"deleteWarning": "Cette action est irréversible !",
|
||||
"deleteWillRemove": "Cette action supprimera définitivement :",
|
||||
"deleteWillRemove": "La suppression de ce document entraînera la perte définitive de :",
|
||||
"deleteItem1": "Toutes les métadonnées du document",
|
||||
"deleteItem2": "La liste des lecteurs attendus",
|
||||
"deleteItem3": "Toutes les confirmations cryptographiques",
|
||||
"deleteItem4": "L'historique des relances"
|
||||
"deleteItem4": "L'historique des relances",
|
||||
"deleteConfirmTitle": "⚠️ Confirmer la suppression",
|
||||
"deleteConfirmButton": "Supprimer définitivement",
|
||||
"documentId": "Document ID:"
|
||||
},
|
||||
"documentForm": {
|
||||
"title": "Référence du document",
|
||||
"label": "Référence (URL, chemin ou ID)",
|
||||
"placeholder": "https://example.com/doc.pdf ou /chemin/vers/doc",
|
||||
"submit": "Confirmer",
|
||||
"placeholder": "URL, PATH ou RÉFÉRENCE du document à lire (optionnel)",
|
||||
"submit": "Commencer",
|
||||
"submitting": "Chargement...",
|
||||
"creating": "Création en cours..."
|
||||
}
|
||||
},
|
||||
"embed": {
|
||||
"loading": "Chargement des informations de signature...",
|
||||
"title": "Signature pour",
|
||||
"document": "Document:",
|
||||
"signedBy": "Signé par",
|
||||
"on": "le",
|
||||
"verified": "Vérifié",
|
||||
"viewAll": "Voir toutes les confirmations",
|
||||
"error": "Impossible de charger les informations de signature"
|
||||
"error": "Impossible de charger les informations de signature",
|
||||
"sign": "Signer",
|
||||
"signDocument": "Signer ce document",
|
||||
"noSignatures": "Aucune signature pour ce document",
|
||||
"confirmationsCount": "{count} confirmation(s)",
|
||||
"poweredBy": "Powered by Ackify",
|
||||
"missingDocId": "ID de document manquant"
|
||||
},
|
||||
"notFound": {
|
||||
"title": "Page non trouvée",
|
||||
|
||||
@@ -28,37 +28,37 @@
|
||||
"connectedAs": "Connesso come"
|
||||
},
|
||||
"choice": {
|
||||
"title": "Accedi ad Ackify",
|
||||
"title": "Accesso ad Ackify",
|
||||
"subtitle": "Scegli il tuo metodo di autenticazione preferito",
|
||||
"privacy": "La tua autenticazione è sicura e crittografata"
|
||||
},
|
||||
"oauth": {
|
||||
"title": "Accedi con OAuth",
|
||||
"description": "Usa il tuo account esistente",
|
||||
"title": "Accesso con OAuth",
|
||||
"description": "Usa il tuo account aziendale",
|
||||
"button": "Continua con OAuth",
|
||||
"error": "Accesso OAuth fallito"
|
||||
},
|
||||
"magiclink": {
|
||||
"title": "Accedi tramite email",
|
||||
"title": "Accesso tramite Email",
|
||||
"description": "Ti invieremo un link magico",
|
||||
"email_label": "Indirizzo email",
|
||||
"email_placeholder": "tu{'@'}esempio.com",
|
||||
"button": "Invia link magico",
|
||||
"sent": {
|
||||
"title": "Controlla la tua email",
|
||||
"message": "Ti abbiamo inviato un link magico. Clicca su di esso per accedere.",
|
||||
"message": "Ti abbiamo inviato un link magico. Cliccaci sopra per accedere.",
|
||||
"expire": "Il link scade tra 15 minuti."
|
||||
},
|
||||
"error_invalid_email": "Inserisci un indirizzo email valido",
|
||||
"error_send": "Errore durante l'invio del link magico"
|
||||
"error_send": "Invio del link magico fallito"
|
||||
}
|
||||
},
|
||||
"sign": {
|
||||
"title": "Conferma di Lettura",
|
||||
"subtitle": "Certifica la tua lettura con una conferma crittografica Ed25519",
|
||||
"loading": {
|
||||
"title": "Caricamento documento...",
|
||||
"description": "Attendere mentre prepariamo il documento per la firma."
|
||||
"title": "Caricamento del documento...",
|
||||
"description": "Attendi mentre prepariamo il documento per la firma."
|
||||
},
|
||||
"noDocument": {
|
||||
"title": "Nessun documento specificato",
|
||||
@@ -98,7 +98,7 @@
|
||||
},
|
||||
"howItWorks": {
|
||||
"title": "Come funziona?",
|
||||
"subtitle": "Ackify ti consente di provare crittograficamente di aver letto un documento",
|
||||
"subtitle": "Ackify ti permette di provare crittograficamente di aver letto un documento",
|
||||
"step1": {
|
||||
"title": "1. Accedi al documento",
|
||||
"description": "Aggiungi {code} all'indirizzo di questa pagina"
|
||||
@@ -109,7 +109,7 @@
|
||||
},
|
||||
"step3": {
|
||||
"title": "3. Conferma la lettura",
|
||||
"description": "La tua conferma viene registrata con una firma Ed25519"
|
||||
"description": "La tua conferma è registrata con una firma Ed25519"
|
||||
},
|
||||
"features": {
|
||||
"crypto": {
|
||||
@@ -122,39 +122,59 @@
|
||||
},
|
||||
"timestamp": {
|
||||
"title": "Timestamp preciso",
|
||||
"description": "Ogni conferma è timestampata e concatenata per garantire l'integrità"
|
||||
"description": "Ogni conferma è datata e concatenata per garantire l'integrità"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"signButton": {
|
||||
"confirm": "Conferma la mia lettura",
|
||||
"confirmAction": "Conferma la lettura",
|
||||
"alreadySigned": "Già confermato",
|
||||
"confirmed": "Lettura confermata",
|
||||
"mustLogin": "Accedi per confermare",
|
||||
"signing": "Conferma in corso...",
|
||||
"verified": "Verificato",
|
||||
"on": "Il",
|
||||
"error": {
|
||||
"title": "Conferma fallita",
|
||||
"notAuthenticated": "Devi essere connesso per confermare un documento.",
|
||||
"alreadySigned": "Hai già confermato questo documento.",
|
||||
"generic": "Si è verificato un errore durante la conferma. Riprova."
|
||||
"generic": "Si è verificato un errore durante la conferma. Riprova.",
|
||||
"missingDocId": "ID documento mancante",
|
||||
"authFailed": "Impossibile avviare l'autenticazione"
|
||||
}
|
||||
},
|
||||
"signatureList": {
|
||||
"loading": "Caricamento conferme...",
|
||||
"loading": "Caricamento delle conferme...",
|
||||
"email": "Email",
|
||||
"date": "Data",
|
||||
"signature": "Firma",
|
||||
"confirmation": "Conferma:",
|
||||
"hash": "Hash",
|
||||
"nonce": "Nonce",
|
||||
"verificationStatus": "Stato di verifica",
|
||||
"verified": "Verificato",
|
||||
"confirmed": "Confermato",
|
||||
"notVerified": "Non verificato",
|
||||
"showDetails": "Mostra dettagli",
|
||||
"hideDetails": "Nascondi dettagli",
|
||||
"viewDetails": "Vedi dettagli",
|
||||
"verificationDetails": "Dettagli di verifica",
|
||||
"copy": "Copia",
|
||||
"copied": "Copiato!",
|
||||
"previousHash": "Hash precedente"
|
||||
"previousHash": "Hash precedente:",
|
||||
"empty": "Nessuna conferma trovata",
|
||||
"documentDeleted": "Documento eliminato",
|
||||
"fields": {
|
||||
"id": "ID:",
|
||||
"document": "Documento:",
|
||||
"reader": "Lettore:",
|
||||
"date": "Data:",
|
||||
"source": "Origine:",
|
||||
"nonce": "Nonce:",
|
||||
"hash": "Hash:"
|
||||
}
|
||||
},
|
||||
"signatures": {
|
||||
"title": "Le mie conferme di lettura",
|
||||
@@ -162,61 +182,66 @@
|
||||
"loading": "Caricamento delle tue conferme...",
|
||||
"empty": {
|
||||
"title": "Nessuna conferma per il momento",
|
||||
"description": "Non hai ancora confermato alcun documento. Inizia confermando un documento per vederlo apparire qui."
|
||||
"description": "Non hai ancora confermato nessun documento. Inizia confermando un documento per vederlo apparire qui.",
|
||||
"alternative": "Non hai ancora confermato la lettura di documenti"
|
||||
},
|
||||
"count": "{count} conferma | {count} conferme",
|
||||
"results": "{count} risultato | {count} risultati",
|
||||
"document": "Documento",
|
||||
"signedAt": "Confermato il",
|
||||
"viewDetails": "Vedi dettagli",
|
||||
"deletedDocuments": "Documenti eliminati",
|
||||
"stats": {
|
||||
"total": "Totale",
|
||||
"totalConfirmations": "Conferme totali",
|
||||
"unique": "Unici",
|
||||
"uniqueDocuments": "Documenti unici",
|
||||
"last": "Ultimo",
|
||||
"lastConfirmation": "Ultima conferma"
|
||||
"lastConfirmation": "Ultima conferma",
|
||||
"notAvailable": "N/D"
|
||||
},
|
||||
"allConfirmations": "Tutte le mie conferme",
|
||||
"about": {
|
||||
"title": "Informazioni sulle conferme",
|
||||
"description": "Ogni conferma è registrata crittograficamente con Ed25519 e concatenata per garantire l'integrità. Le conferme sono non ripudiabili e timestampate con precisione."
|
||||
"description": "Ogni conferma viene registrata crittograficamente con Ed25519 e concatenata per garantire l'integrità. Le conferme sono irrevocabili e timestampate in modo preciso."
|
||||
},
|
||||
"search": "Cerca...",
|
||||
"error": {
|
||||
"title": "Errore nel caricamento delle conferme",
|
||||
"title": "Errore di caricamento delle conferme",
|
||||
"description": "Impossibile caricare le tue conferme. Riprova."
|
||||
}
|
||||
},
|
||||
"admin": {
|
||||
"title": "Amministrazione",
|
||||
"subtitle": "Gestisci documenti e lettori attesi",
|
||||
"subtitle": "Gestire documenti e lettori previsti",
|
||||
"loading": "Caricamento dati...",
|
||||
"dashboard": {
|
||||
"title": "Dashboard",
|
||||
"title": "Pannello di controllo",
|
||||
"totalDocuments": "Documenti totali",
|
||||
"totalSignatures": "Conferme totali",
|
||||
"recentActivity": "Attività recente",
|
||||
"backToDashboard": "Torna al pannello di controllo",
|
||||
"stats": {
|
||||
"documents": "Documenti",
|
||||
"readers": "Lettori",
|
||||
"active": "Attivi",
|
||||
"expected": "Attesi",
|
||||
"expected": "Previsti",
|
||||
"signed": "Firmati",
|
||||
"pending": "In sospeso",
|
||||
"pending": "In attesa",
|
||||
"completion": "Completamento"
|
||||
}
|
||||
},
|
||||
"documents": {
|
||||
"title": "Tutti i documenti",
|
||||
"new": "Crea nuovo documento",
|
||||
"newDescription": "Prepara il riferimento di un documento per tracciare le conferme di lettura",
|
||||
"newDescription": "Preparare un riferimento documento per tracciare le conferme di lettura",
|
||||
"search": "Cerca...",
|
||||
"searchPlaceholder": "Cerca per ID, titolo o URL...",
|
||||
"id": "ID del documento",
|
||||
"idLabel": "ID del documento",
|
||||
"idHelper": "Solo lettere, numeri, trattini e underscore",
|
||||
"idPlaceholder": "es: politica-sicurezza-2025",
|
||||
"id": "ID documento",
|
||||
"idLabel": "Documento",
|
||||
"idHelper": "Accetta URL, percorsi di file o identificatori semplici",
|
||||
"idHelperShort": "Accetta URL, percorsi o identificatori",
|
||||
"idPlaceholder": "URL, PATH o ID del documento",
|
||||
"signatures": "Conferme",
|
||||
"created": "Creato",
|
||||
"createdOn": "Creato il",
|
||||
@@ -224,82 +249,187 @@
|
||||
"url": "URL",
|
||||
"document": "Documento",
|
||||
"actions": "Azioni",
|
||||
"view": "Visualizza",
|
||||
"view": "Vedi",
|
||||
"manage": "Gestisci",
|
||||
"edit": "Modifica",
|
||||
"delete": "Elimina",
|
||||
"empty": "Nessun documento trovato"
|
||||
"empty": "Nessun documento trovato",
|
||||
"noResults": "Nessun risultato",
|
||||
"noDocuments": "Nessun documento",
|
||||
"tryAnotherSearch": "Prova un'altra ricerca",
|
||||
"willAppear": "I documenti appariranno qui una volta creati",
|
||||
"totalCount": "{count} documento totale | {count} documenti totali",
|
||||
"pagination": {
|
||||
"page": "Pagina {current}/{total}",
|
||||
"pageOf": "Pagina {current} di {total}"
|
||||
}
|
||||
},
|
||||
"webhooks": {
|
||||
"title": "Webhook",
|
||||
"subtitle": "Configurare le notifiche verso applicazioni terze",
|
||||
"manage": "Gestisci webhook",
|
||||
"new": "Nuovo webhook",
|
||||
"edit": "Modifica",
|
||||
"delete": "Elimina",
|
||||
"enable": "Attiva",
|
||||
"disable": "Disattiva",
|
||||
"status": {
|
||||
"enabled": "Attivo",
|
||||
"disabled": "Inattivo"
|
||||
},
|
||||
"confirmDelete": "Eliminare questo webhook?",
|
||||
"empty": "Nessun webhook",
|
||||
"listTitle": "Elenco webhook",
|
||||
"listSubtitle": "Un webhook può ascoltare più eventi",
|
||||
"columns": {
|
||||
"title": "Nome",
|
||||
"url": "URL",
|
||||
"events": "Eventi",
|
||||
"status": "Stato",
|
||||
"actions": "Azioni"
|
||||
},
|
||||
"form": {
|
||||
"title": "Parametri del webhook",
|
||||
"subtitle": "Inserisci l'URL, il segreto e gli eventi",
|
||||
"nameLabel": "Nome del webhook",
|
||||
"namePlaceholder": "Webhook CRM",
|
||||
"urlLabel": "URL di destinazione",
|
||||
"secretLabel": "Segreto HMAC",
|
||||
"secretPlaceholder": "Inserisci un segreto (richiesto)",
|
||||
"secretKeep": "Lascia vuoto per mantenere",
|
||||
"eventsLabel": "Eventi da ascoltare",
|
||||
"descriptionLabel": "Descrizione (opzionale)",
|
||||
"descriptionPlaceholder": "Nota interna…",
|
||||
"validation": "Completa il nome, l'URL, il segreto e almeno un evento."
|
||||
},
|
||||
"editTitle": "Modifica il webhook",
|
||||
"events": {
|
||||
"documentCreated": "Documento creato",
|
||||
"signatureCreated": "Firma creata",
|
||||
"documentCompleted": "Documento completato",
|
||||
"reminderSent": "Promemoria inviato",
|
||||
"reminderFailed": "Promemoria fallito"
|
||||
},
|
||||
"eventsMap": {
|
||||
"document.created": "Documento creato",
|
||||
"signature.created": "Firma creata",
|
||||
"document.completed": "Documento completato",
|
||||
"reminder.sent": "Promemoria inviato",
|
||||
"reminder.failed": "Promemoria fallito"
|
||||
}
|
||||
},
|
||||
"documentDetail": {
|
||||
"title": "Dettagli del documento",
|
||||
"metadata": "Metadati e checksum del documento",
|
||||
"title": "Documento",
|
||||
"metadata": "📄 Informazioni sul documento",
|
||||
"metadataDescription": "Metadati e checksum del documento",
|
||||
"checksum": "Checksum",
|
||||
"algorithm": "Algoritmo",
|
||||
"titleLabel": "Titolo",
|
||||
"titlePlaceholder": "Politica di Sicurezza 2025",
|
||||
"titlePlaceholder": "Politica di sicurezza 2025",
|
||||
"urlLabel": "URL",
|
||||
"urlPlaceholder": "https://example.com/doc.pdf",
|
||||
"urlPlaceholder": "https://esempio.com/doc.pdf",
|
||||
"checksumLabel": "Checksum",
|
||||
"checksumPlaceholder": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"algorithmLabel": "Algoritmo",
|
||||
"descriptionLabel": "Descrizione",
|
||||
"descriptionPlaceholder": "Descrizione del documento...",
|
||||
"signatures": "Conferme",
|
||||
"back": "Torna all'elenco",
|
||||
"expectedSigners": "Firmatari attesi",
|
||||
"addExpectedSigner": "Aggiungi firmatario atteso",
|
||||
"addSigners": "Aggiungi lettori attesi",
|
||||
"back": "Indietro",
|
||||
"expectedSigners": "Firmatari previsti",
|
||||
"addExpectedSigner": "Aggiungi firmatario previsto",
|
||||
"addSigners": "Aggiungi lettori previsti",
|
||||
"addButton": "Aggiungi",
|
||||
"adding": "Aggiunta...",
|
||||
"emailsLabel": "Email (una per riga)",
|
||||
"emailsPlaceholder": "Maria Rossi <maria.rossi{'@'}example.com>\ngiovanni.bianchi{'@'}example.com\nSofia Verdi <sofia{'@'}example.com>",
|
||||
"emailsPlaceholder": "Maria Rossi <maria.rossi{'@'}esempio.com>\ngiovanni.bianchi{'@'}esempio.com>\nSofia Verdi <sofia{'@'}esempio.com>",
|
||||
"emailsHelper": "Formati accettati: \"Nome Cognome <email{'@'}esempio.com>\" o \"email{'@'}esempio.com\"",
|
||||
"emailLabel": "Email *",
|
||||
"emailPlaceholder": "email{'@'}example.com",
|
||||
"emailPlaceholder": "email{'@'}esempio.com",
|
||||
"nameLabel": "Nome",
|
||||
"namePlaceholder": "Nome completo",
|
||||
"reader": "Lettore",
|
||||
"readers": "✓ Lettori previsti",
|
||||
"user": "Utente",
|
||||
"status": "Stato",
|
||||
"statusConfirmed": "✓ Confermato",
|
||||
"statusPending": "⏳ In attesa",
|
||||
"confirmedOn": "Confermato il",
|
||||
"noExpectedSigners": "Nessun lettore atteso",
|
||||
"noExpectedSigners": "Nessun lettore previsto",
|
||||
"noSignatures": "Nessuna conferma",
|
||||
"reminders": "Promemoria email",
|
||||
"reminders": "📧 Solleciti via email",
|
||||
"remindersDescription": "Inviare promemoria ai lettori in attesa di conferma",
|
||||
"remindersSent": "Promemoria inviati",
|
||||
"toRemind": "Da ricordare",
|
||||
"lastReminder": "Ultimo promemoria",
|
||||
"sendReminder": "Invia promemoria",
|
||||
"sending": "Invio...",
|
||||
"sendReminders": "Invia solleciti",
|
||||
"sendToAll": "Invia a tutti i lettori in attesa ({count})",
|
||||
"sendToSelected": "Invia solo ai selezionati ({count})",
|
||||
"allContacted": "✓ Tutti i lettori previsti sono stati contattati o hanno confermato",
|
||||
"unexpectedSignatures": "⚠ Conferme di lettura aggiuntive",
|
||||
"unexpectedDescription": "Utenti che hanno confermato ma non presenti nell'elenco dei lettori previsti",
|
||||
"createdBy": "Creato da {by} il {date}",
|
||||
"saving": "Salvataggio...",
|
||||
"deleting": "Eliminazione...",
|
||||
"copiedToClipboard": "Copiato negli appunti",
|
||||
"metadataSaved": "Metadati salvati con successo",
|
||||
"signersAdded": "{count} lettore/i aggiunto/i con successo",
|
||||
"signerRemoved": "{email} rimosso con successo",
|
||||
"remindersSentSuccess": "{count} sollecito/i inviato/i con successo",
|
||||
"remindersSentPartial": "{sent} sollecito/i inviato/i, {failed} fallito/i",
|
||||
"remindersSentGeneric": "Solleciti inviati con successo",
|
||||
"confirmSendReminders": "Inviare solleciti a {count} lettore/i in attesa di conferma?",
|
||||
"confirmSendRemindersSelected": "Inviare solleciti a {count} lettore/i selezionato/i?",
|
||||
"confirmSendRemindersTitle": "📧 Invia solleciti",
|
||||
"removeSignerTitle": "⚠️ Rimuovi lettore previsto",
|
||||
"removeSignerMessage": "Rimuovere {email} dall'elenco dei lettori previsti?",
|
||||
"metadataWarning": {
|
||||
"title": "⚠️ Attenzione: Invalidazione delle firme",
|
||||
"description": "Stai per modificare informazioni critiche del documento (URL, checksum, algoritmo o descrizione).",
|
||||
"warning": "Questa modifica comporterà l'invalidazione di tutte le firme esistenti, poiché sono legate crittograficamente al contenuto attuale del documento.",
|
||||
"warning": "Questa modifica comporterà l'invalidazione di tutte le firme esistenti, poiché sono collegate crittograficamente al contenuto attuale del documento.",
|
||||
"currentSignatures": "Firme attuali che saranno invalidate:",
|
||||
"confirm": "Capisco, continua",
|
||||
"cancel": "Annulla"
|
||||
},
|
||||
"dangerZone": "Zona pericolosa",
|
||||
"dangerZone": "⚠️ Zona di pericolo",
|
||||
"dangerZoneDescription": "Azioni irreversibili su questo documento",
|
||||
"deleteDocument": "Elimina questo documento",
|
||||
"deleteDocumentDescription": "Questa azione eliminerà definitivamente il documento, i suoi metadati, i lettori previsti e tutte le conferme associate.\nQuesta azione è irreversibile.",
|
||||
"deleteWarning": "Questa azione è irreversibile!",
|
||||
"deleteWillRemove": "Questa azione rimuoverà definitivamente:",
|
||||
"deleteWillRemove": "L'eliminazione di questo documento comporterà la perdita definitiva di:",
|
||||
"deleteItem1": "Tutti i metadati del documento",
|
||||
"deleteItem2": "L'elenco dei lettori attesi",
|
||||
"deleteItem2": "L'elenco dei lettori previsti",
|
||||
"deleteItem3": "Tutte le conferme crittografiche",
|
||||
"deleteItem4": "La cronologia dei promemoria"
|
||||
"deleteItem4": "La cronologia dei promemoria",
|
||||
"deleteConfirmTitle": "⚠️ Conferma eliminazione",
|
||||
"deleteConfirmButton": "Elimina definitivamente",
|
||||
"documentId": "ID Documento:"
|
||||
},
|
||||
"documentForm": {
|
||||
"title": "Riferimento del documento",
|
||||
"label": "Riferimento (URL, percorso o ID)",
|
||||
"placeholder": "https://example.com/doc.pdf o /percorso/al/doc",
|
||||
"submit": "Conferma",
|
||||
"placeholder": "URL, PATH o RIFERIMENTO del documento da leggere (opzionale)",
|
||||
"submit": "Inizia",
|
||||
"submitting": "Caricamento...",
|
||||
"creating": "Creazione in corso..."
|
||||
}
|
||||
},
|
||||
"embed": {
|
||||
"loading": "Caricamento informazioni firma...",
|
||||
"loading": "Caricamento delle informazioni di firma...",
|
||||
"title": "Firma per",
|
||||
"document": "Documento:",
|
||||
"signedBy": "Firmato da",
|
||||
"on": "il",
|
||||
"verified": "Verificato",
|
||||
"viewAll": "Vedi tutte le conferme",
|
||||
"error": "Impossibile caricare le informazioni della firma"
|
||||
"error": "Impossibile caricare le informazioni di firma",
|
||||
"sign": "Firma",
|
||||
"signDocument": "Firma questo documento",
|
||||
"noSignatures": "Nessuna firma per questo documento",
|
||||
"confirmationsCount": "{count} conferma/e",
|
||||
"poweredBy": "Powered by Ackify",
|
||||
"missingDocId": "ID documento mancante"
|
||||
},
|
||||
"notFound": {
|
||||
"title": "Pagina non trovata",
|
||||
@@ -319,9 +449,9 @@
|
||||
},
|
||||
"legal": {
|
||||
"title": "Legale",
|
||||
"terms": "Termini di utilizzo",
|
||||
"privacy": "Politica sulla privacy",
|
||||
"contact": "Contatto"
|
||||
"terms": "Condizioni d'uso",
|
||||
"privacy": "Informativa sulla privacy",
|
||||
"contact": "Contatti"
|
||||
},
|
||||
"copyright": "Tutti i diritti riservati.",
|
||||
"license": "Licenza AGPL-3.0-or-later",
|
||||
@@ -329,8 +459,8 @@
|
||||
"by": "da",
|
||||
"links": {
|
||||
"privacy": "Privacy",
|
||||
"terms": "Termini",
|
||||
"contact": "Contatto"
|
||||
"terms": "Condizioni",
|
||||
"contact": "Contatti"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
@@ -355,7 +485,7 @@
|
||||
"actions": "Azioni",
|
||||
"details": "Dettagli",
|
||||
"back": "Indietro",
|
||||
"next": "Avanti",
|
||||
"next": "Successivo",
|
||||
"previous": "Precedente",
|
||||
"skipToContent": "Vai al contenuto principale"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<div v-if="documentData.signatures.length > 0">
|
||||
<div class="mb-6">
|
||||
<h2 class="text-xl font-bold text-foreground mb-2">
|
||||
Document: {{ documentData.title }}
|
||||
{{ t('embed.document') }} {{ documentData.title }}
|
||||
</h2>
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div class="flex items-center space-x-4 text-sm text-muted-foreground">
|
||||
@@ -25,7 +25,7 @@
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
{{ documentData.signatures.length }} confirmation(s)
|
||||
{{ t('embed.confirmationsCount', { count: documentData.signatures.length }) }}
|
||||
</span>
|
||||
<span v-if="documentData.metadata?.title">{{ documentData.metadata.title }}</span>
|
||||
</div>
|
||||
@@ -38,7 +38,7 @@
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/>
|
||||
</svg>
|
||||
Signer
|
||||
{{ t('embed.sign') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -66,7 +66,7 @@
|
||||
<svg class="w-16 h-16 mx-auto mb-4 text-muted-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
||||
</svg>
|
||||
<p class="text-sm text-muted-foreground mb-4">Aucune signature pour ce document</p>
|
||||
<p class="text-sm text-muted-foreground mb-4">{{ t('embed.noSignatures') }}</p>
|
||||
<a
|
||||
:href="signUrl"
|
||||
target="_blank"
|
||||
@@ -75,7 +75,7 @@
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/>
|
||||
</svg>
|
||||
Signer ce document
|
||||
{{ t('embed.signDocument') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
target="_blank"
|
||||
class="text-xs text-muted-foreground hover:text-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded"
|
||||
>
|
||||
Powered by Ackify
|
||||
{{ t('embed.poweredBy') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -96,12 +96,14 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { usePageTitle } from '@/composables/usePageTitle'
|
||||
import { documentService } from '@/services/documents'
|
||||
import http, { extractError } from '@/services/http'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { t } = useI18n()
|
||||
usePageTitle('embed.title')
|
||||
|
||||
// State
|
||||
@@ -130,7 +132,7 @@ function formatDateCompact(dateString: string): string {
|
||||
|
||||
async function loadDocument() {
|
||||
if (!docRef.value) {
|
||||
error.value = 'ID de document manquant'
|
||||
error.value = t('embed.missingDocId')
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ onMounted(() => {
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center gap-1 px-3 py-3 rounded-lg bg-blue-500/10 text-blue-600 dark:text-blue-400">
|
||||
<Clock :size="18" />
|
||||
<span class="text-sm font-bold">{{ lastSignatureDate || 'N/A' }}</span>
|
||||
<span class="text-sm font-bold">{{ lastSignatureDate || t('signatures.stats.notAvailable') }}</span>
|
||||
<span class="text-xs whitespace-nowrap">{{ t('signatures.stats.last') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -155,7 +155,7 @@ onMounted(() => {
|
||||
<div class="flex-1">
|
||||
<p class="text-sm font-medium text-muted-foreground">{{ t('signatures.stats.lastConfirmation') }}</p>
|
||||
<p class="text-lg font-semibold text-foreground">
|
||||
{{ lastSignatureDate || 'N/A' }}
|
||||
{{ lastSignatureDate || t('signatures.stats.notAvailable') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -212,7 +212,7 @@ onMounted(() => {
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||
</svg>
|
||||
<p class="mt-2 text-muted-foreground">Vous n'avez pas encore confirmé la lecture de documents</p>
|
||||
<p class="mt-2 text-muted-foreground">{{ t('signatures.empty.alternative') }}</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="space-y-4">
|
||||
@@ -231,7 +231,7 @@ onMounted(() => {
|
||||
<div v-if="activeSignatures.length > 0 && deletedSignatures.length > 0" class="py-4">
|
||||
<hr class="border-border" />
|
||||
<p class="text-center text-sm text-muted-foreground mt-4 mb-2">
|
||||
Documents supprimés
|
||||
{{ t('signatures.deletedDocuments') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { usePageTitle } from '@/composables/usePageTitle'
|
||||
import { listDocuments, type Document } from '@/services/admin'
|
||||
import { documentService } from '@/services/documents'
|
||||
import { extractError } from '@/services/http'
|
||||
import { FileText, Users, CheckCircle, ExternalLink, Settings, Loader2, Plus, Search, Webhook } from 'lucide-vue-next'
|
||||
import Card from '@/components/ui/Card.vue'
|
||||
@@ -102,8 +103,12 @@ async function createDocument() {
|
||||
try {
|
||||
creating.value = true
|
||||
error.value = ''
|
||||
// Navigate to document detail page (will be created next)
|
||||
await router.push({ name: 'admin-document', params: { docId: newDocId.value.trim() } })
|
||||
|
||||
// Use findOrCreateDocument to handle URL, path, or ID
|
||||
const response = await documentService.findOrCreateDocument(newDocId.value.trim())
|
||||
|
||||
// Navigate to document detail page with the returned docId
|
||||
await router.push({ name: 'admin-document', params: { docId: response.docId } })
|
||||
} catch (err) {
|
||||
error.value = extractError(err)
|
||||
console.error('Failed to create document:', err)
|
||||
@@ -175,7 +180,6 @@ onMounted(() => {
|
||||
id="newDocId"
|
||||
type="text"
|
||||
required
|
||||
pattern="[a-zA-Z0-9\-_]+"
|
||||
:placeholder="t('admin.documents.idPlaceholder')"
|
||||
class="w-full"
|
||||
/>
|
||||
@@ -203,7 +207,6 @@ onMounted(() => {
|
||||
id="newDocIdMobile"
|
||||
type="text"
|
||||
required
|
||||
pattern="[a-zA-Z0-9\-_]+"
|
||||
:placeholder="t('admin.documents.idPlaceholder')"
|
||||
class="flex-1"
|
||||
/>
|
||||
@@ -213,7 +216,7 @@ onMounted(() => {
|
||||
</Button>
|
||||
</div>
|
||||
<p class="text-xs text-muted-foreground">
|
||||
{{ t('admin.documents.idHelper') }}
|
||||
{{ t('admin.documents.idHelperShort') }}
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
@@ -365,7 +368,7 @@ onMounted(() => {
|
||||
>
|
||||
<Button variant="ghost" size="sm">
|
||||
<Settings :size="16" class="mr-1" />
|
||||
Gérer
|
||||
{{ t('admin.documents.manage') }}
|
||||
</Button>
|
||||
</router-link>
|
||||
</TableCell>
|
||||
@@ -417,7 +420,7 @@ onMounted(() => {
|
||||
>
|
||||
<Button variant="outline" size="sm" class="w-full">
|
||||
<Settings :size="16" class="mr-2" />
|
||||
Gérer
|
||||
{{ t('admin.documents.manage') }}
|
||||
</Button>
|
||||
</router-link>
|
||||
</div>
|
||||
@@ -431,10 +434,10 @@ onMounted(() => {
|
||||
<FileText :size="28" class="text-muted-foreground" />
|
||||
</div>
|
||||
<h3 class="mb-2 text-lg font-semibold text-foreground">
|
||||
{{ searchQuery ? 'Aucun résultat' : 'Aucun document' }}
|
||||
{{ searchQuery ? t('admin.documents.noResults') : t('admin.documents.noDocuments') }}
|
||||
</h3>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
{{ searchQuery ? 'Essayez une autre recherche' : 'Les documents apparaîtront ici une fois créés' }}
|
||||
{{ searchQuery ? t('admin.documents.tryAnotherSearch') : t('admin.documents.willAppear') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -448,10 +451,10 @@ onMounted(() => {
|
||||
:disabled="currentPage === 1"
|
||||
@click="prevPage"
|
||||
>
|
||||
Précédent
|
||||
{{ t('common.previous') }}
|
||||
</Button>
|
||||
<span class="text-sm text-muted-foreground">
|
||||
Page {{ currentPage }}/{{ totalPages }}
|
||||
{{ t('admin.documents.pagination.page', { current: currentPage, total: totalPages }) }}
|
||||
</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -459,14 +462,14 @@ onMounted(() => {
|
||||
:disabled="currentPage >= totalPages"
|
||||
@click="nextPage"
|
||||
>
|
||||
Suivant
|
||||
{{ t('common.next') }}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<!-- Desktop Pagination -->
|
||||
<div class="hidden md:flex items-center justify-between w-full">
|
||||
<div class="text-sm text-muted-foreground">
|
||||
{{ totalDocuments }} document{{ totalDocuments > 1 ? 's' : '' }} au total
|
||||
{{ t('admin.documents.totalCount', totalDocuments) }}
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Button
|
||||
@@ -475,10 +478,10 @@ onMounted(() => {
|
||||
:disabled="currentPage === 1"
|
||||
@click="prevPage"
|
||||
>
|
||||
Précédent
|
||||
{{ t('common.previous') }}
|
||||
</Button>
|
||||
<span class="text-sm text-muted-foreground">
|
||||
Page {{ currentPage }} sur {{ totalPages }}
|
||||
{{ t('admin.documents.pagination.pageOf', { current: currentPage, total: totalPages }) }}
|
||||
</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -486,7 +489,7 @@ onMounted(() => {
|
||||
:disabled="currentPage >= totalPages"
|
||||
@click="nextPage"
|
||||
>
|
||||
Suivant
|
||||
{{ t('common.next') }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -177,7 +177,7 @@ async function saveMetadata() {
|
||||
success.value = ''
|
||||
showMetadataWarningModal.value = false
|
||||
await updateDocumentMetadata(docId.value, metadataForm.value)
|
||||
success.value = 'Métadonnées enregistrées avec succès'
|
||||
success.value = t('admin.documentDetail.metadataSaved')
|
||||
await loadDocumentStatus()
|
||||
setTimeout(() => (success.value = ''), 3000)
|
||||
} catch (err) {
|
||||
@@ -216,7 +216,7 @@ async function addSigners() {
|
||||
|
||||
showAddSignersModal.value = false
|
||||
signersEmails.value = ''
|
||||
success.value = `${addedCount} lecteur(s) ajouté(s) avec succès`
|
||||
success.value = t('admin.documentDetail.signersAdded', { count: addedCount })
|
||||
await loadDocumentStatus()
|
||||
setTimeout(() => (success.value = ''), 3000)
|
||||
} catch (err) {
|
||||
@@ -240,7 +240,7 @@ async function removeSigner() {
|
||||
error.value = ''
|
||||
success.value = ''
|
||||
await removeExpectedSigner(docId.value, email)
|
||||
success.value = `${email} retiré avec succès`
|
||||
success.value = t('admin.documentDetail.signerRemoved', { email })
|
||||
showRemoveSignerModal.value = false
|
||||
signerToRemove.value = ''
|
||||
await loadDocumentStatus()
|
||||
@@ -259,8 +259,8 @@ function cancelRemoveSigner() {
|
||||
function confirmSendReminders() {
|
||||
remindersMessage.value =
|
||||
sendMode.value === 'all'
|
||||
? `Envoyer des relances à ${reminderStats.value?.pendingCount || 0} lecteur(s) en attente de confirmation ?`
|
||||
: `Envoyer des relances à ${selectedEmails.value.length} lecteur(s) sélectionné(s) ?`
|
||||
? t('admin.documentDetail.confirmSendReminders', { count: reminderStats.value?.pendingCount || 0 })
|
||||
: t('admin.documentDetail.confirmSendRemindersSelected', { count: selectedEmails.value.length })
|
||||
showSendRemindersModal.value = true
|
||||
}
|
||||
|
||||
@@ -288,12 +288,12 @@ async function sendRemindersAction() {
|
||||
if (response.data.result) {
|
||||
const result = response.data.result
|
||||
if (result.failed > 0) {
|
||||
success.value = `${result.successfullySent} relance(s) envoyée(s), ${result.failed} échec(s)`
|
||||
success.value = t('admin.documentDetail.remindersSentPartial', { sent: result.successfullySent, failed: result.failed })
|
||||
} else {
|
||||
success.value = `${result.successfullySent} relance(s) envoyée(s) avec succès`
|
||||
success.value = t('admin.documentDetail.remindersSentSuccess', { count: result.successfullySent })
|
||||
}
|
||||
} else {
|
||||
success.value = 'Relances envoyées avec succès'
|
||||
success.value = t('admin.documentDetail.remindersSentGeneric')
|
||||
}
|
||||
|
||||
await loadDocumentStatus()
|
||||
@@ -312,7 +312,7 @@ function cancelSendReminders() {
|
||||
|
||||
function copyToClipboard(text: string) {
|
||||
navigator.clipboard.writeText(text)
|
||||
success.value = 'Copié dans le presse-papiers'
|
||||
success.value = t('admin.documentDetail.copiedToClipboard')
|
||||
setTimeout(() => (success.value = ''), 2000)
|
||||
}
|
||||
|
||||
@@ -370,16 +370,16 @@ onMounted(() => {
|
||||
<!-- Header -->
|
||||
<div class="mb-8">
|
||||
<div class="flex items-center space-x-3 mb-2">
|
||||
<Button variant="ghost" size="icon" @click="router.push('/admin')" aria-label="Retour">
|
||||
<Button variant="ghost" size="icon" @click="router.push('/admin')" :aria-label="t('admin.documentDetail.back')">
|
||||
<ArrowLeft :size="20" />
|
||||
</Button>
|
||||
<h1 class="text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
|
||||
Document {{ docId }}
|
||||
{{ t('admin.documentDetail.title') }} {{ docId }}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="flex items-center gap-3 ml-14">
|
||||
<p class="text-sm text-muted-foreground font-mono">{{ shareLink }}</p>
|
||||
<Button @click="copyToClipboard(shareLink)" variant="ghost" size="icon" aria-label="Copier le lien">
|
||||
<Button @click="copyToClipboard(shareLink)" variant="ghost" size="icon" :aria-label="t('signatureList.copy')">
|
||||
<Copy :size="16" />
|
||||
</Button>
|
||||
</div>
|
||||
@@ -397,7 +397,7 @@ onMounted(() => {
|
||||
<!-- Loading -->
|
||||
<div v-if="loading" class="flex flex-col items-center justify-center py-24">
|
||||
<Loader2 :size="48" class="animate-spin text-primary" />
|
||||
<p class="mt-4 text-muted-foreground">Chargement...</p>
|
||||
<p class="mt-4 text-muted-foreground">{{ t('common.loading') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
@@ -411,7 +411,7 @@ onMounted(() => {
|
||||
<Users :size="24" class="text-blue-600" />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-medium text-muted-foreground">Attendus</p>
|
||||
<p class="text-sm font-medium text-muted-foreground">{{ t('admin.dashboard.stats.expected') }}</p>
|
||||
<p class="text-2xl font-bold text-foreground">{{ stats.expectedCount }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -425,7 +425,7 @@ onMounted(() => {
|
||||
<CheckCircle :size="24" class="text-green-600" />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-medium text-muted-foreground">Confirmés</p>
|
||||
<p class="text-sm font-medium text-muted-foreground">{{ t('admin.dashboard.stats.signed') }}</p>
|
||||
<p class="text-2xl font-bold text-foreground">{{ stats.signedCount }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -439,7 +439,7 @@ onMounted(() => {
|
||||
<Clock :size="24" class="text-orange-600" />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-medium text-muted-foreground">En attente</p>
|
||||
<p class="text-sm font-medium text-muted-foreground">{{ t('admin.dashboard.stats.pending') }}</p>
|
||||
<p class="text-2xl font-bold text-foreground">{{ stats.pendingCount }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -453,7 +453,7 @@ onMounted(() => {
|
||||
<Shield :size="24" class="text-purple-600" />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-medium text-muted-foreground">Complétion</p>
|
||||
<p class="text-sm font-medium text-muted-foreground">{{ t('admin.dashboard.stats.completion') }}</p>
|
||||
<p class="text-2xl font-bold text-foreground">{{ Math.round(stats.completionRate) }}%</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -465,8 +465,8 @@ onMounted(() => {
|
||||
<Card class="clay-card">
|
||||
<CardHeader>
|
||||
<div>
|
||||
<CardTitle>📄 Informations sur le document</CardTitle>
|
||||
<CardDescription>Métadonnées et checksum du document</CardDescription>
|
||||
<CardTitle>{{ t('admin.documentDetail.metadata') }}</CardTitle>
|
||||
<CardDescription>{{ t('admin.documentDetail.metadataDescription') }}</CardDescription>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
@@ -474,23 +474,23 @@ onMounted(() => {
|
||||
<!-- Titre et URL côte à côte -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-2">Titre</label>
|
||||
<Input v-model="metadataForm.title" placeholder="Politique de sécurité 2025" />
|
||||
<label class="block text-sm font-medium mb-2">{{ t('admin.documentDetail.titleLabel') }}</label>
|
||||
<Input v-model="metadataForm.title" :placeholder="t('admin.documentDetail.titlePlaceholder')" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-2">URL</label>
|
||||
<Input v-model="metadataForm.url" type="url" placeholder="https://example.com/doc.pdf" />
|
||||
<label class="block text-sm font-medium mb-2">{{ t('admin.documentDetail.urlLabel') }}</label>
|
||||
<Input v-model="metadataForm.url" type="url" :placeholder="t('admin.documentDetail.urlPlaceholder')" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Checksum et Algorithme côte à côte -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-[1fr_auto] gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-2">Checksum</label>
|
||||
<Input v-model="metadataForm.checksum" placeholder="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" class="font-mono text-sm" />
|
||||
<label class="block text-sm font-medium mb-2">{{ t('admin.documentDetail.checksumLabel') }}</label>
|
||||
<Input v-model="metadataForm.checksum" :placeholder="t('admin.documentDetail.checksumPlaceholder')" class="font-mono text-sm" />
|
||||
</div>
|
||||
<div class="md:min-w-[140px]">
|
||||
<label class="block text-sm font-medium mb-2">Algorithme</label>
|
||||
<label class="block text-sm font-medium mb-2">{{ t('admin.documentDetail.algorithmLabel') }}</label>
|
||||
<select v-model="metadataForm.checksumAlgorithm" class="flex h-10 w-full rounded-md clay-input px-3 py-2 text-sm">
|
||||
<option value="SHA-256">SHA-256</option>
|
||||
<option value="SHA-512">SHA-512</option>
|
||||
@@ -500,15 +500,15 @@ onMounted(() => {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-2">Description</label>
|
||||
<Textarea v-model="metadataForm.description" :rows="4" placeholder="Description du document..." />
|
||||
<label class="block text-sm font-medium mb-2">{{ t('admin.documentDetail.descriptionLabel') }}</label>
|
||||
<Textarea v-model="metadataForm.description" :rows="4" :placeholder="t('admin.documentDetail.descriptionPlaceholder')" />
|
||||
</div>
|
||||
<div v-if="documentMetadata" class="text-xs text-muted-foreground pt-2 border-t">
|
||||
Créé par {{ documentMetadata.createdBy }} le {{ formatDate(documentMetadata.createdAt) }}
|
||||
{{ t('admin.documentDetail.createdBy', { by: documentMetadata.createdBy, date: formatDate(documentMetadata.createdAt) }) }}
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
<Button type="submit" :disabled="savingMetadata">
|
||||
{{ savingMetadata ? 'Enregistrement...' : 'Enregistrer' }}
|
||||
{{ savingMetadata ? t('admin.documentDetail.saving') : t('common.save') }}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -520,12 +520,12 @@ onMounted(() => {
|
||||
<CardHeader>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<CardTitle>✓ Lecteurs attendus</CardTitle>
|
||||
<CardDescription v-if="stats">{{ stats.signedCount }} / {{ stats.expectedCount }} confirmés</CardDescription>
|
||||
<CardTitle>{{ t('admin.documentDetail.readers') }}</CardTitle>
|
||||
<CardDescription v-if="stats">{{ stats.signedCount }} / {{ stats.expectedCount }} {{ t('admin.dashboard.stats.signed').toLowerCase() }}</CardDescription>
|
||||
</div>
|
||||
<Button @click="showAddSignersModal = true" size="sm">
|
||||
<Plus :size="16" class="mr-2" />
|
||||
Ajouter
|
||||
{{ t('admin.documentDetail.addButton') }}
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
@@ -539,10 +539,10 @@ onMounted(() => {
|
||||
<input type="checkbox" class="rounded"
|
||||
@change="(e: any) => selectedEmails = e.target.checked ? expectedSigners.filter(s => !s.hasSigned).map(s => s.email) : []" />
|
||||
</TableHead>
|
||||
<TableHead>Lecteur</TableHead>
|
||||
<TableHead>Statut</TableHead>
|
||||
<TableHead>Confirmé le</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
<TableHead>{{ t('admin.documentDetail.reader') }}</TableHead>
|
||||
<TableHead>{{ t('admin.documentDetail.status') }}</TableHead>
|
||||
<TableHead>{{ t('admin.documentDetail.confirmedOn') }}</TableHead>
|
||||
<TableHead>{{ t('common.actions') }}</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@@ -560,7 +560,7 @@ onMounted(() => {
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge :variant="signer.hasSigned ? 'default' : 'secondary'">
|
||||
{{ signer.hasSigned ? '✓ Confirmé' : '⏳ En attente' }}
|
||||
{{ signer.hasSigned ? t('admin.documentDetail.statusConfirmed') : t('admin.documentDetail.statusPending') }}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
@@ -577,24 +577,24 @@ onMounted(() => {
|
||||
</div>
|
||||
<div v-else class="text-center py-8 text-muted-foreground">
|
||||
<Users :size="48" class="mx-auto mb-4 opacity-50" />
|
||||
<p>Aucun lecteur attendu</p>
|
||||
<p>{{ t('admin.documentDetail.noExpectedSigners') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Confirmations complémentaires (toujours visible si présents) -->
|
||||
<div v-if="unexpectedSignatures.length > 0" class="mt-8 pt-8 border-t border-border">
|
||||
<h3 class="text-lg font-semibold mb-4 flex items-center">
|
||||
<span class="mr-2">⚠</span>
|
||||
Confirmations de lecture complémentaires
|
||||
{{ t('admin.documentDetail.unexpectedSignatures') }}
|
||||
<Badge variant="secondary" class="ml-2">{{ unexpectedSignatures.length }}</Badge>
|
||||
</h3>
|
||||
<p class="text-sm text-muted-foreground mb-4">
|
||||
Utilisateurs ayant confirmé mais non présents dans la liste des lecteurs attendus
|
||||
{{ t('admin.documentDetail.unexpectedDescription') }}
|
||||
</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Utilisateur</TableHead>
|
||||
<TableHead>Confirmé le</TableHead>
|
||||
<TableHead>{{ t('admin.documentDetail.user') }}</TableHead>
|
||||
<TableHead>{{ t('admin.documentDetail.confirmedOn') }}</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@@ -616,22 +616,22 @@ onMounted(() => {
|
||||
<!-- Email Reminders -->
|
||||
<Card v-if="reminderStats && stats && stats.expectedCount > 0" class="clay-card">
|
||||
<CardHeader>
|
||||
<CardTitle>📧 Relances par email</CardTitle>
|
||||
<CardDescription>Envoyer des rappels aux lecteurs en attente de confirmation</CardDescription>
|
||||
<CardTitle>{{ t('admin.documentDetail.reminders') }}</CardTitle>
|
||||
<CardDescription>{{ t('admin.documentDetail.remindersDescription') }}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent class="space-y-6">
|
||||
<!-- Stats -->
|
||||
<div class="grid gap-4 sm:grid-cols-3">
|
||||
<div class="bg-muted rounded-lg p-4">
|
||||
<p class="text-sm text-muted-foreground">Relances envoyées</p>
|
||||
<p class="text-sm text-muted-foreground">{{ t('admin.documentDetail.remindersSent') }}</p>
|
||||
<p class="text-2xl font-bold">{{ reminderStats.totalSent }}</p>
|
||||
</div>
|
||||
<div class="bg-muted rounded-lg p-4">
|
||||
<p class="text-sm text-muted-foreground">À relancer</p>
|
||||
<p class="text-sm text-muted-foreground">{{ t('admin.documentDetail.toRemind') }}</p>
|
||||
<p class="text-2xl font-bold">{{ reminderStats.pendingCount }}</p>
|
||||
</div>
|
||||
<div v-if="reminderStats.lastSentAt" class="bg-muted rounded-lg p-4">
|
||||
<p class="text-sm text-muted-foreground">Dernière relance</p>
|
||||
<p class="text-sm text-muted-foreground">{{ t('admin.documentDetail.lastReminder') }}</p>
|
||||
<p class="text-sm font-bold">{{ formatDate(reminderStats.lastSentAt) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -641,20 +641,20 @@ onMounted(() => {
|
||||
<div class="space-y-2">
|
||||
<label class="flex items-center space-x-2">
|
||||
<input type="radio" v-model="sendMode" value="all" class="rounded-full" />
|
||||
<span>Envoyer à tous les lecteurs en attente ({{ reminderStats.pendingCount }})</span>
|
||||
<span>{{ t('admin.documentDetail.sendToAll', { count: reminderStats.pendingCount }) }}</span>
|
||||
</label>
|
||||
<label class="flex items-center space-x-2">
|
||||
<input type="radio" v-model="sendMode" value="selected" class="rounded-full" />
|
||||
<span>Envoyer uniquement aux sélectionnés ({{ selectedEmails.length }})</span>
|
||||
<span>{{ t('admin.documentDetail.sendToSelected', { count: selectedEmails.length }) }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<Button @click="confirmSendReminders" :disabled="sendingReminders || (sendMode === 'selected' && selectedEmails.length === 0)">
|
||||
<Mail :size="16" class="mr-2" />
|
||||
{{ sendingReminders ? 'Envoi...' : 'Envoyer les relances' }}
|
||||
{{ sendingReminders ? t('admin.documentDetail.sending') : t('admin.documentDetail.sendReminders') }}
|
||||
</Button>
|
||||
</div>
|
||||
<div v-else class="text-center py-4 text-muted-foreground">
|
||||
✓ Tous les lecteurs attendus ont été contactés ou ont confirmé
|
||||
{{ t('admin.documentDetail.allContacted') }}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -662,16 +662,15 @@ onMounted(() => {
|
||||
<!-- Danger Zone -->
|
||||
<Card class="clay-card border-destructive/50">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-destructive">⚠️ Zone de danger</CardTitle>
|
||||
<CardDescription>Actions irréversibles sur ce document</CardDescription>
|
||||
<CardTitle class="text-destructive">{{ t('admin.documentDetail.dangerZone') }}</CardTitle>
|
||||
<CardDescription>{{ t('admin.documentDetail.dangerZoneDescription') }}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div class="flex items-center justify-between p-4 bg-destructive/5 rounded-lg">
|
||||
<div class="flex-1">
|
||||
<h3 class="font-semibold text-foreground mb-1">Supprimer ce document</h3>
|
||||
<h3 class="font-semibold text-foreground mb-1">{{ t('admin.documentDetail.deleteDocument') }}</h3>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Cette action supprimera définitivement le document, ses métadonnées, les lecteurs attendus et toutes les confirmations associées.<br>
|
||||
Cette action est irréversible.
|
||||
{{ t('admin.documentDetail.deleteDocumentDescription') }}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
@@ -680,7 +679,7 @@ onMounted(() => {
|
||||
class="ml-4"
|
||||
>
|
||||
<Trash2 :size="16" class="mr-2" />
|
||||
Supprimer
|
||||
{{ t('common.delete') }}
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -696,7 +695,7 @@ onMounted(() => {
|
||||
<Card class="max-w-2xl w-full">
|
||||
<CardHeader>
|
||||
<div class="flex items-center justify-between">
|
||||
<CardTitle>Ajouter des lecteurs attendus</CardTitle>
|
||||
<CardTitle>{{ t('admin.documentDetail.addSigners') }}</CardTitle>
|
||||
<Button variant="ghost" size="icon" @click="showAddSignersModal = false">
|
||||
<X :size="20" />
|
||||
</Button>
|
||||
@@ -705,17 +704,17 @@ onMounted(() => {
|
||||
<CardContent>
|
||||
<form @submit.prevent="addSigners" class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-2">Emails (un par ligne)</label>
|
||||
<label class="block text-sm font-medium mb-2">{{ t('admin.documentDetail.emailsLabel') }}</label>
|
||||
<Textarea v-model="signersEmails" :rows="8"
|
||||
placeholder="Marie Dupont <marie.dupont@example.com> jean.martin@example.com Sophie Bernard <sophie@example.com>" />
|
||||
:placeholder="t('admin.documentDetail.emailsPlaceholder')" />
|
||||
<p class="text-xs text-muted-foreground mt-2">
|
||||
Formats acceptés : "Nom Prénom <email@example.com>" ou "email@example.com"
|
||||
{{ t('admin.documentDetail.emailsHelper') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex justify-end space-x-3">
|
||||
<Button type="button" variant="outline" @click="showAddSignersModal = false">Annuler</Button>
|
||||
<Button type="button" variant="outline" @click="showAddSignersModal = false">{{ t('common.cancel') }}</Button>
|
||||
<Button type="submit" :disabled="addingSigners || !signersEmails.trim()">
|
||||
{{ addingSigners ? 'Ajout...' : 'Ajouter' }}
|
||||
{{ addingSigners ? t('admin.documentDetail.adding') : t('admin.documentDetail.addButton') }}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -728,7 +727,7 @@ onMounted(() => {
|
||||
<Card class="max-w-md w-full border-destructive">
|
||||
<CardHeader>
|
||||
<div class="flex items-center justify-between">
|
||||
<CardTitle class="text-destructive">⚠️ Confirmer la suppression</CardTitle>
|
||||
<CardTitle class="text-destructive">{{ t('admin.documentDetail.deleteConfirmTitle') }}</CardTitle>
|
||||
<Button variant="ghost" size="icon" @click="showDeleteConfirmModal = false">
|
||||
<X :size="20" />
|
||||
</Button>
|
||||
@@ -738,28 +737,26 @@ onMounted(() => {
|
||||
<div class="space-y-4">
|
||||
<Alert variant="destructive" class="border-destructive">
|
||||
<AlertDescription>
|
||||
<p class="font-semibold mb-2">Cette action est irréversible !</p>
|
||||
<p class="font-semibold mb-2">{{ t('admin.documentDetail.deleteWarning') }}</p>
|
||||
<p class="text-sm">
|
||||
La suppression de ce document entraînera la perte définitive de :
|
||||
{{ t('admin.documentDetail.deleteWillRemove') }}
|
||||
</p>
|
||||
<ul class="text-sm list-disc list-inside mt-2 space-y-1">
|
||||
<li>Toutes les métadonnées du document</li>
|
||||
<li>La liste des lecteurs attendus</li>
|
||||
<li>Toutes les confirmations cryptographiques</li>
|
||||
<li>L'historique des relances</li>
|
||||
<li>{{ t('admin.documentDetail.deleteItem1') }}</li>
|
||||
<li>{{ t('admin.documentDetail.deleteItem2') }}</li>
|
||||
<li>{{ t('admin.documentDetail.deleteItem3') }}</li>
|
||||
<li>{{ t('admin.documentDetail.deleteItem4') }}</li>
|
||||
</ul>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<div class="bg-muted p-3 rounded-lg">
|
||||
<p class="text-sm font-mono text-muted-foreground">
|
||||
Document ID: <span class="text-foreground font-semibold">{{ docId }}</span>
|
||||
</p>
|
||||
<p class="text-sm font-mono text-muted-foreground" v-html="t('admin.documentDetail.documentId') + ' ' + docId"></p>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end space-x-3 pt-4">
|
||||
<Button type="button" variant="outline" @click="showDeleteConfirmModal = false">
|
||||
Annuler
|
||||
{{ t('common.cancel') }}
|
||||
</Button>
|
||||
<Button
|
||||
@click="handleDeleteDocument"
|
||||
@@ -768,7 +765,7 @@ onMounted(() => {
|
||||
>
|
||||
<Trash2 v-if="!deletingDocument" :size="16" class="mr-2" />
|
||||
<Loader2 v-else :size="16" class="mr-2 animate-spin" />
|
||||
{{ deletingDocument ? 'Suppression...' : 'Supprimer définitivement' }}
|
||||
{{ deletingDocument ? t('admin.documentDetail.deleting') : t('admin.documentDetail.deleteConfirmButton') }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -838,10 +835,10 @@ onMounted(() => {
|
||||
<!-- Remove Signer Confirmation Dialog -->
|
||||
<ConfirmDialog
|
||||
v-if="showRemoveSignerModal"
|
||||
title="⚠️ Retirer le lecteur attendu"
|
||||
:message="`Retirer ${signerToRemove} de la liste des lecteurs attendus ?`"
|
||||
confirm-text="Retirer"
|
||||
cancel-text="Annuler"
|
||||
:title="t('admin.documentDetail.removeSignerTitle')"
|
||||
:message="t('admin.documentDetail.removeSignerMessage', { email: signerToRemove })"
|
||||
:confirm-text="t('common.delete')"
|
||||
:cancel-text="t('common.cancel')"
|
||||
variant="warning"
|
||||
@confirm="removeSigner"
|
||||
@cancel="cancelRemoveSigner"
|
||||
@@ -850,10 +847,10 @@ onMounted(() => {
|
||||
<!-- Send Reminders Confirmation Dialog -->
|
||||
<ConfirmDialog
|
||||
v-if="showSendRemindersModal"
|
||||
title="📧 Envoyer des relances"
|
||||
:title="t('admin.documentDetail.confirmSendRemindersTitle')"
|
||||
:message="remindersMessage"
|
||||
confirm-text="Envoyer"
|
||||
cancel-text="Annuler"
|
||||
:confirm-text="t('common.confirm')"
|
||||
:cancel-text="t('common.cancel')"
|
||||
variant="default"
|
||||
:loading="sendingReminders"
|
||||
@confirm="sendRemindersAction"
|
||||
|
||||
Reference in New Issue
Block a user