fix(pages): englischer Datumsformatierer nur einmal angelegt, Kommentar im Melden-Dialog berichtigt

- format.ts: `Intl.DateTimeFormat('en-US', …)` wurde bei jedem Aufruf von formatDate neu angelegt (Meine Karten, Galerie, Detailseite, Logo-Infozeile rufen es
  je Karte). Er hängt nicht von der Sprache ab und steht jetzt einmal auf Modulebene (EN_DATE); die Ausgabe ist gleich, die vorhandenen Tests bleiben unverändert.
- report-dialog.ts: Der Kommentar zu reportDialog sprach noch vom „Servertext“; angezeigt wird `apiErrorText`, der Text zum Schlüssel des Fehlers in der
  Sprache der Seite.
- Test: fünf Aufrufe auf Englisch legen höchstens einen Formatierer an (frische Modulkopie, Konstruktor gezählt).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-05 05:49:04 +00:00
1 parent 691b28df19
commit 6e5fe3e199
3 files changed
+23 -3

No files matched your search

+2 -1
View File
@@ -44,7 +44,8 @@ export interface ReportDialogOptions {
/** /**
* Öffnet den Dialog. Löst auf, sobald er geschlossen ist: mit dem Ergebnis der letzten Meldung, sonst mit `cancelled`. * Öffnet den Dialog. Löst auf, sobald er geschlossen ist: mit dem Ergebnis der letzten Meldung, sonst mit `cancelled`.
* Fehler des Dienstes erscheinen mit ihrem Servertext im Dialog; der Dialog bleibt dann offen für einen neuen Versuch. * Fehler des Dienstes erscheinen im Dialog in der Sprache der Seite (`apiErrorText`: der Text zum Schlüssel des Fehlers, nicht der
* Servertext); der Dialog bleibt dann offen für einen neuen Versuch.
*/ */
export function reportDialog(opts: ReportDialogOptions): Promise<ReportOutcome> { export function reportDialog(opts: ReportDialogOptions): Promise<ReportOutcome> {
return new Promise<ReportOutcome>((resolve, reject) => { return new Promise<ReportOutcome>((resolve, reject) => {
+17 -1
View File
@@ -1,7 +1,11 @@
import { describe, expect, it } from 'vitest'; import { afterEach, describe, expect, it, vi } from 'vitest';
import { setLang } from '../i18n/i18n'; import { setLang } from '../i18n/i18n';
import { formatDate, reportsLabel } from './format'; import { formatDate, reportsLabel } from './format';
afterEach(() => {
vi.restoreAllMocks();
});
describe('formatDate', () => { describe('formatDate', () => {
it('schreibt dd.mm.yyyy', () => { it('schreibt dd.mm.yyyy', () => {
expect(formatDate(new Date(2026, 9, 4, 12).toISOString())).toBe('04.10.2026'); expect(formatDate(new Date(2026, 9, 4, 12).toISOString())).toBe('04.10.2026');
@@ -19,6 +23,18 @@ describe('formatDate', () => {
expect(formatDate('kaputt')).toBe(''); expect(formatDate('kaputt')).toBe('');
}); });
it('der englische Formatierer wird einmal angelegt und danach wiederverwendet, nicht bei jedem Aufruf neu', async () => {
// Eine frische Kopie des Moduls (und von i18n.ts), damit das Anlegen mitgezählt wird, wann immer es geschieht.
vi.resetModules();
const created = vi.spyOn(Intl, 'DateTimeFormat');
const fresh = await import('./format');
(await import('../i18n/i18n')).setLang('en', { persist: false });
const iso = new Date(2026, 9, 4, 12).toISOString();
const results = Array.from({ length: 5 }, () => fresh.formatDate(iso));
expect(results).toEqual(Array(5).fill('Oct 4, 2026'));
expect(created.mock.calls.length).toBeLessThanOrEqual(1);
});
it('folgt der Sprache bei jedem Aufruf', () => { it('folgt der Sprache bei jedem Aufruf', () => {
const iso = new Date(2026, 9, 4, 12).toISOString(); const iso = new Date(2026, 9, 4, 12).toISOString();
expect(formatDate(iso)).toBe('04.10.2026'); expect(formatDate(iso)).toBe('04.10.2026');
+4 -1
View File
@@ -1,11 +1,14 @@
// Gemeinsame Formatierung der Seiten (Meine Karten, Community-Detailseite, Galerie-Raster, Logo-Infozeile). // Gemeinsame Formatierung der Seiten (Meine Karten, Community-Detailseite, Galerie-Raster, Logo-Infozeile).
import { currentLang, t } from '../i18n/i18n'; import { currentLang, t } from '../i18n/i18n';
// Der englische Formatierer hängt nicht von der Sprache der Seite ab (er wird nur bei Englisch benutzt): einmal angelegt, nicht je Aufruf.
const EN_DATE = new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
/** Deutsch `dd.mm.yyyy`, Englisch `Oct 4, 2026`, jeweils in der Zeitzone des Betrachters; leer, wenn das Datum unlesbar ist. */ /** Deutsch `dd.mm.yyyy`, Englisch `Oct 4, 2026`, jeweils in der Zeitzone des Betrachters; leer, wenn das Datum unlesbar ist. */
export function formatDate(iso: string): string { export function formatDate(iso: string): string {
const date = new Date(iso); const date = new Date(iso);
if (Number.isNaN(date.getTime())) return ''; if (Number.isNaN(date.getTime())) return '';
if (currentLang() === 'en') return new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(date); if (currentLang() === 'en') return EN_DATE.format(date);
const pad = (n: number) => String(n).padStart(2, '0'); const pad = (n: number) => String(n).padStart(2, '0');
return `${pad(date.getDate())}.${pad(date.getMonth() + 1)}.${date.getFullYear()}`; return `${pad(date.getDate())}.${pad(date.getMonth() + 1)}.${date.getFullYear()}`;
} }