Skip to content

Commit be191ab

Browse files
authored
Merge pull request #1692 from RooVetGit/i18n_mcp
Localize the MCP tab
2 parents a2bd668 + ca8c6f6 commit be191ab

File tree

23 files changed

+1034
-44
lines changed

23 files changed

+1034
-44
lines changed

webview-ui/src/components/mcp/McpEnabledToggle.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
22
import { FormEvent } from "react"
33
import { useExtensionState } from "../../context/ExtensionStateContext"
4+
import { useAppTranslation } from "../../i18n/TranslationContext"
45
import { vscode } from "../../utils/vscode"
56

67
const McpEnabledToggle = () => {
78
const { mcpEnabled, setMcpEnabled } = useExtensionState()
9+
const { t } = useAppTranslation()
810

911
const handleChange = (e: Event | FormEvent<HTMLElement>) => {
1012
const target = ("target" in e ? e.target : null) as HTMLInputElement | null
@@ -16,16 +18,15 @@ const McpEnabledToggle = () => {
1618
return (
1719
<div style={{ marginBottom: "20px" }}>
1820
<VSCodeCheckbox checked={mcpEnabled} onChange={handleChange}>
19-
<span style={{ fontWeight: "500" }}>Enable MCP Servers</span>
21+
<span style={{ fontWeight: "500" }}>{t("mcp:enableToggle.title")}</span>
2022
</VSCodeCheckbox>
2123
<p
2224
style={{
2325
fontSize: "12px",
2426
marginTop: "5px",
2527
color: "var(--vscode-descriptionForeground)",
2628
}}>
27-
When enabled, Roo will be able to interact with MCP servers for advanced functionality. If you're not
28-
using MCP, you can disable this to reduce Roo's token usage.
29+
{t("mcp:enableToggle.description")}
2930
</p>
3031
</div>
3132
)

webview-ui/src/components/mcp/McpToolRow.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
22
import { McpTool } from "../../../../src/shared/mcp"
3+
import { useAppTranslation } from "../../i18n/TranslationContext"
34
import { vscode } from "../../utils/vscode"
45

56
type McpToolRowProps = {
@@ -9,6 +10,7 @@ type McpToolRowProps = {
910
}
1011

1112
const McpToolRow = ({ tool, serverName, alwaysAllowMcp }: McpToolRowProps) => {
13+
const { t } = useAppTranslation()
1214
const handleAlwaysAllowChange = () => {
1315
if (!serverName) return
1416

@@ -36,7 +38,7 @@ const McpToolRow = ({ tool, serverName, alwaysAllowMcp }: McpToolRowProps) => {
3638
</div>
3739
{serverName && alwaysAllowMcp && (
3840
<VSCodeCheckbox checked={tool.alwaysAllow} onChange={handleAlwaysAllowChange} data-tool={tool.name}>
39-
Always allow
41+
{t("mcp:tool.alwaysAllow")}
4042
</VSCodeCheckbox>
4143
)}
4244
</div>
@@ -64,7 +66,7 @@ const McpToolRow = ({ tool, serverName, alwaysAllowMcp }: McpToolRowProps) => {
6466
}}>
6567
<div
6668
style={{ marginBottom: "4px", opacity: 0.8, fontSize: "11px", textTransform: "uppercase" }}>
67-
Parameters
69+
{t("mcp:tool.parameters")}
6870
</div>
6971
{Object.entries(tool.inputSchema.properties as Record<string, any>).map(
7072
([paramName, schema]) => {
@@ -98,7 +100,7 @@ const McpToolRow = ({ tool, serverName, alwaysAllowMcp }: McpToolRowProps) => {
98100
overflowWrap: "break-word",
99101
wordBreak: "break-word",
100102
}}>
101-
{schema.description || "No description"}
103+
{schema.description || t("mcp:tool.noDescription")}
102104
</span>
103105
</div>
104106
)

webview-ui/src/components/mcp/McpView.tsx

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { vscode } from "@/utils/vscode"
1414
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui"
1515

1616
import { useExtensionState } from "../../context/ExtensionStateContext"
17+
import { useAppTranslation } from "../../i18n/TranslationContext"
18+
import { Trans } from "react-i18next"
1719
import { Tab, TabContent, TabHeader } from "../common/Tab"
1820
import McpToolRow from "./McpToolRow"
1921
import McpResourceRow from "./McpResourceRow"
@@ -31,12 +33,13 @@ const McpView = ({ onDone }: McpViewProps) => {
3133
enableMcpServerCreation,
3234
setEnableMcpServerCreation,
3335
} = useExtensionState()
36+
const { t } = useAppTranslation()
3437

3538
return (
3639
<Tab>
3740
<TabHeader className="flex justify-between items-center">
38-
<h3 className="text-vscode-foreground m-0">MCP Servers</h3>
39-
<VSCodeButton onClick={onDone}>Done</VSCodeButton>
41+
<h3 className="text-vscode-foreground m-0">{t("mcp:title")}</h3>
42+
<VSCodeButton onClick={onDone}>{t("mcp:done")}</VSCodeButton>
4043
</TabHeader>
4144

4245
<TabContent>
@@ -47,17 +50,16 @@ const McpView = ({ onDone }: McpViewProps) => {
4750
marginBottom: "10px",
4851
marginTop: "5px",
4952
}}>
50-
The{" "}
51-
<VSCodeLink href="https://github.com/modelcontextprotocol" style={{ display: "inline" }}>
52-
Model Context Protocol
53-
</VSCodeLink>{" "}
54-
enables communication with locally running MCP servers that provide additional tools and resources
55-
to extend Roo's capabilities. You can use{" "}
56-
<VSCodeLink href="https://github.com/modelcontextprotocol/servers" style={{ display: "inline" }}>
57-
community-made servers
58-
</VSCodeLink>{" "}
59-
or ask Roo to create new tools specific to your workflow (e.g., "add a tool that gets the latest npm
60-
docs").
53+
<Trans i18nKey="mcp:description">
54+
<VSCodeLink href="https://github.com/modelcontextprotocol" style={{ display: "inline" }}>
55+
Model Context Protocol
56+
</VSCodeLink>
57+
<VSCodeLink
58+
href="https://github.com/modelcontextprotocol/servers"
59+
style={{ display: "inline" }}>
60+
community-made servers
61+
</VSCodeLink>
62+
</Trans>
6163
</div>
6264

6365
<McpEnabledToggle />
@@ -71,17 +73,15 @@ const McpView = ({ onDone }: McpViewProps) => {
7173
setEnableMcpServerCreation(e.target.checked)
7274
vscode.postMessage({ type: "enableMcpServerCreation", bool: e.target.checked })
7375
}}>
74-
<span style={{ fontWeight: "500" }}>Enable MCP Server Creation</span>
76+
<span style={{ fontWeight: "500" }}>{t("mcp:enableServerCreation.title")}</span>
7577
</VSCodeCheckbox>
7678
<p
7779
style={{
7880
fontSize: "12px",
7981
marginTop: "5px",
8082
color: "var(--vscode-descriptionForeground)",
8183
}}>
82-
When enabled, Roo can help you create new MCP servers via commands like "add a new tool
83-
to...". If you don't need to create MCP servers you can disable this to reduce Roo's
84-
token usage.
84+
{t("mcp:enableServerCreation.description")}
8585
</p>
8686
</div>
8787

@@ -103,7 +103,7 @@ const McpView = ({ onDone }: McpViewProps) => {
103103
vscode.postMessage({ type: "openMcpSettings" })
104104
}}>
105105
<span className="codicon codicon-edit" style={{ marginRight: "6px" }}></span>
106-
Edit MCP Settings
106+
{t("mcp:editSettings")}
107107
</VSCodeButton>
108108
</div>
109109
</>
@@ -114,6 +114,7 @@ const McpView = ({ onDone }: McpViewProps) => {
114114
}
115115

116116
const ServerRow = ({ server, alwaysAllowMcp }: { server: McpServer; alwaysAllowMcp?: boolean }) => {
117+
const { t } = useAppTranslation()
117118
const [isExpanded, setIsExpanded] = useState(false)
118119
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
119120
const [timeoutValue, setTimeoutValue] = useState(() => {
@@ -122,14 +123,14 @@ const ServerRow = ({ server, alwaysAllowMcp }: { server: McpServer; alwaysAllowM
122123
})
123124

124125
const timeoutOptions = [
125-
{ value: 15, label: "15 seconds" },
126-
{ value: 30, label: "30 seconds" },
127-
{ value: 60, label: "1 minute" },
128-
{ value: 300, label: "5 minutes" },
129-
{ value: 600, label: "10 minutes" },
130-
{ value: 900, label: "15 minutes" },
131-
{ value: 1800, label: "30 minutes" },
132-
{ value: 3600, label: "60 minutes" },
126+
{ value: 15, label: t("mcp:networkTimeout.options.15seconds") },
127+
{ value: 30, label: t("mcp:networkTimeout.options.30seconds") },
128+
{ value: 60, label: t("mcp:networkTimeout.options.1minute") },
129+
{ value: 300, label: t("mcp:networkTimeout.options.5minutes") },
130+
{ value: 600, label: t("mcp:networkTimeout.options.10minutes") },
131+
{ value: 900, label: t("mcp:networkTimeout.options.15minutes") },
132+
{ value: 1800, label: t("mcp:networkTimeout.options.30minutes") },
133+
{ value: 3600, label: t("mcp:networkTimeout.options.60minutes") },
133134
]
134135

135136
const getStatusColor = () => {
@@ -291,7 +292,9 @@ const ServerRow = ({ server, alwaysAllowMcp }: { server: McpServer; alwaysAllowM
291292
onClick={handleRestart}
292293
disabled={server.status === "connecting"}
293294
style={{ width: "calc(100% - 20px)", margin: "0 10px 10px 10px" }}>
294-
{server.status === "connecting" ? "Retrying..." : "Retry Connection"}
295+
{server.status === "connecting"
296+
? t("mcp:serverStatus.retrying")
297+
: t("mcp:serverStatus.retryConnection")}
295298
</VSCodeButton>
296299
</div>
297300
) : (
@@ -304,9 +307,11 @@ const ServerRow = ({ server, alwaysAllowMcp }: { server: McpServer; alwaysAllowM
304307
borderRadius: "0 0 4px 4px",
305308
}}>
306309
<VSCodePanels style={{ marginBottom: "10px" }}>
307-
<VSCodePanelTab id="tools">Tools ({server.tools?.length || 0})</VSCodePanelTab>
310+
<VSCodePanelTab id="tools">
311+
{t("mcp:tabs.tools")} ({server.tools?.length || 0})
312+
</VSCodePanelTab>
308313
<VSCodePanelTab id="resources">
309-
Resources (
314+
{t("mcp:tabs.resources")} (
310315
{[...(server.resourceTemplates || []), ...(server.resources || [])].length || 0})
311316
</VSCodePanelTab>
312317

@@ -325,7 +330,7 @@ const ServerRow = ({ server, alwaysAllowMcp }: { server: McpServer; alwaysAllowM
325330
</div>
326331
) : (
327332
<div style={{ padding: "10px 0", color: "var(--vscode-descriptionForeground)" }}>
328-
No tools found
333+
{t("mcp:emptyState.noTools")}
329334
</div>
330335
)}
331336
</VSCodePanelView>
@@ -346,7 +351,7 @@ const ServerRow = ({ server, alwaysAllowMcp }: { server: McpServer; alwaysAllowM
346351
</div>
347352
) : (
348353
<div style={{ padding: "10px 0", color: "var(--vscode-descriptionForeground)" }}>
349-
No resources found
354+
{t("mcp:emptyState.noResources")}
350355
</div>
351356
)}
352357
</VSCodePanelView>
@@ -361,7 +366,7 @@ const ServerRow = ({ server, alwaysAllowMcp }: { server: McpServer; alwaysAllowM
361366
gap: "10px",
362367
marginBottom: "8px",
363368
}}>
364-
<span>Network Timeout</span>
369+
<span>{t("mcp:networkTimeout.label")}</span>
365370
<select
366371
value={timeoutValue}
367372
onChange={handleTimeoutChange}
@@ -388,7 +393,7 @@ const ServerRow = ({ server, alwaysAllowMcp }: { server: McpServer; alwaysAllowM
388393
color: "var(--vscode-descriptionForeground)",
389394
display: "block",
390395
}}>
391-
Maximum time to wait for server responses
396+
{t("mcp:networkTimeout.description")}
392397
</span>
393398
</div>
394399
</div>
@@ -399,18 +404,17 @@ const ServerRow = ({ server, alwaysAllowMcp }: { server: McpServer; alwaysAllowM
399404
<Dialog open={showDeleteConfirm} onOpenChange={setShowDeleteConfirm}>
400405
<DialogContent>
401406
<DialogHeader>
402-
<DialogTitle>Delete MCP Server</DialogTitle>
407+
<DialogTitle>{t("mcp:deleteDialog.title")}</DialogTitle>
403408
<DialogDescription>
404-
Are you sure you want to delete the MCP server "{server.name}"? This action cannot be
405-
undone.
409+
{t("mcp:deleteDialog.description", { serverName: server.name })}
406410
</DialogDescription>
407411
</DialogHeader>
408412
<DialogFooter>
409413
<VSCodeButton appearance="secondary" onClick={() => setShowDeleteConfirm(false)}>
410-
Cancel
414+
{t("mcp:deleteDialog.cancel")}
411415
</VSCodeButton>
412416
<VSCodeButton appearance="primary" onClick={handleDelete}>
413-
Delete
417+
{t("mcp:deleteDialog.delete")}
414418
</VSCodeButton>
415419
</DialogFooter>
416420
</DialogContent>

webview-ui/src/components/mcp/__tests__/McpToolRow.test.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,20 @@ import { render, fireEvent, screen } from "@testing-library/react"
33
import McpToolRow from "../McpToolRow"
44
import { vscode } from "../../../utils/vscode"
55

6+
// Mock the translation hook
7+
jest.mock("../../../i18n/TranslationContext", () => ({
8+
useAppTranslation: () => ({
9+
t: (key: string) => {
10+
const translations: Record<string, string> = {
11+
"mcp:tool.alwaysAllow": "Always allow",
12+
"mcp:tool.parameters": "Parameters",
13+
"mcp:tool.noDescription": "No description",
14+
}
15+
return translations[key] || key
16+
},
17+
}),
18+
}))
19+
620
jest.mock("../../../utils/vscode", () => ({
721
vscode: {
822
postMessage: jest.fn(),
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"title": "خوادم MCP",
3+
"done": "تم",
4+
"description": "يتيح <0>بروتوكول سياق النموذج (Model Context Protocol)</0> الاتصال بخوادم MCP المحلية التي توفر أدوات وموارد إضافية لتوسيع قدرات Roo. يمكنك استخدام <1>الخوادم التي أنشأها المجتمع</1> أو مطالبة Roo بإنشاء أدوات جديدة مخصصة لسير عملك (مثل \"إضافة أداة تحصل على أحدث وثائق npm\").",
5+
"enableToggle": {
6+
"title": "تمكين خوادم MCP",
7+
"description": "عند التمكين، سيتمكن Roo من التفاعل مع خوادم MCP للحصول على وظائف متقدمة. إذا كنت لا تستخدم MCP، يمكنك تعطيل هذا لتقليل استخدام token بواسطة Roo."
8+
},
9+
"enableServerCreation": {
10+
"title": "تمكين إنشاء خادم MCP",
11+
"description": "عند التمكين، يمكن لـ Roo مساعدتك في إنشاء خوادم MCP جديدة عبر أوامر مثل \"إضافة أداة جديدة إلى...\". إذا كنت لا تحتاج إلى إنشاء خوادم MCP، يمكنك تعطيل هذا لتقليل استخدام token بواسطة Roo."
12+
},
13+
"editSettings": "تعديل إعدادات MCP",
14+
"tool": {
15+
"alwaysAllow": "السماح دائمًا",
16+
"parameters": "المعلمات",
17+
"noDescription": "لا يوجد وصف"
18+
},
19+
"tabs": {
20+
"tools": "الأدوات",
21+
"resources": "الموارد"
22+
},
23+
"emptyState": {
24+
"noTools": "لم يتم العثور على أدوات",
25+
"noResources": "لم يتم العثور على موارد"
26+
},
27+
"networkTimeout": {
28+
"label": "مهلة الشبكة",
29+
"description": "الحد الأقصى لوقت الانتظار لاستجابات الخادم",
30+
"options": {
31+
"15seconds": "15 ثانية",
32+
"30seconds": "30 ثانية",
33+
"1minute": "1 دقيقة",
34+
"5minutes": "5 دقائق",
35+
"10minutes": "10 دقائق",
36+
"15minutes": "15 دقيقة",
37+
"30minutes": "30 دقيقة",
38+
"60minutes": "60 دقيقة"
39+
}
40+
},
41+
"deleteDialog": {
42+
"title": "حذف خادم MCP",
43+
"description": "هل أنت متأكد أنك تريد حذف خادم MCP \"{{serverName}}\"؟ لا يمكن التراجع عن هذا الإجراء.",
44+
"cancel": "إلغاء",
45+
"delete": "حذف"
46+
},
47+
"serverStatus": {
48+
"retrying": "إعادة المحاولة...",
49+
"retryConnection": "إعادة محاولة الاتصال"
50+
}
51+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"title": "Servidors MCP",
3+
"done": "Fet",
4+
"description": "El <0>Model Context Protocol</0> permet la comunicació amb servidors MCP que s'executen localment i proporcionen eines i recursos addicionals per ampliar les capacitats de Roo. Pots utilitzar <1>servidors creats per la comunitat</1> o demanar a Roo que creï noves eines específiques per al teu flux de treball (per exemple, \"afegir una eina que obtingui la documentació més recent de npm\").",
5+
"enableToggle": {
6+
"title": "Habilitar servidors MCP",
7+
"description": "Quan està habilitat, Roo podrà interactuar amb servidors MCP per a funcionalitats avançades. Si no utilitzes MCP, pots desactivar això per reduir l'ús de tokens de Roo."
8+
},
9+
"enableServerCreation": {
10+
"title": "Habilitar creació de servidors MCP",
11+
"description": "Quan està habilitat, Roo pot ajudar-te a crear nous servidors MCP mitjançant ordres com \"afegir una nova eina per a...\". Si no necessites crear servidors MCP, pots desactivar això per reduir l'ús de tokens de Roo."
12+
},
13+
"editSettings": "Editar configuració de MCP",
14+
"tool": {
15+
"alwaysAllow": "Permetre sempre",
16+
"parameters": "Paràmetres",
17+
"noDescription": "Sense descripció"
18+
},
19+
"tabs": {
20+
"tools": "Eines",
21+
"resources": "Recursos"
22+
},
23+
"emptyState": {
24+
"noTools": "No s'han trobat eines",
25+
"noResources": "No s'han trobat recursos"
26+
},
27+
"networkTimeout": {
28+
"label": "Temps d'espera de xarxa",
29+
"description": "Temps màxim d'espera per a respostes del servidor",
30+
"options": {
31+
"15seconds": "15 segons",
32+
"30seconds": "30 segons",
33+
"1minute": "1 minut",
34+
"5minutes": "5 minuts",
35+
"10minutes": "10 minuts",
36+
"15minutes": "15 minuts",
37+
"30minutes": "30 minuts",
38+
"60minutes": "60 minuts"
39+
}
40+
},
41+
"deleteDialog": {
42+
"title": "Eliminar servidor MCP",
43+
"description": "Estàs segur que vols eliminar el servidor MCP \"{{serverName}}\"? Aquesta acció no es pot desfer.",
44+
"cancel": "Cancel·lar",
45+
"delete": "Eliminar"
46+
},
47+
"serverStatus": {
48+
"retrying": "Reintentant...",
49+
"retryConnection": "Reintentar connexió"
50+
}
51+
}

0 commit comments

Comments
 (0)