feat: Erste Stufe der iOS-App - Anmeldung und Kontenliste

Neuer Ordner ios/ mit dem Geruest: Netzwerkschicht, Modelle, Offline-Ablage,
Texte in Deutsch und Englisch, Navigation, der komplette Anmeldeweg (Server
waehlen, anmelden, zweiter Faktor, Pflicht-Passwortwechsel) und als erste
Fachansicht die Kontenliste.

Die Anmeldung laeuft einmal ueber das Sitzungs-Cookie, holt sich dabei eine
App-Marke und legt sie in den Schluesselbund. Danach traegt nur noch der
Header. Kein Passwort auf dem Geraet, kein Ablauf nach 30 Tagen.

Der Code ist nie uebersetzt worden - hier gibt es kein Xcode. Geprueft ist
dafuer jedes Modellfeld gegen echte Antworten des laufenden Backends; dabei
kam heraus, dass created_at ohne Zeitzone und mit Mikrosekunden kommt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-20 16:20:03 +02:00
co-authored by Claude Opus 5
parent 8a7545bf5b
commit 6b86a6bf91
25 changed files with 2908 additions and 0 deletions
+104
View File
@@ -0,0 +1,104 @@
/* 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";
/* --- Reiter --- */
"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.";