Task 9: die Infozeile zum gewählten Logo unter dem Raster (Spec § 3 und § 6). - logos/logo-info.ts (neu): „<Name> · von <Anzeigename> · ♥ <Zahl>“ und „Melden“ (auch für Gäste; ein ausgeblendetes Logo lässt sich nicht melden). Der Hochlader sieht „Löschen“ mit Rückfrage (Titel mit Namen, Folgen im Text), Admins „<n> Meldungen“ mit den Gründen als Text (listLogoReports, einmal je Logo und Stand), „Ausblenden“/„Einblenden“ und „Löschen“. Gelöscht: deleteLogo, forgetLogo, Kachel weg, onSelect(null); ein-/ausgeblendet: setLogoVisibility, forgetLogo (ein Null-Bild bleibt nicht im Zwischen- speicher), die Zeile des Pickers wird fortgeschrieben (Einblenden setzt reportCount auf 0). Gewähltes Logo nicht auffindbar: „Das gewählte Logo ist nicht mehr verfügbar.“ (ein Netzfehler von getLogo sagt nichts). Zugleich die Meldezeile (role="alert") für Fehler von Herz, Hochladen und diesen Aktionen; ein Wechsel der Auswahl räumt sie ab. Immer nur eine Aktion zugleich; die Rechte werden nach der Rückfrage noch einmal geprüft; der Aufbau steht einmal da, update() ändert nur Texte und Sichtbarkeit (Fokus bleibt). - logos/logo-picker.ts: hängt die Infozeile als Letztes unter das Raster (info.el). Herz- und Upload-Fehler gehen in die Infozeile, der Statusbereich des Pickers bleibt den Ladefehlern der Liste vorbehalten (ein Klick auf ein Herz löscht ihren Text nicht mehr). Aus dem Review von Task 8: requireLogin, das wirft, zeigt den Grund statt einer unbehandelten Ablehnung; select() nach dispose() ist wirkungslos. Löschen entfernt Kachel, Zeile, Herz und Eintrag der Liste, setzt den Cursor von „Mehr laden“ auf das Logo davor (Appwrite lehnt einen Cursor auf eine gelöschte Zeile ab), hebt die Auswahl über onSelect(null) auf und holt den Fokus nach „Kein Logo“, wenn er auf „Löschen“ lag. LogoPickerDeps erweitert um reportLogo, deleteLogo, setLogoVisibility, listLogoReports, confirm und reportDialog. - community/report-dialog.ts: subject 'card' (Standard, unverändert) oder 'logo': Überschrift „Logo melden“, Einleitung „dieses Logo“, vier Gründe ohne „Echte Kartendaten“, Duplikat-Dank „Danke, du hast dieses Logo schon gemeldet.“. Der ganze Dialog geht durch t()/msg(); Fehler des Dienstes über apiErrorText. - logos/logos.css: das Herz sitzt in der Textzeile unter der Bildfläche (nicht mehr auf dem Logo, folgt dem Theme), die Kachel füllt die Zelle (height: 100%), damit „Kein Logo“ so hoch ist wie sein Nachbar; Stile der Infozeile. - editor/editor-page.ts: Aus dem Review von Task 8: der Ladefehler der Logos verschwindet, sobald ein Logo danach lädt, aber nur der, den der Logo-Zustand selbst ins Fehlerfeld geschrieben hat; jeder andere Text im Feld bleibt. - i18n/en.ts: englische Texte zu allen neuen Beschriftungen und zum Melden-Dialog. - Tests: logo-info.test.ts (neu), logo-picker.test.ts (Infozeile, Löschen, Ein-/Ausblenden, Fehler, Cursor, Fokus), report-dialog.test.ts (Logo und Englisch), editor-page.test.ts (Fehlerfeld). Vitest 52 Dateien, 1764 Tests grün, tsc und Build sauber. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
163 lines
10 KiB
TypeScript
163 lines
10 KiB
TypeScript
// Englisches Wörterbuch: deutscher Text (Schlüssel) → Englisch, gelesen von t() in i18n.ts. Fehlt ein Eintrag, bleibt der deutsche Text.
|
||
// Jeder Eintrag gehört zu einem t('…') oder msg('…') im Quelltext; coverage.test.ts prüft es in beide Richtungen.
|
||
// Englisch: kurz, freundlich, US-Schreibweise. „AirCard-IOS“ ist der Name dieser Seite, „AirCard-iOS“ der Name der App.
|
||
export const EN: Readonly<Record<string, string>> = {
|
||
// Seitentitel (pages/router.ts)
|
||
'AirCard-IOS – Kartendesigns für Apple Wallet': 'AirCard-IOS – Card designs for Apple Wallet',
|
||
'Gestalten – AirCard-IOS': 'Create – AirCard-IOS',
|
||
'Meine Karten – AirCard-IOS': 'My cards – AirCard-IOS',
|
||
'Community – AirCard-IOS': 'Community – AirCard-IOS',
|
||
'Passwort neu setzen – AirCard-IOS': 'Set new password – AirCard-IOS',
|
||
|
||
// Kopfzeile (shell/header.ts)
|
||
'Hauptnavigation': 'Main navigation',
|
||
'Community': 'Community',
|
||
'Gestalten': 'Create',
|
||
'Meine Karten': 'My cards',
|
||
'Unterstützen': 'Support us',
|
||
'Titel, Tags oder Herausgeber': 'Title, tags or issuer',
|
||
'Community-Karten durchsuchen': 'Search community cards',
|
||
'Suchen': 'Search',
|
||
'Hell/Dunkel umschalten': 'Toggle light/dark mode',
|
||
'Menü': 'Menu',
|
||
'AirCard-iOS auf GitHub': 'AirCard-iOS on GitHub',
|
||
|
||
// Spenden-Banner (shell/donate-banner.ts)
|
||
'Banner schließen': 'Close banner',
|
||
'Gefällt dir AirCard-IOS? Spendier uns einen Kaffee – damit das Projekt weiterläuft.':
|
||
'Enjoying AirCard-IOS? Buy us a coffee – it keeps the project running.',
|
||
|
||
// Fußzeile (shell/footer.ts)
|
||
'Inoffizielle Community-Seite für die App AirCard-iOS – kein Teil des Original-Projekts und nicht mit Apple verbunden. Logos und Motive stammen von Nutzern; alle Marken gehören ihren Inhabern.':
|
||
'Unofficial community site for the AirCard-iOS app – not part of the original project and not affiliated with Apple. Logos and artwork are uploaded by users; all trademarks belong to their owners.',
|
||
|
||
// Logo auf der Karte (logos/logo-asset.ts, community/publish.ts, editor/options-panel.ts)
|
||
'Das gewählte Logo ist nicht mehr verfügbar.': 'The selected logo is no longer available.',
|
||
'Das Logo dieser Karte ist nicht mehr verfügbar. Öffne die Karte im Editor und wähle ein anderes.':
|
||
'This card’s logo is no longer available. Open the card in the editor and choose another one.',
|
||
'Logo oben links': 'Top-left logo',
|
||
|
||
// Logo auswählen und verarbeiten (logos/prepare-logo.ts)
|
||
'Bitte ein PNG-, JPG-, WebP- oder SVG-Bild wählen.': 'Please choose a PNG, JPG, WebP or SVG image.',
|
||
'Die Datei ist größer als 5 MB.': 'The file is larger than 5 MB.',
|
||
'Das Bild ist zu groß (max. 40 Megapixel).': 'The image is too large (max. 40 megapixels).',
|
||
'Das Logo konnte nicht gelesen werden.': 'The logo couldn’t be read.',
|
||
'Das Logo ist leer.': 'The logo is empty.',
|
||
'Das Logo ist zu klein (mindestens 8 × 8 Pixel).': 'The logo is too small (at least 8 × 8 pixels).',
|
||
|
||
// Dialog „Logo hochladen“ (logos/logo-dialog.ts). „Bitte gib einen Namen an.“ steht unter den API-Fehlertexten.
|
||
'Logo hochladen': 'Upload logo',
|
||
'Datei (Pflicht)': 'File (required)',
|
||
'PNG, JPG, WebP oder SVG, höchstens 5 MB und 40 Megapixel.': 'PNG, JPG, WebP or SVG, up to 5 MB and 40 megapixels.',
|
||
'Vorschau': 'Preview',
|
||
'Dunkel': 'Dark',
|
||
'Hell': 'Light',
|
||
'Logo-Vorschau auf dunklem Grund': 'Logo preview on a dark background',
|
||
'Logo-Vorschau auf hellem Grund': 'Logo preview on a light background',
|
||
'Einfarbig – passt sich Hell/Dunkel an': 'Single color – adapts to light/dark mode',
|
||
'Nur wählbar, wenn das Logo transparente Bereiche hat.': 'Only available if the logo has transparent areas.',
|
||
'Name (Pflicht)': 'Name (required)',
|
||
'Anzeigename (optional)': 'Display name (optional)',
|
||
'Anonym': 'Anonymous',
|
||
'Leer = „Anonym“. Deine E-Mail-Adresse wird nie angezeigt.': 'Leave empty for “Anonymous”. Your email address is never shown.',
|
||
'Ich habe die Rechte an diesem Logo oder die Erlaubnis des Inhabers, und es darf öffentlich geteilt werden.':
|
||
'I own the rights to this logo or have permission from the owner, and it may be shared publicly.',
|
||
'Abbrechen': 'Cancel',
|
||
'Hochladen': 'Upload',
|
||
'Logo wird verarbeitet …': 'Processing logo …',
|
||
'Wird hochgeladen …': 'Uploading …',
|
||
'Hochladen fehlgeschlagen – {reason}': 'Upload failed – {reason}',
|
||
'Bitte wähle eine Datei.': 'Please choose a file.',
|
||
'Der Name enthält ungültige Zeichen.': 'The name contains invalid characters.',
|
||
'Der Name ist zu lang (höchstens {max} Zeichen).': 'The name is too long (at most {max} characters).',
|
||
'Der Anzeigename enthält ungültige Zeichen.': 'The display name contains invalid characters.',
|
||
'Der Anzeigename ist zu lang (höchstens {max} Zeichen).': 'The display name is too long (at most {max} characters).',
|
||
'Bitte bestätige, dass du das Logo teilen darfst.': 'Please confirm that you’re allowed to share the logo.',
|
||
|
||
// Bereich „Logo unten rechts“ im Editor (logos/logo-picker.ts). „Community“, „Hochladen“ und „Anonym“ stehen weiter oben.
|
||
'Logo unten rechts': 'Bottom-right logo',
|
||
'Logos werden von der Community hochgeladen.': 'Logos are uploaded by the community.',
|
||
'Sortierung': 'Sort order',
|
||
'Beliebt': 'Popular',
|
||
'Neu': 'New',
|
||
'Gemeldet': 'Reported',
|
||
'Ausgeblendet': 'Hidden',
|
||
'Kein Logo': 'No logo',
|
||
'von {name}': 'by {name}',
|
||
'Herz für „{name}“: {count}': 'Heart for “{name}”: {count}',
|
||
'Noch keine Community-Logos – lade das erste hoch.': 'No community logos yet – upload the first one.',
|
||
'Keine Logos in dieser Ansicht.': 'No logos in this view.',
|
||
'Die Logos konnten nicht geladen werden.': 'The logos couldn’t be loaded.',
|
||
'Nochmal versuchen': 'Try again',
|
||
'Mehr laden': 'Load more',
|
||
|
||
// Infozeile zum gewählten Logo (logos/logo-info.ts). „von {name}“, „Anonym“, „Ausgeblendet“ und „Melden“ stehen an anderer Stelle,
|
||
// der Hinweis „Das gewählte Logo ist nicht mehr verfügbar.“ weiter oben (Logo auf der Karte).
|
||
'Löschen': 'Delete',
|
||
'Ausblenden': 'Hide',
|
||
'Einblenden': 'Unhide',
|
||
'Die Gründe konnten nicht geladen werden.': 'The reasons couldn’t be loaded.',
|
||
'Logo „{name}“ löschen?': 'Delete logo “{name}”?',
|
||
'Das Logo, seine Herzen und Meldungen werden endgültig gelöscht. Gespeicherte Karten zeigen es danach nicht mehr. Bereits veröffentlichte Kartenbilder bleiben unverändert.':
|
||
'The logo, its hearts and reports will be deleted permanently. Saved cards will no longer show it. Cards that were already published stay unchanged.',
|
||
|
||
// Melden-Dialog für Karten und Logos (community/report-dialog.ts). „Abbrechen“ steht weiter oben.
|
||
'Melden': 'Report',
|
||
'Karte melden': 'Report card',
|
||
'Logo melden': 'Report logo',
|
||
'Warum möchtest du diese Karte melden?': 'Why do you want to report this card?',
|
||
'Warum möchtest du „{title}“ melden?': 'Why do you want to report “{title}”?',
|
||
'Warum möchtest du dieses Logo melden?': 'Why do you want to report this logo?',
|
||
'Grund der Meldung': 'Reason for the report',
|
||
'Unangemessen': 'Inappropriate',
|
||
'Echte Kartendaten': 'Real card data',
|
||
'Urheberrecht/Marke': 'Copyright/trademark',
|
||
'Spam': 'Spam',
|
||
'Sonstiges': 'Other',
|
||
'Bitte wähle einen Grund.': 'Please choose a reason.',
|
||
'Danke für deine Meldung.': 'Thanks for your report.',
|
||
'Danke, du hast diese Karte schon gemeldet.': 'Thanks, you’ve already reported this card.',
|
||
'Danke, du hast dieses Logo schon gemeldet.': 'Thanks, you’ve already reported this logo.',
|
||
'Schließen': 'Close',
|
||
|
||
// API-Fehlertexte (i18n/api-messages.ts). Schlüssel und deutsche Texte stammen aus MSG (deploy/api/common.js); api-messages.test.ts hält sie gleich.
|
||
'Bitte melde dich an.': 'Please sign in.',
|
||
'Nicht gefunden.': 'Not found.',
|
||
'Diese Karte ist nicht (mehr) verfügbar.': 'This card is no longer available.',
|
||
'Dazu hast du keine Berechtigung.': 'You are not allowed to do that.',
|
||
'Nur für Admins.': 'Admins only.',
|
||
'Diese Datei gehört dir nicht.': 'This file doesn’t belong to you.',
|
||
'Bild nicht gefunden.': 'Image not found.',
|
||
'Das Bild muss eine PNG- oder WebP-Datei sein.': 'The image must be a PNG or WebP file.',
|
||
'Das Bild ist größer als 5 MB.': 'The image is larger than 5 MB.',
|
||
'Diese Karte ist schon veröffentlicht.': 'This card is already published.',
|
||
'Diese Bilder sind bereits veröffentlicht oder gesperrt.': 'These images are already published or blocked.',
|
||
'Das Bild hat nicht das Kartenformat.': 'The image doesn’t match the card format.',
|
||
'Diese Karte gehört nicht zu deinem Konto.': 'This card doesn’t belong to your account.',
|
||
'Du hast schon 20 Karten veröffentlicht. Zieh eine zurück, um eine neue zu veröffentlichen.':
|
||
'You’ve already published 20 cards. Withdraw one to publish a new one.',
|
||
'Zu viele Meldungen – bitte später nochmal.': 'Too many reports – please try again later.',
|
||
'Ungültige Anfrage.': 'Invalid request.',
|
||
'Ungültige Karten-ID.': 'Invalid card ID.',
|
||
'Bitte wähle einen gültigen Grund.': 'Please choose a valid reason.',
|
||
'Ungültige Angabe zur Sichtbarkeit.': 'Invalid visibility value.',
|
||
'Dieses Logo ist nicht (mehr) verfügbar.': 'This logo is no longer available.',
|
||
'Ungültige Logo-ID.': 'Invalid logo ID.',
|
||
'Bitte gib einen Namen an.': 'Please enter a name.',
|
||
'Das Logo muss eine PNG-Datei sein.': 'The logo must be a PNG file.',
|
||
'Das Logo ist größer als 1 MB.': 'The logo is larger than 1 MB.',
|
||
'Das Logo hat ungültige Maße (8 × 8 bis 720 × 250 Pixel).': 'The logo has invalid dimensions (8 × 8 to 720 × 250 pixels).',
|
||
'Diese Datei wird schon für ein Logo verwendet.': 'This file is already used for a logo.',
|
||
'Du hast schon 30 Logos hochgeladen. Lösche eins, um ein neues hochzuladen.':
|
||
'You’ve already uploaded 30 logos. Delete one to upload a new one.',
|
||
'Ungültige Angabe zum Herz.': 'Invalid heart value.',
|
||
'Ungültige Angabe zu „einfarbig“.': 'Invalid value for “single color”.',
|
||
'Die Anfrage ist zu groß.': 'The request is too large.',
|
||
'Nur application/json wird unterstützt.': 'Only application/json is supported.',
|
||
'Der Dienst ist gerade nicht erreichbar.': 'The service is currently unavailable.',
|
||
'Interner Fehler.': 'Internal error.',
|
||
'Etwas ist schiefgelaufen. Bitte nochmal versuchen.': 'Something went wrong. Please try again.',
|
||
'Anmeldung per Token ist auf dem Server ausgeschaltet – bitte den Betreiber informieren.':
|
||
'Token sign-in is turned off on the server – please let the site owner know.',
|
||
};
|