Translate admin panel to all 6 languages
This commit is contained in:
1 parent
f381aa987f
commit
befa4ec282
63 files changed
+9353
-1443
No files matched your search
@@ -3,11 +3,10 @@ import { saveRadioSetting, saveRadioSettings } from '@/actions/admin-radio-extra
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { StatusCard } from '@/components/admin/dashboard';
|
||||
import { Settings } from 'lucide-react';
|
||||
import { getTranslations } from "next-intl/server";
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
// Curated radio_* keys (faithful to AtomCMS RadioSettingsSeeder), grouped for
|
||||
// the editor. Any extra radio_* rows found in the DB are appended under "Other".
|
||||
type Field = { key: string; comment: string };
|
||||
type Group = { title: string; fields: Field[] };
|
||||
|
||||
@@ -184,6 +183,8 @@ const GROUPS: Group[] = [
|
||||
const CURATED_KEYS = new Set(GROUPS.flatMap((g) => g.fields.map((f) => f.key)));
|
||||
|
||||
export default async function AdminRadioSettingsPage() {
|
||||
const t = await getTranslations("pages.admin.radio");
|
||||
|
||||
let values: Map<string, string> = new Map();
|
||||
let dbError = false;
|
||||
let extra: Field[] = [];
|
||||
@@ -205,13 +206,12 @@ export default async function AdminRadioSettingsPage() {
|
||||
}
|
||||
|
||||
const groups: Group[] = extra.length
|
||||
? [...GROUPS, { title: 'Other radio settings', fields: extra }]
|
||||
? [...GROUPS, { title: t("settingsForm.otherSettings"), fields: extra }]
|
||||
: GROUPS;
|
||||
|
||||
const allKeys = [...CURATED_KEYS, ...extra.map((e) => e.key)].join(',');
|
||||
|
||||
const totalKeys = CURATED_KEYS.size + extra.length;
|
||||
// Curated keys that already have a non-empty stored value.
|
||||
const configuredKeys = [...CURATED_KEYS].filter((k) => {
|
||||
const v = values.get(k);
|
||||
return v != null && v !== '';
|
||||
@@ -221,11 +221,11 @@ export default async function AdminRadioSettingsPage() {
|
||||
return (
|
||||
<main>
|
||||
<nav className="text-xs text-gray-500 dark:text-gray-400 mb-2">
|
||||
<Link href="/admin/radio">Radio</Link> ·{' '}
|
||||
<Link href="/admin/radio/settings">Settings</Link> ·{' '}
|
||||
<Link href="/admin/radio/banners">Banners</Link> ·{' '}
|
||||
<Link href="/admin/radio/ranks">Ranks</Link> ·{' '}
|
||||
<Link href="/admin/radio/history">History</Link>
|
||||
<Link href="/admin/radio">{t("title")}</Link> ·{' '}
|
||||
<Link href="/admin/radio/settings">{t("settings")}</Link> ·{' '}
|
||||
<Link href="/admin/radio/banners">{t("banners.title")}</Link> ·{' '}
|
||||
<Link href="/admin/radio/ranks">{t("ranks")}</Link> ·{' '}
|
||||
<Link href="/admin/radio/history">{t("history")}</Link>
|
||||
</nav>
|
||||
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
@@ -233,38 +233,37 @@ export default async function AdminRadioSettingsPage() {
|
||||
<Settings size={20} className="text-[var(--color-primary)]" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="m-0 text-xl font-extrabold text-[var(--color-text)]">Radio Settings</h1>
|
||||
<p className="m-0 text-xs text-[var(--color-text-muted)] mt-0.5">Edits write to <code>website_settings</code> (radio_* keys) and bust the runtime settings cache. Booleans use <code>0</code> / <code>1</code>.</p>
|
||||
<h1 className="m-0 text-xl font-extrabold text-[var(--color-text)]">{t("settingsForm.title")}</h1>
|
||||
<p className="m-0 text-xs text-[var(--color-text-muted)] mt-0.5">{t("settingsForm.subtitle")}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{dbError ? (
|
||||
<div className="admin-card mb-6">
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400 m-0">
|
||||
Could not load settings (database unavailable). Defaults will be
|
||||
created on save.
|
||||
{t("settingsForm.dbError")}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-[repeat(auto-fit,minmax(180px,1fr))] gap-3.5 mb-6">
|
||||
<StatusCard
|
||||
label="Radio"
|
||||
value={radioEnabled ? 'Enabled' : 'Disabled'}
|
||||
value={radioEnabled ? t("settingsForm.enabled") : t("settingsForm.disabled")}
|
||||
state={radioEnabled ? 'ok' : 'danger'}
|
||||
icon="📻"
|
||||
icon="\u{1F4BB}"
|
||||
/>
|
||||
<StatusCard label="Total keys" value={totalKeys} icon="🔑" />
|
||||
<StatusCard label={t("settingsForm.totalKeys")} value={totalKeys} icon="\u{1F511}" />
|
||||
<StatusCard
|
||||
label="Configured"
|
||||
label={t("settingsForm.configured")}
|
||||
value={`${configuredKeys}/${CURATED_KEYS.size}`}
|
||||
hint="curated keys with a value"
|
||||
icon="⚙️"
|
||||
hint={t("settingsForm.curatedHint")}
|
||||
icon="\u{2699}\uFE0F"
|
||||
/>
|
||||
<StatusCard
|
||||
label="Custom keys"
|
||||
label={t("settingsForm.customKeys")}
|
||||
value={extra.length}
|
||||
state={extra.length > 0 ? 'warn' : 'neutral'}
|
||||
icon="➕"
|
||||
icon="\u{2795}"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -273,7 +272,7 @@ export default async function AdminRadioSettingsPage() {
|
||||
<input type="hidden" name="__keys" value={allKeys} />
|
||||
<div className="flex justify-end mb-4">
|
||||
<button type="submit" className="btn btn-primary">
|
||||
Save all
|
||||
{t("settingsForm.saveAll")}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -308,19 +307,19 @@ export default async function AdminRadioSettingsPage() {
|
||||
|
||||
<div className="flex justify-end">
|
||||
<button type="submit" className="btn btn-primary">
|
||||
Save all
|
||||
{t("settingsForm.saveAll")}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<section className="admin-card" style={{ marginTop: '1.5rem' }}>
|
||||
<h3 style={{ marginTop: 0 }}>Add / overwrite a single key</h3>
|
||||
<h3 style={{ marginTop: 0 }}>{t("settingsForm.singleKey")}</h3>
|
||||
<form action={saveRadioSetting} className="flex gap-2 flex-wrap">
|
||||
<input name="key" placeholder="radio_custom_key" required />
|
||||
<input name="value" placeholder="value" className="flex-1 min-w-[160px]" />
|
||||
<input name="comment" placeholder="comment (optional)" />
|
||||
<input name="key" placeholder={t("settingsForm.keyPlaceholder")} required />
|
||||
<input name="value" placeholder={t("settingsForm.valuePlaceholder")} className="flex-1 min-w-[160px]" />
|
||||
<input name="comment" placeholder={t("settingsForm.commentPlaceholder")} />
|
||||
<button type="submit" className="btn btn-primary">
|
||||
Save
|
||||
{t("settingsForm.saveSingle")}
|
||||
</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
Reference in new issue
Block a user