feat(i18n): Konto, Editor und Karte auf Englisch
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>
This commit is contained in:
1 parent
a75be2d44c
commit
1ff1873b27
23 files changed
+857
-169
No files matched your search
@@ -35,7 +35,8 @@ const EN_FOOTER = 'Unofficial community site for the AirCard-iOS app';
|
||||
const slot = () => document.getElementById('account-slot') as HTMLElement;
|
||||
const langButton = () => document.querySelector<HTMLButtonElement>('button.lang-btn')!;
|
||||
const navTexts = () => [...document.querySelectorAll('nav.app-nav a[data-link]')].map((a) => a.textContent);
|
||||
const signIn = () => [...slot().querySelectorAll('button')].find((b) => b.textContent === 'Anmelden');
|
||||
// Der Anmelden-Knopf des Konto-Menüs in der Sprache der Seite („Anmelden“ auf Deutsch, „Sign in“ nach dem Wechsel auf Englisch).
|
||||
const signIn = (label = 'Anmelden') => [...slot().querySelectorAll('button')].find((b) => b.textContent === label);
|
||||
|
||||
/** Startet main.ts frisch (es läuft beim Import) auf der Adresse `path`; `storedLang` ist die gespeicherte Sprachwahl (null: keine). */
|
||||
async function start(path = '/', storedLang: string | null = 'de') {
|
||||
@@ -139,7 +140,7 @@ describe('Sprachwechsel', () => {
|
||||
|
||||
langButton().click();
|
||||
|
||||
expect(signIn()).toBeDefined(); // kein leerer Platz bis zur nächsten Änderung
|
||||
expect(signIn('Sign in')).toBeDefined(); // kein leerer Platz bis zur nächsten Änderung, jetzt auf Englisch
|
||||
expect(mocks.authListeners.size).toBe(1); // das alte Menü hat sich abgemeldet
|
||||
expect(mocks.getCurrentUser).toHaveBeenCalledTimes(1); // der Status wird nicht noch einmal geholt
|
||||
});
|
||||
@@ -155,7 +156,7 @@ describe('Sprachwechsel', () => {
|
||||
expect(mocks.authListeners.size).toBe(1);
|
||||
|
||||
answer(null);
|
||||
await vi.waitFor(() => expect(signIn()).toBeDefined());
|
||||
await vi.waitFor(() => expect(signIn('Sign in')).toBeDefined());
|
||||
});
|
||||
|
||||
it('der Fokus bleibt auf dem Sprachknopf, auch wenn die Kopfzeile neu gebaut wird', async () => {
|
||||
|
||||
Reference in new issue
Block a user