import "server-only"; import { query, queryOne, withTransaction } from "@/lib/db"; export interface LanguageRow { code: string; label: string; is_base: boolean; active: boolean; template_version: string | null; updated_at: string; } export async function listLanguages(): Promise { return query( "select * from languages order by is_base desc, code" ); } export async function listActiveLanguageCodes(): Promise { const rows = await query<{ code: string }>( "select code from languages where active = true order by is_base desc, code" ); return rows.map((r) => r.code); } export async function getLanguage(code: string): Promise { return queryOne("select * from languages where code = $1", [code]); } export async function createLanguage(code: string, label: string): Promise { return (await queryOne( `insert into languages (code, label, is_base, active, template_version) values ($1, $2, false, true, null) returning *`, [code, label] ))!; } export async function updateLanguageLabel(code: string, label: string): Promise { return queryOne( "update languages set label = $1, updated_at = now() where code = $2 returning *", [label, code] ); } /** Wirft, wenn dadurch keine aktive Sprache mehr übrig bliebe. */ export async function setLanguageActive(code: string, active: boolean): Promise { return withTransaction(async (client) => { if (!active) { const { rows } = await client.query<{ count: string }>( "select count(*)::int as count from languages where active = true and code != $1", [code] ); if (Number(rows[0].count) === 0) { throw new Error("cannot_deactivate_last"); } } const { rows } = await client.query( "update languages set active = $1, updated_at = now() where code = $2 returning *", [active, code] ); return rows[0]; }); } export async function deleteLanguage(code: string): Promise { const lang = await getLanguage(code); if (lang?.is_base) throw new Error("cannot_delete_base"); await query("delete from languages where code = $1", [code]); } export interface TranslationEntry { key: string; value: string; } export async function listTranslations(code: string): Promise { return query( "select key, value from ui_translations where language_code = $1", [code] ); } /** Übernimmt neu importierte Übersetzungen (Insert/Update je Schlüssel) * und aktualisiert den gespeicherten Vorlagen-Stand. Bewusst kein * vollständiges Ersetzen: ein erneuter Import mit nur den zuvor * fehlenden Schlüsseln darf bereits vorhandene Übersetzungen nicht * löschen. */ export async function importTranslations( code: string, entries: TranslationEntry[], templateVersion: string ): Promise { await withTransaction(async (client) => { for (const entry of entries) { await client.query( `insert into ui_translations (language_code, key, value) values ($1, $2, $3) on conflict (language_code, key) do update set value = excluded.value`, [code, entry.key, entry.value] ); } await client.query( "update languages set template_version = $1, updated_at = now() where code = $2", [templateVersion, code] ); }); }