- Neu `account/profile.ts`: Muster, Sperrliste und Schlüssel (ein Test vergleicht
sie mit `deploy/api/common.js`), Profile lesen (`getUsername`, `usernamesFor`
gesammelt in einer Abfrage und zwischengespeichert, bei einem Fehler nur die
bekannten Namen), `isUsernameTaken`, `saveUsername` (POST /api/profil,
Zwischenspeicher + `onUsernameChange`), `myUsername`/`loadMyUsername` und der
Merker `aircard.usernamePrompted`. `IDS.profiles`.
- Neu `account/username-dialog.ts`: Dialog „Benutzername wählen“ in den Modi
prompt („Später“), required („Abbrechen“) und change (vorbelegt), Fehler am
Feld, Busy-Sperre, höchstens ein Dialog zur Zeit; dazu `requireUsername()`.
- Registrieren: Pflichtfeld „Benutzername“ vor der E-Mail. Muster, Sperrliste und
Verfügbarkeit werden vor dem Anlegen des Kontos geprüft (kein halbes Konto);
danach wird der Name gespeichert, scheitert das, schließt der Login-Dialog und
der Namensdialog fragt.
- Konto-Menü: „@name“ oben, die E-Mail klein darunter, Eintrag „Benutzername
ändern“ bzw. „Benutzername wählen“.
- main.ts: Name nach Start und Anmeldung lesen; ohne Namen einmal pro Sitzung der
Dialog „prompt“ (nicht, wenn der Name nicht lesbar ist).
- Texte in `en.ts`, Stile in `account.css`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Der Editor-Zustand überlebt den Sprachwechsel (nur die Seite wird neu aufgebaut). Sein Standardname „Meine Karte“ blieb dabei deutsch, auch wenn die Seite
danach Englisch sprach: Herunterladen („aircard-meine-karte.png“) und Speichern nahmen ihn mit.
- state.ts: `defaultCardName()` (der Standardname in der Sprache der Seite, trägt auch initialEditorState) und `followLanguage(store)`: ein Hörer von
onLangChange, der den Namen einer noch nicht gespeicherten Karte ersetzt, wenn er dem unberührten Standardnamen der bisherigen Sprache gleicht. Ein eigener
Name bleibt, ebenso der Name einer gespeicherten Karte (auch wenn er dem Standard gleicht). Er merkt sich den Standard der Sprache bis zum nächsten Wechsel,
so braucht es kein Wörterbuch der Gegensprache; gibt die Abmeldung zurück.
- main.ts: `followLanguage(editorStore)` direkt nach bindEditorToAuth, also vor dem Hörer, der Rahmen und Seite neu aufbaut: die neue Seite sieht den neuen Namen.
- Tests: Wechsel hin und zurück, Start auf Englisch, eigener Name, zurückgesetzter Name, gespeicherte Karte, leerer Name, Rest des Zustands und genau
eine Benachrichtigung, Abmeldung; in main.test.ts mit dem echten Sprachknopf samt Name, den die neu gebaute Seite beim Aufbau sieht.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Das Banner merkte sich „geschlossen“ nur in localStorage. Bei gesperrtem Speicher (privates Fenster, gesperrte Website-Daten) baute der Neuaufbau
des Rahmens beim Sprachwechsel (main.ts) es wieder auf.
- donate-banner.ts: zusätzlich ein Merker im Speicher des Moduls (closedThisSession); er gilt neben localStorage.
- Tests: donate-banner.test.ts lädt je Test eine frische Modulkopie (der Merker lebt im Modul); neue Fälle: gesperrter Speicher, erneutes Einhängen
nach dem Schließen (bleibt weg) und ohne Schließen (kommt wieder); main.test.ts: Sprachwechsel nach dem Schließen bei gesperrtem Speicher.
Die beiden schon vorhandenen Fälle zum gesperrten Speicher sperren jetzt wirklich (vi.stubGlobal): vi.spyOn(Storage.prototype, …) greift in
happy-dom nicht, die Fälle waren leer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Task 10: alle sichtbaren Texte von account/, editor/, card/ und der Seite „Passwort neu setzen“ (Texte, aria-label, title, Meldungen,
Rückfragen) gehen durch t()/msg(); en.ts bekommt 87 Einträge.
- account/: Konto-Menü, Login-Dialog (Titel, Reiter, Felder, Meldungen) und errors.ts (errorMessage übersetzt beim Zurückgeben).
validatePassword nutzt {min}/{max}. Der Login-Dialog wird nur einmal gebaut: die Beschriftung des Schließen-Knopfs wird bei jedem
Öffnen in der aktuellen Sprache gesetzt. LOGIN_NEEDED und DEFAULT_CARD_NAME bleiben deutsche Konstanten (msg), angezeigt werden sie
mit t(); der Standardname einer neuen Karte folgt damit der Sprache („My card“).
- editor/: Vorlagen-, Options- und Vorschauspalte, Bild-Upload, Speichern, Download, Rückfragen. Konstanten (upload.ts, download.ts,
editor-page.ts) bleiben deutsche Strings per msg(); validateImageFile, pngSizeWarning und das Speichern („Speichern fehlgeschlagen –
{reason}“) liefern den Text schon übersetzt, Fehler tragen weiter die deutsche Konstante (Vergleiche mit READ_MESSAGE/PIXELS_MESSAGE
gehen weiter) und werden beim Anzeigen mit t(error.message) übersetzt. Zoom „100 %“ / „100%“ und „Bearbeitet: {name}“ mit Platzhaltern.
- card/: Bezeichnungen der Marken (msg) und die Meldungen des Renderers (msg, Anzeige im Editor über t()).
- pages/reset-page.ts, account/login-dialog.ts: Die Meldung „Die Passwörter stimmen nicht überein.“ ist nicht mehr der Schlüssel zum
Fokus: es zählt die Bedingung selbst, nicht der Vergleich mit dem (nun übersetzten) Text.
- i18n/coverage.test.ts: Heuristik für deutsche Text-Literale außerhalb von t()/msg() (Umlaut/ß, mindestens zwei Wörter, einzelnes
großgeschriebenes Wort; gelesen wird der Syntaxbaum) für account/, editor/, card/ und pages/reset-page.ts; Ausnahmen mit Grund, jede
muss noch zutreffen; Scanner mit eigenen Tests. Die Liste der Bereiche ist eine Konstante für Task 11.
- i18n/english-ui.test.ts (neu): Stichproben auf Englisch (Konto-Menü, Login-Dialog, Passwort-Seite, Editor inkl. Fehlerwege) und
„kein deutscher Wörterbuchtext auf der englischen Seite“.
- test-setup.ts: Wer Module mit vi.resetModules() frisch lädt, bekam eine neue Kopie von i18n.ts mit der Browsersprache (happy-dom: en-US);
der Browser meldet im Test jetzt Deutsch, damit auch diese Tests deutsch beginnen. main.test.ts: nach dem Wechsel auf Englisch heißt
der Knopf des Konto-Menüs „Sign in“.
- Tests: Vitest 53 Dateien, 1779 Tests grün, tsc und Build sauber.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- i18n-Kern im gettext-Stil (t/msg, Wörterbuch en.ts); Startsprache aus localStorage, sonst Browsersprache;
<html lang> setzt auch das Inline-Skript in index.html. Ein Test prüft t()/msg() und en.ts in beide Richtungen.
- Kopfzeile: GitHub-Link und Sprachknopf (Zielsprache, Beschriftung und lang in der Zielsprache), Fußzeile aus mountFooter,
Banner und Seitentitel übersetzt, statisches index.html englisch.
- Sprachwechsel ohne Neuladen (main.ts): Kopfzeile, Banner, Konto-Menü und Fußzeile neu aufgebaut, rerender() des Routers baut
die Seite neu auf, der Editor-Store bleibt; der Appwrite-Client bekommt die Sprache.
- Kopfzeile bleibt in einer Zeile: einzeilig ab 1000 px (vorher 900), GitHub-Text ab 1230 px, auf schmalen Telefonen steht
„Anmelden“ neben der Suche.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>