Files
kibiandClaude Opus 5.5 06ac414457 Add audit log for moderation and admin actions
New audit_log table records actor, action, target and a JSON snapshot
of the details, so entries stay readable after the target is deleted;
the actor is set to NULL when the user is removed. logAudit() is called
from upload delete (single and bulk), comment delete, tag removal, role
create/delete, role permission changes, role assign/revoke and MOTD
updates. Logging failures only warn and never fail the action itself.

The admin page gets an audit card behind the new audit.view permission
with action filter, click-to-filter by user, readable summaries per
action and server-side pagination. Action catalog lives in
shared/utils/audit.ts, labels under admin.auditActions (de/en).

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 19:27:28 +02:00

309 lines
11 KiB
JSON

{
"common": {
"loading": "Lädt…",
"save": "Speichern",
"saving": "Speichern…",
"cancel": "Abbrechen",
"delete": "Löschen",
"deleting": "Löscht…",
"remove": "Entfernen",
"close": "Schließen",
"back": "Zurück",
"next": "Weiter",
"previous": "Zurück",
"reset": "Zurücksetzen",
"loginLink": "Melde dich an",
"name": "Name",
"password": "Passwort",
"email": "E-Mail"
},
"auth": {
"login": "Anmelden",
"logout": "Ausloggen",
"register": "Registrieren",
"loginTitle": "Login",
"loginDesc": "Melde dich mit Name und Passwort an.",
"registerTitle": "Registrieren",
"registerDesc": "Name und Passwort reichen — E-Mail ist optional.",
"emailOptional": "E-Mail (optional)",
"createAccount": "Konto erstellen",
"noAccount": "Noch kein Konto?",
"alreadyRegistered": "Schon registriert?",
"loginFailed": "Login fehlgeschlagen",
"registerFailed": "Registrierung fehlgeschlagen"
},
"nav": {
"users": "Benutzer",
"admin": "Admin",
"thread": "Thread",
"profile": "Profil",
"settings": "Einstellungen",
"search": "Suchen…",
"searchAria": "Schnellsuche öffnen (Strg+K)",
"searchShortcut": "Strg K",
"gridBento": "Bento-Layout",
"gridUniform": "Einheitliche Größe"
},
"upload": {
"upload": "Hochladen",
"uploading": "Lädt hoch…",
"dropToUpload": "Zum Hochladen loslassen",
"desc": "Datei oder URL — Bilder, Videos, Audio (MP3/FLAC), YouTube- und Twitch-Links.",
"file": "Datei",
"orUrl": "oder URL",
"urlHint": "Direkte Bild-/Video-URLs werden gespeichert, YouTube- und Twitch-Links eingebettet.",
"loginToUpload": ", um Dateien hochzuladen.",
"loginToUploadToast": "Melde dich an, um hochzuladen.",
"onlyMedia": "Nur Bilder, Videos und Audiodateien sind erlaubt",
"failedCount": "{failed} von {total} Dateien fehlgeschlagen",
"failed": "Upload fehlgeschlagen",
"threadLoadFailed": "Thread konnte nicht geladen werden",
"dropzoneText": "Datei hierher ziehen oder klicken",
"dropzoneHint": "Bilder, Videos & Audio, max. 200 MB",
"avatarHint": "Bilder, max. 5 MB"
},
"grid": {
"loading": "Lade Uploads…",
"emptyFiltered": "Keine Uploads für die aktiven Filter.",
"empty": "Noch keine Uploads. Sei der Erste!",
"count": "{n} Uploads",
"select": "Auswählen",
"selected": "{n} ausgewählt",
"selectAll": "Alle auf dieser Seite",
"deleteConfirmTitle": "Uploads löschen?",
"deleteConfirmDesc": "{n} Uploads werden endgültig gelöscht.",
"deletedCount": "{n} Uploads gelöscht",
"deleteFailed": "Löschen fehlgeschlagen"
},
"filters": {
"filter": "Filter",
"type": "Typ",
"uploader": "Uploader",
"period": "Zeitraum",
"allUploaders": "Alle Uploader",
"searchUser": "Nutzer suchen…",
"noUser": "Kein Nutzer gefunden.",
"images": "Bilder",
"videos": "Videos",
"audio": "Audio",
"links": "Links",
"today": "Heute",
"days7": "7 Tage",
"days30": "30 Tage",
"lastYear": "Letztes Jahr",
"allTime": "Gesamter Zeitraum",
"removeTag": "Tag-Filter entfernen",
"removeType": "Typ-Filter {label} entfernen",
"removeUploader": "Uploader-Filter entfernen",
"removePeriod": "Zeitraum-Filter entfernen"
},
"comments": {
"none": "Noch keine Kommentare.",
"loading": "Lade Kommentare…",
"placeholder": "Kommentar schreiben… {'@'} zum Erwähnen, Dateien hierher ziehen",
"submit": "Kommentieren",
"submitting": "Sendet…",
"loginToComment": "um zu kommentieren.",
"attachFiles": "Dateien anhängen",
"removeAttachment": "Anhang entfernen",
"attachments": "Anhänge",
"deleteComment": "Kommentar löschen",
"commentAria": "Kommentar",
"mentionAria": "Benutzer erwähnen",
"recordStart": "Sprachnachricht aufnehmen",
"recordStop": "Aufnahme beenden",
"voiceMessage": "Sprachnachricht",
"maxAttachments": "Maximal {n} Anhänge pro Kommentar",
"fileTooLarge": "{name}: Datei ist zu groß (max. 200 MB)",
"noMic": "Kein Zugriff aufs Mikrofon",
"sendFailed": "Kommentar konnte nicht gesendet werden",
"addReaction": "Reaktion hinzufügen",
"reactionFailed": "Reaktion fehlgeschlagen",
"loginToReact": "Melde dich an, um zu reagieren.",
"playAttachment": "{name} abspielen"
},
"thread": {
"notFound": "Upload nicht gefunden.",
"newer": "Neuerer Upload",
"older": "Älterer Upload",
"favAdd": "Zu Favoriten hinzufügen",
"favRemove": "Aus Favoriten entfernen",
"loginToFavorite": "Melde dich an, um zu favorisieren.",
"deleteUpload": "Upload löschen",
"deleteTitle": "Upload wirklich löschen?",
"deleteDesc": "Der Beitrag und alle Kommentare werden entfernt.",
"deleteFailed": "Löschen fehlgeschlagen",
"editTags": "Tags bearbeiten",
"addTag": "Tag hinzufügen…",
"addTagButton": "Tag hinzufügen",
"removeTag": "Tag {tag} entfernen",
"tagsSaveFailed": "Tags konnten nicht gespeichert werden",
"subscribeOn": "Benachrichtigungen für diesen Thread aktivieren",
"subscribeOff": "Benachrichtigungen für diesen Thread deaktivieren",
"subOn": "Thread-Benachrichtigungen aktiviert",
"subOff": "Thread-Benachrichtigungen deaktiviert",
"subFailed": "Abonnement konnte nicht geändert werden"
},
"audio": {
"play": "Abspielen",
"pause": "Pause",
"seek": "Wiedergabeposition",
"mute": "Stumm",
"unmute": "Ton an",
"volume": "Lautstärke",
"download": "Herunterladen"
},
"notifications": {
"aria": "Benachrichtigungen",
"empty": "Keine Benachrichtigungen.",
"commented": "hat kommentiert",
"mentioned": "hat dich erwähnt",
"view": "Ansehen",
"toastCommented": "{name} hat in einem abonnierten Thread kommentiert",
"toastMentioned": "{name} hat dich erwähnt"
},
"settings": {
"title": "Einstellungen",
"desc": "Profil und Sprache anpassen.",
"nameColor": "Name-Farbe",
"pickColor": "Farbe auswählen",
"cardEffect": "Hover-Card-Effekt",
"noEffect": "Keiner",
"noEffectPlaceholder": "Kein Effekt",
"ownEffectColor": "Eigene Effekt-Farbe",
"pickEffectColor": "Effekt-Farbe auswählen",
"vignette": "Vignette (Text lesbar halten)",
"cardBorder": "Hover-Card-Border",
"ownBorderColor": "Eigene Border-Farbe",
"pickBorderColor": "Border-Farbe auswählen",
"preview": "Vorschau",
"previewHint": "So sieht deine Hover-Card für andere aus.",
"avatar": "Avatar",
"currentAvatar": "Aktueller Avatar",
"language": "Sprache",
"saved": "Einstellungen gespeichert",
"saveFailed": "Speichern fehlgeschlagen",
"loginToChange": ", um deine Einstellungen zu ändern."
},
"admin": {
"roles": "Rollen",
"rolesDesc": "Bestehende Rollen und neue anlegen (z. B. moderator). Die admin-Rolle hat immer alle Berechtigungen.",
"memberCount": "{n} Nutzer",
"deleteRole": "Rolle löschen",
"newRole": "Neuer Rollenname",
"create": "Anlegen",
"users": "Benutzer",
"usersDesc": "Rollen zuweisen oder entfernen.",
"searchUsers": "Name oder E-Mail suchen…",
"noRoles": "keine Rollen",
"chooseRole": "Rolle wählen…",
"assign": "Zuweisen",
"removeRole": "Rolle {name} entfernen",
"rolesCol": "Rollen",
"actionCol": "Aktion",
"motd": "Ansage",
"motdDesc": "Wird allen Besuchern direkt unter der Kopfzeile angezeigt und bei Änderung sofort aktualisiert. Leer lassen, um sie zu entfernen.",
"motdPlaceholder": "Ansagetext…",
"actionFailed": "Aktion fehlgeschlagen",
"perms": {
"admin": { "access": "Admin-Bereich öffnen" },
"roles": { "manage": "Rollen & Berechtigungen verwalten" },
"users": { "manage": "Benutzer & Rollen verwalten" },
"site": { "manage": "Seiten-Einstellungen verwalten" },
"comment": { "delete": "Kommentare löschen" },
"upload": { "delete": "Uploads löschen" },
"tag": { "delete": "Tags löschen" },
"audit": { "view": "Audit-Log einsehen" }
},
"audit": {
"title": "Audit-Log",
"desc": "Protokoll aller Moderations- und Admin-Aktionen. Klick auf einen Namen filtert nach diesem Nutzer.",
"filterAction": "Nach Aktion filtern",
"allActions": "Alle Aktionen",
"filterUser": "Nur Aktionen von {name} anzeigen",
"clearUser": "Nutzerfilter entfernen",
"count": "{n} Einträge",
"refresh": "Aktualisieren",
"time": "Zeit",
"actor": "Nutzer",
"action": "Aktion",
"details": "Details",
"deletedUser": "gelöschter Nutzer",
"empty": "Keine Einträge."
},
"auditActions": {
"delete_upload": "Upload gelöscht",
"bulk_delete_uploads": "Uploads gesammelt gelöscht",
"delete_comment": "Kommentar gelöscht",
"remove_tags": "Tags entfernt",
"create_role": "Rolle angelegt",
"delete_role": "Rolle gelöscht",
"update_role_permissions": "Berechtigungen geändert",
"assign_role": "Rolle zugewiesen",
"remove_role": "Rolle entzogen",
"update_motd": "Ansage geändert"
},
"auditDetails": {
"deleteUpload": "{name} von {user}",
"bulkDelete": "{n} Uploads",
"deleteComment": "{user}: {content}",
"role": "{role} → {user}",
"noChanges": "keine Änderungen",
"motdCleared": "Ansage entfernt"
}
},
"palette": {
"title": "Schnellsuche",
"desc": "Seiten, Tags oder Uploader suchen",
"placeholder": "Seiten, Tags oder Uploader suchen…",
"empty": "Keine Ergebnisse.",
"pages": "Seiten",
"home": "Startseite",
"users": "Benutzer",
"myProfile": "Mein Profil",
"settings": "Einstellungen",
"adminArea": "Admin-Bereich",
"login": "Login",
"register": "Registrieren",
"tags": "Tags",
"uploaders": "Uploader"
},
"timeAgo": {
"justNow": "gerade eben",
"min": "vor {n} Min",
"hour": "vor {n} Std",
"day": "vor {n} T",
"month": "vor {n} Mon",
"year": "vor {n} J"
},
"misc": {
"userNotFound": "Nutzer nicht gefunden.",
"memberSince": "Mitglied seit {date}",
"since": "seit {date}",
"noUsers": "Noch keine Benutzer.",
"noUploads": "Noch keine Uploads.",
"joined": "Dabei seit",
"commentsCol": "Kommentare",
"uploadsCol": "Uploads",
"noEntries": "Keine Einträge.",
"pageOf": "Seite {page} von {total}",
"theme": "Theme",
"toggleSidebar": "Seitenleiste umschalten",
"sidebar": "Seitenleiste",
"sidebarDesc": "Zeigt die mobile Seitenleiste.",
"more": "Mehr",
"setColor": "Farbe auf {color} setzen",
"breadcrumb": "Brotkrumennavigation"
},
"pagination": {
"prev": "Vorherige Seite",
"next": "Nächste Seite",
"first": "Erste Seite",
"firstShort": "Erste",
"last": "Letzte Seite",
"lastShort": "Letzte",
"page": "Seite {page}",
"more": "Weitere Seiten"
}
}