From 5cf001f6d595869d1187fbb3a40002ea35dda6f7 Mon Sep 17 00:00:00 2001 From: w287346141 <287346141@qq.com> Date: Sun, 24 May 2026 09:11:51 +0800 Subject: [PATCH] Localize setup MCP argument placeholders --- src/cli/ui/Wizard.tsx | 6 +++--- src/i18n/EN.ts | 2 ++ src/i18n/types.ts | 2 ++ src/i18n/zh-CN.ts | 2 ++ tests/wizard.test.tsx | 28 +++++++++++++++++++++++++++- 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/cli/ui/Wizard.tsx b/src/cli/ui/Wizard.tsx index 9706f8b..7acffb4 100644 --- a/src/cli/ui/Wizard.tsx +++ b/src/cli/ui/Wizard.tsx @@ -726,9 +726,9 @@ function mcpItems(): SelectItem[] { }); } -function placeholderFor(entry: CatalogEntry): string { - if (entry.name === "filesystem") return "e.g. /tmp/carboncode-sandbox"; - if (entry.name === "sqlite") return "e.g. ./notes.sqlite"; +export function placeholderFor(entry: CatalogEntry): string { + if (entry.name === "filesystem") return t("wizard.mcpArgsFilesystemPlaceholder"); + if (entry.name === "sqlite") return t("wizard.mcpArgsSqlitePlaceholder"); return entry.userArgs ?? ""; } diff --git a/src/i18n/EN.ts b/src/i18n/EN.ts index 0ac9539..fc2d6d8 100644 --- a/src/i18n/EN.ts +++ b/src/i18n/EN.ts @@ -464,6 +464,8 @@ export const EN: TranslationSchema = { mcpArgsRequiredParam: "Required parameter: ", mcpArgsEmpty: "{name} needs a value — got an empty string.", mcpArgsNotADir: "{path} exists but is not a directory.", + mcpArgsFilesystemPlaceholder: "e.g. /tmp/carboncode-sandbox", + mcpArgsSqlitePlaceholder: "e.g. ./notes.sqlite", reviewTitle: "Ready to save", reviewLabelApiKey: "API key", reviewLabelLanguage: "Language", diff --git a/src/i18n/types.ts b/src/i18n/types.ts index 8282c0a..1d9d92a 100644 --- a/src/i18n/types.ts +++ b/src/i18n/types.ts @@ -301,6 +301,8 @@ export interface TranslationSchema { mcpArgsRequiredParam: string; mcpArgsEmpty: string; mcpArgsNotADir: string; + mcpArgsFilesystemPlaceholder: string; + mcpArgsSqlitePlaceholder: string; themeTitle: string; themeSubtitle: string; themeSampleHeading: string; diff --git a/src/i18n/zh-CN.ts b/src/i18n/zh-CN.ts index 7afc2e3..d94e4d4 100644 --- a/src/i18n/zh-CN.ts +++ b/src/i18n/zh-CN.ts @@ -450,6 +450,8 @@ export const zhCN: TranslationSchema = { mcpArgsRequiredParam: "必填参数:", mcpArgsEmpty: "{name} 需要一个值 — 不能为空。", mcpArgsNotADir: "{path} 存在但不是目录。", + mcpArgsFilesystemPlaceholder: "例如:/tmp/carboncode-sandbox", + mcpArgsSqlitePlaceholder: "例如:./notes.sqlite", reviewTitle: "确认保存", reviewLabelApiKey: "API key", reviewLabelLanguage: "语言", diff --git a/tests/wizard.test.tsx b/tests/wizard.test.tsx index 552e2b4..a29366e 100644 --- a/tests/wizard.test.tsx +++ b/tests/wizard.test.tsx @@ -3,7 +3,7 @@ import { render } from "ink-testing-library"; import React from "react"; import { afterEach, describe, expect, it } from "vitest"; -import { Wizard, buildSpec, validateDeepSeekApiKey } from "../src/cli/ui/Wizard.js"; +import { Wizard, buildSpec, placeholderFor, validateDeepSeekApiKey } from "../src/cli/ui/Wizard.js"; import { setLanguageRuntime } from "../src/i18n/index.js"; import { parseMcpSpec } from "../src/mcp/spec.js"; @@ -66,6 +66,32 @@ describe("Wizard — first-launch language picker", () => { }); }); +describe("Wizard — localized MCP argument placeholders", () => { + afterEach(() => { + setLanguageRuntime("EN"); + }); + + it("localizes filesystem and sqlite placeholders in zh-CN", () => { + setLanguageRuntime("zh-CN"); + + expect( + placeholderFor({ name: "filesystem", command: "npx", args: [], userArgs: "" }), + ).toBe("例如:/tmp/carboncode-sandbox"); + expect(placeholderFor({ name: "sqlite", command: "npx", args: [], userArgs: "" })).toBe( + "例如:./notes.sqlite", + ); + }); + + it("keeps filesystem and sqlite placeholders in EN", () => { + expect( + placeholderFor({ name: "filesystem", command: "npx", args: [], userArgs: "" }), + ).toBe("e.g. /tmp/carboncode-sandbox"); + expect(placeholderFor({ name: "sqlite", command: "npx", args: [], userArgs: "" })).toBe( + "e.g. ./notes.sqlite", + ); + }); +}); + describe("Wizard API-key validation", () => { it("accepts a key when DeepSeek auth check succeeds", async () => { const fetcher = async () => new Response(JSON.stringify({ data: [] }), { status: 200 });