/** * 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: { gerbils: 'Rennmäuse', litters: 'Würfe', breeders: 'Züchter', genetics: 'Genetik', // FEAT-2 (Oscar): Becken + Kontakte (GEHEGE-RENAME: Becken → Gehege) enclosures: 'Gehege', contacts: 'Kontakte', // FEAT-7 (Kelly): Statistik statistics: 'Statistik', // FEAT-7 (Kevin): „Mehr“-Overflow auf dem Smartphone more: 'Mehr', // FEAT-12a (Kevin): Abgabe forSale: 'Abgabe', // ABGABE-STATUS: Reservierungs-/Abgabe-Status (verfügbar → reserviert → abgegeben) reservations: 'Reservierungen', // FEAT-13 (Kelly): Verträge + Einstellungen contracts: 'Verträge', settings: 'Einstellungen', // INBOX-1 (Kelly): Anfragen-Posteingang requests: 'Anfragen', // WAITLIST: Warteliste/Nachfrage (RennmausPro nachfrage_tb) waitingList: 'Warteliste', // RÜCKNAHMEN: zurückgekommene/zurückgenommene Tiere returns: 'Rücknahmen', openMenu: 'Menü öffnen', closeMenu: 'Menü schließen', mainNavigation: 'Hauptnavigation', // HELP-1 help: 'Hilfe', // WEB-0b (Kevin): CMS-Verwaltung der öffentlichen Webseite website: 'Webseite', colorCatalog: 'Farbkatalog', }, pages: { gerbils: { title: 'Rennmäuse', nameless: '(ohne Namen)', // Liste newButton: 'Neue Rennmaus', empty: 'Keine Rennmäuse gefunden.', countLabel: 'Tiere', searchPlaceholder: 'Name suchen …', // DESIGN (Rennmaus Filter): „geb." Präfix vor dem Geburtsdatum auf der Karte. born: 'geb.', // Zurück-nach-oben-Button (erscheint beim Scrollen der langen Liste). backToTop: 'Nach oben', // 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', // DESIGN (Rennmaus Filter): kurze Variante für den Toggle-Chip. showExternalShort: 'Externe Ahnen', showExternalHint: 'Tiere aus fremden Zuchten, die nur für den Stammbaum erfasst sind.', // BESTAND-FILTER: Tiere ohne Geburtsdatum ausblenden (Toggle-Chip neben „Externe Ahnen“). hideUndatedShort: 'Mit Geburtsdatum', hideUndatedHint: 'Tiere ohne hinterlegtes Geburtsdatum ausblenden.', }, // 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: 'Gehege', colorVariety: 'Farbschlag', origin: 'Herkunft', originBreeder: 'Herkunft (Freitext)', isDeaf: 'Gehörlos', receiver: 'Abnehmer', genotype: 'Genotyp', isCastrated: 'Kastrat', notes: 'Notizen', spottingType: 'Scheckungsart', }, // Detailseite detail: { masterData: 'Stammdaten', genetics: 'Genetik', resolvedFarbschlag: 'Errechneter Farbschlag', resolvedPrefix: 'Errechnet', farbschlagMismatch: 'Weicht vom eingetragenen Farbschlag ab.', genotypeNotSet: 'Kein Genotyp hinterlegt.', // GEN-5: ein unbekannter Gencode-Buchstabe wurde aus einem reinerbigen // Elternteil ergänzt (z. B. Vater ee ⇒ Kind erbt e). %s = aufgelöster Genotyp. genotypeInferred: 'Aus den Eltern ergänzt', genotypeInferredTitle: 'Ein unbekanntes Gen wurde aus einem reinerbigen Elternteil abgeleitet.', testMating: 'Probeverpaarung', edit: 'Bearbeiten', back: 'Zurück zur Liste', tabs: { photos: 'Fotos', health: 'Gesundheit', weight: 'Gewicht', exhibitions: 'Ausstellungen', }, tabPlaceholder: 'Dieser Bereich entsteht in einem späteren Schritt.', notFound: 'Diese Rennmaus wurde nicht gefunden.', moreData: 'Weitere Daten', // ANIMAL-LITTERS: Würfe als Elternteil parentLittersTitle: 'Würfe als Elternteil', parentLittersEmpty: 'Keine Würfe als Elternteil erfasst.', parentLittersRoleVater: 'Vater', parentLittersRoleMutter: 'Mutter', // WURFCHRONIK-FILTER: Wurf ist nicht in der Wurfchronik (showInChronicle=false), // wird daher nur hier (am Elterntier) gezeigt, nicht in der Wurf-Liste. parentLittersNotInChronicle: 'Nicht in der Wurfchronik', offspringInBreedingTitle: 'Nachzucht in der Zucht', offspringInBreedingEmpty: 'Keine Nachkommen dieses Tiers sind in die Zucht gegangen.', // Hinweis: Eltern dieses Tiers sind Vollgeschwister (gleicher Wurf). siblingPairing: 'Geschwisterverpaarung', siblingPairingTitle: 'Die Eltern dieses Tiers stammen aus demselben Wurf (Vollgeschwister).', // Externe Tiere (nur als Vorfahre erfasst): Würfe & Charakter werden // ausgeblendet, da das Tier nie im eigenen Bestand war. nonResidentNote: 'Externes Tier — nur als Vorfahre erfasst. Würfe und Charakter werden nicht angezeigt, da es nie im eigenen Bestand war.', // Vorfahren-Nachzucht-Zeile: statt Wurf-Karten nur ein Hinweis auf die Nachzucht. nonResidentOffspringLabel: 'Nachzucht dieses Vorfahren:', // Positives „Zuchttier“-Kennzeichen (Tier hatte eigene Würfe in der Zucht). zuchttierBadge: '★ Zuchttier', zuchttierBadgeTitle: 'Dieses Tier wurde bei dir in der Zucht eingesetzt (hatte eigene Würfe).', // Zeile „Zuchtpartner“ in den Stammdaten (bisherige Verpaarungspartner). zuchtpartner: 'Zuchtpartner', }, // Formular (anlegen/bearbeiten) form: { createTitle: 'Neue Rennmaus anlegen', editTitle: 'Rennmaus bearbeiten', none: '— keine Angabe —', // Herkunft-Standardoption: eigene Zucht (leere Herkunft = selbst gezüchtet). ownBreeding: 'Eigene Zucht', genotypeHint: 'Optional. Format z. B. „Aa CC Dd EE GG Pp Spsp rere“. Unbekannte Allele als „-“.', // BESTAND-FILTER: Zuchtanwärter/in (eigenes Zuchttier) vs. reine Ahne isResidentLabel: 'Zuchtanwärter/innen', isResidentHint: 'Abwählen für reine Vorfahren, die nur für den Stammbaum erfasst sind und keine eigenen Zuchttiere waren.', isDeafUnknown: 'Unbekannt', isDeafYes: 'Ja', isDeafNo: 'Nein', isScheckeLabel: 'Ist eine Schecke', colorSectionTitle: 'Farbe & Genetik', // STATUS-MODEL: Hinweis für abgeleitete Statuswerte statusDerivedHint: { Deceased: 'Wird automatisch gesetzt wenn Todesdatum erfasst.', GivenAway: 'Wird automatisch gesetzt nach Abgabe.', }, 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', }, // STATUS-MODEL: Breeding/Pet ersetzen Active; Deceased+GivenAway = abgeleitet (Backend) statusLabels: { Breeding: 'Zucht', Pet: 'Liebhaber', Deceased: 'Verstorben', GivenAway: 'Abgegeben', ForSale: 'Zur Abgabe', }, spottingTypes: { none: '— keine Scheckungsart —', notRecorded: 'noch nicht erfasst', Punktschecke: 'Punktschecke', Kragenschecke: 'Kragenschecke', Ansatzschecke: 'Ansatzschecke', Starkschecke: 'Starkschecke', Superschecke: 'Superschecke', 'DP (Dark Patch)': 'DP (Dark Patch)', WP: 'Minimalschecke (WP)', wp: 'WP', }, }, // ── 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', searchPlaceholder: 'Wurf suchen …', filterYear: 'Jahr', allYears: 'Alle Jahre', sort: { dateDesc: 'Wurfdatum (neueste)', dateAsc: 'Wurfdatum (älteste)', nameAsc: 'Alphabetisch (A-Z)', nameDesc: 'Alphabetisch (Z-A)', }, // Felder fields: { name: 'Bezeichnung', date: 'Wurfdatum', father: 'Vater', mother: 'Mutter', totalBorn: 'Wurfstärke', deathsWithin8Weeks: 'In den ersten 8 Wochen verstorben', stillborn: 'Totgeburten', expectedGoHomeDate: 'Voraussichtliches Abgabedatum', socializeDate: 'Vergesellschaftung (ab 8 Wochen)', groupGoHomeDate: 'Abgabe als Gruppe (ab 10 Wochen)', 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.', // LITTER-JUVENILE-DETAILS: pro-Jungtier-Felder juvenileFields: { colorVariety: 'Farbschlag', goHomeDate: 'Abgegeben', receiver: 'Abnehmer', dateOfDeath: 'Verstorben', causeOfDeath: 'Todesursache', }, }, // 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.', deathsExceedTotalBorn: 'Die Anzahl der Frühverluste darf die Wurfstärke nicht überschreiten.', }, // 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.', }, farbkatalog: { title: 'Farbkatalog', subtitle: 'Übersicht aller {count} registrierten Farbschläge und deren genetischen Formeln.', searchPlaceholder: 'Nach Name, englischem Begriff oder Genen suchen (z. B. \'Zobel\', \'dd\', \'ee\', \'pp\')...', empty: 'Keine Farbschläge gefunden, die Ihrer Suche entsprechen.', }, 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 Gehege vorgeschlagen', ungrouped: 'Ohne Gehege', 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.', }, }, // ── ABGABE-STATUS: Reservierungs-/Abgabe-Status (verfügbar → reserviert → abgegeben) ── reservierungen: { title: 'Reservierungen', subtitle: 'Reservierungs- und Abgabe-Status der Abgabetiere verwalten.', loadError: 'Reservierungen konnten nicht geladen werden.', empty: 'Noch keine Reservierungen erfasst.', newButton: 'Neue Reservierung', // Status-Werte (Anzeige). status: { verfuegbar: 'Verfügbar', reserviert: 'Reserviert', abgegeben: 'Abgegeben', }, // Filter-Chips nach Status. filters: { all: 'Alle', verfuegbar: 'Verfügbar', reserviert: 'Reserviert', abgegeben: 'Abgegeben', }, // Spalten / Feld-Beschriftungen. fields: { animal: 'Tier', status: 'Status', reservedFor: 'Reserviert für', appointment: 'Termin', price: 'Preis', note: 'Notiz', handedOver: 'Abgegeben am', none: '—', }, // Formular (Anlegen / Bearbeiten). form: { addTitle: 'Reservierung anlegen', editTitle: 'Reservierung bearbeiten', animal: 'Tier', animalPlaceholder: 'Tier auswählen …', status: 'Status', reservedFor: 'Reserviert für (Kontakt)', contactNone: '— niemand —', appointment: 'Termin', price: 'Preis (€)', note: 'Notiz', handedOver: 'Abgegeben am', save: 'Speichern', cancel: 'Abbrechen', saveError: 'Speichern fehlgeschlagen.', chooseAnimal: 'Bitte ein Tier auswählen.', }, // Aktionen pro Zeile. actions: { edit: 'Bearbeiten', delete: 'Löschen', markReserved: 'Reservieren', markHandedOver: 'Als abgegeben markieren', markAvailable: 'Wieder freigeben', confirmDelete: 'Diese Reservierung wirklich löschen?', deleteError: 'Löschen fehlgeschlagen.', }, // Hinweis: Status ≠ Vertrag. contractHint: 'Hinweis: Der Status ist eine Vormerkung. Die rechtliche Abgabe erfolgt weiterhin über einen Vertrag.', }, // ── FEAT-2 (Oscar): Gehege (Enclosures) — GEHEGE-RENAME: Becken → Gehege ── becken: { title: 'Gehege', newButton: 'Neues Gehege', empty: 'Keine Gehege gefunden.', countLabel: 'Gehege', searchPlaceholder: 'Name suchen …', fields: { name: 'Name', notes: 'Notizen', // Reinigungszyklus (RennmausPro becken_tb). size: 'Maße', capacity: 'Empf. Tieranzahl', lastCleanedDate: 'Zuletzt gereinigt', cleaningCycleDays: 'Reinigungszyklus (Tage)', nextCleaningDate: 'Nächste Reinigung', }, // Reinigungszyklus: Hinweise + Aktion auf der Detailseite. cleaning: { title: 'Reinigung', due: 'Reinigung fällig', dueSince: (date: string) => `Reinigung fällig (seit ${date})`, nextOn: (date: string) => `Nächste Reinigung am ${date}`, noCycle: 'Kein Reinigungszyklus hinterlegt.', neverCleaned: 'Noch nie als gereinigt vermerkt.', markCleaned: 'Als gereinigt markieren', marking: 'Wird gespeichert …', marked: 'Reinigung vermerkt.', capacityUnit: (n: number) => `${n} ${n === 1 ? 'Tier' : 'Tiere'}`, cycleUnit: (n: number) => `alle ${n} Tage`, }, // Bilder-Sektion auf der Gehege-Detailseite. photosTitle: 'Bilder', occupancy: { title: 'Bewohner', empty: 'Dieses Gehege ist derzeit leer.', countOne: 'Tier', countMany: 'Tiere', }, detail: { edit: 'Bearbeiten', back: 'Zurück zur Liste', notFound: 'Dieses Gehege wurde nicht gefunden.', }, form: { createTitle: 'Neues Gehege anlegen', editTitle: 'Gehege bearbeiten', save: 'Speichern', cancel: 'Abbrechen', saving: 'Speichern …', }, validation: { nameRequired: 'Bitte einen Namen eingeben.', }, delete: { action: 'Löschen', confirmMessage: 'Soll dieses Gehege wirklich gelöscht werden?', conflict: 'Gehege ist nicht leer — bitte zuerst alle Tiere in ein anderes Gehege 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.', /** Mini-Legende unter dem Baum (STAMMBAUM-EXPAND). */ hintName: 'Namenslink: Tierakte öffnen', hintExpand: '+: weitere Vorfahren nachladen', hintContext: 'Rechtsklick (oder Karte lange gedrückt halten): ID kopieren / Fehler melden', hintSiblings: '⟲: Eltern sind Geschwister — gemeinsame Vorfahren siehe Vaterlinie', /** Verweis-Knoten bei Geschwister-Verpaarung (Vater & Mutter aus demselben Wurf). */ siblingPairing: { refLabel: (name: string) => `Geschwister von ${name}`, refHint: 'Eltern siehe oben', }, /** Würfe-Panel links (STAMMBAUM-LITTERS). */ littersTitle: 'Würfe', littersJunge: 'Junge', 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.', }, /** FEEDBACK: Rechtsklick-Kontextmenü auf einer Stammbaum-Karte. */ contextMenu: { copyId: 'ID kopieren', reportError: 'Fehler melden', }, }, // ── 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: 'Word', downloadPdf: 'PDF', noWordFileShort: 'Keine Word-Datei', noWordFile: 'Für importierte Verträge liegt keine Word-Datei vor — das PDF wird aus den Daten erzeugt.', 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.', photoLabel: 'Foto für den Vertrag', photoNone: 'Kein Foto', // 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', nameSuffix: 'Namens-Anhängsel der Zucht', nameSuffixHint: 'Wird wie ein „Nachname" an eigene Tiere angehängt, z. B. „von den kleinen Chaoten“ → „Danako von den kleinen Chaoten“.', 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 …', // Quick-Chip-Filter nach Rolle (Züchter / Abnehmer). filters: { role: 'Rolle', breeder: 'Züchter', receiver: 'Abnehmer', }, // 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', isBreeder: 'Ist Züchter (Zucht)', isReceiver: 'Ist Abnehmer (Käufer)', nameSuffix: 'Namens-Anhängsel der Zucht', nameSuffixHint: 'Wird an Tiere aus dieser Zucht angehängt, z. B. „von den Wüstenwinden“.', }, 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.', }, }, // ERWERB: Erwerb/Kauf je Tier (Kaufdatum, Preis, Notiz) — eigene Sektion in der Akte. acquisition: { sectionTitle: 'Erwerb', intro: 'Wann und zu welchem Preis dieses Tier erworben wurde.', addTitle: 'Erwerb erfassen', editTitle: 'Erwerb bearbeiten', fields: { date: 'Kaufdatum', price: 'Preis (€)', note: 'Notiz', }, addButton: 'Hinzufügen', saveButton: 'Speichern', saving: 'Speichern …', cancel: 'Abbrechen', edit: 'Bearbeiten', delete: 'Löschen', empty: 'Noch keine Erwerbsdaten erfasst.', noDate: 'Ohne Datum', noPrice: '—', deleteConfirm: 'Diesen Erwerbseintrag wirklich löschen?', validation: { empty: 'Bitte mindestens Kaufdatum, Preis oder Notiz angeben.', priceRange: 'Bitte einen plausiblen Preis (0 bis 9999 €) angeben.', }, }, // ── Ausstellungen/Auszeichnungen je Tier (RennmausPro ausz_tb) ── exhibitions: { empty: 'Noch keine Ausstellungsergebnisse erfasst.', newButton: 'Neues Ergebnis', createTitle: 'Neues Ausstellungsergebnis', editTitle: 'Ausstellungsergebnis bearbeiten', fields: { eventName: 'Veranstaltung', date: 'Datum', placement: 'Platzierung', award: 'Auszeichnung', note: 'Notiz', }, placeholders: { eventName: 'z. B. Nationale Rennmausschau 2026', placement: 'z. B. 1. Platz', award: 'z. B. Best in Show', }, validation: { eventNameRequired: 'Bitte eine Veranstaltung angeben.', }, deleteConfirm: 'Dieses Ausstellungsergebnis wirklich löschen?', }, }, // ── 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', // ── WEB-3 (Kelly): lokale Vorschau ── vorschau: { button: 'Vorschau', title: 'Vorschau der Webseite', intro: 'So sieht deine Webseite nach dem Veröffentlichen aus. Entwürfe erscheinen hier noch nicht.', pageSelect: 'Seite', reload: 'Neu laden', viewPhone: 'Smartphone', viewDesktop: 'Desktop', frameTitle: 'Vorschau der öffentlichen Webseite', empty: 'Noch keine veröffentlichte Seite — stelle eine Seite auf „Veröffentlicht“, um die Vorschau zu sehen.', draftHint: 'Entwurf — erscheint noch nicht in der Vorschau.', openPage: 'Ansehen', }, // 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.', }, }, }, // ── RPRO3: RennmausPro-III-Backup-Import (Rubrik unter „Hilfe") ── rpro3Import: { title: 'RennmausPro-Import', subtitle: 'Daten aus deiner alten RennmausPro-III-Software übernehmen — Tiere, Würfe, Stammbäume, Kontakte und Genotypen.', intro: 'Lade hier deine RennmausPro-Sicherungsdatei hoch (die Datei endet auf „.backup"). Optional kannst du zusätzlich das zugehörige Bilder-Archiv (endet auf „_bilder.zip") hochladen. Zuerst wird die Datei nur ausgewertet — es wird noch nichts gespeichert. Du siehst dann eine Übersicht und entscheidest selbst, ob du den Import durchführst.', // Umfang: was der Import übernimmt und was (noch) nicht. scope: { title: 'Was wird übernommen?', importedTitle: 'Wird übernommen', imported: [ 'Tiere (eigene + Ahnen aus fremden Zuchten) mit Stammbaum/Eltern', 'Farbschläge & Genotypen', 'Würfe (mit Eltern & Datum)', 'Kontakte (Züchter & Abnehmer)', 'Todesfälle & Todesursachen, Gewichte, Krankheiten, Fotos', 'Gehege inkl. Reinigungszyklus', 'Erwerb/Kauf, Reservierungen/Abgaben, Rücknahmen, Warteliste, Ausstellungen', ], notImportedTitle: 'Wird (noch) nicht übernommen', notImported: [ 'Finanzen (Einnahmen, Ausgaben, Artikel, Bestand/Kasse)', 'Termine & Kalender', 'Tierarzt-Stammdaten (Adressbuch der Tierärzte)', 'Tagebuch-Einträge als eigener Bereich (werden, falls vorhanden, als Gesundheitsnotiz „Sonstiges" abgelegt)', ], }, step1Title: '1. Dateien auswählen', backupLabel: 'RennmausPro-Sicherung (.backup)', backupHint: 'Pflicht. Die Datei aus deiner RennmausPro-III-Software.', imagesLabel: 'Bilder-Archiv (_bilder.zip)', imagesHint: 'Optional. Wird gebraucht, um die Tierfotos zuzuordnen.', analyzeButton: 'Auswerten', analyzing: 'Datei wird ausgewertet …', noBackup: 'Bitte zuerst eine RennmausPro-Sicherung (.backup) auswählen.', step2Title: '2. Auswertung', overviewTitle: 'Was steckt in der Datei?', counts: { ownAnimals: 'Eigene Tiere', externalAfterDedup: 'Externe Ahnen (nach Bereinigung)', externalRaw: 'Externe Ahnen (roh, vor Bereinigung)', litters: 'Würfe', contacts: 'Kontakte (Züchter & Abnehmer)', genotypes: 'Hinterlegte Genotypen', duplicatesMerged: 'Erkannte Dubletten (zusammengelegt)', }, newVsExistingTitle: 'Abgleich mit deinem aktuellen Bestand', newCount: (n: number) => `${n} Tiere wären neu`, existingCount: (n: number) => `${n} Tiere sind vermutlich schon vorhanden`, dedupExplain: 'RennmausPro hat beim Import vorhandene Tiere nicht erkannt — dadurch kommt dasselbe Tier oft mehrfach vor. Diese Dubletten werden automatisch anhand von Name, Geburtsdatum, Farbe und Herkunft zusammengelegt.', topMergesTitle: 'Größte automatische Zusammenlegungen', topMergesCol: { name: 'Tier', count: 'Datensätze', dob: 'Geburtsdatum', farbe: 'Farbe', origin: 'Herkunft' }, ambiguousTitle: 'Mehrdeutige Namen — bitte später prüfen', ambiguousIntro: 'Bei diesen Namen gibt es mehrere unterschiedliche Tiere. Sie werden vorsichtshalber NICHT automatisch zusammengelegt, damit nichts falsch verknüpft wird. Du kannst sie nach dem Import in der Tierliste prüfen.', ambiguousVariant: (count: number, dob: string, farbe: string, origin: string) => `${count}× · ${dob} · ${farbe} · ${origin}`, ambiguousOwn: 'eigenes Tier', ambiguousMore: (n: number) => `… und ${n} weitere mehrdeutige Namen.`, photosNote: (n: number) => `Bilder-Archiv erkannt: ${n} Bilddateien werden den Tieren zugeordnet.`, photosNoneNote: 'Kein Bilder-Archiv hochgeladen — Tiere werden ohne Fotos importiert.', step3Title: '3. Import durchführen', executeWarning: 'Beim Import werden die Tiere, Würfe, Kontakte und Genotypen aus RennmausPro übernommen. Ein erneuter Import aktualisiert dieselben Daten (es entstehen keine Dubletten). Deine manuell angelegten Tiere bleiben unberührt.', executeButton: 'Import jetzt durchführen', executing: 'Import läuft … das kann einen Moment dauern.', successTitle: 'Import abgeschlossen', resultCounts: { gerbils: 'Tiere importiert', litters: 'Würfe importiert', contacts: 'Kontakte importiert', health: 'Gesundheitseinträge', weights: 'Gewichtseinträge', photos: 'Fotos', }, errorTitle: 'Es ist ein Fehler aufgetreten', restart: 'Neue Datei auswählen', }, // ── WAITLIST (RennmausPro nachfrage_tb): Warteliste/Nachfrage ── warteliste: { title: 'Warteliste', subtitle: 'Interessenten warten auf bestimmte Tiere', newButton: 'Neuer Eintrag', empty: 'Keine Wartelisten-Einträge vorhanden.', emptyOpen: 'Keine offenen Einträge.', countLabel: 'Einträge', onlyOpen: 'Nur offene', loadError: 'Die Warteliste konnte nicht geladen werden.', saveError: 'Der Eintrag konnte nicht gespeichert werden.', deleteError: 'Der Eintrag konnte nicht gelöscht werden.', deleteConfirm: 'Diesen Wartelisten-Eintrag wirklich löschen?', // Status-Bezeichnungen (Backend-Werte: offen | erfuellt | storniert) status: { offen: 'Offen', erfuellt: 'Erfüllt', storniert: 'Storniert', }, // Geschlechts-Wunsch wishGender: { any: 'Egal', male: 'Männlich', female: 'Weiblich', }, fields: { contact: 'Kontakt', contactNone: '— kein Kontakt —', contactName: 'Name (falls kein Kontakt)', wishColor: 'Wunsch-Farbschlag', wishColorAny: 'Egal', wishGender: 'Wunsch-Geschlecht', requestedAt: 'Angefragt am', status: 'Status', note: 'Notiz', }, // Aktionen je Eintrag edit: 'Bearbeiten', delete: 'Löschen', save: 'Speichern', cancel: 'Abbrechen', formTitleNew: 'Neuer Wartelisten-Eintrag', formTitleEdit: 'Eintrag bearbeiten', validationName: 'Bitte einen Kontakt wählen oder einen Namen eingeben.', noContactLink: 'Kein Kontakt verknüpft', }, // ── RÜCKNAHMEN: zurückgekommene/zurückgenommene Tiere (getback_tb) ── ruecknahmen: { title: 'Rücknahmen', subtitle: 'Tiere, die zur Zucht zurückgekommen sind', countText: (n: number) => n === 1 ? '1 Rücknahme erfasst' : `${n} Rücknahmen erfasst`, empty: 'Noch keine Rücknahmen erfasst.', newButton: 'Rücknahme erfassen', // Formular formTitle: 'Rücknahme erfassen', editTitle: 'Rücknahme bearbeiten', fields: { gerbil: 'Tier', gerbilName: 'Tiername', gerbilNameHint: 'Falls das Tier nicht in der Liste steht, hier den Namen eintragen.', returnDate: 'Rücknahmedatum', returnPrice: 'Rücknahmepreis (€)', originalPrice: 'Ursprünglicher Abgabepreis (€)', originalSaleDate: 'Ursprüngliches Abgabedatum', fromContact: 'Zurück von (Kontakt)', fromContactName: 'Name (frei)', fromContactNameHint: 'Falls der Kontakt nicht in der Liste steht, hier den Namen eintragen.', note: 'Grund / Notiz', notePlaceholder: 'Warum kam das Tier zurück?', }, gerbilPlaceholder: '— Tier wählen —', contactPlaceholder: '— Kontakt wählen —', // Listen-Karte returnedOn: 'zurück am', from: 'von', unknownAnimal: '(unbekanntes Tier)', // Aktionen save: 'Speichern', saving: 'Wird gespeichert …', edit: 'Bearbeiten', cancel: 'Abbrechen', delete: 'Löschen', confirmDelete: 'Diese Rücknahme wirklich löschen?', validationNoAnimal: 'Bitte ein Tier wählen oder einen Tiernamen eintragen.', saveSuccess: 'Rücknahme gespeichert.', saveError: 'Rücknahme konnte nicht gespeichert werden.', }, }, // ── 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: 'Gehege', 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', rpro3Import: 'Daten aus RennmausPro übernehmen', }, // Verweis auf die eigene RennmausPro-Import-Rubrik. rpro3Link: { text: 'Hast du früher mit der Software „RennmausPro III" gearbeitet? Du kannst deine alten Daten (Tiere, Würfe, Stammbäume, Kontakte) bequem übernehmen.', button: 'Zum RennmausPro-Import', }, }, // ── GEPRÜFTE TIERE: „vollständig korrekt"-Markierung + Schutz manueller Änderungen ── // Ziel laienverständlich erklären: eine geprüfte Maus wird vom automatischen Import // nicht mehr verändert; so wird der Bestand Tier für Tier sauber. verified: { // Karte auf der Rennmausakte sectionTitle: 'Prüfstatus & Schutz', explainIntro: 'Wenn bei dieser Maus alle Angaben stimmen, markiere sie als „vollständig korrekt". ' + 'Der automatische Import verändert sie dann nicht mehr — deine geprüften Angaben bleiben erhalten. ' + 'So wird dein Bestand nach und nach sauber, ohne dass der Import raten muss.', explainProtected: 'Diese Maus enthält von dir geänderte Angaben. Diese sind vor dem Import geschützt und bleiben erhalten. ' + 'Felder, die du nicht angefasst hast, werden weiterhin automatisch aus dem Import verbessert.', verifiedBadge: '✓ Vollständig korrekt', verifiedBadgeTitle: 'Geprüft — der automatische Import verändert diese Maus nicht mehr.', protectedBadge: '🔒 Geschützte Änderungen', protectedBadgeTitle: 'Enthält von dir geänderte Angaben, die der Import nicht überschreibt.', driftBadge: '⚠ Weicht vom Import ab', driftBadgeTitle: 'Der automatische Import liefert für einige Felder andere Werte als dein geprüfter Stand.', markAction: 'Als vollständig korrekt markieren', unmarkAction: 'Markierung entfernen', releaseAction: 'Schutz aufheben (wieder aus Import)', marking: 'Wird gespeichert …', markSuccess: 'Als vollständig korrekt markiert. Der Import verändert diese Maus nicht mehr.', unmarkSuccess: 'Markierung entfernt. Beim nächsten Import wird die Maus wieder automatisch aktualisiert.', error: 'Konnte nicht gespeichert werden.', unmarkConfirm: 'Markierung wirklich entfernen? Die aktuellen Werte bleiben stehen; beim nächsten Import wird diese Maus wieder automatisch aktualisiert.', releaseConfirm: 'Schutz wirklich aufheben? Beim nächsten Import wird diese Maus wieder komplett aus dem Import übernommen — deine Änderungen gehen dann verloren.', statusUnchanged: 'Der Import stimmt mit deinem geprüften Stand überein.', driftHeading: 'Abweichungen zum automatischen Import', driftHint: 'So sieht es der Import gerade. Ist dein Stand richtig, kannst du das ignorieren — oder Julian passt den Import an. Deine geprüften Werte bleiben so oder so erhalten.', colField: 'Feld', colGolden: 'Dein geprüfter Stand', colImport: 'Automatischer Import', // Übersichtsseite (/hilfe/verifizierte-tiere) pageTitle: 'Geprüfte Tiere', pageSubtitle: 'Alle Mäuse, die du als „vollständig korrekt" markiert oder von Hand geändert hast.', pageIntro1: 'Hier siehst du alle Mäuse, deren Angaben du geprüft und markiert hast. Diese werden vom automatischen Import nicht mehr verändert — dein Bestand wird so Tier für Tier sauber.', pageIntro2: '„Weicht vom Import ab" heißt: der Import liefert inzwischen andere Werte als dein geprüfter Stand — ein Hinweis, dass am Import noch etwas zu korrigieren ist. Deine Angaben bleiben trotzdem erhalten.', empty: 'Noch keine Mäuse als vollständig korrekt markiert.', loadError: 'Die geprüften Tiere konnten nicht geladen werden.', sectionVerified: 'Vollständig korrekt', sectionProtected: 'Geschützte Änderungen (von Hand bearbeitet)', openAkte: 'Zur Akte', protectedFieldsLabel: 'Geschützte Felder:', warningsHeading: 'Hinweise', statusLabels: { unchanged: 'Unverändert', drifted: 'Weicht vom Import ab', missing: 'Im Import nicht mehr vorhanden', } as Record, // Link auf der Hilfe-Seite hilfeLink: 'Geprüfte Tiere (vollständig korrekt)', // Feld-Bezeichnungen für Diff-/Schutz-Anzeige (Schlüssel = Backend-Feldnamen). fieldLabels: { name: 'Name', gender: 'Geschlecht', dateOfBirth: 'Geburtsdatum', dateOfDeath: 'Todesdatum', causeOfDeath: 'Todesursache', goHomeDate: 'Abgabedatum', genotype: 'Genotyp', spottingType: 'Scheckung', colorName: 'Farbschlag', colorVarietyId: 'Farbschlag', isResident: 'Zuchtanwärter/in', isDeaf: 'Gehörlos', isCastrated: 'Kastrat', originBreeder: 'Herkunft (Zucht)', originContact: 'Herkunft (Kontakt)', originContactId: 'Herkunft (Kontakt)', receiverContact: 'Abnehmer', receiverContactId: 'Abnehmer', notes: 'Notizen', characterTraits: 'Charakter-Merkmale', characterNote: 'Charakter-Notiz', birthLitter: 'Geburtswurf', father: 'Vater', mother: 'Mutter', } as Record, }, 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.', }, }, // ── FEEDBACK: "Fehler melden" Dialog + "ID kopieren" Aktion ── feedback: { /** Button-Beschriftung (Tierakte, Wurf-Ansicht). */ button: 'Fehler melden', dialogTitle: 'Fehler melden', intro: 'Beschreibe kurz, was nicht stimmt. Technische Angaben werden automatisch mitgesendet.', label: 'Beschreibung', placeholder: 'Was funktioniert nicht oder ist falsch dargestellt?', /** Überschrift über den automatisch erfassten Debug-Angaben. */ debugTitle: 'Automatisch erfasst', debugFields: { context: 'Ansicht', entity: 'Datensatz', url: 'Adresse', }, contexts: { stammbaum: 'Stammbaum', 'gerbil-detail': 'Rennmausakte', 'litter-detail': 'Wurf', 'contact-detail': 'Kontakt', 'rpro3-import': 'RennmausPro-Import', }, submit: 'Senden', submitting: 'Wird gesendet …', cancel: 'Abbrechen', close: 'Schließen', success: 'Danke! Dein Fehlerbericht wurde gesendet.', error: 'Fehlerbericht konnte nicht gesendet werden.', emptyMessage: 'Bitte beschreibe den Fehler.', /** „Ähnliche bereits gelöste Tickets" im Melde-Fenster. */ similarTitle: 'Schon mal gelöst? Vielleicht hilft eines davon:', similarOpen: 'ansehen', /** Datei-Anhänge. */ attachLabel: 'Fotos anhängen (optional)', attachmentError: 'Ein Anhang konnte nicht hochgeladen werden.', /** Toast nach erfolgreichem "ID kopieren". */ idCopied: 'ID kopiert', idCopyFailed: 'ID konnte nicht kopiert werden.', /** "Meine Tickets" — Verwaltung der eingereichten Fehlerberichte. */ tickets: { title: 'Meine Tickets', subtitle: 'Deine eingereichten Fehlerberichte — bearbeite, schließe oder lösche sie hier.', /** Link auf der Hilfe-Seite. */ link: 'Meine Tickets (Fehlerberichte)', empty: 'Du hast noch keine Fehlerberichte gesendet.', loadError: 'Tickets konnten nicht geladen werden.', statusOpen: 'Offen', statusResolved: 'Gelöst', statusNeedsInfo: 'Rückfrage offen', statusAnswered: 'Beantwortet', /** Spalte/Label für die Ansicht, aus der der Bericht kam. */ contextLabel: 'Ansicht', entityLabel: 'Datensatz', createdLabel: 'Gesendet am', resolvedLabel: 'Gelöst am', reopenedLabel: 'Wieder geöffnet am', markResolved: 'Als gelöst markieren', reopen: 'Wieder öffnen', reopenRequest: 'Du hast dieses Ticket wieder geöffnet. Bitte beschreibe kurz, was noch fehlt oder nicht stimmt — dann schaue ich es mir erneut an.', edit: 'Bearbeiten', save: 'Speichern', cancel: 'Abbrechen', saving: 'Wird gespeichert …', delete: 'Löschen', confirmDelete: 'Dieses Ticket in den Papierkorb verschieben? Du kannst es unter „Gelöscht" wiederherstellen.', editTitle: 'Fehlerbericht bearbeiten', editLabel: 'Beschreibung', saved: 'Änderung gespeichert.', resolvedToast: 'Ticket als gelöst markiert.', reopenedToast: 'Ticket wieder geöffnet.', deletedToast: 'Ticket in den Papierkorb verschoben.', restore: 'Wiederherstellen', restoredToast: 'Ticket wiederhergestellt.', restoreError: 'Ticket konnte nicht wiederhergestellt werden.', /** Countdown im Papierkorb bis zur endgültigen Löschung. {n} = verbleibende Tage. */ trashCountdownDays: 'Wird in {n} Tagen endgültig gelöscht.', trashCountdownTomorrow: 'Wird morgen endgültig gelöscht.', trashCountdownToday: 'Wird heute endgültig gelöscht.', deletedLabel: 'Gelöscht am', updateError: 'Ticket konnte nicht aktualisiert werden.', deleteError: 'Ticket konnte nicht gelöscht werden.', emptyMessage: 'Bitte beschreibe den Fehler.', /** Rückfrage (Question) + Antwort der Züchterin (Answer). */ questionLabel: 'Rückfrage', answerLabel: 'Deine Antwort', answerPlaceholder: 'Antwort auf die Rückfrage eingeben …', answerButton: 'Antworten', /** Button auf einem beantworteten Ticket, um die eigene Antwort noch zu ändern. */ amendAnswer: 'Antwort ändern', answering: 'Wird gesendet …', answeredOn: 'Beantwortet am', answeredToast: 'Antwort gesendet.', emptyAnswer: 'Bitte gib eine Antwort ein.', /** Gefilterte Verlinkungen (wie die Filter-Chips der Rennmaus-Liste). */ filters: { /** Gruppe „Rückfragen": Tickets im Dialog (NeedsInfo + Answered). */ dialog: 'Rückfragen', /** Gruppe „Offen": noch nicht bearbeitete Tickets. */ open: 'Offen', /** Gruppe „Geschlossen": erledigte Tickets mit Changelog. */ closed: 'Geschlossen', /** Gruppe „Gelöscht": in den Papierkorb verschobene Tickets (wiederherstellbar). */ deleted: 'Gelöscht', }, /** Leertext je gefilterter Ansicht. */ emptyDialog: 'Aktuell keine Tickets im Dialog.', emptyOpen: 'Keine offenen Tickets.', emptyClosed: 'Noch keine geschlossenen Tickets.', emptyDeleted: 'Der Papierkorb ist leer.', /** Suche + Kategorie-Filter. */ searchPlaceholder: 'Tickets durchsuchen …', categoryFilterLabel: 'Nach Kategorie filtern', categoryAll: 'Alle Kategorien', emptySearch: 'Keine Tickets passen zu Suche/Filter.', /** Daumen-Rückmeldung auf gelösten Tickets. */ helpfulQuestion: 'Hat dir das geholfen?', helpfulYes: '👍 Ja', helpfulNo: '👎 Nein', helpfulThanks: 'Danke für die Rückmeldung!', helpfulReopenNote: 'Schade — ich öffne das Ticket wieder. Bitte schreib kurz, was noch fehlt.', /** Anhänge auf einem Ticket. */ attachmentsLabel: 'Anhänge', addAttachment: 'Foto anhängen', removeAttachment: 'Anhang entfernen', attachmentAdded: 'Anhang hinzugefügt.', attachmentRemoved: 'Anhang entfernt.', attachmentError: 'Anhang konnte nicht verarbeitet werden.', /** Push-Benachrichtigungen (PWA). */ pushEnable: 'Benachrichtigungen aktivieren', pushDisable: 'Benachrichtigungen aus', pushEnabledToast: 'Benachrichtigungen aktiviert — du wirst informiert, sobald ich antworte.', pushDisabledToast: 'Benachrichtigungen deaktiviert.', pushDenied: 'Benachrichtigungen wurden im Browser blockiert. Bitte in den Browser-Einstellungen erlauben.', pushUnavailable: 'Benachrichtigungen sind auf diesem Gerät nicht verfügbar.', /** Changelog (fixNote) auf geschlossenen Tickets. */ changelogLabel: 'Was wurde geändert', /** Überschrift des Frage/Antwort-Verlaufs (frühere Runden). */ threadLabel: 'Bisheriger Verlauf', /** Rollen-Beschriftungen im Verlauf. */ threadMaintainer: 'Rückfrage', threadBreeder: 'Deine Antwort', /** Tooltip am verlinkten Datensatz-Namen (Tier/Wurf/Kontakt). */ entityLinkTitle: 'Datensatz ansehen', /** Link-Beschriftung für eine im Text referenzierte andere Ticket-Nummer. */ ticketRefLabel: 'verknüpftes Ticket ansehen', }, }, /** NACHVERFOLGUNG: Datenherkunft eines importierten Tiers (Rennmausakte). */ provenance: { /** Button-Beschriftung in den Akten-Aktionen. */ button: 'Datenherkunft', dialogTitle: 'Nachverfolgungsinformationen', intro: 'Woher stammen die Daten dieses Eintrags? Diese Angaben werden beim Import automatisch erfasst.', /** Wie {@link intro}, aber mit Entitätsbezeichnung (z. B. „dieses Kontakts"). */ introFor: (label: string) => `Woher stammen die Daten ${label}? Diese Angaben werden beim Import automatisch erfasst.`, /** Entitätsbezeichnungen für introFor (Genitiv). */ entityLabels: { contact: 'dieses Kontakts', litter: 'dieses Wurfs', }, /** Überschrift des chronologischen, dateibezogenen Verlaufs (Primärinhalt). */ historyTitle: 'Verlauf', /** Legende für die mit „⚠“ markierten Verlaufszeilen, in denen Daten aus * einer Quelle verworfen wurden (mit Grund und verwendetem Ersatz). */ discardLegend: '⚠ markiert verworfene Quelldaten (mit Grund und verwendetem Ersatz).', /** Überschriften / Feldbeschriftungen. */ sourceFilesTitle: 'Quelldateien', sourceFilesCount: (n: number) => (n === 1 ? 'aus 1 Quelle' : `aus ${n} Quellen`), mergedTitle: 'Datensätze', mergedCount: (n: number) => n === 1 ? 'aus 1 Datensatz' : `zusammengeführt aus ${n} Datensätzen`, fromWurfchronik: 'Enthält Angaben aus der Wurfchronik', parentsTitle: 'Eltern-Herkunft', parentMethodLabel: 'Methode', parentConfidenceLabel: 'Konfidenz', /** Übersetzungen für die technischen Methoden-/Konfidenz-Werte. */ methods: { 'chart-position': 'Position im Stammbaum', decision: 'Manuelle Entscheidung', } as Record, confidences: { low: 'niedrig', medium: 'mittel', high: 'hoch', } as Record, notesTitle: 'Hinweise', /** Wenn ein Tier keine Importdaten hat (manuell angelegt). */ empty: 'Keine Herkunftsdaten vorhanden.', close: 'Schließen', }, 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', // Toast-Rückmeldungen saved: 'Gespeichert', saveFailed: 'Speichern fehlgeschlagen', deleted: 'Gelöscht', }, // 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 / CHARAKTERBOGEN-2: Charakterbogen — Eigenschaften + Notiz, speist KI-Verkaufstext ── // Traits: stabile KEYS (gespeichert, NIEMALS umbenennen) + deutsche LABELS (UI + KI-Prompt). // Neue Traits = neuen Eintrag hinzufügen; warn:true = Warnsignal (visuell abgesetzt). 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.', warnLabel: '⚠ Warnsignal', traitCategories: [ { category: 'Sozialverhalten', traits: [ { key: 'dominant', label: 'dominant (Leittier)' }, { key: 'rangniedrig', label: 'rangniedrig / unterwürfig' }, { key: 'sozialkompetent', label: 'sozialkompetent / gut sozialisiert' }, { key: 'schwer-vergesellschaftbar', label: 'schwer vergesellschaftbar', warn: true }, ], }, { category: 'Eignung & Umgang', traits: [ { key: 'anfaengergeeignet', label: 'anfängergeeignet' }, { key: 'erfahrene-halter', label: 'für erfahrene Halter' }, { key: 'beobachtungstier', label: 'reines Beobachtungstier' }, { key: 'familiengeeignet', label: 'familiengeeignet / stressresistent' }, ], }, { category: 'Hobbys & Eigenarten', traits: [ { key: 'futterfreudig', label: 'futterfreudig' }, { key: 'buddelt', label: 'buddelt gern' }, { key: 'klettert', label: 'klettert gern' }, { key: 'laufrad', label: 'läuft gern im Laufrad' }, { key: 'schredder', label: 'Schredder-Meister' }, { key: 'nestbauer', label: 'Nestbauer / Architekt' }, { key: 'territorial', label: 'territorial', warn: true }, ], }, { category: 'Wesen & Temperament', 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: 'vertraeglich', label: 'gut verträglich' }, { key: 'schreckhaft', label: 'schreckhaft' }, ], }, ], }, // ── UX-MOBILE-1 (Kevin): FilterPanel — einklappbare Filter auf Mobil ── filterPanel: { toggleButton: 'Filter', resetButton: 'Filter zurücksetzen', closeButton: 'Schließen', }, // ── DESIGN (Rennmaus Filter): Quick-Chips-Filter mit Bottom-Sheet ── filterBar: { title: 'Filter', done: 'Fertig', clearAll: 'Alle löschen', remove: 'entfernen', searchPlaceholder: 'Suchen …', noMatch: 'Kein Treffer', searchClear: 'Suche leeren', }, // ── FEAT-NAMEGEN: Namensvorschläge (KI-gestützt, UC-1 Einzeltier) ── namegen: { button: 'Name vorschlagen', panelTitle: 'Namensvorschläge', letterLabel: 'Anfangsbuchstabe', letterPlaceholder: 'z. B. A', genderLabel: 'Geschlecht', genderAny: 'Egal', genderFemale: 'Weiblich', genderMale: 'Männlich', usagesLabel: 'Herkunftskultur', loadButton: 'Vorschläge laden', loading: 'Lade Vorschläge …', empty: 'Keine Vorschläge — andere Einstellungen versuchen.', keyMissing: 'Namensvorschläge benötigen einen API-Key — bitte in den Einstellungen konfigurieren.', close: 'Schließen', }, } as const export type Strings = typeof de