/* ===================================================================== lib/translate.js — automatische Übersetzung für admin-gepflegte Texte (aktuell nur "Event des Jahres" auf der Startseite, 20.08.2026). Bewusste Entscheidung (Nutzer-Rückfrage 20.08.2026): Dogi tippt Titel/Text nur auf Deutsch in die Verwaltung ein, die anderen Sprachen entstehen automatisch beim Speichern — NICHT die sonst auf der ganzen Seite geltende Regel "immer echte, geprüfte Übersetzungen", sondern eine bewusste Ausnahme für diesen einen admin-gepflegten Bereich. Maschinen-Übersetzung ist NIE so gut wie eine echte — für schnell änderbare Startseiten-Teaser akzeptabel, für Rechtstexte/feste Seiteninhalte weiterhin NICHT verwenden. de-CH bekommt bewusst NICHT automatisch übersetzt: der Website-Dialekt (Solothurn/Zürich-nahe Schreibweise, siehe main.js-Kommentar zu I18N_CORE) ist keine von Übersetzungs-APIs unterstützte Zielsprache — eine automatische "Übersetzung" nach de-CH würde bestenfalls Standarddeutsch zurückgeben, das wäre nicht ehrlich als "Dialekt" beschriftet. de-CH bekommt stattdessen exakt denselben Text wie de. MyMemory (https://mymemory.translated.net) statt Google/DeepL: völlig kostenlos, kein API-Key/Anmeldung nötig (passt zu "Kosten möglichst 0€"), für kurze Teaser-Texte ausreichende Qualität. Absichtlich KEIN lokal gehosteter Übersetzungsdienst (z.B. LibreTranslate) — bei der seltenen Nutzung (2 kurze Texte, gelegentlich geändert) wäre ein dauerhaft laufender zusätzlicher Dienst auf dem ohnehin schon mehrfach belegten Server unverhältnismäßig viel Aufwand für den tatsächlichen Bedarf. */ const SPRACHEN_ZIEL = ["en", "fr", "pt"]; async function uebersetzeEinzeln(text, ziel) { if (!text || !text.trim()) return ""; const url = `https://api.mymemory.translated.net/get?q=${encodeURIComponent(text)}&langpair=de|${ziel}`; const res = await fetch(url, { signal: AbortSignal.timeout(8000) }); if (!res.ok) throw new Error(`Übersetzungsdienst antwortete mit ${res.status}`); const data = await res.json(); const uebersetzt = data?.responseData?.translatedText; if (!uebersetzt || typeof uebersetzt !== "string") throw new Error("Keine Übersetzung erhalten."); return uebersetzt; } /** Übersetzt einen deutschen Text nach en/fr/pt, de-CH = 1:1 Kopie von de. Bei Fehlern (Dienst nicht erreichbar etc.) fällt die jeweilige Sprache auf den deutschen Text zurück, statt die ganze Speicherung scheitern zu lassen — "fail closed" mit sichtbarem Ergebnis statt kaputter Anzeige. */ export async function uebersetzeAlleSprachen(textDe) { const ergebnis = { de: textDe || "", "de-CH": textDe || "" }; await Promise.all( SPRACHEN_ZIEL.map(async (ziel) => { try { ergebnis[ziel] = await uebersetzeEinzeln(textDe, ziel); } catch (err) { console.error(`[translate] ${ziel} fehlgeschlagen, falle auf Deutsch zurück:`, err?.message || err); ergebnis[ziel] = textDe || ""; } }) ); return ergebnis; }