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:
1 parent
691b28df19
commit
6e5fe3e199
3 files changed
+23
-3
No files matched your search
@@ -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) => {
|
||||||
|
|||||||
@@ -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');
|
||||||
|
|||||||
@@ -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()}`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user