mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-05-05 09:46:30 +00:00
feat(i18n): replace hardcoded strings with translation keys in HomePageClient
Replace hardcoded English text in quick start links and getting started steps with proper i18n translation keys. Use `t.rich()` for step descriptions containing inline links to support rich text interpolation.
This commit is contained in:
parent
187aba0514
commit
107b9e8cd2
27 changed files with 1497 additions and 869 deletions
|
|
@ -4,6 +4,7 @@ import { useState, useEffect, useRef } from "react";
|
|||
import { Card, Button, ModelSelectModal, ManualConfigModal } from "@/shared/components";
|
||||
import Image from "next/image";
|
||||
import CliStatusBadge from "./CliStatusBadge";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const CLOUD_URL = process.env.NEXT_PUBLIC_CLOUD_URL;
|
||||
|
||||
|
|
@ -19,6 +20,7 @@ export default function ClineToolCard({
|
|||
batchStatus,
|
||||
lastConfiguredAt,
|
||||
}) {
|
||||
const t = useTranslations("cliTools");
|
||||
const [clineStatus, setClineStatus] = useState(null);
|
||||
const [checkingCline, setCheckingCline] = useState(false);
|
||||
const [applying, setApplying] = useState(false);
|
||||
|
|
@ -109,12 +111,12 @@ export default function ClineToolCard({
|
|||
body: JSON.stringify({ tool: "cline", backupId }),
|
||||
});
|
||||
if (res.ok) {
|
||||
setMessage({ type: "success", text: "Backup restored! Reloading status..." });
|
||||
setMessage({ type: "success", text: t("backupRestoredReloading") });
|
||||
await checkClineStatus();
|
||||
await fetchBackups();
|
||||
} else {
|
||||
const data = await res.json();
|
||||
setMessage({ type: "error", text: data.error || "Failed to restore backup" });
|
||||
setMessage({ type: "error", text: data.error || t("failedRestoreBackup") });
|
||||
}
|
||||
} catch (e) {
|
||||
setMessage({ type: "error", text: e.message });
|
||||
|
|
@ -161,11 +163,11 @@ export default function ClineToolCard({
|
|||
});
|
||||
const data = await res.json();
|
||||
if (res.ok) {
|
||||
setMessage({ type: "success", text: data.message || "Applied!" });
|
||||
setMessage({ type: "success", text: data.message || t("applied") });
|
||||
await checkClineStatus();
|
||||
await fetchBackups();
|
||||
} else {
|
||||
setMessage({ type: "error", text: data.error || "Failed" });
|
||||
setMessage({ type: "error", text: data.error || t("failed") });
|
||||
}
|
||||
} catch (error) {
|
||||
setMessage({ type: "error", text: error.message });
|
||||
|
|
@ -181,13 +183,13 @@ export default function ClineToolCard({
|
|||
const res = await fetch("/api/cli-tools/cline-settings", { method: "DELETE" });
|
||||
const data = await res.json();
|
||||
if (res.ok) {
|
||||
setMessage({ type: "success", text: data.message || "Reset!" });
|
||||
setMessage({ type: "success", text: data.message || t("resetDone") });
|
||||
setSelectedModel("");
|
||||
hasInitializedModel.current = false;
|
||||
await checkClineStatus();
|
||||
await fetchBackups();
|
||||
} else {
|
||||
setMessage({ type: "error", text: data.error || "Failed" });
|
||||
setMessage({ type: "error", text: data.error || t("failed") });
|
||||
}
|
||||
} catch (error) {
|
||||
setMessage({ type: "error", text: error.message });
|
||||
|
|
@ -240,7 +242,7 @@ export default function ClineToolCard({
|
|||
lastConfiguredAt={lastConfiguredAt}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-text-muted truncate">{tool.description}</p>
|
||||
<p className="text-xs text-text-muted truncate">{t("toolDescriptions.cline")}</p>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
|
|
@ -257,7 +259,7 @@ export default function ClineToolCard({
|
|||
<span className="material-symbols-outlined animate-spin text-base">
|
||||
progress_activity
|
||||
</span>
|
||||
<span>Checking Cline CLI...</span>
|
||||
<span>{t("checkingCli", { tool: "Cline" })}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -273,14 +275,14 @@ export default function ClineToolCard({
|
|||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm font-medium">
|
||||
{cliReady
|
||||
? "Cline CLI detected and ready"
|
||||
? t("cliDetectedReady", { tool: "Cline" })
|
||||
: clineStatus.installed
|
||||
? "Cline CLI installed but not runnable"
|
||||
: "Cline CLI not detected"}
|
||||
? t("cliNotRunnable", { tool: "Cline" })
|
||||
: t("cliNotDetected", { tool: "Cline" })}
|
||||
</p>
|
||||
{clineStatus.commandPath && (
|
||||
<p className="text-xs text-text-muted">
|
||||
Binary:{" "}
|
||||
{t("binary")}:{" "}
|
||||
<code className="px-1 py-0.5 rounded bg-black/5 dark:bg-white/10">
|
||||
{clineStatus.commandPath}
|
||||
</code>
|
||||
|
|
@ -288,7 +290,7 @@ export default function ClineToolCard({
|
|||
)}
|
||||
{clineStatus.globalStatePath && (
|
||||
<p className="text-xs text-text-muted">
|
||||
Config:{" "}
|
||||
{t("configPathShort")}:{" "}
|
||||
<code className="px-1 py-0.5 rounded bg-black/5 dark:bg-white/10">
|
||||
{clineStatus.globalStatePath}
|
||||
</code>
|
||||
|
|
@ -307,10 +309,10 @@ export default function ClineToolCard({
|
|||
</span>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm text-green-700 dark:text-green-300">
|
||||
OmniRoute is configured as OpenAI-compatible provider
|
||||
{t("omnirouteConfiguredOpenAiCompatible")}
|
||||
</p>
|
||||
<p className="text-xs text-text-muted">
|
||||
Provider: <strong>openai</strong> • Model:{" "}
|
||||
{t("provider")}: <strong>openai</strong> • {t("model")}:{" "}
|
||||
<strong>{clineStatus.settings?.openAiModelId || "—"}</strong>
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -319,13 +321,13 @@ export default function ClineToolCard({
|
|||
|
||||
{/* Model selection */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-sm text-text-muted">Model</label>
|
||||
<label className="text-sm text-text-muted">{t("model")}</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="text"
|
||||
value={selectedModel}
|
||||
onChange={(e) => setSelectedModel(e.target.value)}
|
||||
placeholder="provider/model-id"
|
||||
placeholder={t("providerModelPlaceholder")}
|
||||
className="flex-1 px-3 py-2 bg-bg-secondary rounded-lg text-sm border border-border focus:outline-none focus:ring-1 focus:ring-primary/50"
|
||||
/>
|
||||
<Button
|
||||
|
|
@ -334,7 +336,7 @@ export default function ClineToolCard({
|
|||
onClick={() => setModalOpen(true)}
|
||||
disabled={!hasActiveProviders}
|
||||
>
|
||||
Select
|
||||
{t("select")}
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
|
|
@ -348,7 +350,7 @@ export default function ClineToolCard({
|
|||
|
||||
{/* API Key selection */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-sm text-text-muted">API Key</label>
|
||||
<label className="text-sm text-text-muted">{t("apiKey")}</label>
|
||||
{apiKeys && apiKeys.length > 0 ? (
|
||||
<select
|
||||
value={selectedApiKey}
|
||||
|
|
@ -363,7 +365,7 @@ export default function ClineToolCard({
|
|||
</select>
|
||||
) : (
|
||||
<p className="text-sm text-text-muted">
|
||||
{cloudEnabled ? "No API keys available" : "Using default: sk_omniroute"}
|
||||
{cloudEnabled ? t("noApiKeysAvailable") : t("usingDefaultOmniroute")}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -378,14 +380,14 @@ export default function ClineToolCard({
|
|||
loading={applying}
|
||||
>
|
||||
<span className="material-symbols-outlined text-[14px] mr-1">save</span>
|
||||
{configStatus === "configured" ? "Update Config" : "Apply Config"}
|
||||
{configStatus === "configured" ? t("updateConfig") : t("applyConfig")}
|
||||
</Button>
|
||||
{configStatus === "configured" && (
|
||||
<Button variant="outline" size="sm" onClick={handleReset} loading={restoring}>
|
||||
<span className="material-symbols-outlined text-[14px] mr-1">
|
||||
restart_alt
|
||||
</span>
|
||||
Reset
|
||||
{t("reset")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -414,7 +416,7 @@ export default function ClineToolCard({
|
|||
chevron_right
|
||||
</span>
|
||||
<span className="material-symbols-outlined text-[16px]">backup</span>
|
||||
Backups {backups.length > 0 && `(${backups.length})`}
|
||||
{t("backups")} {backups.length > 0 && `(${backups.length})`}
|
||||
</button>
|
||||
{showBackups && backups.length > 0 && (
|
||||
<div className="mt-2 flex flex-col gap-1.5 pl-6">
|
||||
|
|
@ -435,14 +437,14 @@ export default function ClineToolCard({
|
|||
onClick={() => handleRestoreBackup(b.id)}
|
||||
loading={restoringBackup === b.id}
|
||||
>
|
||||
Restore
|
||||
{t("restore")}
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{showBackups && backups.length === 0 && (
|
||||
<p className="mt-2 pl-6 text-xs text-text-muted">No backups available.</p>
|
||||
<p className="mt-2 pl-6 text-xs text-text-muted">{t("noBackupsAvailable")}</p>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
|
|
@ -458,13 +460,13 @@ export default function ClineToolCard({
|
|||
onSelect={handleSelectModel}
|
||||
selectedModel={selectedModel}
|
||||
activeProviders={activeProviders}
|
||||
title="Select Model for Cline"
|
||||
title={t("selectModelForTool", { tool: "Cline" })}
|
||||
/>
|
||||
{showManualConfigModal && (
|
||||
<ManualConfigModal
|
||||
isOpen={showManualConfigModal}
|
||||
onClose={() => setShowManualConfigModal(false)}
|
||||
title="Cline Manual Configuration"
|
||||
title={t("clineManualConfiguration")}
|
||||
{...({
|
||||
onApply: handleManualConfig,
|
||||
currentConfig: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue