Translate admin panel to all 6 languages

This commit is contained in:
openhands committed 2026-07-04 21:21:15 +02:00
1 parent f381aa987f
commit befa4ec282
63 files changed
+9353 -1443

No files matched your search

+17 -17
View File
@@ -1,3 +1,4 @@
import { getTranslations } from "next-intl/server";
import { applyPreset, saveTheme } from "@/actions/admin-theme";
import { siteSettings } from "@/lib/services/site-settings";
import { FONTS, PRESETS } from "@/lib/theme-presets";
@@ -35,7 +36,6 @@ const HEADINGS: { key: string; label: string; def: string }[] = [
const ALL_COLORS = [...COLOR_FIELDS, ...BUTTON_FIELDS];
/** A <input type=color> needs #rrggbb — fall back to the default otherwise. */
function toHex(value: string | null, def: string): string {
return value && /^#[0-9a-fA-F]{6}$/.test(value) ? value : def;
}
@@ -72,6 +72,8 @@ export default async function AdminTheme({
}: {
searchParams: Promise<{ saved?: string; preset?: string }>;
}) {
const t = await getTranslations("pages.admin.theme");
const sp = await searchParams;
const current = Object.fromEntries(
@@ -95,27 +97,26 @@ export default async function AdminTheme({
<span className="text-lg">🎨</span>
</div>
<div>
<h1 className="m-0 text-xl font-extrabold text-[var(--color-text)]">Theme</h1>
<h1 className="m-0 text-xl font-extrabold text-[var(--color-text)]">{t("title")}</h1>
<p className="m-0 text-xs text-[var(--color-text-muted)] mt-0.5">
Restyle the whole site. Values are written to <code>website_settings</code> and applied
live (no rebuild).
{t.rich("subtitle", { code: (chunks) => <code>{chunks}</code> })}
</p>
</div>
</div>
{sp.saved ? (
<div className="mb-4 p-3 rounded-lg bg-green-600/10 text-green-600 dark:text-green-400 text-xs">
Theme saved
{t("saved")}
</div>
) : null}
{sp.preset ? (
<div className="mb-4 p-3 rounded-lg bg-green-600/10 text-green-600 dark:text-green-400 text-xs">
Applied preset “{sp.preset}”
{t("presetApplied", { preset: sp.preset })}
</div>
) : null}
<section className="mt-6">
<h2 className="admin-section-title">Presets</h2>
<h2 className="admin-section-title">{t("presetsTitle")}</h2>
<div className="flex flex-wrap gap-2">
{Object.entries(PRESETS).map(([name, palette]) => (
<form key={name} action={applyPreset}>
@@ -148,25 +149,25 @@ export default async function AdminTheme({
<form action={saveTheme}>
<section className="mt-6">
<h2 className="admin-section-title">Colours</h2>
<h2 className="admin-section-title">{t("colours")}</h2>
<div className="admin-card">
{colorGrid(COLOR_FIELDS, current)}
</div>
</section>
<section className="mt-6">
<h2 className="admin-section-title">Buttons & links</h2>
<h2 className="admin-section-title">{t("buttonsLinks")}</h2>
<div className="admin-card">
{colorGrid(BUTTON_FIELDS, current)}
</div>
</section>
<section className="mt-6">
<h2 className="admin-section-title">Typography & layout</h2>
<h2 className="admin-section-title">{t("typographyLayout")}</h2>
<div className="admin-card">
<div className="flex flex-wrap gap-5 items-center">
<label className="flex items-center gap-2">
<span className="text-sm">Font</span>
<span className="text-sm">{t("font")}</span>
<select name="font_family" defaultValue={fontKey}>
{Object.entries(FONTS).map(([key, f]) => (
<option key={key} value={key}>
@@ -189,7 +190,7 @@ export default async function AdminTheme({
</label>
))}
<label className="flex items-center gap-2">
<span className="text-sm">Border radius (px)</span>
<span className="text-sm">{t("borderRadius")}</span>
<input
name="border_radius"
type="number"
@@ -204,22 +205,21 @@ export default async function AdminTheme({
</section>
<section className="mt-6">
<h2 className="admin-section-title">Custom CSS</h2>
<h2 className="admin-section-title">{t("cssTitle")}</h2>
<p className="text-xs text-[var(--color-text-muted)] mb-2">
Injected raw into every page (after the theme variables). Use it for tweaks the controls
above don’t cover.
{t("cssSubtitle")}
</p>
<textarea
name="custom_css"
defaultValue={customCss}
rows={8}
spellCheck={false}
placeholder={"/* e.g. */\n.nav-item { letter-spacing: 0.5px; }"}
placeholder={t("cssPlaceholder")}
className="w-full font-mono text-sm"
/>
<div className="mt-4 text-right">
<button type="submit" className="btn btn-primary">
Save theme
{t("saveCss")}
</button>
</div>
</section>