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
@@ -1,7 +1,9 @@
|
||||
// Konto-Menü im Seitenkopf: abgemeldet „Anmelden“, angemeldet ein Avatar-Kreis mit Initiale
|
||||
// und einem Menü (E-Mail, „Meine Karten“, „Abmelden“).
|
||||
// und einem Menü (E-Mail, „Meine Karten“, „Abmelden“). Die Texte stehen in der Sprache der Seite; nach einem Sprachwechsel
|
||||
// baut main.ts das Menü neu auf.
|
||||
import './account.css';
|
||||
import { el } from '../editor/dom';
|
||||
import { t } from '../i18n/i18n';
|
||||
import { currentUser, logout, onAuthChange } from './auth';
|
||||
import { errorMessage } from './errors';
|
||||
import { requireLogin } from './login-dialog';
|
||||
@@ -26,7 +28,7 @@ export function mountAccountMenu(slot: HTMLElement): AccountMenu {
|
||||
}
|
||||
const user = currentUser();
|
||||
if (!user) {
|
||||
const signIn = el('button', { type: 'button', class: 'auth-btn auth-btn-small' }, 'Anmelden');
|
||||
const signIn = el('button', { type: 'button', class: 'auth-btn auth-btn-small' }, t('Anmelden'));
|
||||
signIn.addEventListener('click', () => void requireLogin('login'));
|
||||
slot.replaceChildren(el('div', { class: 'account-menu' }, signIn));
|
||||
return;
|
||||
@@ -38,18 +40,18 @@ export function mountAccountMenu(slot: HTMLElement): AccountMenu {
|
||||
{
|
||||
type: 'button',
|
||||
class: 'account-avatar',
|
||||
'aria-label': 'Konto-Menü',
|
||||
'aria-label': t('Konto-Menü'),
|
||||
'aria-expanded': 'false',
|
||||
'aria-controls': 'account-dropdown',
|
||||
},
|
||||
initial,
|
||||
);
|
||||
const email = el('span', { class: 'account-email', title: user.email }, user.email);
|
||||
const myCards = el('a', { class: 'account-item', href: '/karten', 'data-link': true }, 'Meine Karten');
|
||||
const signOut = el('button', { type: 'button', class: 'account-item' }, 'Abmelden');
|
||||
const myCards = el('a', { class: 'account-item', href: '/karten', 'data-link': true }, t('Meine Karten'));
|
||||
const signOut = el('button', { type: 'button', class: 'account-item' }, t('Abmelden'));
|
||||
const error = el('span', { class: 'account-error', role: 'alert' });
|
||||
const dropdown = el('div', { class: 'account-dropdown', id: 'account-dropdown', hidden: true }, email, myCards, signOut, error);
|
||||
const wrap = el('div', { class: 'account-menu', role: 'group', 'aria-label': 'Konto' }, avatar, dropdown);
|
||||
const wrap = el('div', { class: 'account-menu', role: 'group', 'aria-label': t('Konto') }, avatar, dropdown);
|
||||
|
||||
let isOpen = false;
|
||||
function setOpen(open: boolean): void {
|
||||
|
||||
Reference in new issue
Block a user