import { NextResponse } from "next/server"; import { query } from "@/lib/db"; import { requireRole, UnauthorizedError, ForbiddenError } from "@/lib/auth/session"; import { isSameOrigin } from "@/lib/origin"; // Übersetzt einen deutschen Text nach Englisch/Polnisch via DeepL und // schreibt das Ergebnis in die _en/_pl-Spalte der angegebenen Zeile. // Ohne DEEPL_API_KEY läuft die Route kontrolliert ins Leere (configured: // false), damit das UI die manuelle Eingabe anbieten kann. const ALLOWED_TABLES: Record = { dishes: { idColumn: "id", textColumn: "name" }, sections: { idColumn: "key", textColumn: "label" }, allergens: { idColumn: "code", textColumn: "name" }, additives: { idColumn: "code", textColumn: "name" }, }; async function translateWithDeepL(text: string, targetLang: "EN" | "PL", apiKey: string) { const host = apiKey.endsWith(":fx") ? "https://api-free.deepl.com" : "https://api.deepl.com"; const res = await fetch(`${host}/v2/translate`, { method: "POST", headers: { Authorization: `DeepL-Auth-Key ${apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ text: [text], target_lang: targetLang, source_lang: "DE", }), }); if (!res.ok) { throw new Error(`DeepL antwortete mit ${res.status}: ${await res.text()}`); } const data = await res.json(); return data.translations?.[0]?.text as string | undefined; } export async function POST(request: Request) { if (!isSameOrigin(request)) { return NextResponse.json({ error: "Nicht erlaubt." }, { status: 403 }); } try { await requireRole(["staff", "admin"]); } catch (err) { if (err instanceof UnauthorizedError) { return NextResponse.json({ error: "Nicht angemeldet." }, { status: 401 }); } if (err instanceof ForbiddenError) { return NextResponse.json({ error: "Nicht berechtigt." }, { status: 403 }); } throw err; } const body = await request.json().catch(() => null); const { table, id, text } = body ?? {}; const config = ALLOWED_TABLES[table]; if (!config || typeof text !== "string" || !text.trim()) { return NextResponse.json({ error: "Ungültige Eingaben." }, { status: 400 }); } // Bei einem noch nicht gespeicherten (neuen) Eintrag gibt es keine // Zeile zum Aktualisieren – nur übersetzen, das Speichern übernimmt // anschließend das reguläre Formular. const persist = typeof id === "string" && id.length > 0; const apiKey = process.env.DEEPL_API_KEY; if (!apiKey) { return NextResponse.json({ configured: false }); } try { const [en, pl] = await Promise.all([ translateWithDeepL(text, "EN", apiKey), translateWithDeepL(text, "PL", apiKey), ]); if (!en || !pl) throw new Error("Keine Übersetzung erhalten."); if (persist) { // table/idColumn/textColumn kommen ausschließlich aus dem oben // geprüften ALLOWED_TABLES-Whitelist, nie aus Nutzereingaben – // sicher für die String-Interpolation in der Query. await query( `update ${table} set ${config.textColumn}_en = $1, ${config.textColumn}_pl = $2 where ${config.idColumn} = $3`, [en, pl, id] ); } return NextResponse.json({ configured: true, en, pl }); } catch (err) { return NextResponse.json( { error: err instanceof Error ? err.message : "Übersetzung fehlgeschlagen." }, { status: 502 } ); } }