From 4b29c648eccc65be3c815a774c50ae27dfd54a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B9=E9=9B=AA?= <2b@yorha.xyz> Date: Thu, 11 Jun 2026 07:33:57 +0900 Subject: [PATCH] feat(ui): i18n for MCP tool permissions --- .../MCPToolPermissions.tsx | 38 ++++++++++++------- ui/litellm-dashboard/src/locales/en.json | 13 +++++++ ui/litellm-dashboard/src/locales/zh-CN.json | 13 +++++++ 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/ui/litellm-dashboard/src/components/mcp_server_management/MCPToolPermissions.tsx b/ui/litellm-dashboard/src/components/mcp_server_management/MCPToolPermissions.tsx index e05352d434f..681a5377cb7 100644 --- a/ui/litellm-dashboard/src/components/mcp_server_management/MCPToolPermissions.tsx +++ b/ui/litellm-dashboard/src/components/mcp_server_management/MCPToolPermissions.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useRef, useState, useMemo } from "react"; +import { useTranslation } from "react-i18next"; import { listMCPTools } from "../networking"; import { MCPTool, MCPServer } from "../mcp_tools/types"; import { Text } from "@tremor/react"; @@ -22,6 +23,7 @@ const MCPToolPermissions: React.FC = ({ onChange, disabled = false, }) => { + const { t } = useTranslation(); const { data: allServers = [] } = useMCPServers(); const [serverTools, setServerTools] = useState>({}); const [loadingTools, setLoadingTools] = useState>({}); @@ -52,7 +54,10 @@ const MCPToolPermissions: React.FC = ({ const response = await listMCPTools(token, serverId); if (response.error) { - setToolErrors((prev) => ({ ...prev, [serverId]: response.message || "Failed to fetch tools" })); + setToolErrors((prev) => ({ + ...prev, + [serverId]: response.message || t("mcpServerManagement.mcpToolPermissions.failedToFetchTools"), + })); setServerTools((prev) => ({ ...prev, [serverId]: [] })); } else { const fetchedTools: MCPTool[] = response.tools || []; @@ -63,14 +68,17 @@ const MCPToolPermissions: React.FC = ({ const latestPermissions = toolPermissionsRef.current; if (!latestPermissions[serverId] && fetchedTools.length > 0) { const nonDeleteTools = fetchedTools - .filter((t) => classifyToolOp(t.name, t.description || "") !== "delete") - .map((t) => t.name); + .filter((tool) => classifyToolOp(tool.name, tool.description || "") !== "delete") + .map((tool) => tool.name); onChange({ ...latestPermissions, [serverId]: nonDeleteTools }); } } } catch (err) { console.error(`Error fetching tools for server ${serverId}:`, err); - setToolErrors((prev) => ({ ...prev, [serverId]: "Failed to fetch tools" })); + setToolErrors((prev) => ({ + ...prev, + [serverId]: t("mcpServerManagement.mcpToolPermissions.failedToFetchTools"), + })); setServerTools((prev) => ({ ...prev, [serverId]: [] })); } finally { setLoadingTools((prev) => ({ ...prev, [serverId]: false })); @@ -95,7 +103,7 @@ const MCPToolPermissions: React.FC = ({ const handleSelectAll = (serverId: string) => { const tools = serverTools[serverId] || []; - onChange({ ...toolPermissions, [serverId]: tools.map((t) => t.name) }); + onChange({ ...toolPermissions, [serverId]: tools.map((tool) => tool.name) }); }; const handleDeselectAll = (serverId: string) => { @@ -133,8 +141,8 @@ const MCPToolPermissions: React.FC = ({ optionType="button" buttonStyle="solid" options={[ - { label: "Risk Groups", value: "crud" }, - { label: "Flat List", value: "flat" }, + { label: t("mcpServerManagement.mcpToolPermissions.riskGroups"), value: "crud" }, + { label: t("mcpServerManagement.mcpToolPermissions.flatList"), value: "flat" }, ]} /> )} @@ -146,7 +154,7 @@ const MCPToolPermissions: React.FC = ({ onClick={() => handleSelectAll(server.server_id)} disabled={isLoading} > - Select All + {t("mcpServerManagement.mcpToolPermissions.selectAll")} )} @@ -167,14 +175,16 @@ const MCPToolPermissions: React.FC = ({ {isLoading && (
- Loading tools... + {t("mcpServerManagement.mcpToolPermissions.loadingTools")}
)} {/* Error */} {error && !isLoading && (
- Unable to load tools + + {t("mcpServerManagement.mcpToolPermissions.unableToLoadTools")} + {error}
)} @@ -212,7 +222,9 @@ const MCPToolPermissions: React.FC = ({
{tool.name} - - {tool.description || "No description"} + + - {tool.description || t("mcpServerManagement.mcpToolPermissions.noDescription")} +
@@ -224,7 +236,7 @@ const MCPToolPermissions: React.FC = ({ {/* Empty State */} {!isLoading && !error && tools.length === 0 && (
- No tools available + {t("mcpServerManagement.mcpToolPermissions.noToolsAvailable")}
)} diff --git a/ui/litellm-dashboard/src/locales/en.json b/ui/litellm-dashboard/src/locales/en.json index a35cddb5b46..9e5ebd52038 100644 --- a/ui/litellm-dashboard/src/locales/en.json +++ b/ui/litellm-dashboard/src/locales/en.json @@ -8409,5 +8409,18 @@ "maxSpendPlaceholder": "Max spend ($)", "addBudgetWindow": "+ Add Budget Window" } + }, + "mcpServerManagement": { + "mcpToolPermissions": { + "failedToFetchTools": "Failed to fetch tools", + "riskGroups": "Risk Groups", + "flatList": "Flat List", + "selectAll": "Select All", + "deselectAll": "Deselect All", + "loadingTools": "Loading tools...", + "unableToLoadTools": "Unable to load tools", + "noDescription": "No description", + "noToolsAvailable": "No tools available" + } } } diff --git a/ui/litellm-dashboard/src/locales/zh-CN.json b/ui/litellm-dashboard/src/locales/zh-CN.json index 3df6e5e978b..591f4a0b8f6 100644 --- a/ui/litellm-dashboard/src/locales/zh-CN.json +++ b/ui/litellm-dashboard/src/locales/zh-CN.json @@ -8409,5 +8409,18 @@ "maxSpendPlaceholder": "最大花费 ($)", "addBudgetWindow": "+ 添加预算窗口" } + }, + "mcpServerManagement": { + "mcpToolPermissions": { + "failedToFetchTools": "获取工具失败", + "riskGroups": "风险分组", + "flatList": "平铺列表", + "selectAll": "全选", + "deselectAll": "取消全选", + "loadingTools": "正在加载工具...", + "unableToLoadTools": "无法加载工具", + "noDescription": "无描述", + "noToolsAvailable": "暂无可用工具" + } } }