Completes residency end-to-end: a 'Gehört zum eigenen Bestand' checkbox on the Rennmaus-Formular (default on for new animals) lets the user mark a tier as an external ancestor by hand — previously isResident was only set at import. Wired through FormState + formFromGerbil (defaults true) + the CreateGerbil payload. German via de.ts (LF). e2e: edit Krümel, untick Bestand, save -> detail shows the 'Extern' badge (proves form field -> payload -> persistence). Gate green: build, eslint, vitest 78, e2e 86. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
797 lines
29 KiB
TypeScript
797 lines
29 KiB
TypeScript
/**
|
||
* Zentrale deutsche Texte der Anwendung.
|
||
* Alle für Benutzer sichtbaren Zeichenketten gehören hierher —
|
||
* niemals Texte direkt in Komponenten hartkodieren.
|
||
*/
|
||
export const de = {
|
||
app: {
|
||
title: 'Rennmaus-Manager',
|
||
tagline: 'Verwaltung für Rennmäuse, Würfe und Züchter',
|
||
},
|
||
nav: {
|
||
home: 'Start',
|
||
gerbils: 'Rennmäuse',
|
||
litters: 'Würfe',
|
||
breeders: 'Züchter',
|
||
genetics: 'Genetik',
|
||
// FEAT-2 (Oscar): Becken + Kontakte
|
||
enclosures: 'Becken',
|
||
contacts: 'Kontakte',
|
||
// FEAT-7 (Kelly): Statistik
|
||
statistics: 'Statistik',
|
||
// FEAT-7 (Kevin): „Mehr“-Overflow auf dem Smartphone
|
||
more: 'Mehr',
|
||
// FEAT-12a (Kevin): Abgabe
|
||
forSale: 'Abgabe',
|
||
// FEAT-13 (Kelly): Verträge + Einstellungen
|
||
contracts: 'Verträge',
|
||
settings: 'Einstellungen',
|
||
// INBOX-1 (Kelly): Anfragen-Posteingang
|
||
requests: 'Anfragen',
|
||
openMenu: 'Menü öffnen',
|
||
closeMenu: 'Menü schließen',
|
||
mainNavigation: 'Hauptnavigation',
|
||
// HELP-1
|
||
help: 'Hilfe',
|
||
// WEB-0b (Kevin): CMS-Verwaltung der öffentlichen Webseite
|
||
website: 'Webseite',
|
||
},
|
||
pages: {
|
||
home: {
|
||
title: 'Willkommen',
|
||
intro:
|
||
'Hier verwaltest du deine Rennmäuse, Würfe und Züchter. Wähle einen Bereich aus der Navigation.',
|
||
},
|
||
gerbils: {
|
||
title: 'Rennmäuse',
|
||
// Liste
|
||
newButton: 'Neue Rennmaus',
|
||
empty: 'Keine Rennmäuse gefunden.',
|
||
countLabel: 'Tiere',
|
||
searchPlaceholder: 'Name suchen …',
|
||
// BESTAND-FILTER: Kennzeichnung externer (nicht zum eigenen Bestand gehörender) Tiere
|
||
externalBadge: 'Extern',
|
||
externalTitle: 'Externes Tier — gehört nicht zum eigenen Bestand, nur für den Stammbaum erfasst.',
|
||
// Filter-Beschriftungen
|
||
filters: {
|
||
title: 'Filter',
|
||
status: 'Status',
|
||
gender: 'Geschlecht',
|
||
colorVariety: 'Farbschlag',
|
||
all: 'Alle',
|
||
reset: 'Filter zurücksetzen',
|
||
sortBy: 'Sortieren nach',
|
||
// BESTAND-FILTER: eigener Bestand (Clan) vs. externe Ahnen (nur Stammbaum)
|
||
showExternal: 'Externe Ahnen einblenden',
|
||
showExternalHint: 'Tiere aus fremden Zuchten, die nur für den Stammbaum erfasst sind.',
|
||
},
|
||
// Sortier-Optionen
|
||
sort: {
|
||
nameAsc: 'Name (A–Z)',
|
||
nameDesc: 'Name (Z–A)',
|
||
birthDesc: 'Geburtsdatum (neueste)',
|
||
birthAsc: 'Geburtsdatum (älteste)',
|
||
},
|
||
// Feld-Beschriftungen (Stammdaten)
|
||
fields: {
|
||
name: 'Name',
|
||
gender: 'Geschlecht',
|
||
status: 'Status',
|
||
dateOfBirth: 'Geburtsdatum',
|
||
dateOfDeath: 'Todesdatum',
|
||
causeOfDeath: 'Todesursache',
|
||
goHomeDate: 'Abgabedatum',
|
||
litter: 'Wurf',
|
||
enclosure: 'Becken',
|
||
colorVariety: 'Farbschlag',
|
||
origin: 'Herkunft',
|
||
receiver: 'Abnehmer',
|
||
genotype: 'Genotyp',
|
||
notes: 'Notizen',
|
||
},
|
||
// Detailseite
|
||
detail: {
|
||
masterData: 'Stammdaten',
|
||
genetics: 'Genetik',
|
||
resolvedFarbschlag: 'Errechneter Farbschlag',
|
||
resolvedPrefix: 'Errechnet',
|
||
farbschlagMismatch: 'Weicht vom eingetragenen Farbschlag ab.',
|
||
genotypeNotSet: 'Kein Genotyp hinterlegt.',
|
||
testMating: 'Probeverpaarung',
|
||
edit: 'Bearbeiten',
|
||
back: 'Zurück zur Liste',
|
||
tabs: {
|
||
photos: 'Fotos',
|
||
health: 'Gesundheit',
|
||
weight: 'Gewicht',
|
||
},
|
||
tabPlaceholder: 'Dieser Bereich entsteht in einem späteren Schritt.',
|
||
notFound: 'Diese Rennmaus wurde nicht gefunden.',
|
||
moreData: 'Weitere Daten',
|
||
},
|
||
// Formular (anlegen/bearbeiten)
|
||
form: {
|
||
createTitle: 'Neue Rennmaus anlegen',
|
||
editTitle: 'Rennmaus bearbeiten',
|
||
none: '— keine Angabe —',
|
||
genotypeHint:
|
||
'Optional. Format z. B. „Aa CC Dd EE GG Pp Spsp rere“. Unbekannte Allele als „-“.',
|
||
// BESTAND-FILTER: Zugehörigkeit zum eigenen Bestand (sonst externe Ahne)
|
||
isResidentLabel: 'Gehört zum eigenen Bestand',
|
||
isResidentHint: 'Abwählen für externe Ahnen, die nur für den Stammbaum erfasst sind.',
|
||
save: 'Speichern',
|
||
cancel: 'Abbrechen',
|
||
saving: 'Speichern …',
|
||
},
|
||
// Validierungsmeldungen
|
||
validation: {
|
||
nameRequired: 'Bitte einen Namen eingeben.',
|
||
genderRequired: 'Bitte ein Geschlecht auswählen.',
|
||
genotypeInvalid: 'Der Genotyp ist ungültig.',
|
||
dateOfDeathBeforeBirth: 'Das Todesdatum darf nicht vor dem Geburtsdatum liegen.',
|
||
},
|
||
// Aufzählungen
|
||
genderLabels: {
|
||
unknown: 'Unbekannt',
|
||
male: 'Männlich',
|
||
female: 'Weiblich',
|
||
},
|
||
statusLabels: {
|
||
Active: 'Aktiv',
|
||
Deceased: 'Verstorben',
|
||
GivenAway: 'Abgegeben',
|
||
ForSale: 'Zur Abgabe',
|
||
},
|
||
},
|
||
// ── FEAT-3 (Kevin): Zucht — Würfe + Zuchtpaare ──
|
||
litters: {
|
||
title: 'Würfe',
|
||
tabs: {
|
||
litters: 'Würfe',
|
||
pairs: 'Zuchtpaare',
|
||
},
|
||
// Liste
|
||
newButton: 'Neuer Wurf',
|
||
empty: 'Keine Würfe gefunden.',
|
||
countLabel: 'Würfe',
|
||
filterYear: 'Jahr',
|
||
allYears: 'Alle Jahre',
|
||
sort: {
|
||
dateDesc: 'Wurfdatum (neueste)',
|
||
dateAsc: 'Wurfdatum (älteste)',
|
||
},
|
||
// Felder
|
||
fields: {
|
||
name: 'Bezeichnung',
|
||
date: 'Wurfdatum',
|
||
father: 'Vater',
|
||
mother: 'Mutter',
|
||
totalBorn: 'Wurfstärke',
|
||
expectedGoHomeDate: 'Voraussichtliches Abgabedatum',
|
||
notes: 'Notizen',
|
||
},
|
||
// Detail / Arbeitsbereich
|
||
detail: {
|
||
parents: 'Elterntiere',
|
||
registered: 'Erfasste Jungtiere',
|
||
juveniles: 'Jungtiere',
|
||
registerJuvenile: 'Jungtier erfassen',
|
||
expectedColors: 'Erwartete Farbschläge dieser Verpaarung',
|
||
needParentsGenotype:
|
||
'Für die Farbvorhersage müssen bei Vater und Mutter Genotypen hinterlegt sein.',
|
||
noJuveniles: 'Noch keine Jungtiere erfasst.',
|
||
unknownParent: 'Unbekannt',
|
||
edit: 'Bearbeiten',
|
||
back: 'Zurück zur Liste',
|
||
notFound: 'Dieser Wurf wurde nicht gefunden.',
|
||
},
|
||
// Formular
|
||
form: {
|
||
createTitle: 'Neuen Wurf anlegen',
|
||
editTitle: 'Wurf bearbeiten',
|
||
none: '— keine Angabe —',
|
||
goHomeHint: 'Vorschlag: 35 Tage nach dem Wurfdatum. Anpassbar.',
|
||
save: 'Speichern',
|
||
cancel: 'Abbrechen',
|
||
saving: 'Speichern …',
|
||
},
|
||
validation: {
|
||
nameRequired: 'Bitte eine Bezeichnung eingeben.',
|
||
dateRequired: 'Bitte ein Wurfdatum angeben.',
|
||
invalidParentGender: 'Der Vater muss männlich und die Mutter weiblich sein.',
|
||
},
|
||
// Zuchtpaar-Übersicht
|
||
pairs: {
|
||
title: 'Zuchtpaare',
|
||
empty: 'Noch keine Zuchtpaare — diese ergeben sich aus den erfassten Würfen.',
|
||
litterCount: 'Würfe',
|
||
lastLitter: 'Letzter Wurf',
|
||
testMating: 'Probeverpaarung',
|
||
},
|
||
},
|
||
breeders: {
|
||
title: 'Züchter',
|
||
comingSoon: 'Die Züchter-Verwaltung entsteht gerade. Bald kannst du hier Züchter erfassen.',
|
||
},
|
||
notFound: {
|
||
title: 'Seite nicht gefunden',
|
||
message: 'Die angeforderte Seite existiert nicht.',
|
||
backHome: 'Zur Startseite',
|
||
},
|
||
// ── FEAT-5 (Kevin): Genetik / Probeverpaarung ──
|
||
genetik: {
|
||
title: 'Genetik',
|
||
subtitle: 'Probeverpaarung – Farbschläge der Nachkommen vorhersagen',
|
||
father: 'Vater',
|
||
mother: 'Mutter',
|
||
pickAnimal: 'Tier auswählen',
|
||
pickAnimalSearch: 'Name suchen …',
|
||
pickAnimalNone: 'Keine passenden Tiere gefunden.',
|
||
pickAnimalNoGenotype: 'Für dieses Tier ist kein Genotyp hinterlegt – bitte unten eingeben.',
|
||
clearAnimal: 'Auswahl entfernen',
|
||
genotypeLabel: 'Genotyp',
|
||
genotypeHint: 'Format z. B. „Aa CC Dd EE GG Pp Spsp rere“. Unbekannte Allele als „-“.',
|
||
genotypeInvalid: 'Der Genotyp ist ungültig.',
|
||
genotypePreview: 'Farbschlag',
|
||
run: 'Probeverpaarung berechnen',
|
||
needBoth: 'Bitte für Vater und Mutter einen gültigen Genotyp angeben.',
|
||
resultsTitle: 'Mögliche Nachkommen',
|
||
byFarbschlag: 'Nach Farbschlag',
|
||
byGenotype: 'Nach Genotyp',
|
||
showGenotypes: 'Genotypen anzeigen',
|
||
hideGenotypes: 'Genotypen ausblenden',
|
||
probability: 'Wahrscheinlichkeit',
|
||
noOffspring: 'Keine lebend geborenen Nachkommen möglich.',
|
||
warningsTitle: 'Hinweise',
|
||
},
|
||
// ── FEAT-12a (Kevin): Abgabe (For-Sale / Inserate) ──
|
||
abgabe: {
|
||
title: 'Abgabe',
|
||
subtitle: 'Abgabetiere gruppieren und Inserate erstellen',
|
||
empty: 'Keine Tiere zur Abgabe. Stelle Tiere über „Zur Abgabe stellen“ ein.',
|
||
markAction: 'Zur Abgabe stellen',
|
||
markMultiAction: 'Ausgewählte zur Abgabe stellen',
|
||
grouping: {
|
||
title: 'Gruppen',
|
||
byEnclosure: 'Nach Becken vorgeschlagen',
|
||
ungrouped: 'Ohne Becken',
|
||
moveTo: 'Verschieben nach',
|
||
newGroup: 'Neue Gruppe',
|
||
groupLabel: 'Gruppe',
|
||
},
|
||
// Inserat-Komposer (Vorlage der Züchterin)
|
||
listing: {
|
||
headingFor: (n: number, gender: string) => `Gruppe ${n} (${gender})`,
|
||
genderMale: 'männlich',
|
||
genderFemale: 'weiblich',
|
||
genderMixed: 'gemischt',
|
||
status: 'Status',
|
||
statusFree: 'FREI',
|
||
statusLooseReserved: 'LOCKER RESERVIERT',
|
||
statusReserved: 'RESERVIERT',
|
||
reservedName: 'Name (bei Reservierung)',
|
||
tagline: 'Überschrift (emotionaler Einzeiler)',
|
||
taglinePlaceholder: 'z. B. „Großer und kleiner Bruder“ – Männliches Rennmaus-Duo sucht ein Zuhause',
|
||
bornOn: 'geboren am',
|
||
personality: 'Charakter',
|
||
personalityPlaceholder: 'Ein paar Sätze zum Charakter des Tieres …',
|
||
photos: 'Fotos',
|
||
noPhotos: 'Für dieses Tier sind keine Fotos hinterlegt.',
|
||
},
|
||
// Export / Paste-Paket
|
||
export: {
|
||
copyText: 'Text kopieren',
|
||
copied: 'Text in die Zwischenablage kopiert.',
|
||
copyFailed: 'Kopieren fehlgeschlagen.',
|
||
downloadPhotos: 'Fotos herunterladen',
|
||
zipping: 'Fotos werden gepackt …',
|
||
noPhotosSelected: 'Keine Fotos ausgewählt.',
|
||
zipFailed: 'Fotos konnten nicht gepackt werden.',
|
||
finish: 'Abgabe abschließen',
|
||
finishHint: 'Vertrag erstellen (folgt in einem späteren Schritt).',
|
||
},
|
||
// KI-Assistent (Backend folgt mit API-Schlüssel)
|
||
ai: {
|
||
improve: 'Text mit KI verbessern',
|
||
generating: 'KI erstellt den Text …',
|
||
hintsLabel: 'Hinweise für die KI (optional)',
|
||
notConfigured: 'KI-Funktion: API-Schlüssel noch nicht konfiguriert.',
|
||
},
|
||
},
|
||
// ── FEAT-2 (Oscar): Becken (Enclosures) ──
|
||
becken: {
|
||
title: 'Becken',
|
||
newButton: 'Neues Becken',
|
||
empty: 'Keine Becken gefunden.',
|
||
countLabel: 'Becken',
|
||
searchPlaceholder: 'Name suchen …',
|
||
fields: {
|
||
name: 'Name',
|
||
notes: 'Notizen',
|
||
},
|
||
occupancy: {
|
||
title: 'Bewohner',
|
||
empty: 'Dieses Becken ist derzeit leer.',
|
||
countOne: 'Tier',
|
||
countMany: 'Tiere',
|
||
},
|
||
detail: {
|
||
edit: 'Bearbeiten',
|
||
back: 'Zurück zur Liste',
|
||
notFound: 'Dieses Becken wurde nicht gefunden.',
|
||
},
|
||
form: {
|
||
createTitle: 'Neues Becken anlegen',
|
||
editTitle: 'Becken bearbeiten',
|
||
save: 'Speichern',
|
||
cancel: 'Abbrechen',
|
||
saving: 'Speichern …',
|
||
},
|
||
validation: {
|
||
nameRequired: 'Bitte einen Namen eingeben.',
|
||
},
|
||
delete: {
|
||
action: 'Löschen',
|
||
confirmMessage: 'Soll dieses Becken wirklich gelöscht werden?',
|
||
conflict:
|
||
'Becken ist nicht leer — bitte zuerst alle Tiere in ein anderes Becken umsetzen.',
|
||
},
|
||
},
|
||
// ── FEAT-4 (Kelly): Stammbaum (Ahnentafel) ──
|
||
stammbaum: {
|
||
title: 'Stammbaum',
|
||
/** Überschrift mit Tiername. */
|
||
titleFor: (name: string) => `Stammbaum von ${name}`,
|
||
/** Button auf der Tier-Detailseite (Integration durch FEAT-1). */
|
||
openButton: 'Stammbaum',
|
||
backToAnimal: 'Zur Tierakte',
|
||
notFound: 'Diese Rennmaus wurde nicht gefunden.',
|
||
unknown: 'unbekannt',
|
||
/** Auf Karten am Rand: weitere Vorfahren nachladen. */
|
||
expand: 'Vorfahren laden',
|
||
tapHint: 'Tippe auf ein Tier, um dessen Stammbaum anzuzeigen.',
|
||
zoomIn: 'Vergrößern',
|
||
zoomOut: 'Verkleinern',
|
||
zoomFit: 'Ansicht einpassen',
|
||
print: 'Drucken / PDF',
|
||
inbreeding: {
|
||
label: 'Inzuchtkoeffizient',
|
||
unavailable: 'wird berechnet …',
|
||
},
|
||
printView: {
|
||
/** Spaltenüberschriften der Ahnentafel, Index = Generation. */
|
||
generations: ['Tier', 'Eltern', 'Großeltern', 'Urgroßeltern', 'Ur-Urgroßeltern'],
|
||
createdOn: 'Erstellt am',
|
||
born: 'geb.',
|
||
},
|
||
},
|
||
// ── FEAT-7 (Kelly): Statistik & Berichte ──
|
||
statistik: {
|
||
title: 'Statistik & Berichte',
|
||
empty:
|
||
'Noch keine Daten — lege zuerst Tiere und Würfe an oder importiere deinen Bestand.',
|
||
sectionEmpty: 'Noch keine Daten für diese Auswertung.',
|
||
littersPerYear: 'Würfe pro Jahr',
|
||
avgLitterSize: 'Durchschnittliche Wurfstärke pro Jahr',
|
||
avgLitterSizeHint: 'Nur Würfe mit erfasster Wurfstärke.',
|
||
farbschlag: 'Farbschlag-Verteilung',
|
||
farbschlagHint: 'Nur aktive Tiere.',
|
||
withoutFarbschlag: 'ohne Farbschlag',
|
||
population: 'Bestandsentwicklung',
|
||
populationHint:
|
||
'Lebende, nicht abgegebene Tiere im Zeitverlauf. Tiere ohne Geburtsdatum sind nicht enthalten.',
|
||
populationUnit: 'Tiere',
|
||
losses: 'Verluste pro Jahr',
|
||
lossesHint: 'Verstorbene Tiere nach Todesjahr.',
|
||
},
|
||
// ── FEAT-13 (Kelly): Abgabeverträge ──
|
||
vertraege: {
|
||
title: 'Abgabeverträge',
|
||
newButton: 'Neuer Vertrag',
|
||
empty: 'Noch keine Verträge — erstelle den ersten über „Neuer Vertrag“ oder den Abgabe-Bereich.',
|
||
countText: (n: number) => (n === 1 ? '1 Vertrag' : `${n} Verträge`),
|
||
download: 'Herunterladen',
|
||
delete: 'Löschen',
|
||
confirmDelete:
|
||
'Vertrag wirklich löschen? Die Word-Datei wird mit entfernt; der Status der Tiere bleibt unverändert.',
|
||
animalsCount: (n: number) => (n === 1 ? '1 Tier' : `${n} Tiere`),
|
||
fields: {
|
||
contact: 'Abnehmer',
|
||
animals: 'Tiere',
|
||
price: 'Kaufpreis',
|
||
handoverDate: 'Übergabedatum',
|
||
contractDate: 'Vertragsdatum',
|
||
createdAt: 'Erstellt',
|
||
},
|
||
// Assistent (/vertraege/neu)
|
||
wizard: {
|
||
title: 'Abgabe abschließen',
|
||
steps: ['Abnehmer', 'Tiere', 'Preis & Datum', 'Vertrag'],
|
||
back: 'Zurück',
|
||
next: 'Weiter',
|
||
cancel: 'Abbrechen',
|
||
// Schritt 1
|
||
pickContact: 'Abnehmer auswählen',
|
||
searchContact: 'Name suchen …',
|
||
noContacts: 'Keine Kontakte gefunden.',
|
||
orCreateNew: 'Oder neuen Kontakt anlegen',
|
||
createContact: 'Kontakt anlegen und auswählen',
|
||
contactNameRequired: 'Bitte einen Namen für den Kontakt eingeben.',
|
||
// Schritt 2
|
||
pickAnimals: 'Tiere bestätigen',
|
||
pickAnimalsHint: 'Nur lebende, nicht abgegebene Tiere werden angezeigt.',
|
||
noAnimals: 'Keine abgebbaren Tiere gefunden.',
|
||
animalsRequired: 'Bitte mindestens ein Tier auswählen.',
|
||
// Schritt 3
|
||
priceLabel: 'Kaufpreis (€)',
|
||
pricePlaceholder: 'z. B. 72,00',
|
||
priceInvalid: 'Bitte einen gültigen Preis eingeben (z. B. 72,00).',
|
||
handoverLabel: 'Übergabedatum',
|
||
contractDateLabel: 'Vertragsdatum (optional, Standard = Übergabedatum)',
|
||
// Schritt 4
|
||
summaryTitle: 'Zusammenfassung',
|
||
profileIncomplete:
|
||
'Das Zuchtprofil ist unvollständig — Name, Adresse und Ort erscheinen im Vertrag. Jetzt unter Einstellungen ergänzen?',
|
||
profileLink: 'Zu den Einstellungen',
|
||
generate: 'Vertrag erzeugen',
|
||
generating: 'Vertrag wird erzeugt …',
|
||
successTitle: 'Vertrag erstellt!',
|
||
successText:
|
||
'Die Tiere wurden als „Abgegeben“ markiert (Abnehmer und Abgabedatum gesetzt).',
|
||
downloadDocx: 'Vertrag herunterladen (.docx)',
|
||
toList: 'Zur Vertragsliste',
|
||
anotherOne: 'Weiteren Vertrag erstellen',
|
||
},
|
||
},
|
||
// ── FEAT-13 (Kelly): Einstellungen (Zuchtprofil) ──
|
||
einstellungen: {
|
||
title: 'Einstellungen',
|
||
zuchtprofil: {
|
||
title: 'Zuchtprofil',
|
||
intro:
|
||
'Diese Angaben erscheinen als Verkäufer-Block in jedem Abgabevertrag.',
|
||
incompleteHint:
|
||
'Noch unvollständig: Name, Adresse und Ort werden für den Vertrag benötigt.',
|
||
fields: {
|
||
zuchtName: 'Zuchtname',
|
||
name: 'Vor- und Nachname',
|
||
nameHint: 'Mit Anrede, z. B. „Frau Erika Muster“.',
|
||
address: 'Adresse',
|
||
addressHint: 'Straße Nr, PLZ Ort.',
|
||
phone: 'Telefon',
|
||
email: 'E-Mail',
|
||
homepage: 'Homepage',
|
||
city: 'Ort (Unterschriftszeile)',
|
||
},
|
||
save: 'Speichern',
|
||
saving: 'Speichern …',
|
||
saved: 'Gespeichert.',
|
||
},
|
||
},
|
||
// ── INBOX-1 (Kelly): Anfragen-Posteingang ──
|
||
anfragen: {
|
||
title: 'Anfragen',
|
||
empty: 'Keine Anfragen — hole neue E-Mails mit „Anfragen abrufen“.',
|
||
emptyFiltered: 'Keine Anfragen mit diesem Status.',
|
||
countText: (n: number) => (n === 1 ? '1 Anfrage' : `${n} Anfragen`),
|
||
sync: 'Anfragen abrufen',
|
||
syncing: 'Abrufen …',
|
||
syncImported: (n: number) =>
|
||
n === 0 ? 'Keine neuen Anfragen.' : n === 1 ? '1 neue Anfrage abgerufen.' : `${n} neue Anfragen abgerufen.`,
|
||
mailNotConfigured:
|
||
'Gmail ist noch nicht eingerichtet — Adresse und App-Passwort folgen in den Einstellungen.',
|
||
mailAuthFailed:
|
||
'Gmail-Anmeldung fehlgeschlagen — bitte das App-Passwort neu eintragen.',
|
||
filterAll: 'Alle',
|
||
statusLabels: {
|
||
New: 'Neu',
|
||
InProgress: 'In Bearbeitung',
|
||
Assigned: 'Zugeordnet',
|
||
Answered: 'Beantwortet',
|
||
Abandoned: 'Verworfen',
|
||
},
|
||
// Detailansicht
|
||
detail: {
|
||
back: 'Zurück zur Liste',
|
||
notFound: 'Diese Anfrage wurde nicht gefunden.',
|
||
from: 'Von',
|
||
receivedAt: 'Eingegangen',
|
||
answeredAt: 'Beantwortet am',
|
||
message: 'Nachricht',
|
||
noBody: '(kein Text)',
|
||
noSubject: '(kein Betreff)',
|
||
// Triage
|
||
triage: 'Bearbeitung',
|
||
statusLabel: 'Status',
|
||
abandon: 'Verwerfen',
|
||
abandonConfirm: 'Anfrage wirklich verwerfen?',
|
||
assignContact: 'Abnehmer zuordnen',
|
||
assignNone: '— kein Abnehmer —',
|
||
assignedTo: 'Zugeordneter Abnehmer',
|
||
// Antwort
|
||
reply: 'Antwort',
|
||
replyPlaceholder: 'Antwort schreiben oder mit KI entwerfen …',
|
||
draftButton: 'Antwort entwerfen',
|
||
drafting: 'Entwurf wird erstellt …',
|
||
draftHint: 'Die KI erstellt nur einen Entwurf — gesendet wird erst nach deiner Bestätigung.',
|
||
aiKeyMissing: 'KI-Schlüssel fehlt — der Entwurfs-Assistent wird mit dem Schlüssel aktiviert.',
|
||
aiUpstreamError: 'Der KI-Dienst hat gerade ein Problem — bitte später erneut versuchen.',
|
||
send: 'Antwort senden',
|
||
sending: 'Senden …',
|
||
sendConfirm: 'Antwort jetzt per E-Mail senden?',
|
||
sendEmptyBody: 'Bitte zuerst eine Antwort schreiben.',
|
||
sent: 'Antwort gesendet — die Anfrage ist als „Beantwortet“ markiert.',
|
||
},
|
||
},
|
||
// ── FEAT-2 (Oscar): Kontakte (Contacts — Herkunft/Abnehmer) ──
|
||
kontakte: {
|
||
title: 'Kontakte',
|
||
newButton: 'Neuer Kontakt',
|
||
empty: 'Keine Kontakte gefunden.',
|
||
countLabel: 'Kontakte',
|
||
searchPlaceholder: 'Name suchen …',
|
||
// FEAT-13: contactInfo (Freitext) wurde durch strukturierte Felder ersetzt
|
||
// (DATA-2-Schema: email/phone/address) — gebraucht für den Käufer-Block der Verträge.
|
||
fields: {
|
||
name: 'Name',
|
||
email: 'E-Mail',
|
||
phone: 'Telefon',
|
||
address: 'Adresse',
|
||
notes: 'Notizen',
|
||
},
|
||
linked: {
|
||
title: 'Verknüpfte Tiere',
|
||
empty: 'Diesem Kontakt sind keine Tiere zugeordnet.',
|
||
originRole: 'Herkunft von',
|
||
receiverRole: 'Abnehmer von',
|
||
},
|
||
detail: {
|
||
edit: 'Bearbeiten',
|
||
back: 'Zurück zur Liste',
|
||
notFound: 'Dieser Kontakt wurde nicht gefunden.',
|
||
},
|
||
form: {
|
||
createTitle: 'Neuen Kontakt anlegen',
|
||
editTitle: 'Kontakt bearbeiten',
|
||
addressHint: 'Straße Nr, PLZ Ort — so erscheint sie im Abgabevertrag.',
|
||
save: 'Speichern',
|
||
cancel: 'Abbrechen',
|
||
saving: 'Speichern …',
|
||
},
|
||
validation: {
|
||
nameRequired: 'Bitte einen Namen eingeben.',
|
||
},
|
||
delete: {
|
||
action: 'Löschen',
|
||
confirmMessage: 'Soll dieser Kontakt wirklich gelöscht werden?',
|
||
conflict:
|
||
'Kontakt ist noch mit Tieren verknüpft (Herkunft/Abnehmer) und kann nicht gelöscht werden.',
|
||
},
|
||
},
|
||
// ── FEAT-6 (Oscar): Tier-Detail-Tabs (Gesundheit / Gewicht / Fotos) ──
|
||
tierTabs: {
|
||
actions: {
|
||
save: 'Speichern',
|
||
saving: 'Speichern …',
|
||
cancel: 'Abbrechen',
|
||
edit: 'Bearbeiten',
|
||
delete: 'Löschen',
|
||
},
|
||
health: {
|
||
empty: 'Noch keine Gesundheitseinträge.',
|
||
newButton: 'Neuer Eintrag',
|
||
createTitle: 'Neuer Gesundheitseintrag',
|
||
editTitle: 'Gesundheitseintrag bearbeiten',
|
||
fields: {
|
||
date: 'Datum',
|
||
type: 'Art',
|
||
description: 'Beschreibung',
|
||
veterinarian: 'Tierarzt',
|
||
},
|
||
typeLabels: {
|
||
Examination: 'Untersuchung',
|
||
Treatment: 'Behandlung',
|
||
Injury: 'Verletzung',
|
||
Vaccination: 'Impfung',
|
||
Other: 'Sonstiges',
|
||
},
|
||
validation: {
|
||
dateRequired: 'Bitte ein Datum angeben.',
|
||
descriptionRequired: 'Bitte eine Beschreibung eingeben.',
|
||
},
|
||
deleteConfirm: 'Diesen Gesundheitseintrag wirklich löschen?',
|
||
},
|
||
weight: {
|
||
addTitle: 'Gewicht erfassen',
|
||
fields: {
|
||
date: 'Datum',
|
||
weightGrams: 'Gewicht (g)',
|
||
},
|
||
addButton: 'Hinzufügen',
|
||
adding: 'Speichern …',
|
||
historyTitle: 'Verlauf',
|
||
chartTitle: 'Gewichtsverlauf',
|
||
chartNeedsTwo: 'Für die Verlaufskurve sind mindestens zwei Einträge nötig.',
|
||
empty: 'Noch keine Gewichtseinträge.',
|
||
gramsSuffix: 'g',
|
||
validation: {
|
||
dateRequired: 'Bitte ein Datum angeben.',
|
||
weightRequired: 'Bitte ein Gewicht in Gramm eingeben.',
|
||
weightRange: 'Bitte ein plausibles Gewicht zwischen 1 und 500 g eingeben.',
|
||
},
|
||
deleteConfirm: 'Diesen Gewichtseintrag wirklich löschen?',
|
||
},
|
||
photos: {
|
||
empty: 'Noch keine Fotos.',
|
||
uploadTitle: 'Foto hochladen',
|
||
chooseFile: 'Foto auswählen',
|
||
captionLabel: 'Bildunterschrift (optional)',
|
||
uploadButton: 'Hochladen',
|
||
uploading: 'Hochladen …',
|
||
profileBadge: 'Profilfoto',
|
||
deleteConfirm: 'Dieses Foto wirklich löschen?',
|
||
validation: {
|
||
fileRequired: 'Bitte zuerst ein Foto auswählen.',
|
||
},
|
||
},
|
||
},
|
||
// ── EXPORT-1 (Oscar): Datenexport (Karte auf /einstellungen) ──
|
||
datenexport: {
|
||
title: 'Datenexport',
|
||
intro:
|
||
'Sicherung deiner Daten — alle Tiere, Würfe und Kontakte als Tabellen (CSV für Excel) plus eine vollständige Datensicherung (JSON), gebündelt als Zip.',
|
||
button: 'Export herunterladen',
|
||
photoNote:
|
||
'Fotos sind nicht enthalten — sie liegen als Bilddateien im Datenordner der Anwendung und können von dort gesichert werden.',
|
||
},
|
||
// ── WEB-0b (Kevin): CMS-Verwaltung der öffentlichen Webseite ──
|
||
webseite: {
|
||
title: 'Webseite',
|
||
intro:
|
||
'Hier pflegst du die Inhalte deiner öffentlichen Webseite. Änderungen werden erst beim Veröffentlichen online sichtbar.',
|
||
empty: 'Es sind noch keine Seiten angelegt.',
|
||
statusLabel: 'Status',
|
||
statusDraft: 'Entwurf',
|
||
statusPublished: 'Veröffentlicht',
|
||
edit: 'Bearbeiten',
|
||
back: 'Zurück zur Übersicht',
|
||
// Seiten-Editor (Kopf)
|
||
editor: {
|
||
pageTitleLabel: 'Seitentitel',
|
||
seoLabel: 'Beschreibung für Suchmaschinen (SEO)',
|
||
seoHint: 'Kurzer Text (ca. 1–2 Sätze), der bei Google unter dem Titel erscheint.',
|
||
save: 'Seite speichern',
|
||
saved: 'Seite gespeichert.',
|
||
},
|
||
// Block-Editor
|
||
blocks: {
|
||
sectionTitle: 'Inhaltsblöcke',
|
||
empty: 'Diese Seite hat noch keine Inhaltsblöcke. Füge unten den ersten hinzu.',
|
||
addLabel: 'Block hinzufügen:',
|
||
moveUp: 'Nach oben',
|
||
moveDown: 'Nach unten',
|
||
delete: 'Block löschen',
|
||
confirmDelete: 'Diesen Block wirklich löschen?',
|
||
save: 'Block speichern',
|
||
saved: 'Gespeichert.',
|
||
// Block-Typ-Namen
|
||
types: {
|
||
Heading: 'Überschrift',
|
||
RichText: 'Textabschnitt',
|
||
Image: 'Bild',
|
||
Gallery: 'Bildergalerie',
|
||
ContactInfo: 'Kontaktangaben',
|
||
AbgabetiereList: 'Abgabetiere (automatisch)',
|
||
},
|
||
// Feld-Beschriftungen je Block-Typ
|
||
fields: {
|
||
headingText: 'Überschrift-Text',
|
||
headingLevel: 'Größe',
|
||
levelMain: 'Hauptüberschrift',
|
||
levelSub: 'Unterüberschrift',
|
||
markdown: 'Text',
|
||
markdownHint:
|
||
'Einfache Formatierung möglich: **fett**, *kursiv*, Listen mit „- “, Links als [Text](https://…).',
|
||
imageUrl: 'Bild-Adresse (URL)',
|
||
imageAlt: 'Bildbeschreibung (für Suchmaschinen & Barrierefreiheit)',
|
||
galleryImages: 'Bilder',
|
||
galleryAdd: 'Bild hinzufügen',
|
||
galleryRemove: 'Entfernen',
|
||
contactName: 'Name',
|
||
contactEmail: 'E-Mail',
|
||
contactPhone: 'Telefon',
|
||
contactAddress: 'Adresse',
|
||
abgabeIntro: 'Einleitungstext',
|
||
abgabeAutoNote:
|
||
'Die Liste der Abgabetiere wird beim Veröffentlichen automatisch aus deinen aktuellen Abgabetieren erzeugt. Du kannst nur den Einleitungstext bearbeiten.',
|
||
},
|
||
},
|
||
},
|
||
},
|
||
// ── HELP-1: In-App-Anleitung ──
|
||
hilfe: {
|
||
title: 'Hilfe & Anleitung',
|
||
subtitle: 'Kurzanleitung für den Rennmaus-Manager',
|
||
sections: {
|
||
ersteSchritte: 'Erste Schritte',
|
||
tiere: 'Rennmäuse anlegen & Fotos',
|
||
becken: 'Becken',
|
||
wuerfe: 'Würfe & Jungtiere',
|
||
genetik: 'Probeverpaarung & Genetik',
|
||
stammbaum: 'Stammbaum',
|
||
abgabe: 'Abgabe-Ablauf',
|
||
// FEAT-13-Followup (Kelly): Vertrag + Zuchtprofil
|
||
vertraege: 'Abgabevertrag erstellen',
|
||
einstellungen: 'Zuchtprofil (Einstellungen)',
|
||
statistik: 'Statistik',
|
||
datensicherung: 'Datensicherung',
|
||
},
|
||
},
|
||
api: {
|
||
errors: {
|
||
network: 'Verbindung zum Server fehlgeschlagen. Bitte später erneut versuchen.',
|
||
notFound: 'Der Eintrag wurde nicht gefunden.',
|
||
server: 'Auf dem Server ist ein Fehler aufgetreten.',
|
||
unknown: 'Ein unbekannter Fehler ist aufgetreten.',
|
||
},
|
||
},
|
||
common: {
|
||
loading: 'Lädt …',
|
||
retry: 'Erneut versuchen',
|
||
previous: 'Zurück',
|
||
next: 'Weiter',
|
||
page: 'Seite',
|
||
of: 'von',
|
||
yes: 'Ja',
|
||
no: 'Nein',
|
||
delete: 'Löschen',
|
||
confirmDelete: 'Wirklich löschen?',
|
||
pageNav: 'Seitennavigation',
|
||
},
|
||
// Genetik-Warnungen: der Engine (src/genetics) liefert nur CODES,
|
||
// die deutschen Texte stehen hier. Schlüssel = GeneticsWarningCode-Werte.
|
||
genetics: {
|
||
warnings: {
|
||
SCHECKE_LETHAL:
|
||
'Schecke × Schecke: Reinerbige Tiere (SpSp) sterben bereits im Mutterleib — etwa ein Viertel weniger Jungtiere.',
|
||
REX_SEMI_LETHAL:
|
||
'Rex × Rex: Reinerbige Tiere (ReRe) sind nur eingeschränkt lebensfähig.',
|
||
SLS_LETHAL:
|
||
'WP × WP: Reinerbige Tiere (S(l)S(l)) sterben bereits im Mutterleib (Rumpback) — weniger Jungtiere.',
|
||
SUPERSCHECKE_DEAF:
|
||
'Schecke × WP: Superschecken (sehr hoher Weißanteil) sind möglich — erhöhtes Taubheitsrisiko.',
|
||
},
|
||
unknownFarbschlag: 'Unbekannter Farbschlag',
|
||
},
|
||
// ── FEAT-14 (Kevin): Charakterbogen — Eigenschaften + Notiz, speist den KI-Verkaufstext ──
|
||
// Traits: stabile KEYS (gespeichert) + deutsche LABELS (UI + KI-Prompt).
|
||
// Erweitern = eine Zeile in der Liste; Julian verfeinert die Auswahl.
|
||
character: {
|
||
sectionTitle: 'Charakter & Eigenschaften',
|
||
noteLabel: 'Notizen zum Charakter',
|
||
notePlaceholder: 'Ein paar Sätze zum Charakter dieses Tieres …',
|
||
save: 'Charakter speichern',
|
||
saved: 'Charakter gespeichert.',
|
||
none: 'Noch keine Eigenschaften ausgewählt.',
|
||
traits: [
|
||
{ key: 'zutraulich', label: 'zutraulich' },
|
||
{ key: 'handzahm', label: 'handzahm' },
|
||
{ key: 'neugierig', label: 'neugierig' },
|
||
{ key: 'aufgeschlossen', label: 'aufgeschlossen' },
|
||
{ key: 'ruhig', label: 'ruhig / ausgeglichen' },
|
||
{ key: 'lebhaft', label: 'lebhaft / aktiv' },
|
||
{ key: 'verschmust', label: 'verschmust' },
|
||
{ key: 'eigenstaendig', label: 'eigenständig' },
|
||
{ key: 'anfaengergeeignet', label: 'anfängergeeignet' },
|
||
{ key: 'futterfreudig', label: 'futterfreudig' },
|
||
{ key: 'buddelt', label: 'buddelt gern' },
|
||
{ key: 'klettert', label: 'klettert gern' },
|
||
{ key: 'laufrad', label: 'läuft gern im Laufrad' },
|
||
{ key: 'vertraeglich', label: 'gut verträglich' },
|
||
{ key: 'schreckhaft', label: 'schreckhaft' },
|
||
],
|
||
},
|
||
} as const
|
||
|
||
export type Strings = typeof de
|