Die App kann jetzt lesen, wofuer man sie oeffnet. Vier neue Reiter: - Uebersicht: Einnahmen/Ausgaben des Monats, Budget-Fortschritt je Gruppe, Kontostaende und die letzten Buchungen. Feste Auswahl statt des verschiebbaren Rasters der Weboberflaeche - auf Telefonbreite waere das Arbeit ohne Gewinn. Vier Endpunkte nebeneinander in einem Abruf, damit der Offline-Stand nicht aus vier verschiedenen Momenten stammt. - Budget: Soll gegen Ist je Gruppe und Kategorie, blaetterbar ueber prev/next aus der Antwort. Rot nur bei echter Ueberschreitung - wer mehr zuruecklegt als geplant, hat nichts ueberzogen. Vertraege ohne Kategorie und fehlende Wechselkurse stehen als Hinweis darunter, statt die Summen still zu verfaelschen. - Buchungen: Suche und Filter laufen im Server (Backend-Ergaenzung B), nicht im Telefon. Gesucht wird beim Absenden, nicht je Tastendruck. - Vertraege: Monats- und Jahressumme, Rhythmus, naechste Faelligkeit. Zwei Dinge, die das Backend bewusst dem Client ueberlaesst: Ein Uebertrag kommt in zwei Gestalten - am Stueck (eine Buchung mit to_account_id) oder als zwei verknuepfte Buchungen, wie die Bank sie liefert. Beide Beine als zwei Zeilen zu zeigen hiesse, dasselbe Geld zweimal zu zeigen. Buchungszeile.zeilen fasst sie zusammen, aber nur wenn beide in der Liste stehen - sonst liesse ein Kontofilter Zeilen verschwinden, die sehr wohl zu diesem Konto gehoeren. Die Richtung kommt aus der Verknuepfung, nicht aus dem Vorzeichen: Manche Banken liefern beide Beine positiv. Kategorien, Schlagwoerter und Konten liegen als Nachschlagewerk im AppZustand, einmal geladen. Je Ansicht neu zu holen waere genau das N+1, das das Backend sich selbst verbietet. Texte in Deutsch und Englisch, zeilengleich. 44 Tests gruen, darunter die Uebertrags-Paarung und jedes Modell gegen eine echte Serverantwort. Nicht geprueft: der Weg gegen ein echtes Backend. Die App laesst nur https zu, ein lokaler Server haette eine ATS-Ausnahme gebraucht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
166 lines
7.4 KiB
Plaintext
166 lines
7.4 KiB
Plaintext
/* Certain für iOS – Deutsch (Grundsprache)
|
||
|
||
Die Schlüssel sind nach Bereich benannt. Bitte beim Ergänzen die englische
|
||
Fassung gleich mitpflegen; im Web stehen de.json und en.json zeilengleich,
|
||
und das ist der Grund, warum dort nie etwas fehlt. */
|
||
|
||
/* --- Allgemein --- */
|
||
"allgemein.nochmal" = "Nochmal versuchen";
|
||
"allgemein.abbrechen" = "Abbrechen";
|
||
"allgemein.abmelden" = "Abmelden";
|
||
"allgemein.unbekannt" = "Unbekannt";
|
||
|
||
/* --- Reiter --- */
|
||
"reiter.dashboard" = "Übersicht";
|
||
"reiter.budget" = "Budget";
|
||
"reiter.buchungen" = "Buchungen";
|
||
"reiter.abos" = "Verträge";
|
||
"reiter.konten" = "Konten";
|
||
"reiter.einstellungen" = "Einstellungen";
|
||
|
||
/* --- Fehler --- */
|
||
"fehler.titel" = "Das hat nicht geklappt";
|
||
"fehler.unbekannt" = "Unbekannter Fehler.";
|
||
"fehler.keineVerbindung" = "Keine Verbindung zum Server: %@";
|
||
"fehler.keinCertainServer" = "Unter dieser Adresse antwortet zwar etwas, aber kein Certain.";
|
||
"fehler.nichtAngemeldet" = "Die Anmeldung dieses Geräts gilt nicht mehr. Vermutlich wurde sie am Rechner widerrufen.";
|
||
"fehler.passwortWechseln" = "Bevor es weitergeht, muss das Passwort gewechselt werden.";
|
||
"fehler.zweiterFaktor" = "Dieses Konto braucht einen zweiten Faktor.";
|
||
"fehler.nichtGefunden" = "Gibt es nicht.";
|
||
"fehler.server" = "Der Server meldet einen Fehler (%d).";
|
||
"fehler.antwortUnlesbar" = "Die Antwort des Servers passt nicht zu dem, was die App erwartet: %@";
|
||
|
||
/* --- Offline --- */
|
||
"stand.hinweis" = "Stand von %@ – der Server ist gerade nicht erreichbar.";
|
||
|
||
/* --- Server-Adresse --- */
|
||
"server.titel" = "Mit Certain verbinden";
|
||
"server.ueberschrift" = "Adresse";
|
||
"server.platzhalter" = "budget.beispiel.com";
|
||
"server.erklaerung" = "Dieselbe Adresse, unter der du Certain im Browser öffnest. Ohne https davor geht auch.";
|
||
"server.verbinden" = "Verbinden";
|
||
"server.keineAdresse" = "Das sieht nicht nach einer Adresse aus.";
|
||
|
||
/* --- Anmeldung --- */
|
||
"anmeldung.titel" = "Anmelden";
|
||
"anmeldung.benutzer" = "Benutzername";
|
||
"anmeldung.passwort" = "Passwort";
|
||
"anmeldung.anmelden" = "Anmelden";
|
||
"anmeldung.erklaerung" = "Nur dieses eine Mal. Danach merkt sich das Gerät einen eigenen Schlüssel, und dein Passwort wird nirgends gespeichert.";
|
||
"anmeldung.andererServer" = "Anderen Server wählen";
|
||
"anmeldung.aktuellerServer" = "Verbunden mit %@";
|
||
"anmeldung.markeOhneSchluessel" = "Der Server hat keinen Schlüssel zurückgegeben. Bitte nochmal versuchen.";
|
||
|
||
/* --- Zweiter Faktor --- */
|
||
"zweifaktor.titel" = "Zweiter Faktor";
|
||
"zweifaktor.ueberschrift" = "Code";
|
||
"zweifaktor.platzhalterCode" = "123456";
|
||
"zweifaktor.platzhalterWiederherstellung" = "ABCDE-FGHIJ";
|
||
"zweifaktor.erklaerungCode" = "Die sechs Ziffern aus deiner Authenticator-App.";
|
||
"zweifaktor.erklaerungWiederherstellung" = "Einer der Codes, die du beim Einrichten bekommen hast. Jeder gilt nur einmal.";
|
||
"zweifaktor.bestaetigen" = "Bestätigen";
|
||
"zweifaktor.dochWiederherstellung" = "Stattdessen einen Wiederherstellungscode benutzen";
|
||
"zweifaktor.dochCode" = "Stattdessen den Code aus der App benutzen";
|
||
"zweifaktor.abbrechen" = "Anmeldung abbrechen";
|
||
"zweifaktor.verbraucht" = "Zu viele Fehlversuche. Bitte von vorn anmelden.";
|
||
|
||
/* --- Zweiter Faktor fehlt noch --- */
|
||
"zweifaktorEinrichten.titel" = "Zweiter Faktor nötig";
|
||
"zweifaktorEinrichten.erklaerung" = "Für dieses Konto verlangt die Richtlinie einen zweiten Faktor. Einrichten lässt er sich bisher nur im Browser – in der App kommt das noch.";
|
||
"zweifaktorEinrichten.imBrowser" = "Im Browser öffnen";
|
||
|
||
/* --- Passwortwechsel --- */
|
||
"passwort.titel" = "Passwort wechseln";
|
||
"passwort.bisher" = "Bisheriges Passwort";
|
||
"passwort.neu" = "Neues Passwort";
|
||
"passwort.wiederholen" = "Noch einmal";
|
||
"passwort.erklaerung" = "Für dieses Konto steht ein Passwortwechsel an. Vorher lässt der Server nichts anderes zu.";
|
||
"passwort.stimmtNichtUeberein" = "Die beiden stimmen nicht überein.";
|
||
"passwort.speichern" = "Passwort wechseln";
|
||
|
||
/* --- Konten --- */
|
||
"konten.titel" = "Konten";
|
||
"konten.leerTitel" = "Noch keine Konten";
|
||
"konten.leerErklaerung" = "Lege dein erstes Konto im Browser an – in der App kommt das in einer späteren Stufe.";
|
||
"konten.archivierteZeigen" = "Archivierte zeigen";
|
||
"konten.archiviert" = "archiviert";
|
||
"konten.gebunden" = "Gebundenes Geld";
|
||
"konten.gebundenSumme" = "Davon gebunden";
|
||
"konten.verfuegbar" = "Verfügbar";
|
||
"konten.bankWeichtAb" = "Die Bank meldet einen anderen Saldo";
|
||
|
||
/* --- Kontoarten --- */
|
||
"kontoart.girokonto" = "Girokonto";
|
||
"kontoart.sparkonto" = "Sparkonto";
|
||
"kontoart.bargeld" = "Bargeld";
|
||
"kontoart.kreditkarte" = "Kreditkarte";
|
||
"kontoart.depot" = "Depot";
|
||
"kontoart.sonstiges" = "Sonstiges";
|
||
|
||
/* --- Einstellungen --- */
|
||
"einstellungen.zugang" = "Zugang";
|
||
"einstellungen.angemeldetAls" = "Angemeldet als";
|
||
"einstellungen.server" = "Server";
|
||
"einstellungen.markeErklaerung" = "Dieses Gerät hat einen eigenen Schlüssel. Du kannst ihn am Rechner unter Einstellungen → Gerätemarken jederzeit widerrufen; dann meldet sich die App sofort ab.";
|
||
"einstellungen.ausDemServer" = "Vom Server";
|
||
"einstellungen.hauptwaehrung" = "Hauptwährung";
|
||
"einstellungen.budgetStarttag" = "Budget beginnt am";
|
||
"einstellungen.abmeldenFrage" = "Von diesem Gerät abmelden?";
|
||
"einstellungen.abmeldenErklaerung" = "Beim Abmelden wird der Schlüssel dieses Geräts auch am Server entfernt.";
|
||
|
||
/* --- Dashboard --- */
|
||
"dashboard.bilanz" = "Dieser Monat";
|
||
"dashboard.einnahmen" = "Einnahmen";
|
||
"dashboard.ausgaben" = "Ausgaben";
|
||
"dashboard.budgetfortschritt" = "Budget";
|
||
"dashboard.keinBudget" = "Für diesen Monat ist noch nichts geplant.";
|
||
"dashboard.kontostaende" = "Konten";
|
||
"dashboard.letzteBuchungen" = "Zuletzt";
|
||
|
||
/* --- Budget --- */
|
||
"budget.einnahmen" = "Geplante Einnahmen";
|
||
"budget.uebrig" = "übrig";
|
||
"budget.vonGeplant" = "%1$@ von %2$@ ausgegeben";
|
||
"budget.vonBetrag" = "von %@";
|
||
"budget.angepasst" = "angepasst";
|
||
"budget.vorigerMonat" = "Voriger Monat";
|
||
"budget.naechsterMonat" = "Nächster Monat";
|
||
"budget.ausVertraegenHinweis" = "%1$d Verträge: %2$@";
|
||
"budget.ausVertraegenBerechnet" = "Berechnet aus %1$d Verträgen: %2$@";
|
||
"budget.vertraegeOhneKategorie" = "%1$d Verträge ohne Kategorie (%2$@) fehlen in diesen Summen.";
|
||
"budget.ohneKurs" = "Kein Wechselkurs für %@ – diese Beträge fehlen in den Summen.";
|
||
|
||
/* --- Buchungen --- */
|
||
"buchungen.suchen" = "Empfänger, Zweck, Notiz";
|
||
"buchungen.konto" = "Konto";
|
||
"buchungen.alleKonten" = "Alle Konten";
|
||
"buchungen.art" = "Art";
|
||
"buchungen.alleArten" = "Alle Arten";
|
||
"buchungen.leerTitel" = "Keine Buchungen";
|
||
"buchungen.leerErklaerung" = "Sobald etwas gebucht ist, steht es hier.";
|
||
"buchungen.leerGefiltert" = "Zu dieser Suche gibt es nichts. Andere Filter versuchen?";
|
||
"buchung.ohneBezeichnung" = "Ohne Bezeichnung";
|
||
"buchung.ohneKategorie" = "Ohne Kategorie";
|
||
"buchung.uebertrag" = "Übertrag";
|
||
|
||
/* --- Buchungsarten --- */
|
||
"buchungsart.ausgabe" = "Ausgabe";
|
||
"buchungsart.einnahme" = "Einnahme";
|
||
"buchungsart.uebertrag" = "Übertrag";
|
||
|
||
/* --- Verträge --- */
|
||
"abos.leerTitel" = "Keine Verträge";
|
||
"abos.leerErklaerung" = "Hier stehen Abos und Verträge, sobald welche angelegt sind.";
|
||
"abos.beendeteZeigen" = "Beendete zeigen";
|
||
"abos.beendet" = "beendet";
|
||
"abos.jaehrlichUndAnzahl" = "%1$@ im Jahr · %2$d aktiv";
|
||
"abos.ohneKurs" = "Kein Wechselkurs für %@ – diese Verträge fehlen in der Summe.";
|
||
"abo.monatlich" = "monatlich";
|
||
"abo.vierteljaehrlich" = "vierteljährlich";
|
||
"abo.halbjaehrlich" = "halbjährlich";
|
||
"abo.jaehrlich" = "jährlich";
|
||
"abo.alleNMonate" = "alle %d Monate";
|
||
"abo.proMonat" = "%@ im Monat";
|
||
"abo.naechste" = "nächste am %@";
|
||
"abo.inTagen" = "fällig in %d Tagen";
|