// Übersetzbare Fehlertexte der API: Der Dienst `aircard-api` (deploy/api) antwortet auf Fehler mit `{error, code}`. `error` ist der // deutsche Text, `code` sein Schlüssel in MSG (deploy/api/common.js). Hier steht jeder Text noch einmal unter seinem Schlüssel // (der Browser lädt den Dienst nicht); api-messages.test.ts lädt MSG und prüft den Gleichlauf. Dazu kommen zwei Client-Codes. // Übersetzt wird beim Anzeigen (`apiMessage`); `ApiError.message` bleibt der deutsche Text, damit Vergleiche damit weiter gehen. import { currentLang, msg, t } from './i18n'; export const API_MESSAGES: Readonly> = { // Die Schlüssel und Texte von MSG, in derselben Reihenfolge. unauthorized: msg('Bitte melde dich an.'), notFound: msg('Nicht gefunden.'), cardGone: msg('Diese Karte ist nicht (mehr) verfügbar.'), forbidden: msg('Dazu hast du keine Berechtigung.'), adminOnly: msg('Nur für Admins.'), foreignFile: msg('Diese Datei gehört dir nicht.'), fileMissing: msg('Bild nicht gefunden.'), fileType: msg('Das Bild muss eine PNG- oder WebP-Datei sein.'), fileSize: msg('Das Bild ist größer als 5 MB.'), alreadyPublished: msg('Diese Karte ist schon veröffentlicht.'), filesTaken: msg('Diese Bilder sind bereits veröffentlicht oder gesperrt.'), imageFormat: msg('Das Bild hat nicht das Kartenformat.'), notYourCard: msg('Diese Karte gehört nicht zu deinem Konto.'), tooManyPublications: msg('Du hast schon 20 Karten veröffentlicht. Zieh eine zurück, um eine neue zu veröffentlichen.'), tooManyReports: msg('Zu viele Meldungen – bitte später nochmal.'), badRequest: msg('Ungültige Anfrage.'), badCardId: msg('Ungültige Karten-ID.'), badReason: msg('Bitte wähle einen gültigen Grund.'), badVisibility: msg('Ungültige Angabe zur Sichtbarkeit.'), logoGone: msg('Dieses Logo ist nicht (mehr) verfügbar.'), badLogoId: msg('Ungültige Logo-ID.'), logoNameMissing: msg('Bitte gib einen Namen an.'), logoFileType: msg('Das Logo muss eine PNG-Datei sein.'), logoFileSize: msg('Das Logo ist größer als 1 MB.'), logoFormat: msg('Das Logo hat ungültige Maße (8 × 8 bis 720 × 250 Pixel).'), logoTaken: msg('Diese Datei wird schon für ein Logo verwendet.'), tooManyLogos: msg('Du hast schon 30 Logos hochgeladen. Lösche eins, um ein neues hochzuladen.'), badHeart: msg('Ungültige Angabe zum Herz.'), badMono: msg('Ungültige Angabe zu „einfarbig“.'), tooLarge: msg('Die Anfrage ist zu groß.'), jsonOnly: msg('Nur application/json wird unterstützt.'), unavailable: msg('Der Dienst ist gerade nicht erreichbar.'), internal: msg('Interner Fehler.'), // Nur im Client (kein Schlüssel im Dienst): allgemeiner Fehler und „Anmeldung per Token ausgeschaltet“. generic: msg('Etwas ist schiefgelaufen. Bitte nochmal versuchen.'), jwtUnsupported: msg('Anmeldung per Token ist auf dem Server ausgeschaltet – bitte den Betreiber informieren.'), }; /** Die allgemeine Meldung zu einem Status, wenn der Code unbekannt ist (Spec § 7): 400, 403, 404, sonst „Etwas ist schiefgelaufen“. */ function fallbackText(status: number): string { if (status === 400) return API_MESSAGES.badRequest; if (status === 403) return API_MESSAGES.forbidden; if (status === 404) return API_MESSAGES.notFound; return API_MESSAGES.generic; } /** * Der Text zu einem Fehler des Dienstes (oder einem Fehler, den der Client mit denselben Codes erzeugt) in der Sprache der Seite. * Ein bekannter Code wird über das Wörterbuch übersetzt. Ein unbekannter oder fehlender Code (älterer Dienst, Proxy) zeigt auf * Deutsch den Text des Dienstes, auf Englisch eine allgemeine Meldung je Status. */ export function apiMessage(serverCode: string | null, status: number, serverText: string): string { const english = currentLang() === 'en'; if (serverCode !== null && Object.hasOwn(API_MESSAGES, serverCode)) { // `badRequest` tragen auch die dynamischen Prüftexte des Dienstes („Der Titel ist zu lang (höchstens 60 Zeichen).“): // Deutsch zeigt dann den genaueren Servertext, Englisch den allgemeinen Text des Codes. if (!english && serverCode === 'badRequest') return serverText; return t(API_MESSAGES[serverCode]); } return english ? t(fallbackText(status)) : serverText; }