import { formatFileSize } from "./kit-labels";
import type { UiKitLabels } from "./kit-labels";

/**
 * The kit's German, formal ("Sie"), written in standard spelling with "ß" — the SOURCE
 * the public `de-CH` catalogue is derived from (via `swiss()`), not a catalogue itself.
 *
 * Internal on purpose: it lives outside `src/i18n/locales/` because every file there is
 * a public `@eifi1/ui-kit/i18n/<code>` subpath, and the kit ships ONE German — Swiss,
 * formal (0.18.0 removed `/i18n/de`, `/i18n/de-informal` and `/i18n/de-CH-informal`).
 * The text stays written with "ß" because `swiss()` respells at runtime, so a Swiss app
 * also gets an argument it passes in (a file name, a phrase to type) respelled; writing
 * "ss" here instead would change that behaviour for every function label.
 *
 * Counts and sizes are formatted with `numberLocale`'s digits; the words never change.
 */
export function germanLabels(numberLocale: string): UiKitLabels {
  const num = new Intl.NumberFormat(numberLocale);
  const n = (value: number) => num.format(value);

  return {
    feedbackAttachment: {
      attachmentAdd: "Bild anhängen",
      attachmentCapture: "Screenshot aufnehmen",
      attachmentPaste: "…oder einen Screenshot aus der Zwischenablage einfügen.",
      attachmentRemove: "Anhang entfernen",
      attachmentList: "Anhänge",
      attachmentScreenshot: "Screenshot",
      attachmentRemoveFile: (name) => `${name} entfernen`,
      attachmentLimit: (max) => `Maximal ${n(max)} ${max === 1 ? "Anhang" : "Anhänge"} – zum Hinzufügen erst einen entfernen.`,
      attachmentUploading: "Wird hochgeladen…",
    },
    feedbackDialog: {
      title: "Feedback senden",
      category: "Kategorie",
      subject: "Betreff",
      body: "Was ist passiert?",
      bodyOptional: "Was ist passiert? (optional)",
      attachment: "Screenshot",
      submitHint: "Strg/⌘ + Enter zum Senden",
      cancel: "Abbrechen",
      save: "Senden",
    },
    feedbackThread: {
      thread: "Kommentare",
      empty: "Noch keine Kommentare",
      loading: "Kommentare werden geladen…",
      // The reader's own messages. "Ich" rather than "Sie": it reads the same whether
      // the app addresses its users with "Sie" or "du", so neither has to override it.
      you: "Ich",
      staff: "Team",
      attachments: "Anhänge",
    },
    feedbackComposer: {
      field: "Kommentar schreiben",
      placeholder: "Kommentar schreiben…",
      send: "Senden",
      // German keyboards label the key "Strg".
      sendHint: (modifier) => `${modifier === "Ctrl" ? "Strg" : modifier} + Enter zum Senden`,
      // "Umschalt", the German key label, as in the table's sort hint.
      sendHintEnter: "Enter zum Senden, Umschalt + Enter für neue Zeile",
    },
    accountSettings: {
      profile: {
        title: "Profil",
        email: "E-Mail",
        role: "Rolle",
        memberSince: "Mitglied seit",
        displayName: "Anzeigename",
        save: "Speichern",
      },
      password: {
        title: "Passwort ändern",
        current: "Aktuelles Passwort",
        next: "Neues Passwort",
        confirm: "Neues Passwort bestätigen",
        submit: "Passwort ändern",
        tooShort: "Das neue Passwort ist zu kurz.",
        mismatch: "Die Passwörter stimmen nicht überein.",
      },
      twoFactor: {
        status: "Zwei-Faktor-Authentifizierung",
        enabledText: "Aktiv",
        disabledText: "Inaktiv",
        enable: "Zwei-Faktor-Authentifizierung einrichten",
        scanHint: "Diesen Code mit der Authenticator-App scannen und den angezeigten Code eingeben.",
        codeLabel: "Bestätigungscode",
        verify: "Bestätigen und aktivieren",
        disableSection: "Zwei-Faktor-Authentifizierung deaktivieren",
        password: "Aktuelles Passwort",
        disable: "Deaktivieren",
        qrAlt: "QR-Code für die Authenticator-App",
        secretHint: "Scannen nicht möglich? Stattdessen diesen Schlüssel in der App eingeben:",
        copySecret: "Schlüssel kopieren",
      },
      passkeys: {
        title: "Passkeys",
        description: "Mit Fingerabdruck, Gesichtserkennung oder Geräte-PIN statt Passwort anmelden.",
        descriptionAlongside: "Mit Fingerabdruck, Gesichtserkennung oder Geräte-PIN anmelden. Das Passwort funktioniert weiterhin.",
        empty: "Noch keine Passkeys",
        loading: "Passkeys werden geladen…",
        list: "Registrierte Passkeys",
        nameLabel: "Name (optional)",
        namePlaceholder: "z. B. Laptop, Handy",
        add: "Passkey hinzufügen",
        adding: "Warten auf das Gerät…",
        rename: "Umbenennen",
        renameItem: (name) => `${name} umbenennen`,
        renameField: (name) => `Neuer Name für ${name}`,
        save: "Speichern",
        cancel: "Abbrechen",
        delete: "Löschen",
        deleteItem: (name) => `${name} löschen`,
        deleteConfirm: (name) => `„${name}“ löschen? Eine Anmeldung damit ist dann nicht mehr möglich.`,
        confirmDelete: "Passkey löschen",
        created: (date) => `Hinzugefügt am ${date}`,
        lastUsed: (date) => `Zuletzt verwendet am ${date}`,
        neverUsed: "Noch nie verwendet",
      },
    },
    measuredGrid: {
      view: "Tabellenansicht",
      cellsView: "Zellen",
      textView: "Text",
      addRow: "Zeile hinzufügen",
      removeRow: (row) => `Zeile ${row} entfernen`,
      clear: "Tabelle leeren",
      pasteHint: "Einen Block aus einer Tabellenkalkulation in eine beliebige Zelle einfügen",
      cell: (column, row) => `${column}, Zeile ${row}`,
      rowNumber: "Zeile",
      rowActions: "Zeilenaktionen",
      keyboardHint:
        "Pfeiltasten wechseln zwischen Zellen. Tippen ersetzt eine Zelle, F2 bearbeitet sie, Escape macht die Bearbeitung rückgängig. Enter geht nach unten und fügt am Ende eine Zeile hinzu.",
      lineError: (line) => `Zeile ${line} konnte nicht gelesen werden`,
      points: (count) => (count === 1 ? "1 Punkt" : `${count} Punkte`),
      problems: (count) =>
        count === 1 ? "1 Zelle ist keine Zahl" : `${count} Zellen sind keine Zahlen`,
    },
    pageContents: { title: "Auf dieser Seite" },
    common: {
      dismiss: "Schließen",
      close: "Schließen",
      clear: "Leeren",
      search: "Suchen",
      done: "Fertig",
      cancel: "Abbrechen",
      save: "Speichern",
      back: "Zurück",
      next: "Weiter",
      remove: "Entfernen",
      loading: "Wird geladen…",
      noResults: "Keine Ergebnisse",
      fieldValue: (field, value) => `${field}: ${value}`,
      opensInNewTab: "öffnet in einem neuen Tab",
    },
    dataTable: {
      columns: "Spalten",
      selectAllRows: "Alle Zeilen auswählen",
      sortHint: "Klicken zum Sortieren · Umschalt-Klick für weitere Sortierung",
      filter: "Filter",
      close: "Schließen",
      selectRow: "Zeile auswählen",
      autoSize: "Spaltenbreiten anpassen",
      loading: "Wird geladen…",
      filters: "Filter",
      // Resets every active filter; "Alle löschen" would read as deleting the filters.
      clearAll: "Alle zurücksetzen",
      done: "Fertig",
      pageSize: "Zeilen pro Seite",
      // Sits among 10 / 25 / 50 counting "Zeilen", so the plural "Alle", not "Alles".
      pageSizeAll: "Alle",
      prevPage: "Vorherige Seite",
      nextPage: "Nächste Seite",
      clearFilter: "Filter zurücksetzen",
      filterPlaceholder: "Filtern…",
      selectFilter: "Auswählen",
      selectAll: "Alle",
      selectNone: "Keine",
      dateFrom: "Von",
      dateTo: "Bis",
      numberMin: "Min.",
      numberMax: "Max.",
      numberAbs: "Betrag",
      presets: {
        today: "Heute",
        yesterday: "Gestern",
        this_week: "Diese Woche",
        last_week: "Letzte Woche",
        last_7_days: "Letzte 7 Tage",
        last_30_days: "Letzte 30 Tage",
        this_month: "Dieser Monat",
        last_month: "Letzter Monat",
        last_3_months: "Letzte 3 Monate",
        ytd: "Seit Jahresbeginn",
        last_year: "Letztes Jahr",
      },
      table: "Datentabelle",
      filterResults: (shown, total) =>
        `${n(shown)} von ${n(total)} ${total === 1 ? "Zeile" : "Zeilen"}`,
      sortedAscending: (column) => `Sortiert nach ${column}, aufsteigend`,
      sortedDescending: (column) => `Sortiert nach ${column}, absteigend`,
      sortCleared: (column) => `Sortierung nach ${column} aufgehoben`,
      pageChanged: (page, totalPages) => `Seite ${n(page)} von ${n(totalPages)}`,
      pageRange: (from, to, total) => `${n(from)}–${n(to)} / ${n(total)}`,
      rowCount: (total) => n(total),
      columnsCount: (visible, total) => `Spalten (${n(visible)}/${n(total)})`,
      empty: "Keine Einträge",
      actions: "Aktionen",
      edit: "Bearbeiten",
      delete: "Löschen",
      booleanTrue: "Ja",
      booleanFalse: "Nein",
      booleanUnset: "Nicht festgelegt",
      sortBy: "Sortieren nach",
      sortDefault: "Standardreihenfolge",
      sortAscending: "Aufsteigend",
      sortDescending: "Absteigend",
    },
    miniCalendar: {
      previousMonth: "Vorheriger Monat",
      nextMonth: "Nächster Monat",
      // Already formatted in the provider's locale ("Montag, 14. September 2026").
      day: (date) => date,
      chooseStart: "Startdatum wählen",
      chooseEnd: "Enddatum wählen",
      startSelected: (date) => `${date} als Startdatum gewählt. Wählen Sie jetzt ein Enddatum.`,
      rangeSelected: (from, to) =>
        `Zeitraum ${from} bis ${to} gewählt. Wählen Sie ein Startdatum, um neu zu beginnen.`,
    },
    calendarHeatmap: {
      grid: "Tageswerte",
      day: (date, value) => `${date}: ${value}`,
      less: "Weniger",
      more: "Mehr",
      truncated: (count) =>
        `Die neuesten Tage werden angezeigt; ${n(count)} ${count === 1 ? "früherer Tag wird" : "frühere Tage werden"} nicht angezeigt.`,
    },
    datePicker: {
      apply: "Übernehmen",
      cancel: "Abbrechen",
      presets: "Schnellauswahl",
      panel: "Datum wählen",
      rangePanel: "Zeitraum wählen",
      clear: "Leeren",
      previousDay: "Vorheriger Tag",
      nextDay: "Nächster Tag",
      today: "Heute",
    },
    monthPicker: {
      previousYear: "Vorheriges Jahr",
      nextYear: "Nächstes Jahr",
      panel: "Monat wählen",
      month: (monthYear) => monthYear,
      previousMonth: "Vorheriger Monat",
      nextMonth: "Nächster Monat",
      today: "Heute",
      yearPanel: "Jahr wählen",
      earlierYears: "Frühere Jahre",
      laterYears: "Spätere Jahre",
      thisYear: "Dieses Jahr",
    },
    popover: {
      panel: "Aufklappfenster",
    },
    combobox: {
      search: "Suchen",
      noResults: "Keine Ergebnisse",
      clear: "Leeren",
      loading: "Wird geladen…",
      create: (query) => `„${query}“ anlegen`,
      selectedCount: (count) => `${n(count)} ausgewählt`,
      loadError: "Ergebnisse konnten nicht geladen werden",
      resultCount: (count) => `${n(count)} ${count === 1 ? "Ergebnis" : "Ergebnisse"}`,
      // "Zeichen" is the same in singular and plural.
      minChars: (count) => `Mindestens ${n(count)} Zeichen eingeben`,
    },
    multiSelect: {
      search: "Suchen",
      selectAll: "Alle auswählen",
      clear: "Leeren",
      all: "Alle",
      // The bare count, as in English: the trigger has always shown just the number.
      selectedCount: (count) => n(count),
    },
    calculator: {
      open: "Taschenrechner öffnen",
      panel: "Taschenrechner",
      calculation: "Rechnung",
      backspace: "Rücktaste",
      clear: "Löschen",
      equals: "Ist gleich",
      done: "Fertig",
      plus: "Plus",
      minus: "Minus",
      times: "Mal",
      divide: "Geteilt durch",
      decimal: "Dezimaltrennzeichen",
    },
    currency: {
      currency: "Währung",
      search: "Währung suchen",
    },
    chipInput: {
      // The value is arbitrary user text, quoted as a citation, so the participle agrees
      // with the implied "Eintrag" whatever the chip says.
      added: (value) => `„${value}“ hinzugefügt`,
      removed: (value) => `„${value}“ entfernt`,
      remove: "Entfernen",
      // `von` governs the dative, visible only in the plural: "von 1 Eintrag", "von 2 Einträgen".
      atLimit: (max) => `Grenze von ${n(max)} ${max === 1 ? "Eintrag" : "Einträgen"} erreicht`,
      duplicate: (value) => `„${value}“ steht bereits in der Liste`,
    },
    swatchPicker: {
      none: "Keine Farbe",
      mixed: "Gemischt: Die ausgewählten Elemente haben unterschiedliche Farben",
    },
    iconPicker: {
      none: "Kein Symbol",
      mixed: "Gemischt: Die ausgewählten Elemente haben unterschiedliche Symbole",
      search: "Symbole suchen",
      noResults: "Keine passenden Symbole",
      resultCount: (count) => `${n(count)} ${count === 1 ? "Symbol" : "Symbole"}`,
    },
    fieldSync: {
      synced: "Gespeichert",
      edited: "Nicht gespeicherte Änderungen",
      pending: "Wird gespeichert…",
      error: "Speichern fehlgeschlagen",
      retry: "Erneut versuchen",
    },
    passwordReveal: {
      show: "Passwort anzeigen",
      hide: "Passwort verbergen",
    },
    dangerConfirm: {
      arm: "Löschen…",
      confirm: "Löschen",
      cancel: "Abbrechen",
      prompt: "Dies kann nicht rückgängig gemacht werden.",
      password: "Passwort",
      phrase: (phrase) => `Geben Sie zur Bestätigung „${phrase}“ ein`,
      acknowledge: "Ich habe gelesen, was dies bewirkt, und möchte fortfahren.",
    },
    tabs: {
      // "Tab" is what German UIs say; "Registerkarte" reads like a 1990s manual.
      add: "Tab hinzufügen",
      remove: (tab) => `${tab} entfernen`,
    },
    appShell: {
      collapse: "Seitenleiste einklappen",
      expand: "Seitenleiste ausklappen",
      toggleGroup: (groupLabel) => `${groupLabel}: Seiten`,
    },
    topBar: {
      theme: "Theme wechseln",
      palette: "Darstellungsvorlage",
      language: "Sprache",
      switchRole: "Rolle wechseln",
      role: (value) => `Rolle: ${value}`,
    },
    pickerSheet: {
      close: "Schließen",
    },
    dialogFrame: {
      close: "Schließen",
    },
    bulkActionBar: {
      selected: (count) => `${n(count)} ausgewählt`,
      clear: "Auswahl aufheben",
      cleared: "Auswahl aufgehoben",
    },
    swipeableRow: {
      actions: "Zeilenaktionen",
    },
    file: {
      // The kit's own `Intl` unit formatting, pinned to this locale ("3,4 MB").
      size: (bytes) => formatFileSize(bytes, numberLocale),
    },
    filePicker: {
      dropzone: "Datei-Upload",
      browse: "Durchsuchen",
      empty: "Datei hier ablegen",
      emptyMultiple: "Dateien hier ablegen",
      hint: (accept) => (accept ? `Erlaubt: ${accept}` : "Beliebiger Dateityp"),
      busy: "Wird hochgeladen…",
      rejectedPick: (count) =>
        count === 1
          ? "Die Datei wurde nicht hinzugefügt"
          : `Keine der ${count} Dateien wurde hinzugefügt`,
      rejectedType: (name) => `„${name}“ hat einen nicht unterstützten Dateityp`,
      rejectedTypeOnly: (accept) => `Nur ${accept}-Dateien`,
      rejectedSize: (name, maxSize) => `„${name}“ ist größer als ${maxSize}`,
      rejectedCount: (name, maxFiles) =>
        `„${name}“ wurde nicht hinzugefügt: höchstens ${n(maxFiles)} ${maxFiles === 1 ? "Datei" : "Dateien"}`,
      rejectedInvalid: (name) => `„${name}“ kann hier nicht verwendet werden`,
      rejectedMany: (count) =>
        count === 1
          ? "1 Datei wurde nicht hinzugefügt"
          : `${n(count)} Dateien wurden nicht hinzugefügt`,
      selected: (count, firstName) =>
        count === 1 ? `„${firstName}“ ausgewählt` : `${n(count)} Dateien ausgewählt`,
      remove: (name) => `„${name}“ entfernen`,
      clearAll: "Alle Dateien entfernen",
      removed: (name) => `„${name}“ entfernt`,
      cleared: "Alle Dateien entfernt",
    },
    wizard: {
      done: "Fertig",
      cancel: "Abbrechen",
      back: "Zurück",
      next: "Weiter",
      skip: "Überspringen",
      finish: "Abschließen",
      submitting: "Wird erstellt…",
      steps: "Schritte",
      step: (current, total) => `Schritt ${n(current)} von ${n(total)}`,
      cancelTitle: "Formular verwerfen?",
      confirmCancel: "Ihre Eingaben gehen verloren.",
      cancelConfirmLabel: "Verwerfen",
      cancelDismissLabel: "Weiter bearbeiten",
      reviewTitle: "Überprüfen",
      edit: "Bearbeiten",
      missingRequired: "Bitte füllen Sie alle Pflichtfelder aus.",
      genericError: "Ein Fehler ist aufgetreten",
    },
    tour: {
      next: "Weiter",
      back: "Zurück",
      skip: "Überspringen",
      done: "Fertig",
      awaitClickHint: "Klicken Sie auf das hervorgehobene Element, um fortzufahren",
      step: (current, total) => `${n(current)} / ${n(total)}`,
    },
    commandPalette: {
      clear: "Suche löschen",
      submit: "Suchen",
      close: "Schließen",
      placeholder: "Suchen…",
      empty: "Keine Ergebnisse",
      loading: "Wird gesucht…",
      dialog: "Suche",
      error: "Die Suche ist fehlgeschlagen. Bitte erneut versuchen.",
    },
    globalSearch: {
      trigger: "Suche",
      placeholder: "Suchen oder springen zu…",
      shortcut: (keys) => `Suche (${keys})`,
      suggestions: "Vorschläge",
      results: "Ergebnisse",
    },
    sparkline: {
      rising: (first, last) => `Steigend von ${first} auf ${last}`,
      falling: (first, last) => `Fallend von ${first} auf ${last}`,
      flat: (value) => `Unverändert bei ${value}`,
      single: (value) => `Ein Wert: ${value}`,
      noData: "Keine Daten",
      named: (name, summary) => `${name}: ${summary}`,
    },
    statTile: {
      // `amount` arrives formatted and unsigned ("5 %", "1.200 €").
      increase: (amount) => `Um ${amount} gestiegen`,
      decrease: (amount) => `Um ${amount} gesunken`,
      unchanged: "Keine Veränderung",
      better: (change) => `${change} (besser)`,
      worse: (change) => `${change} (schlechter)`,
      noValue: "Keine Daten",
      loading: "Wird geladen…",
    },
    signaturePad: {
      label: "Unterschrift",
      instructions: "Unterschreiben Sie im Feld mit der Maus, dem Finger oder einem Stift.",
      typedFallbackHint: "Wenn Sie nicht zeichnen können, geben Sie stattdessen Ihren Namen ein.",
      empty: "Noch nichts gezeichnet",
      signed: "Unterschrift gezeichnet",
      undo: "Letzten Strich rückgängig machen",
      clear: "Leeren",
      save: "Unterschrift speichern",
      useTyped: "Stattdessen Namen eingeben",
      useDrawn: "Stattdessen zeichnen",
      typedName: "Vollständiger Name",
      cleared: "Unterschrift gelöscht",
      undone: "Letzter Strich entfernt",
      viewEmpty: "Nicht unterschrieben",
      viewDrawn: "Handschriftliche Unterschrift",
      viewTyped: (name) => `Unterschrieben mit dem eingegebenen Namen ${name}`,
    },
    passwordStrength: {
      tooShort: "Zu kurz",
      weak: "Schwach",
      fair: "Mittel",
      good: "Gut",
      strong: "Stark",
      announcement: (level) => `Passwortstärke: ${level}`,
      // "Zeichen" is the same in singular and plural. The English default does not
      // format these counts, so neither does this file.
      ruleLength: (minLength) => `Mindestens ${minLength} Zeichen`,
      ruleCase: "Groß- und Kleinbuchstaben",
      ruleDigit: "Eine Ziffer",
      ruleSymbol: "Ein Sonderzeichen",
      optional: (rule) => `${rule} (optional)`,
      met: "Erfüllt:",
      notMet: "Nicht erfüllt:",
      tooLong: (maxBytes) =>
        `Höchstens ${maxBytes} Zeichen (Buchstaben mit Akzent und Emojis zählen mehrfach).`,
    },
    seriesChart: {
      resetZoom: "Zoom zurücksetzen",
      zoomHint:
        "Zum Zoomen ziehen: Eine annähernd quadratische Auswahl zoomt beide Achsen, eine lange, schmale nur ihre eigene. Doppelklick setzt zurück.",
      empty: "Keine Daten",
      legend: "Datenreihen",
      points: "Diagrammwerte",
    },
    pieChart: {
      slices: "Diagrammsegmente",
      slice: (label, value, percent) => `${label}: ${value} (${percent})`,
      total: "Gesamt",
      empty: "Keine Daten",
      legend: "Kategorien",
    },
    confirmDialog: {
      confirm: "Bestätigen",
      cancel: "Abbrechen",
      typed: (text) => `Geben Sie zur Bestätigung „${text}“ ein`,
    },
    floatingPanel: {
      close: "Schließen",
      badge: (count) => `${n(count)} neu`,
    },
    copyButton: {
      copy: "Kopieren",
      copied: "Kopiert",
      failed: "Kopieren fehlgeschlagen",
      copiedAnnouncement: "In die Zwischenablage kopiert",
      failedAnnouncement: "Kopieren in die Zwischenablage fehlgeschlagen",
    },
    list: {
      unread: "Ungelesen",
      opensInNewTab: "öffnet in einem neuen Tab",
    },
    breadcrumbs: {
      label: "Brotkrümelnavigation",
      showAll: "Vollständigen Pfad anzeigen",
    },
    toast: {
      close: "Benachrichtigung schließen",
      notifications: "Benachrichtigungen",
      undo: "Rückgängig",
      redo: "Wiederholen",
    },
    form: {
      save: "Speichern",
      cancel: "Abbrechen",
      // German keyboards label the key "Strg"; Apple's ⌘ is the same everywhere.
      submitShortcut: (apple) => (apple ? "⌘ Enter" : "Strg+Enter"),
    },
    descriptionList: {
      empty: "—",
    },
    lineItems: {
      add: "Zeile hinzufügen",
      remove: (row) => `Zeile ${row} entfernen`,
      confirmRemove: (row) => `Zeile ${row} entfernen? Zum Bestätigen erneut drücken`,
      row: (row) => `Zeile ${row}`,
      cell: (column, row) => `${column}, Zeile ${row}`,
      totals: "Summe",
    },
    progressBar: {
      unlimited: "Unbegrenzt",
      overLimit: (amount) => `${amount} über dem Limit`,
    },
    signedAmount: {
      positive: (amount) => `plus ${amount}`,
      negative: (amount) => `minus ${amount}`,
    },
    errorBoundary: {
      title: "Etwas ist schiefgelaufen",
      message: "Dieser Teil der Seite konnte nicht angezeigt werden. Bitte erneut versuchen oder die Seite neu laden.",
      retry: "Erneut versuchen",
      details: "Fehlerdetails",
      reload: "Neu laden",
      updateTitle: "Eine neue Version ist verfügbar",
      updateMessage: "Ein Teil der App hat sich seit dem Laden dieser Seite geändert. Zum Aktualisieren die Seite neu laden.",
      offlineTitle: "Keine Internetverbindung",
      offlineMessage: "Diese Seite konnte ohne Verbindung nicht geladen werden. Nach dem Wiederherstellen der Verbindung die Seite neu laden.",
      copyReport: "Fehlerbericht kopieren",
      reported: "Der Fehler wurde automatisch gemeldet.",
      reportedAs: (reference) => `Gemeldet unter ${reference}`,
    },
    authedImage: {
      loading: "Bild wird geladen…",
      loadError: "Bild konnte nicht geladen werden",
      failedImage: (alt) => `${alt}: Bild konnte nicht geladen werden`,
    },
    imageGrid: {
      list: "Bilder",
      item: (index, count) => `Bild ${n(index)} von ${n(count)}`,
      actions: (name) => `Aktionen für ${name}`,
    },
    lightbox: {
      dialog: "Bildansicht",
      close: "Schließen",
      previous: "Vorheriges Bild",
      next: "Nächstes Bild",
      counter: (index, count) => `${n(index)} / ${n(count)}`,
      position: (index, count) => `Bild ${n(index)} von ${n(count)}`,
      download: "Herunterladen",
      zoom: "Zoomen",
      noPreview: "Für diese Datei ist keine Vorschau verfügbar",
      openInNewTab: "In neuem Tab öffnen",
    },
    writeLock: {
      // Impersonal, like the rest of this catalogue where it can be: an app that
      // addresses its users with "du" then has fewer keys to override.
      reason: "Nur zum Ansehen – Änderungen sind hier nicht möglich.",
    },
    accountState: {
      active: "Aktiv",
      inactive: "Inaktiv",
      invited: "Eingeladen",
      registered: "Registriert",
      unverified: "Nicht bestätigt",
      passwordChange: "Passwortänderung erforderlich",
    },
    shareCard: {
      dialogTitle: "Teilen",
      close: "Schließen",
      email: "E-Mail-Adresse",
      emailOptional: "E-Mail-Adresse (optional)",
      // example.com is reserved for examples (RFC 2606); a German-looking domain is
      // somebody's real one.
      emailPlaceholder: "name@example.com",
      invalidEmail: "Bitte eine vollständige E-Mail-Adresse eingeben.",
      role: "Rolle",
      roleOf: (name) => `Rolle von ${name}`,
      add: "Teilen",
      whoHasAccess: "Wer hat Zugriff",
      nobodyYet: "Bisher hat niemand sonst Zugriff.",
      pending: "Ausstehend",
      openInvite: "Offener Einladungslink",
      copyLink: "Link kopieren",
      team: "Team",
      teamHint: (name) => `Alle in ${name} erhalten Zugriff.`,
      remove: "Zugriff entfernen",
      removeConfirm: (name) => `Zugriff für ${name} entfernen?`,
      revokePending: "Einladung zurückziehen",
      revokePendingConfirm: (name) => `Einladung für ${name} zurückziehen?`,
      failed: "Das hat nicht geklappt. Bitte erneut versuchen.",
      loading: "Wird geladen…",
    },
    reauthDialog: {
      title: "Identität bestätigen",
      description: "Zum Fortfahren das aktuelle Passwort eingeben.",
      password: "Aktuelles Passwort",
      submit: "Weiter",
      cancel: "Abbrechen",
    },
    serverWake: {
      slow: "Lädt noch – das dauert länger als sonst.",
      waking: (appName) =>
        `Der Server schläft ein, wenn ${appName ?? "die App"} gerade niemand benutzt. Die erste Anfrage nach einer Pause muss ihn erst wieder starten. Das kann einen Moment dauern – es geht nichts verloren, die Seite füllt sich von selbst.`,
    },
    legal: {
      navLabel: "Rechtliches",
    },
    characterCount: {
      // "Zeichen" is the same in singular and plural.
      count: (used, max) => `${n(used)} von ${n(max)} Zeichen`,
      remaining: (left) => `Noch ${n(left)} Zeichen`,
      limitReached: "Zeichenlimit erreicht",
    },
    countrySelect: {
      country: "Land",
      search: "Land suchen",
      others: "Weitere Länder",
    },
    inlineEdit: {
      edit: (label) => `${label} bearbeiten`,
      failed: "Die Änderung konnte nicht gespeichert werden.",
      empty: "Leer",
    },
    ibanInput: {
      format: "Eine IBAN beginnt mit einem Ländercode aus zwei Buchstaben und zwei Prüfziffern.",
      country: (code) => `„${code}“ ist kein Ländercode einer IBAN.`,
      length: (actual, expected) =>
        `Eine IBAN aus diesem Land hat ${n(expected)} Zeichen – diese hat ${n(actual)}.`,
      checksum: "Die Prüfziffern stimmen nicht – vermutlich ist ein Zeichen falsch eingegeben.",
      qrRequired: "Dies ist eine reguläre IBAN. Eine QR-Rechnung braucht die QR-IBAN des Kontos.",
      qrNotAllowed:
        "Dies ist eine QR-IBAN, die nur Zahlungen mit QR-Rechnung empfängt. Geben Sie die reguläre IBAN des Kontos ein.",
    },
    phoneInput: {
      countryCode: "Ländervorwahl",
      other: "Andere",
    },
    signChip: {
      outflow: "Ausgabe",
      inflow: "Einnahme",
      direction: (current, next) => `Richtung: ${current} – zu ${next} wechseln`,
    },
    translationReview: {
      statusMissing: "Fehlt",
      statusUnreviewed: "Ungeprüft",
      statusChanged: "Seit der Prüfung geändert",
      statusNeedsChange: "Änderung nötig",
      statusApproved: "Bestätigt",
      statusFilter: "Status",
      all: "Alle",
      filterCount: (label, count) => `${label} · ${n(count)}`,
      source: "Texte",
      allSources: "Alle Texte",
      namespace: "Bereich",
      allNamespaces: "Alle Bereiche",
      search: "Schlüssel und Texte durchsuchen",
      placeholdersOnly: (count) => `Nur Platzhalter-Probleme (${n(count)})`,
      placeholderChip: "Platzhalter",
      key: "Schlüssel",
      statusColumn: "Status",
      empty: "Keine Texte passen zu diesen Filtern.",
      missingText: "Fehlt in dieser Sprache",
      progress: (approved, total) => `${n(approved)} von ${n(total)} bestätigt`,
      localeProgress: (approved, total) => `${n(approved)}/${n(total)}`,
      locales: "Sprachen",
      approve: "Bestätigen",
      flag: "Änderung nötig",
      suggest: "Übersetzung vorschlagen",
      reset: "Als ungeprüft markieren",
      cancel: "Abbrechen",
      approveSelected: "Auswahl bestätigen",
      resetSelected: "Auswahl als ungeprüft markieren",
      selectShown: "Alle angezeigten auswählen",
      changedSince: "Dieser Text wurde nach der Prüfung geändert. Bitte lesen Sie ihn noch einmal.",
      reviewedWording: "Wortlaut bei der Prüfung",
      reviewedReference: "Vorlage bei der Prüfung",
      placeholderMismatch: (reference, text) =>
        `Die Platzhalter weichen von der Vorlage ab – Vorlage: ${reference}; dieser Text: ${text}. Die App setzt dort Werte ein, deshalb müssen sie genau so bleiben.`,
      lastApproved: (name, date) => `Bestätigt von ${name} am ${date}`,
      lastFlagged: (name, date) => `Als änderungsbedürftig markiert von ${name} am ${date}`,
      // Dative, after "von": "Bestätigt von einem gelöschten Konto".
      erasedReviewer: "einem gelöschten Konto",
      suggestion: "Bessere Formulierung",
      translation: "Übersetzung",
      note: "Notiz (optional)",
      notePlaceholder: "Was falsch ist oder worauf zu achten ist",
      readOnly: "Sie können diese Sprache lesen, aber nicht prüfen.",
      scope: (areas) => `Ihre Prüfung ist beschränkt auf: ${areas}.`,
      exportCorrections: (count) => `Korrekturen exportieren (${n(count)})`,
      failed: "Das hat nicht geklappt. Bitte erneut versuchen.",
    },
  };
}
