-
+
onOpenChange(false)}
disabled={saving}
>
- Cancel
+ {t("cancel")}
diff --git a/src/app/components/ConfigDialog.tsx b/src/app/components/ConfigDialog.tsx
index 229ed9b..57e4c82 100644
--- a/src/app/components/ConfigDialog.tsx
+++ b/src/app/components/ConfigDialog.tsx
@@ -1,4 +1,5 @@
"use client";
+import { useTranslations } from "next-intl";
import {
Dialog,
DialogContent,
@@ -18,6 +19,7 @@ interface ConfigDialogProps {
}
export function ConfigDialog({ open, onOpenChange }: ConfigDialogProps) {
+ const t = useTranslations("modelConfig");
// The hook owns the UI-preference localStorage round-trip.
const { value: collapseAgentActions, setValue: setCollapseAgentActions } =
useCollapseAgentActions();
@@ -34,11 +36,8 @@ export function ConfigDialog({ open, onOpenChange }: ConfigDialogProps) {
onEscapeKeyDown={(event) => event.preventDefault()}
>
- Model registry
-
- Manage providers, models, credentials and defaults. Admin only;
- every save is validated by the backend.
-
+ {t("title")}
+ {t("description")}
{open &&
}
@@ -47,18 +46,18 @@ export function ConfigDialog({ open, onOpenChange }: ConfigDialogProps) {
type="checkbox"
checked={collapseAgentActions}
onChange={(e) => setCollapseAgentActions(e.target.checked)}
- aria-label="Collapse agent actions by default"
+ aria-label={t("collapseAgentActions")}
className="mt-1 size-4 rounded border-border accent-[var(--brand)]"
/>
-
+
diff --git a/src/app/components/ImageModelsDialog.tsx b/src/app/components/ImageModelsDialog.tsx
index 64016a1..ab6d482 100644
--- a/src/app/components/ImageModelsDialog.tsx
+++ b/src/app/components/ImageModelsDialog.tsx
@@ -1,4 +1,5 @@
"use client";
+import { useTranslations } from "next-intl";
import {
Dialog,
DialogContent,
@@ -16,6 +17,7 @@ interface ImageModelsDialogProps {
}
export function ImageModelsDialog({ open, onOpenChange }: ImageModelsDialogProps) {
+ const t = useTranslations("imageModels");
return (
diff --git a/src/app/components/ImageModelsEditor.tsx b/src/app/components/ImageModelsEditor.tsx
index 9de2e5e..4c48f9e 100644
--- a/src/app/components/ImageModelsEditor.tsx
+++ b/src/app/components/ImageModelsEditor.tsx
@@ -1,6 +1,7 @@
"use client";
import { useCallback, useEffect, useMemo, useState } from "react";
+import { useTranslations } from "next-intl";
import { Eye, EyeOff } from "lucide-react";
import { toast } from "sonner";
import { errorToast } from "@/lib/errorReporter";
@@ -80,7 +81,7 @@ function toDraftState(settings: ImageGenerationSettings): DraftState {
type ParsedParams =
| { ok: true; value: Record
}
- | { ok: false; message: string };
+ | { ok: false; code: "notObject" | "invalidJson" };
function parseParams(text: string): ParsedParams {
const trimmed = text.trim();
@@ -88,11 +89,11 @@ function parseParams(text: string): ParsedParams {
try {
const parsed: unknown = JSON.parse(trimmed);
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
- return { ok: false, message: "params must be a JSON object" };
+ return { ok: false, code: "notObject" };
}
return { ok: true, value: parsed as Record };
} catch {
- return { ok: false, message: "invalid JSON" };
+ return { ok: false, code: "invalidJson" };
}
}
@@ -137,8 +138,11 @@ function ImageModelCard({
const [showKey, setShowKey] = useState(false);
const [testing, setTesting] = useState(false);
const [outcome, setOutcome] = useState(null);
+ const t = useTranslations("imageModels");
const paramsResult = parseParams(model.paramsText);
- const paramsError = paramsResult.ok ? null : paramsResult.message;
+ const paramsError = paramsResult.ok
+ ? null
+ : t(`card.paramsErrors.${paramsResult.code}`);
const runTest = async () => {
if (!paramsResult.ok) return;
@@ -158,15 +162,21 @@ function ImageModelCard({
});
setOutcome({ ok: true, latencyMs: result.latency_ms });
toast.success(
- `${model.id || "Image model"} passed the test in ${(result.latency_ms / 1000).toFixed(1)} s.`
+ t("card.testPassed", {
+ id: model.id || t("card.unnamed"),
+ seconds: (result.latency_ms / 1000).toFixed(1),
+ })
);
} catch (reason) {
const message =
- reason instanceof Error ? reason.message : "Test failed.";
+ reason instanceof Error ? reason.message : t("card.testFailedGeneric");
setOutcome({ ok: false, message });
errorToast(
"models.image-test",
- `${model.id || "Image model"} failed the test: ${message}`
+ t("card.testFailedToast", {
+ id: model.id || t("card.unnamed"),
+ message,
+ })
);
} finally {
setTesting(false);
@@ -177,7 +187,7 @@ function ImageModelCard({
@@ -358,6 +371,7 @@ export function ImageModelsEditor() {
const [loadError, setLoadError] = useState(null);
const [forbidden, setForbidden] = useState(false);
const [saving, setSaving] = useState(false);
+ const t = useTranslations("imageModels");
const load = useCallback(async () => {
setLoadError(null);
@@ -368,16 +382,14 @@ export function ImageModelsEditor() {
setDraft(toDraftState(settings));
} catch (reason) {
const message =
- reason instanceof Error
- ? reason.message
- : "Failed to load image models.";
+ reason instanceof Error ? reason.message : t("loadFailed");
if (message.includes("(403)")) {
setForbidden(true);
} else {
setLoadError(message);
}
}
- }, []);
+ }, [t]);
useEffect(() => {
void load();
@@ -394,7 +406,7 @@ export function ImageModelsEditor() {
if (!draft) return;
const payload = buildPayload(draft);
if (!payload) {
- toast.error("Fix the invalid params JSON before saving.");
+ toast.error(t("fixParamsBeforeSaving"));
return;
}
setSaving(true);
@@ -402,21 +414,21 @@ export function ImageModelsEditor() {
const saved = await putImageGeneration(payload);
setData(saved);
setDraft(toDraftState(saved));
- toast.success("Image models saved.");
+ toast.success(t("saved"));
} catch (reason) {
errorToast(
"models.image-save",
- reason instanceof Error ? reason.message : "Failed to save image models."
+ reason instanceof Error ? reason.message : t("saveFailed")
);
} finally {
setSaving(false);
}
- }, [draft]);
+ }, [draft, t]);
if (forbidden) {
return (
- Image model configuration requires an admin account.
+ {t("forbidden")}
);
}
@@ -430,13 +442,13 @@ export function ImageModelsEditor() {
size="sm"
onClick={() => void load()}
>
- Retry
+ {t("retry")}
);
}
if (!data || !draft) {
- return