Web-Anwendung: Design-Tokens, Texte, Gesundheitsendpunkt
Design-Tokens aus docs/10-design-system.md als CSS-Variablen: Grundpalette, die sechs Klassifizierungsfarben, Eckenradius durchgehend 2 px, keine Schatten ausser dem Fokusring. Der Schwärzungsbalken mit dem einmaligen Durchwischen respektiert prefers-reduced-motion. Vier Tests halten die Tokens gegen das Dokument. IBM Plex selbst gehostet als woff2, latin und latin-ext getrennt über unicode-range, font-display: swap, immutable-Cache. Alle Oberflächentexte in lib/i18n/de.ts. Ein Test durchsucht app/ und components/ nach Umlauten im JSX und schlägt fehl, wenn dort deutscher Text steht. Er hat beim ersten Lauf gleich einen Verstoss gefunden. /api/health prüft Datenbank, Discord-Gateway und ClamAV. Die Gesamtbewertung fällt nur auf "down", wenn die Datenbank weg ist: die anderen Dienste haben eigene Healthchecks im Stack, und ein ausgefallener Virenscanner soll nicht den Web-Container als tot markieren. Strikte CSP mit Nonce, kein unsafe-inline für Skripte. Die erste Route liegt bei 100 kB JavaScript nach Kompression, Budget sind 120 kB. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
51984f17d4
commit
6b0cd331bb
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Alle Oberflaechentexte. Nie deutsche Strings hart ins JSX, siehe CLAUDE.md.
|
||||
* Die Begriffe folgen dem Glossar in docs/01-produkt.md.
|
||||
*
|
||||
* Schreibweise nach docs/10-design-system.md:
|
||||
* - Aktive Verben, die sagen, was passiert: "Vermerk speichern", nicht "Absenden"
|
||||
* - Dieselbe Bezeichnung durch den ganzen Ablauf
|
||||
* - Fehler nennen Ursache und naechsten Schritt, ohne Entschuldigung
|
||||
* - Leere Zustaende sind eine Aufforderung
|
||||
* - Keine Ausrufezeichen, kein "bitte", kein "erfolgreich"
|
||||
*/
|
||||
export const de = {
|
||||
app: {
|
||||
name: 'AfiS-Aktensystem',
|
||||
shortName: 'AfiS',
|
||||
description: 'Fallakten, Personalakten und Ermittlungen der Abteilung für innere Sicherheit',
|
||||
},
|
||||
|
||||
nav: {
|
||||
dashboard: 'Übersicht',
|
||||
cases: 'Fallakten',
|
||||
personnel: 'Personalakten',
|
||||
search: 'Suche',
|
||||
admin: 'Verwaltung',
|
||||
skipToContent: 'Zum Inhalt springen',
|
||||
},
|
||||
|
||||
auth: {
|
||||
signIn: 'Mit Discord anmelden',
|
||||
signOut: 'Abmelden',
|
||||
signedInAs: 'Angemeldet als',
|
||||
notInGuild: {
|
||||
title: 'Du bist nicht auf dem AfiS-Discord',
|
||||
body: 'Die Anmeldung setzt eine Mitgliedschaft auf dem Discord-Server voraus. Wende dich an die Abteilungsleitung.',
|
||||
},
|
||||
sessionEnded: {
|
||||
title: 'Sitzung beendet',
|
||||
body: 'Deine Rollen haben sich geändert. Melde dich neu an.',
|
||||
},
|
||||
error: {
|
||||
title: 'Anmeldung nicht möglich',
|
||||
body: 'Der Anmeldevorgang wurde abgebrochen. Erneut versuchen.',
|
||||
},
|
||||
},
|
||||
|
||||
clearance: {
|
||||
label: 'Freigabestufe',
|
||||
classification: 'Klassifizierung',
|
||||
level: (n: number) => `Stufe ${n}`,
|
||||
names: {
|
||||
0: 'Offen',
|
||||
1: 'Intern',
|
||||
2: 'Vertraulich',
|
||||
3: 'Geheim',
|
||||
4: 'Streng geheim',
|
||||
5: 'Leitungssache',
|
||||
} as Record<number, string>,
|
||||
locked: 'Inhalt gesperrt',
|
||||
lockedHint: (n: number) => `Sichtbar ab Stufe ${n}`,
|
||||
redacted: 'Geschwärzt',
|
||||
redactedHint: (n: number) => `Geschwärzt, ab Stufe ${n} sichtbar`,
|
||||
},
|
||||
|
||||
case: {
|
||||
one: 'Fallakte',
|
||||
many: 'Fallakten',
|
||||
number: 'Aktenzeichen',
|
||||
title: 'Titel',
|
||||
type: 'Fallart',
|
||||
status: 'Status',
|
||||
dueAt: 'Wiedervorlage',
|
||||
outcome: 'Ergebnis',
|
||||
createdBy: 'Angelegt von',
|
||||
timeline: 'Verlauf',
|
||||
sections: 'Abschnitte',
|
||||
chat: 'Aktenchat',
|
||||
changes: 'Änderungen',
|
||||
participants: 'Beteiligte',
|
||||
links: 'Verknüpfungen',
|
||||
attachments: 'Anhänge',
|
||||
empty: 'Noch keine Fallakte. Erste Fallakte anlegen.',
|
||||
statusNames: {
|
||||
DRAFT: 'Entwurf',
|
||||
OPEN: 'Offen',
|
||||
DORMANT: 'Ruhend',
|
||||
REVIEW: 'In Prüfung',
|
||||
CLOSED: 'Abgeschlossen',
|
||||
ARCHIVED: 'Archiviert',
|
||||
SEALED: 'Versiegelt',
|
||||
} as Record<string, string>,
|
||||
},
|
||||
|
||||
entry: {
|
||||
one: 'Vermerk',
|
||||
many: 'Vermerke',
|
||||
create: 'Vermerk speichern',
|
||||
empty: 'Noch kein Vermerk. Ersten Vermerk anlegen.',
|
||||
edited: (v: number) => `bearbeitet · v${v}`,
|
||||
history: 'Änderungsverlauf',
|
||||
changeReason: 'Begründung',
|
||||
retracted: (date: string, person: string, reason: string) =>
|
||||
`Eintrag zurückgezogen am ${date} durch ${person} · Begründung: ${reason}`,
|
||||
types: {
|
||||
NOTE: 'Vermerk',
|
||||
INTERROGATION: 'Befragung',
|
||||
EVIDENCE: 'Beweismittel',
|
||||
STATUS_CHANGE: 'Statuswechsel',
|
||||
CORRECTION: 'Korrektur',
|
||||
SYSTEM: 'System',
|
||||
} as Record<string, string>,
|
||||
},
|
||||
|
||||
personnel: {
|
||||
one: 'Personalakte',
|
||||
many: 'Personalakten',
|
||||
serviceNumber: 'Dienstnummer',
|
||||
rank: 'Dienstgrad',
|
||||
department: 'Abteilung',
|
||||
empty: 'Noch keine Personalakte. Erste Personalakte anlegen.',
|
||||
},
|
||||
|
||||
common: {
|
||||
save: 'Speichern',
|
||||
cancel: 'Abbrechen',
|
||||
undo: 'Rückgängig',
|
||||
retry: 'Erneut versuchen',
|
||||
loading: 'Wird geladen',
|
||||
offline: 'Keine Verbindung, wird nachgesendet',
|
||||
unknown: 'Unbekannt',
|
||||
},
|
||||
|
||||
errors: {
|
||||
notFound: {
|
||||
title: 'Nicht gefunden',
|
||||
body: 'Die Seite gibt es nicht, oder du darfst sie nicht sehen.',
|
||||
},
|
||||
unexpected: {
|
||||
title: 'Nicht geladen',
|
||||
body: 'Der Abruf ist fehlgeschlagen. Erneut versuchen.',
|
||||
},
|
||||
conflict: 'Nicht gespeichert, die Akte wurde zwischenzeitlich geändert. Fassungen vergleichen.',
|
||||
},
|
||||
|
||||
health: {
|
||||
heading: 'Systemzustand',
|
||||
service: 'Dienst',
|
||||
state: 'Zustand',
|
||||
checkedAt: (when: string) => `Zustand der Dienste, abgefragt ${when}`,
|
||||
ok: 'Betriebsbereit',
|
||||
degraded: 'Eingeschränkt',
|
||||
down: 'Gestört',
|
||||
components: {
|
||||
database: 'Datenbank',
|
||||
discordGateway: 'Discord-Gateway',
|
||||
clamav: 'Virenprüfung',
|
||||
} as Record<string, string>,
|
||||
},
|
||||
} as const
|
||||
|
||||
export type Messages = typeof de
|
||||
Reference in New Issue
Block a user