From 287a666e1b2bb155e86aa88ebace201d1e8a51f6 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期四, 19 三月 2026 13:26:02 +0800
Subject: [PATCH] #AI.国际化

---
 rsf-admin/src/page/system/aiShared/AiRuntimeSummary.jsx       |   25 
 rsf-admin/src/page/system/aiMcpMount/AiMcpMountToolsPanel.jsx |   55 +-
 rsf-admin/src/page/system/aiPrompt/AiPromptForm.jsx           |   54 +-
 rsf-admin/src/page/system/aiParam/AiParamList.jsx             |   41 
 rsf-admin/src/page/system/aiMcpMount/AiMcpMountForm.jsx       |   48 +
 rsf-admin/src/page/system/aiCallLog/AiCallLogList.jsx         |  104 ++--
 rsf-admin/src/i18n/zh.js                                      |  304 +++++++++++++
 rsf-admin/src/page/system/aiPrompt/AiPromptList.jsx           |   43 +
 rsf-admin/src/i18n/en.js                                      |  304 +++++++++++++
 rsf-admin/src/page/system/aiMcpMount/AiMcpMountList.jsx       |   73 +-
 rsf-admin/src/page/system/aiParam/AiParamForm.jsx             |   56 +-
 rsf-admin/src/layout/AiChatDrawer.jsx                         |  174 ++++---
 rsf-admin/src/page/system/aiShared/AiConfigDialog.jsx         |   14 
 13 files changed, 986 insertions(+), 309 deletions(-)

diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index f0b39e1..ae41b15 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -232,6 +232,310 @@
         taskPathTemplateMerge: 'TaskPathTemplateMerge',
         missionFlowStepInstance: 'Mission Flow Steps',
     },
+    ai: {
+        common: {
+            cancel: "Cancel",
+            close: "Close",
+            save: "Save",
+            new: "New",
+            detail: "Details",
+            delete: "Delete",
+            enabled: "Enabled",
+            disabled: "Disabled",
+            saveSuccess: "Saved successfully",
+            updateSuccess: "Updated successfully",
+            deleteSuccess: "Deleted successfully",
+            deleteFailed: "Delete failed",
+            operationFailed: "Operation failed",
+            confirmDelete: "Delete \"%{name}\"?",
+            none: "None",
+            notValidated: "Not validated",
+            notTested: "Not tested",
+            lastUpdatedBy: "Last updated by",
+            lastUpdatedAt: "Last updated at",
+            target: "Target",
+            lastTest: "Last test",
+            prompt: "Prompt",
+            model: "Model",
+            error: "Error",
+            testing: "Testing...",
+        },
+        runtimeSummary: {
+            fetchFailed: "Failed to load runtime summary",
+            title: "Current Runtime",
+            description: "Shows the active model, prompt, and MCP mounts.",
+            currentModel: "Current Model",
+            validateStatus: "Validate %{status}",
+            currentPrompt: "Current Prompt",
+            lastUpdated: "Last updated: %{time} / %{user}",
+            enabledMcp: "Enabled MCP",
+            enabledMcpCount: "%{count} enabled",
+        },
+        param: {
+            fields: {
+                providerType: "Provider Type",
+                model: "Model",
+                baseUrl: "Base URL",
+                apiKey: "API Key",
+                temperature: "Temperature",
+                topP: "Top P",
+                maxTokens: "Max Tokens",
+                timeoutMs: "Timeout(ms)",
+                streamingEnabled: "Enable Streaming",
+                validateStatus: "Latest Validate Status",
+                lastValidateElapsedMs: "Latest Validate Elapsed(ms)",
+                lastValidateTime: "Latest Validate Time",
+                lastValidateMessage: "Latest Validate Result",
+            },
+            list: {
+                emptyTitle: "No AI parameter configs",
+                emptyDescription: "Create an OpenAI-compatible model card first.",
+                streaming: "Streaming",
+                nonStreaming: "Non-streaming",
+            },
+            dialog: {
+                create: "New AI Parameter",
+                edit: "Edit AI Parameter",
+                show: "View AI Parameter Details",
+            },
+            validate: {
+                success: "AI parameter validation succeeded",
+                failed: "AI parameter validation failed",
+                loading: "Validating...",
+                beforeSave: "Validate Before Save",
+                description: "Validates the current Base URL, API Key, and model directly.",
+            },
+            form: {
+                sections: {
+                    main: "Main Configuration",
+                    runtime: "Runtime and Audit",
+                },
+            },
+        },
+        prompt: {
+            fields: {
+                code: "Code",
+                scene: "Scene",
+                systemPrompt: "System Prompt",
+                userPromptTemplate: "User Prompt Template",
+            },
+            list: {
+                emptyTitle: "No prompt configs",
+                emptyDescription: "Once you create a prompt card, AI chat will load it dynamically.",
+                sceneValue: "Scene: %{value}",
+            },
+            dialog: {
+                create: "New Prompt",
+                edit: "Edit Prompt",
+                show: "View Prompt Details",
+            },
+            preview: {
+                defaultInput: "Please summarize what this page can do",
+                success: "Prompt preview generated",
+                failed: "Prompt preview failed",
+                title: "Prompt Preview",
+                input: "Sample Input",
+                metadata: "Sample Metadata JSON",
+                loading: "Rendering...",
+                render: "Render Preview",
+                description: "Render the System Prompt and User Prompt with the current form values.",
+                resolvedVariables: "Resolved variables: %{value}",
+                renderedSystemPrompt: "Rendered System Prompt",
+                renderedUserPrompt: "Rendered User Prompt",
+            },
+            form: {
+                sections: {
+                    main: "Prompt Configuration",
+                    runtime: "Runtime and Audit",
+                },
+            },
+        },
+        mcp: {
+            fields: {
+                transportType: "Transport Type",
+                builtinCode: "Built-in MCP",
+                serverUrl: "Server URL",
+                command: "Command",
+                sort: "Sort",
+                healthStatus: "Health Status",
+                lastInitElapsedMs: "Last Init Elapsed(ms)",
+                lastTestTime: "Last Test Time",
+                lastTestMessage: "Last Test Result",
+            },
+            groups: {
+                builtin: {
+                    title: "Built-in MCP",
+                    description: "Built-in tool mounts for exposing platform capabilities directly.",
+                },
+                sse: {
+                    title: "Remote SSE MCP",
+                    description: "Mount external tools through a remote MCP server.",
+                },
+                stdio: {
+                    title: "Local STDIO MCP",
+                    description: "Mount external MCP tools through a local command process.",
+                },
+            },
+            health: {
+                healthy: "Healthy",
+                unhealthy: "Failed",
+            },
+            list: {
+                emptyTitle: "No MCP mounts",
+                emptyDescription: "Create a built-in MCP, remote SSE mount, or local STDIO mount.",
+                sortValue: "Sort %{value}",
+                noConnectivityTest: "No connectivity test has been run yet",
+                connectivityTest: "Connectivity Test",
+            },
+            dialog: {
+                create: "New MCP Mount",
+                edit: "Edit MCP Mount",
+                show: "View MCP Mount Details",
+            },
+            connectivity: {
+                success: "Connectivity test completed",
+                failed: "Connectivity test failed",
+            },
+            form: {
+                testBeforeSave: "Test Before Save",
+                testDescription: "Validate connectivity directly with the current draft without saving.",
+                sections: {
+                    main: "MCP Mount Configuration",
+                    runtime: "Runtime Info",
+                },
+            },
+            tools: {
+                schemaParseFailed: "Failed to parse input schema: %{message}",
+                loadFailed: "Failed to load tools",
+                inputRequired: "Please enter tool test JSON",
+                testSuccess: "Tool %{name} test completed",
+                testFailed: "Tool test failed",
+                saveBeforePreview: "Save the mount before previewing tools and running tests.",
+                title: "Tool Preview and Test",
+                description: "Supports connectivity checks, structured schema preview, and generated test forms from input parameters.",
+                refresh: "Refresh Tools",
+                noTools: "No tools were resolved for this mount.",
+                purpose: "Purpose: %{value}",
+                fieldCount: "%{count} fields",
+                queryBoundary: "Query boundary: %{value}",
+                exampleQuestions: "Example Questions",
+                formattedSchema: "Formatted Input Schema",
+                testInput: "Test Input JSON",
+                testInputPlaceholder: "Example: {\"code\":\"A01\"}",
+                executeTest: "Run Test",
+                testResult: "Test Result",
+            },
+        },
+        observe: {
+            fields: {
+                requestId: "Request ID",
+                promptCode: "Prompt Code",
+                userId: "User ID",
+                sessionId: "Session ID",
+                mountedMcp: "MCP Mounts",
+            },
+            summary: {
+                fetchFailed: "Failed to load AI observe stats",
+                title: "Observe Overview",
+                description: "Statistics for AI chats and MCP tool calls in the current tenant.",
+                callCount: "AI Calls",
+                successFailure: "Success %{success} / Failed %{failure}",
+                avgElapsed: "Average Elapsed",
+                firstToken: "First token %{value} ms",
+                tokenUsage: "Token Usage",
+                avgToken: "Average %{value}",
+                toolSuccessRate: "Tool Success Rate",
+                toolCallFailure: "Calls %{call} / Failed %{failure}",
+            },
+            status: {
+                completed: "Success",
+                failed: "Failed",
+                aborted: "Aborted",
+            },
+            detail: {
+                mcpLogsFailed: "Failed to load MCP call logs",
+                title: "AI Call Details",
+                mcpLogs: "MCP Tool Call Logs",
+                noMcpLogs: "No MCP tool logs were generated for this call.",
+                inputSummary: "Input Summary",
+                outputSummary: "Output Summary / Error",
+            },
+            list: {
+                emptyTitle: "No AI call logs",
+                emptyDescription: "After starting AI chats, statistics and audit records will appear here.",
+                userValue: "User %{value}",
+                elapsedValue: "Elapsed %{value} ms",
+                tokenValue: "Token %{value}",
+                mcpToolCalls: "MCP / Tool Calls",
+                mcpToolSummary: "%{mcp} mounts, %{success} tool successes, %{failure} failures",
+            },
+        },
+        drawer: {
+            title: "AI Chat",
+            runtimeFailed: "Failed to load AI runtime",
+            sessionListFailed: "Failed to load AI sessions",
+            sessionDeleted: "Session deleted",
+            deleteSessionFailed: "Failed to delete AI session",
+            pinned: "Session pinned",
+            unpinned: "Session unpinned",
+            pinFailed: "Failed to update session pin state",
+            renamed: "Session renamed",
+            renameFailed: "Failed to rename session",
+            memoryCleared: "Session memory cleared",
+            clearMemoryFailed: "Failed to clear session memory",
+            retainLatestRoundSuccess: "Only the latest round was kept",
+            retainLatestRoundFailed: "Failed to keep only the latest round",
+            stopSuccess: "Current output stopped",
+            chatFailed: "AI chat failed",
+            newSession: "New Session",
+            sessionList: "Sessions",
+            searchPlaceholder: "Search session titles",
+            noSessions: "No history sessions",
+            sessionTitle: "Session %{id}",
+            pinAction: "Pin session",
+            unpinAction: "Unpin session",
+            renameAction: "Rename session",
+            deleteAction: "Delete session",
+            toolTrace: "Tool Trace",
+            noToolTrace: "No tool call was triggered in this round",
+            unknownTool: "Unknown tool",
+            toolStatusFailed: "Failed",
+            toolStatusCompleted: "Completed",
+            toolStatusRunning: "Running",
+            collapseDetail: "Hide Details",
+            viewDetail: "View Details",
+            toolInput: "Input: %{value}",
+            toolOutput: "Output summary: %{value}",
+            toolError: "Error: %{value}",
+            hasSummary: "Summary",
+            noSummary: "No Summary",
+            hasFacts: "Facts",
+            noFacts: "No Facts",
+            retainLatestRound: "Keep Latest Round",
+            clearMemory: "Clear Memory",
+            loadingRuntime: "Loading AI runtime info...",
+            emptyHint: "AI responses stream back through SSE here. You can also maintain parameters, prompts, and MCP mounts from the quick links above.",
+            userRole: "You",
+            assistantRole: "AI",
+            thinking: "Thinking...",
+            inputPlaceholder: "Type your question. Press Enter to send, Shift + Enter for a new line",
+            clearInput: "Clear Input",
+            stop: "Stop",
+            send: "Send",
+            renameDialogTitle: "Rename Session",
+            sessionTitleField: "Session Title",
+            requestMetric: "Req: %{value}",
+            sessionMetric: "Session: %{id}",
+            promptMetric: "Prompt: %{value}",
+            modelMetric: "Model: %{value}",
+            mcpMetric: "MCP: %{value}",
+            historyMetric: "History: %{value}",
+            recentMetric: "Recent: %{value}",
+            elapsedMetric: "Elapsed: %{value} ms",
+            firstTokenMetric: "First token: %{value} ms",
+            tokenMetric: "Tokens: prompt %{prompt} / completion %{completion} / total %{total}",
+        },
+    },
     table: {
         field: {
             basStationArea: {
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index 7998128..ba8a698 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -248,6 +248,310 @@
         taskPathTemplateMerge: '浠诲姟璺緞妯℃澘鍚堝苟',
         missionFlowStepInstance: '浠诲姟娴佺▼姝ラ',
     },
+    ai: {
+        common: {
+            cancel: "鍙栨秷",
+            close: "鍏抽棴",
+            save: "淇濆瓨",
+            new: "鏂板缓",
+            detail: "璇︽儏",
+            delete: "鍒犻櫎",
+            enabled: "鍚敤",
+            disabled: "鍋滅敤",
+            saveSuccess: "淇濆瓨鎴愬姛",
+            updateSuccess: "鏇存柊鎴愬姛",
+            deleteSuccess: "鍒犻櫎鎴愬姛",
+            deleteFailed: "鍒犻櫎澶辫触",
+            operationFailed: "鎿嶄綔澶辫触",
+            confirmDelete: "纭鍒犻櫎鈥�%{name}鈥濆悧锛�",
+            none: "鏃�",
+            notValidated: "鏈牎楠�",
+            notTested: "鏈祴璇�",
+            lastUpdatedBy: "鏈�杩戞洿鏂颁汉",
+            lastUpdatedAt: "鏈�杩戞洿鏂版椂闂�",
+            target: "鐩爣",
+            lastTest: "鏈�杩戞祴璇�",
+            prompt: "Prompt",
+            model: "妯″瀷",
+            error: "閿欒",
+            testing: "娴嬭瘯涓�...",
+        },
+        runtimeSummary: {
+            fetchFailed: "鑾峰彇杩愯鎬佹憳瑕佸け璐�",
+            title: "褰撳墠杩愯鎬�",
+            description: "灞曠ず褰撳墠鐢熸晥鐨勬ā鍨嬨�丳rompt 涓� MCP 鎸傝浇淇℃伅銆�",
+            currentModel: "褰撳墠妯″瀷",
+            validateStatus: "鏍¢獙 %{status}",
+            currentPrompt: "褰撳墠 Prompt",
+            lastUpdated: "鏈�杩戞洿鏂帮細%{time} / %{user}",
+            enabledMcp: "宸插惎鐢� MCP",
+            enabledMcpCount: "%{count} 涓�",
+        },
+        param: {
+            fields: {
+                providerType: "鎻愪緵鏂圭被鍨�",
+                model: "妯″瀷",
+                baseUrl: "Base URL",
+                apiKey: "API Key",
+                temperature: "Temperature",
+                topP: "Top P",
+                maxTokens: "Max Tokens",
+                timeoutMs: "Timeout(ms)",
+                streamingEnabled: "鍚敤娴佸紡鍝嶅簲",
+                validateStatus: "鏈�杩戞牎楠岀姸鎬�",
+                lastValidateElapsedMs: "鏈�杩戞牎楠岃�楁椂(ms)",
+                lastValidateTime: "鏈�杩戞牎楠屾椂闂�",
+                lastValidateMessage: "鏈�杩戞牎楠岀粨鏋�",
+            },
+            list: {
+                emptyTitle: "鏆傛棤 AI 鍙傛暟閰嶇疆",
+                emptyDescription: "鍙互鍏堟柊寤轰竴涓� OpenAI 鍏煎妯″瀷鍙傛暟鍗$墖銆�",
+                streaming: "娴佸紡鍝嶅簲",
+                nonStreaming: "闈炴祦寮�",
+            },
+            dialog: {
+                create: "鏂板缓 AI 鍙傛暟",
+                edit: "缂栬緫 AI 鍙傛暟",
+                show: "鏌ョ湅 AI 鍙傛暟璇︽儏",
+            },
+            validate: {
+                success: "AI 鍙傛暟楠岃瘉鎴愬姛",
+                failed: "AI 鍙傛暟楠岃瘉澶辫触",
+                loading: "楠岃瘉涓�...",
+                beforeSave: "淇濆瓨鍓嶉獙璇�",
+                description: "浼氱洿鎺ユ牎楠屽綋鍓� Base URL銆丄PI Key 涓庢ā鍨嬫槸鍚﹀彲璋冪敤銆�",
+            },
+            form: {
+                sections: {
+                    main: "涓昏閰嶇疆",
+                    runtime: "杩愯涓庡璁′俊鎭�",
+                },
+            },
+        },
+        prompt: {
+            fields: {
+                code: "缂栫爜",
+                scene: "鍦烘櫙",
+                systemPrompt: "System Prompt",
+                userPromptTemplate: "User Prompt Template",
+            },
+            list: {
+                emptyTitle: "鏆傛棤 Prompt 閰嶇疆",
+                emptyDescription: "鏂板缓涓�寮� Prompt 鍗$墖鍚庯紝AI 瀵硅瘽浼氬姩鎬佸姞杞借繖閲岀殑鍐呭銆�",
+                sceneValue: "鍦烘櫙: %{value}",
+            },
+            dialog: {
+                create: "鏂板缓 Prompt",
+                edit: "缂栬緫 Prompt",
+                show: "鏌ョ湅 Prompt 璇︽儏",
+            },
+            preview: {
+                defaultInput: "璇峰府鎴戞�荤粨褰撳墠椤甸潰鑳藉仛浠�涔�",
+                success: "Prompt 棰勮瀹屾垚",
+                failed: "Prompt 棰勮澶辫触",
+                title: "Prompt 棰勮",
+                input: "绀轰緥杈撳叆",
+                metadata: "绀轰緥鍏冩暟鎹� JSON",
+                loading: "棰勮涓�...",
+                render: "棰勮娓叉煋",
+                description: "鐢ㄥ綋鍓嶈〃鍗曞唴瀹规覆鏌� System Prompt 鍜� User Prompt銆�",
+                resolvedVariables: "宸茶В鏋愬彉閲忥細%{value}",
+                renderedSystemPrompt: "娓叉煋鍚庣殑 System Prompt",
+                renderedUserPrompt: "娓叉煋鍚庣殑 User Prompt",
+            },
+            form: {
+                sections: {
+                    main: "Prompt 閰嶇疆",
+                    runtime: "杩愯涓庡璁′俊鎭�",
+                },
+            },
+        },
+        mcp: {
+            fields: {
+                transportType: "浼犺緭绫诲瀷",
+                builtinCode: "鍐呯疆 MCP",
+                serverUrl: "鏈嶅姟鍦板潃",
+                command: "鍛戒护",
+                sort: "鎺掑簭",
+                healthStatus: "鍋ュ悍鐘舵��",
+                lastInitElapsedMs: "鏈�杩戝垵濮嬪寲鑰楁椂(ms)",
+                lastTestTime: "鏈�杩戞祴璇曟椂闂�",
+                lastTestMessage: "鏈�杩戞祴璇曠粨鏋�",
+            },
+            groups: {
+                builtin: {
+                    title: "鍐呯疆 MCP",
+                    description: "绯荤粺鍐呯疆宸ュ叿鎸傝浇锛岄�傚悎鐩存帴鏆撮湶骞冲彴鑳藉姏銆�",
+                },
+                sse: {
+                    title: "杩滅▼ SSE MCP",
+                    description: "閫氳繃杩滅▼ MCP Server 鎸傝浇澶栭儴宸ュ叿銆�",
+                },
+                stdio: {
+                    title: "鏈湴 STDIO MCP",
+                    description: "閫氳繃鏈湴鍛戒护杩涚▼鎸傝浇澶栭儴 MCP銆�",
+                },
+            },
+            health: {
+                healthy: "姝e父",
+                unhealthy: "澶辫触",
+            },
+            list: {
+                emptyTitle: "鏆傛棤 MCP 鎸傝浇",
+                emptyDescription: "鍙互鏂板缓鍐呯疆 MCP銆佽繙绋� SSE 鎸傝浇鎴栨湰鍦� STDIO 鎸傝浇銆�",
+                sortValue: "鎺掑簭 %{value}",
+                noConnectivityTest: "灏氭湭鎵ц杩為�氭�ф祴璇�",
+                connectivityTest: "杩為�氭祴璇�",
+            },
+            dialog: {
+                create: "鏂板缓 MCP 鎸傝浇",
+                edit: "缂栬緫 MCP 鎸傝浇",
+                show: "鏌ョ湅 MCP 鎸傝浇璇︽儏",
+            },
+            connectivity: {
+                success: "杩為�氭�ф祴璇曞畬鎴�",
+                failed: "杩為�氭�ф祴璇曞け璐�",
+            },
+            form: {
+                testBeforeSave: "淇濆瓨鍓嶆祴璇�",
+                testDescription: "鐢ㄥ綋鍓嶈崏绋块厤缃洿鎺ユ牎楠岃繛閫氭�э紝涓嶄細钀藉簱銆�",
+                sections: {
+                    main: "MCP 鎸傝浇閰嶇疆",
+                    runtime: "杩愯鎬佷俊鎭�",
+                },
+            },
+            tools: {
+                schemaParseFailed: "Input Schema 瑙f瀽澶辫触: %{message}",
+                loadFailed: "鑾峰彇宸ュ叿鍒楄〃澶辫触",
+                inputRequired: "璇疯緭鍏ュ伐鍏锋祴璇� JSON",
+                testSuccess: "宸ュ叿 %{name} 娴嬭瘯瀹屾垚",
+                testFailed: "宸ュ叿娴嬭瘯澶辫触",
+                saveBeforePreview: "淇濆瓨鎸傝浇鍚庡嵆鍙瑙堝伐鍏峰苟鎵ц娴嬭瘯銆�",
+                title: "宸ュ叿棰勮涓庢祴璇�",
+                description: "鏀寔杩為�氭�ф祴璇曘�佺粨鏋勫寲 Schema 棰勮鍜屾寜杈撳叆鍙傛暟鑷姩鐢熸垚娴嬭瘯琛ㄥ崟銆�",
+                refresh: "鍒锋柊宸ュ叿",
+                noTools: "褰撳墠鎸傝浇鏈В鏋愬嚭浠讳綍宸ュ叿銆�",
+                purpose: "鐢ㄩ��: %{value}",
+                fieldCount: "%{count} 涓弬鏁�",
+                queryBoundary: "鏌ヨ杈圭晫: %{value}",
+                exampleQuestions: "绀轰緥鎻愰棶",
+                formattedSchema: "鏍煎紡鍖� Input Schema",
+                testInput: "娴嬭瘯杈撳叆 JSON",
+                testInputPlaceholder: "渚嬪锛歿\"code\":\"A01\"}",
+                executeTest: "鎵ц娴嬭瘯",
+                testResult: "娴嬭瘯缁撴灉",
+            },
+        },
+        observe: {
+            fields: {
+                requestId: "璇锋眰ID",
+                promptCode: "Prompt 缂栫爜",
+                userId: "鐢ㄦ埛ID",
+                sessionId: "浼氳瘽ID",
+                mountedMcp: "MCP 鎸傝浇",
+            },
+            summary: {
+                fetchFailed: "鑾峰彇 AI 瑙傛祴缁熻澶辫触",
+                title: "瑙傛祴鎬昏",
+                description: "褰撳墠绉熸埛涓嬬殑 AI 瀵硅瘽璋冪敤涓� MCP 宸ュ叿璋冪敤缁熻銆�",
+                callCount: "AI 璋冪敤閲�",
+                successFailure: "鎴愬姛 %{success} / 澶辫触 %{failure}",
+                avgElapsed: "骞冲潎鑰楁椂",
+                firstToken: "棣栧寘 %{value} ms",
+                tokenUsage: "Token 浣跨敤",
+                avgToken: "骞冲潎 %{value}",
+                toolSuccessRate: "宸ュ叿鎴愬姛鐜�",
+                toolCallFailure: "璋冪敤 %{call} / 澶辫触 %{failure}",
+            },
+            status: {
+                completed: "鎴愬姛",
+                failed: "澶辫触",
+                aborted: "涓柇",
+            },
+            detail: {
+                mcpLogsFailed: "鑾峰彇 MCP 璋冪敤鏃ュ織澶辫触",
+                title: "AI 璋冪敤璇︽儏",
+                mcpLogs: "MCP 宸ュ叿璋冪敤鏃ュ織",
+                noMcpLogs: "褰撳墠璋冪敤娌℃湁浜х敓 MCP 宸ュ叿鏃ュ織銆�",
+                inputSummary: "杈撳叆鎽樿",
+                outputSummary: "杈撳嚭鎽樿 / 閿欒",
+            },
+            list: {
+                emptyTitle: "鏆傛棤 AI 璋冪敤鏃ュ織",
+                emptyDescription: "鍙戣捣 AI 瀵硅瘽鍚庯紝杩欓噷浼氬睍绀鸿皟鐢ㄧ粺璁″拰瀹¤璁板綍銆�",
+                userValue: "鐢ㄦ埛 %{value}",
+                elapsedValue: "鑰楁椂 %{value} ms",
+                tokenValue: "Token %{value}",
+                mcpToolCalls: "MCP / 宸ュ叿璋冪敤",
+                mcpToolSummary: "鎸傝浇 %{mcp} 涓紝宸ュ叿鎴愬姛 %{success}锛屽け璐� %{failure}",
+            },
+        },
+        drawer: {
+            title: "AI 瀵硅瘽",
+            runtimeFailed: "鑾峰彇 AI 杩愯鏃跺け璐�",
+            sessionListFailed: "鑾峰彇 AI 浼氳瘽鍒楄〃澶辫触",
+            sessionDeleted: "浼氳瘽宸插垹闄�",
+            deleteSessionFailed: "鍒犻櫎 AI 浼氳瘽澶辫触",
+            pinned: "浼氳瘽宸茬疆椤�",
+            unpinned: "浼氳瘽宸插彇娑堢疆椤�",
+            pinFailed: "鏇存柊浼氳瘽缃《鐘舵�佸け璐�",
+            renamed: "浼氳瘽宸查噸鍛藉悕",
+            renameFailed: "閲嶅懡鍚嶄細璇濆け璐�",
+            memoryCleared: "浼氳瘽璁板繂宸叉竻绌�",
+            clearMemoryFailed: "娓呯┖浼氳瘽璁板繂澶辫触",
+            retainLatestRoundSuccess: "宸蹭粎淇濈暀褰撳墠杞蹇�",
+            retainLatestRoundFailed: "淇濈暀褰撳墠杞蹇嗗け璐�",
+            stopSuccess: "宸插仠姝㈠綋鍓嶅璇濊緭鍑�",
+            chatFailed: "AI 瀵硅瘽澶辫触",
+            newSession: "鏂板缓浼氳瘽",
+            sessionList: "浼氳瘽鍒楄〃",
+            searchPlaceholder: "鎼滅储浼氳瘽鏍囬",
+            noSessions: "鏆傛棤鍘嗗彶浼氳瘽",
+            sessionTitle: "浼氳瘽 %{id}",
+            pinAction: "缃《浼氳瘽",
+            unpinAction: "鍙栨秷缃《",
+            renameAction: "閲嶅懡鍚嶄細璇�",
+            deleteAction: "鍒犻櫎浼氳瘽",
+            toolTrace: "宸ュ叿璋冪敤杞ㄨ抗",
+            noToolTrace: "褰撳墠杞湭瑙﹀彂宸ュ叿璋冪敤",
+            unknownTool: "鏈煡宸ュ叿",
+            toolStatusFailed: "澶辫触",
+            toolStatusCompleted: "瀹屾垚",
+            toolStatusRunning: "鎵ц涓�",
+            collapseDetail: "鏀惰捣璇︽儏",
+            viewDetail: "鏌ョ湅璇︽儏",
+            toolInput: "鍏ュ弬: %{value}",
+            toolOutput: "缁撴灉鎽樿: %{value}",
+            toolError: "閿欒: %{value}",
+            hasSummary: "鏈夋憳瑕�",
+            noSummary: "鏃犳憳瑕�",
+            hasFacts: "鏈変簨瀹�",
+            noFacts: "鏃犱簨瀹�",
+            retainLatestRound: "浠呬繚鐣欏綋鍓嶈疆",
+            clearMemory: "娓呯┖璁板繂",
+            loadingRuntime: "姝e湪鍔犺浇 AI 杩愯鏃朵俊鎭�...",
+            emptyHint: "杩欓噷浼氶�氳繃 SSE 娴佸紡杩斿洖 AI 鍥炲銆備綘涔熷彲浠ュ厛鍘讳笂闈㈢殑蹇嵎鍏ュ彛缁存姢鍙傛暟銆丳rompt 鍜� MCP 鎸傝浇銆�",
+            userRole: "浣�",
+            assistantRole: "AI",
+            thinking: "鎬濊�冧腑...",
+            inputPlaceholder: "杈撳叆浣犵殑闂锛屾寜 Enter 鍙戦�侊紝Shift + Enter 鎹㈣",
+            clearInput: "娓呯┖杈撳叆",
+            stop: "鍋滄",
+            send: "鍙戦��",
+            renameDialogTitle: "閲嶅懡鍚嶄細璇�",
+            sessionTitleField: "浼氳瘽鏍囬",
+            requestMetric: "Req: %{value}",
+            sessionMetric: "Session: %{id}",
+            promptMetric: "Prompt: %{value}",
+            modelMetric: "Model: %{value}",
+            mcpMetric: "MCP: %{value}",
+            historyMetric: "History: %{value}",
+            recentMetric: "Recent: %{value}",
+            elapsedMetric: "鑰楁椂: %{value} ms",
+            firstTokenMetric: "棣栧寘: %{value} ms",
+            tokenMetric: "Tokens: prompt %{prompt} / completion %{completion} / total %{total}",
+        },
+    },
     table: {
         field: {            
             flowStepInstance: { 
diff --git a/rsf-admin/src/layout/AiChatDrawer.jsx b/rsf-admin/src/layout/AiChatDrawer.jsx
index e649aad..e557728 100644
--- a/rsf-admin/src/layout/AiChatDrawer.jsx
+++ b/rsf-admin/src/layout/AiChatDrawer.jsx
@@ -1,6 +1,6 @@
 import React, { useEffect, useMemo, useRef, useState } from "react";
 import { useLocation, useNavigate } from "react-router-dom";
-import { useNotify } from "react-admin";
+import { useNotify, useTranslate } from "react-admin";
 import {
     Alert,
     Box,
@@ -43,17 +43,14 @@
 
 const DEFAULT_PROMPT_CODE = "home.default";
 
-const quickLinks = [
-    { label: "AI 鍙傛暟", path: "/aiParam", icon: <SettingsSuggestOutlinedIcon fontSize="small" /> },
-    { label: "Prompt", path: "/aiPrompt", icon: <PsychologyAltOutlinedIcon fontSize="small" /> },
-    { label: "MCP", path: "/aiMcpMount", icon: <CableOutlinedIcon fontSize="small" /> },
-];
-
 const AiChatDrawer = ({ open, onClose }) => {
     const navigate = useNavigate();
     const location = useLocation();
     const notify = useNotify();
+    const translate = useTranslate();
     const abortRef = useRef(null);
+    const messagesContainerRef = useRef(null);
+    const messagesBottomRef = useRef(null);
     const [runtime, setRuntime] = useState(null);
     const [sessionId, setSessionId] = useState(null);
     const [sessions, setSessions] = useState([]);
@@ -68,6 +65,12 @@
     const [drawerError, setDrawerError] = useState("");
     const [sessionKeyword, setSessionKeyword] = useState("");
     const [renameDialog, setRenameDialog] = useState({ open: false, sessionId: null, title: "" });
+
+    const quickLinks = useMemo(() => ([
+        { label: translate("menu.aiParam"), path: "/aiParam", icon: <SettingsSuggestOutlinedIcon fontSize="small" /> },
+        { label: translate("menu.aiPrompt"), path: "/aiPrompt", icon: <PsychologyAltOutlinedIcon fontSize="small" /> },
+        { label: translate("menu.aiMcpMount"), path: "/aiMcpMount", icon: <CableOutlinedIcon fontSize="small" /> },
+    ]), [translate]);
 
     const promptCode = runtime?.promptCode || DEFAULT_PROMPT_CODE;
 
@@ -95,6 +98,16 @@
         stopStream(false);
     }, []);
 
+    useEffect(() => {
+        if (!open) {
+            return;
+        }
+        const timer = window.requestAnimationFrame(() => {
+            scrollMessagesToBottom();
+        });
+        return () => window.cancelAnimationFrame(timer);
+    }, [open, messages, streaming]);
+
     const initializeDrawer = async (targetSessionId = null) => {
         setToolEvents([]);
         setExpandedToolIds([]);
@@ -115,7 +128,7 @@
             setPersistedMessages(historyMessages);
             setMessages(historyMessages);
         } catch (error) {
-            const message = error.message || "鑾峰彇 AI 杩愯鏃跺け璐�";
+            const message = error.message || translate("ai.drawer.runtimeFailed");
             setDrawerError(message);
         } finally {
             setLoadingRuntime(false);
@@ -127,7 +140,7 @@
             const data = await getAiSessions(DEFAULT_PROMPT_CODE, keyword);
             setSessions(data);
         } catch (error) {
-            const message = error.message || "鑾峰彇 AI 浼氳瘽鍒楄〃澶辫触";
+            const message = error.message || translate("ai.drawer.sessionListFailed");
             setDrawerError(message);
         }
     };
@@ -171,14 +184,14 @@
         }
         try {
             await removeAiSession(targetSessionId);
-            notify("浼氳瘽宸插垹闄�");
+            notify(translate("ai.drawer.sessionDeleted"));
             if (targetSessionId === sessionId) {
                 startNewSession();
                 await loadRuntime(null);
             }
             await loadSessions(sessionKeyword);
         } catch (error) {
-            const message = error.message || "鍒犻櫎 AI 浼氳瘽澶辫触";
+            const message = error.message || translate("ai.drawer.deleteSessionFailed");
             setDrawerError(message);
             notify(message, { type: "error" });
         }
@@ -190,10 +203,10 @@
         }
         try {
             await pinAiSession(targetSessionId, pinned);
-            notify(pinned ? "浼氳瘽宸茬疆椤�" : "浼氳瘽宸插彇娑堢疆椤�");
+            notify(translate(pinned ? "ai.drawer.pinned" : "ai.drawer.unpinned"));
             await loadSessions(sessionKeyword);
         } catch (error) {
-            const message = error.message || "鏇存柊浼氳瘽缃《鐘舵�佸け璐�";
+            const message = error.message || translate("ai.drawer.pinFailed");
             setDrawerError(message);
             notify(message, { type: "error" });
         }
@@ -217,11 +230,11 @@
         }
         try {
             await renameAiSession(renameDialog.sessionId, renameDialog.title);
-            notify("浼氳瘽宸查噸鍛藉悕");
+            notify(translate("ai.drawer.renamed"));
             closeRenameDialog();
             await loadSessions(sessionKeyword);
         } catch (error) {
-            const message = error.message || "閲嶅懡鍚嶄細璇濆け璐�";
+            const message = error.message || translate("ai.drawer.renameFailed");
             setDrawerError(message);
             notify(message, { type: "error" });
         }
@@ -233,13 +246,13 @@
         }
         try {
             await clearAiSessionMemory(sessionId);
-            notify("浼氳瘽璁板繂宸叉竻绌�");
+            notify(translate("ai.drawer.memoryCleared"));
             await Promise.all([
                 loadRuntime(sessionId),
                 loadSessions(sessionKeyword),
             ]);
         } catch (error) {
-            const message = error.message || "娓呯┖浼氳瘽璁板繂澶辫触";
+            const message = error.message || translate("ai.drawer.clearMemoryFailed");
             setDrawerError(message);
             notify(message, { type: "error" });
         }
@@ -251,13 +264,13 @@
         }
         try {
             await retainAiSessionLatestRound(sessionId);
-            notify("宸蹭粎淇濈暀褰撳墠杞蹇�");
+            notify(translate("ai.drawer.retainLatestRoundSuccess"));
             await Promise.all([
                 loadRuntime(sessionId),
                 loadSessions(sessionKeyword),
             ]);
         } catch (error) {
-            const message = error.message || "淇濈暀褰撳墠杞蹇嗗け璐�";
+            const message = error.message || translate("ai.drawer.retainLatestRoundFailed");
             setDrawerError(message);
             notify(message, { type: "error" });
         }
@@ -269,8 +282,18 @@
             abortRef.current = null;
             setStreaming(false);
             if (showTip) {
-                notify("宸插仠姝㈠綋鍓嶅璇濊緭鍑�");
+                notify(translate("ai.drawer.stopSuccess"));
             }
+        }
+    };
+
+    const scrollMessagesToBottom = () => {
+        if (messagesBottomRef.current) {
+            messagesBottomRef.current.scrollIntoView({ block: "end" });
+            return;
+        }
+        if (messagesContainerRef.current) {
+            messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight;
         }
     };
 
@@ -380,7 +403,7 @@
                             }
                         }
                         if (eventName === "error") {
-                            const message = payload?.message || "AI 瀵硅瘽澶辫触";
+                            const message = payload?.message || translate("ai.drawer.chatFailed");
                             const displayMessage = payload?.requestId ? `${message} [${payload.requestId}]` : message;
                             setDrawerError(displayMessage);
                             notify(displayMessage, { type: "error" });
@@ -390,7 +413,7 @@
             );
         } catch (error) {
             if (error?.name !== "AbortError") {
-                const message = error.message || "AI 瀵硅瘽澶辫触";
+                const message = error.message || translate("ai.drawer.chatFailed");
                 setDrawerError(message);
                 notify(message, { type: "error" });
             }
@@ -432,12 +455,12 @@
                 <Stack direction="row" alignItems="center" spacing={1} px={2} py={1.5}>
                     <SmartToyOutlinedIcon color="primary" />
                     <Typography variant="h6" flex={1}>
-                        AI 瀵硅瘽
+                        {translate("ai.drawer.title")}
                     </Typography>
-                    <IconButton size="small" onClick={startNewSession} title="鏂板缓浼氳瘽" disabled={streaming}>
+                    <IconButton size="small" onClick={startNewSession} title={translate("ai.drawer.newSession")} disabled={streaming}>
                         <AddCommentOutlinedIcon fontSize="small" />
                     </IconButton>
-                    <IconButton size="small" onClick={onClose} title="鍏抽棴">
+                    <IconButton size="small" onClick={onClose} title={translate("ai.common.close")}>
                         <CloseIcon fontSize="small" />
                     </IconButton>
                 </Stack>
@@ -454,9 +477,9 @@
                     >
                         <Box px={2} py={1.5}>
                             <Stack direction="row" alignItems="center" justifyContent="space-between" mb={1}>
-                                <Typography variant="subtitle2">浼氳瘽鍒楄〃</Typography>
+                                <Typography variant="subtitle2">{translate("ai.drawer.sessionList")}</Typography>
                                 <Button size="small" onClick={startNewSession} disabled={streaming}>
-                                    鏂板缓浼氳瘽
+                                    {translate("ai.drawer.newSession")}
                                 </Button>
                             </Stack>
                             <TextField
@@ -464,7 +487,7 @@
                                 onChange={(event) => setSessionKeyword(event.target.value)}
                                 fullWidth
                                 size="small"
-                                placeholder="鎼滅储浼氳瘽鏍囬"
+                                placeholder={translate("ai.drawer.searchPlaceholder")}
                                 InputProps={{
                                     startAdornment: <SearchOutlinedIcon fontSize="small" sx={{ mr: 1, color: "text.secondary" }} />,
                                 }}
@@ -474,7 +497,7 @@
                                 {!sessions.length ? (
                                     <Box px={1.5} py={1.25}>
                                         <Typography variant="body2" color="text.secondary">
-                                            鏆傛棤鍘嗗彶浼氳瘽
+                                            {translate("ai.drawer.noSessions")}
                                         </Typography>
                                     </Box>
                                 ) : (
@@ -488,8 +511,8 @@
                                                 alignItems="flex-start"
                                             >
                                                 <ListItemText
-                                                    primary={item.title || `浼氳瘽 ${item.sessionId}`}
-                                                    secondary={item.lastMessagePreview || item.lastMessageTime || `Session ${item.sessionId}`}
+                                                    primary={item.title || translate("ai.drawer.sessionTitle", { id: item.sessionId })}
+                                                    secondary={item.lastMessagePreview || item.lastMessageTime || translate("ai.drawer.sessionMetric", { id: item.sessionId })}
                                                     primaryTypographyProps={{
                                                         noWrap: true,
                                                         fontSize: 14,
@@ -508,7 +531,7 @@
                                                         event.stopPropagation();
                                                         handlePinSession(item.sessionId, !item.pinned);
                                                     }}
-                                                    title={item.pinned ? "鍙栨秷缃《" : "缃《浼氳瘽"}
+                                                    title={translate(item.pinned ? "ai.drawer.unpinAction" : "ai.drawer.pinAction")}
                                                 >
                                                     {item.pinned ? <PushPinIcon fontSize="small" /> : <PushPinOutlinedIcon fontSize="small" />}
                                                 </IconButton>
@@ -520,7 +543,7 @@
                                                         event.stopPropagation();
                                                         openRenameDialog(item);
                                                     }}
-                                                    title="閲嶅懡鍚嶄細璇�"
+                                                    title={translate("ai.drawer.renameAction")}
                                                 >
                                                     <EditOutlinedIcon fontSize="small" />
                                                 </IconButton>
@@ -532,7 +555,7 @@
                                                         event.stopPropagation();
                                                         handleDeleteSession(item.sessionId);
                                                     }}
-                                                    title="鍒犻櫎浼氳瘽"
+                                                    title={translate("ai.drawer.deleteAction")}
                                                 >
                                                     <DeleteOutlineOutlinedIcon fontSize="small" />
                                                 </IconButton>
@@ -554,13 +577,13 @@
                     >
                         <Box px={2} py={1.5} display="flex" flexDirection="column" minHeight={0}>
                             <Typography variant="subtitle2" mb={1}>
-                                宸ュ叿璋冪敤杞ㄨ抗
+                                {translate("ai.drawer.toolTrace")}
                             </Typography>
                             <Paper variant="outlined" sx={{ flex: 1, minHeight: { xs: 140, md: 0 }, overflow: "hidden", bgcolor: "grey.50" }}>
                                 {!toolEvents.length ? (
                                     <Box px={1.5} py={1.25}>
                                         <Typography variant="body2" color="text.secondary">
-                                            褰撳墠杞湭瑙﹀彂宸ュ叿璋冪敤
+                                            {translate("ai.drawer.noToolTrace")}
                                         </Typography>
                                     </Box>
                                 ) : (
@@ -577,12 +600,12 @@
                                             >
                                                 <Stack direction="row" spacing={1} alignItems="center" flexWrap="wrap" useFlexGap>
                                                     <Typography variant="body2" fontWeight={700}>
-                                                        {item.toolName || "鏈煡宸ュ叿"}
+                                                        {item.toolName || translate("ai.drawer.unknownTool")}
                                                     </Typography>
                                                     <Chip
                                                         size="small"
                                                         color={item.status === "FAILED" ? "error" : item.status === "COMPLETED" ? "success" : "info"}
-                                                        label={item.status === "FAILED" ? "澶辫触" : item.status === "COMPLETED" ? "瀹屾垚" : "鎵ц涓�"}
+                                                        label={translate(item.status === "FAILED" ? "ai.drawer.toolStatusFailed" : item.status === "COMPLETED" ? "ai.drawer.toolStatusCompleted" : "ai.drawer.toolStatusRunning")}
                                                     />
                                                     {item.durationMs != null && (
                                                         <Typography variant="caption" color="text.secondary">
@@ -598,24 +621,24 @@
                                                                 : <ExpandMoreOutlinedIcon fontSize="small" />}
                                                             sx={{ ml: "auto", minWidth: "auto", px: 0.5 }}
                                                         >
-                                                            {expandedToolIds.includes(item.toolCallId) ? "鏀惰捣璇︽儏" : "鏌ョ湅璇︽儏"}
+                                                            {expandedToolIds.includes(item.toolCallId) ? translate("ai.drawer.collapseDetail") : translate("ai.drawer.viewDetail")}
                                                         </Button>
                                                     )}
                                                 </Stack>
                                                 <Collapse in={expandedToolIds.includes(item.toolCallId)} timeout="auto" unmountOnExit>
                                                     {!!item.inputSummary && (
                                                         <Typography variant="caption" display="block" sx={{ mt: 0.75, whiteSpace: "pre-wrap" }}>
-                                                            鍏ュ弬: {item.inputSummary}
+                                                            {translate("ai.drawer.toolInput", { value: item.inputSummary })}
                                                         </Typography>
                                                     )}
                                                     {!!item.outputSummary && (
                                                         <Typography variant="caption" display="block" sx={{ mt: 0.75, whiteSpace: "pre-wrap" }}>
-                                                            缁撴灉鎽樿: {item.outputSummary}
+                                                            {translate("ai.drawer.toolOutput", { value: item.outputSummary })}
                                                         </Typography>
                                                     )}
                                                     {!!item.errorMessage && (
                                                         <Typography variant="caption" color="error.main" display="block" sx={{ mt: 0.75, whiteSpace: "pre-wrap" }}>
-                                                            閿欒: {item.errorMessage}
+                                                            {translate("ai.drawer.toolError", { value: item.errorMessage })}
                                                         </Typography>
                                                     )}
                                                 </Collapse>
@@ -630,15 +653,15 @@
                     <Box flex={1} display="flex" flexDirection="column" minHeight={0}>
                         <Box px={2} py={1.5}>
                             <Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap>
-                                <Chip size="small" label={`Req: ${runtimeSummary.requestId}`} />
-                                <Chip size="small" label={`Session: ${sessionId || "--"}`} />
-                                <Chip size="small" label={`Prompt: ${runtimeSummary.promptName}`} />
-                                <Chip size="small" label={`Model: ${runtimeSummary.model}`} />
-                                <Chip size="small" label={`MCP: ${runtimeSummary.mountedMcpCount}`} />
-                                <Chip size="small" label={`History: ${persistedMessages.length}`} />
-                                <Chip size="small" label={`Recent: ${runtimeSummary.recentMessageCount}`} />
-                                <Chip size="small" color={runtimeSummary.hasSummary ? "success" : "default"} label={runtimeSummary.hasSummary ? "鏈夋憳瑕�" : "鏃犳憳瑕�"} />
-                                <Chip size="small" color={runtimeSummary.hasFacts ? "info" : "default"} label={runtimeSummary.hasFacts ? "鏈変簨瀹�" : "鏃犱簨瀹�"} />
+                                <Chip size="small" label={translate("ai.drawer.requestMetric", { value: runtimeSummary.requestId })} />
+                                <Chip size="small" label={translate("ai.drawer.sessionMetric", { id: sessionId || "--" })} />
+                                <Chip size="small" label={translate("ai.drawer.promptMetric", { value: runtimeSummary.promptName })} />
+                                <Chip size="small" label={translate("ai.drawer.modelMetric", { value: runtimeSummary.model })} />
+                                <Chip size="small" label={translate("ai.drawer.mcpMetric", { value: runtimeSummary.mountedMcpCount })} />
+                                <Chip size="small" label={translate("ai.drawer.historyMetric", { value: persistedMessages.length })} />
+                                <Chip size="small" label={translate("ai.drawer.recentMetric", { value: runtimeSummary.recentMessageCount })} />
+                                <Chip size="small" color={runtimeSummary.hasSummary ? "success" : "default"} label={translate(runtimeSummary.hasSummary ? "ai.drawer.hasSummary" : "ai.drawer.noSummary")} />
+                                <Chip size="small" color={runtimeSummary.hasFacts ? "info" : "default"} label={translate(runtimeSummary.hasFacts ? "ai.drawer.hasFacts" : "ai.drawer.noFacts")} />
                             </Stack>
                             <Stack direction="row" spacing={1} mt={1.5} flexWrap="wrap" useFlexGap>
                                 {quickLinks.map((item) => (
@@ -659,7 +682,7 @@
                                     onClick={handleRetainLatestRound}
                                     disabled={!sessionId || streaming}
                                 >
-                                    浠呬繚鐣欏綋鍓嶈疆
+                                    {translate("ai.drawer.retainLatestRound")}
                                 </Button>
                                 <Button
                                     size="small"
@@ -669,7 +692,7 @@
                                     onClick={handleClearMemory}
                                     disabled={!sessionId || streaming}
                                 >
-                                    娓呯┖璁板繂
+                                    {translate("ai.drawer.clearMemory")}
                                 </Button>
                             </Stack>
                             {!!runtime?.memorySummary && (
@@ -688,7 +711,7 @@
                             )}
                             {loadingRuntime && (
                                 <Typography variant="body2" color="text.secondary" mt={1}>
-                                    姝e湪鍔犺浇 AI 杩愯鏃朵俊鎭�...
+                                    {translate("ai.drawer.loadingRuntime")}
                                 </Typography>
                             )}
                             {!!drawerError && (
@@ -700,11 +723,20 @@
 
                         <Divider />
 
-                        <Box flex={1} overflow="auto" px={2} py={2} display="flex" flexDirection="column" gap={1.5}>
+                        <Box
+                            ref={messagesContainerRef}
+                            flex={1}
+                            overflow="auto"
+                            px={2}
+                            py={2}
+                            display="flex"
+                            flexDirection="column"
+                            gap={1.5}
+                        >
                             {!messages.length && (
                                 <Paper variant="outlined" sx={{ p: 2, bgcolor: "grey.50" }}>
                                     <Typography variant="body2" color="text.secondary">
-                                        杩欓噷浼氶�氳繃 SSE 娴佸紡杩斿洖 AI 鍥炲銆備綘涔熷彲浠ュ厛鍘讳笂闈㈢殑蹇嵎鍏ュ彛缁存姢鍙傛暟銆丳rompt 鍜� MCP 鎸傝浇銆�
+                                        {translate("ai.drawer.emptyHint")}
                                     </Typography>
                                 </Paper>
                             )}
@@ -728,14 +760,15 @@
                                         }}
                                     >
                                         <Typography variant="caption" display="block" sx={{ opacity: 0.72, mb: 0.5 }}>
-                                            {message.role === "user" ? "浣�" : "AI"}
+                                            {message.role === "user" ? translate("ai.drawer.userRole") : translate("ai.drawer.assistantRole")}
                                         </Typography>
                                         <Typography variant="body2">
-                                            {message.content || (streaming && index === messages.length - 1 ? "鎬濊�冧腑..." : "")}
+                                            {message.content || (streaming && index === messages.length - 1 ? translate("ai.drawer.thinking") : "")}
                                         </Typography>
                                     </Paper>
                                 </Box>
                             ))}
+                            <Box ref={messagesBottomRef} sx={{ height: 1 }} />
                         </Box>
 
                         <Divider />
@@ -743,12 +776,17 @@
                         <Box px={2} py={1.5}>
                             {usage?.elapsedMs != null && (
                                 <Typography variant="caption" color="text.secondary" display="block" mb={0.5}>
-                                    Elapsed: {usage.elapsedMs} ms{usage?.firstTokenLatencyMs != null ? ` / First token: ${usage.firstTokenLatencyMs} ms` : ""}
+                                    {translate("ai.drawer.elapsedMetric", { value: usage.elapsedMs })}
+                                    {usage?.firstTokenLatencyMs != null ? ` / ${translate("ai.drawer.firstTokenMetric", { value: usage.firstTokenLatencyMs })}` : ""}
                                 </Typography>
                             )}
                             {usage?.totalTokens != null && (
                                 <Typography variant="caption" color="text.secondary" display="block" mb={1}>
-                                    Tokens: prompt {usage?.promptTokens ?? 0} / completion {usage?.completionTokens ?? 0} / total {usage?.totalTokens ?? 0}
+                                    {translate("ai.drawer.tokenMetric", {
+                                        prompt: usage?.promptTokens ?? 0,
+                                        completion: usage?.completionTokens ?? 0,
+                                        total: usage?.totalTokens ?? 0,
+                                    })}
                                 </Typography>
                             )}
                             <TextField
@@ -759,17 +797,17 @@
                                 multiline
                                 minRows={3}
                                 maxRows={6}
-                                placeholder="杈撳叆浣犵殑闂锛屾寜 Enter 鍙戦�侊紝Shift + Enter 鎹㈣"
+                                placeholder={translate("ai.drawer.inputPlaceholder")}
                             />
                             <Stack direction="row" spacing={1} justifyContent="flex-end" mt={1.25}>
-                                <Button onClick={() => setInput("")}>娓呯┖杈撳叆</Button>
+                                <Button onClick={() => setInput("")}>{translate("ai.drawer.clearInput")}</Button>
                                 {streaming ? (
                                     <Button variant="outlined" color="warning" startIcon={<StopCircleOutlinedIcon />} onClick={() => stopStream(true)}>
-                                        鍋滄
+                                        {translate("ai.drawer.stop")}
                                     </Button>
                                 ) : (
                                     <Button variant="contained" startIcon={<SendRoundedIcon />} onClick={handleSend}>
-                                        鍙戦��
+                                        {translate("ai.drawer.send")}
                                     </Button>
                                 )}
                             </Stack>
@@ -778,21 +816,21 @@
                 </Box>
             </Box>
             <Dialog open={renameDialog.open} onClose={closeRenameDialog} fullWidth maxWidth="xs">
-                <DialogTitle>閲嶅懡鍚嶄細璇�</DialogTitle>
+                <DialogTitle>{translate("ai.drawer.renameDialogTitle")}</DialogTitle>
                 <DialogContent>
                     <TextField
                         value={renameDialog.title}
                         onChange={(event) => setRenameDialog((prev) => ({ ...prev, title: event.target.value }))}
                         autoFocus
                         margin="dense"
-                        label="浼氳瘽鏍囬"
+                        label={translate("ai.drawer.sessionTitleField")}
                         fullWidth
                     />
                 </DialogContent>
                 <DialogActions>
-                    <Button onClick={closeRenameDialog}>鍙栨秷</Button>
+                    <Button onClick={closeRenameDialog}>{translate("ai.common.cancel")}</Button>
                     <Button onClick={handleRenameSubmit} variant="contained" disabled={streaming || !renameDialog.title.trim()}>
-                        淇濆瓨
+                        {translate("ai.common.save")}
                     </Button>
                 </DialogActions>
             </Dialog>
diff --git a/rsf-admin/src/page/system/aiCallLog/AiCallLogList.jsx b/rsf-admin/src/page/system/aiCallLog/AiCallLogList.jsx
index abb70b1..d3f73e5 100644
--- a/rsf-admin/src/page/system/aiCallLog/AiCallLogList.jsx
+++ b/rsf-admin/src/page/system/aiCallLog/AiCallLogList.jsx
@@ -8,6 +8,7 @@
     TopToolbar,
     useListContext,
     useNotify,
+    useTranslate,
 } from "react-admin";
 import {
     Alert,
@@ -32,12 +33,12 @@
 
 const filters = [
     <SearchInput source="condition" alwaysOn />,
-    <TextInput source="requestId" label="璇锋眰ID" />,
-    <TextInput source="promptCode" label="Prompt 缂栫爜" />,
-    <TextInput source="userId" label="鐢ㄦ埛ID" />,
+    <TextInput source="requestId" label="ai.observe.fields.requestId" />,
+    <TextInput source="promptCode" label="ai.observe.fields.promptCode" />,
+    <TextInput source="userId" label="ai.observe.fields.userId" />,
     <SelectInput
         source="status"
-        label="鐘舵��"
+        label="common.field.status"
         choices={[
             { id: "RUNNING", name: "RUNNING" },
             { id: "COMPLETED", name: "COMPLETED" },
@@ -48,6 +49,7 @@
 ];
 
 const ObserveSummary = () => {
+    const translate = useTranslate();
     const [stats, setStats] = useState(null);
     const [loading, setLoading] = useState(true);
     const [error, setError] = useState("");
@@ -64,7 +66,7 @@
             })
             .catch((err) => {
                 if (active) {
-                    setError(err?.message || "鑾峰彇 AI 瑙傛祴缁熻澶辫触");
+                    setError(err?.message || translate("ai.observe.summary.fetchFailed"));
                 }
             })
             .finally(() => {
@@ -83,9 +85,9 @@
                 <CardContent>
                     <Stack direction="row" justifyContent="space-between" alignItems="center" mb={2}>
                         <Box>
-                            <Typography variant="h6">瑙傛祴鎬昏</Typography>
+                            <Typography variant="h6">{translate("ai.observe.summary.title")}</Typography>
                             <Typography variant="body2" color="text.secondary">
-                                褰撳墠绉熸埛涓嬬殑 AI 瀵硅瘽璋冪敤涓� MCP 宸ュ叿璋冪敤缁熻銆�
+                                {translate("ai.observe.summary.description")}
                             </Typography>
                         </Box>
                         {loading && <CircularProgress size={24} />}
@@ -94,31 +96,31 @@
                     {!loading && !error && stats && (
                         <Grid container spacing={2}>
                             <Grid item xs={12} md={3}>
-                                <Typography variant="caption" color="text.secondary">AI 璋冪敤閲�</Typography>
+                                <Typography variant="caption" color="text.secondary">{translate("ai.observe.summary.callCount")}</Typography>
                                 <Typography variant="h5">{stats.callCount ?? 0}</Typography>
                                 <Typography variant="body2" color="text.secondary">
-                                    鎴愬姛 {stats.successCount ?? 0} / 澶辫触 {stats.failureCount ?? 0}
+                                    {translate("ai.observe.summary.successFailure", { success: stats.successCount ?? 0, failure: stats.failureCount ?? 0 })}
                                 </Typography>
                             </Grid>
                             <Grid item xs={12} md={3}>
-                                <Typography variant="caption" color="text.secondary">骞冲潎鑰楁椂</Typography>
+                                <Typography variant="caption" color="text.secondary">{translate("ai.observe.summary.avgElapsed")}</Typography>
                                 <Typography variant="h5">{stats.avgElapsedMs ?? 0} ms</Typography>
                                 <Typography variant="body2" color="text.secondary">
-                                    棣栧寘 {stats.avgFirstTokenLatencyMs ?? 0} ms
+                                    {translate("ai.observe.summary.firstToken", { value: stats.avgFirstTokenLatencyMs ?? 0 })}
                                 </Typography>
                             </Grid>
                             <Grid item xs={12} md={3}>
-                                <Typography variant="caption" color="text.secondary">Token 浣跨敤</Typography>
+                                <Typography variant="caption" color="text.secondary">{translate("ai.observe.summary.tokenUsage")}</Typography>
                                 <Typography variant="h5">{stats.totalTokens ?? 0}</Typography>
                                 <Typography variant="body2" color="text.secondary">
-                                    骞冲潎 {stats.avgTotalTokens ?? 0}
+                                    {translate("ai.observe.summary.avgToken", { value: stats.avgTotalTokens ?? 0 })}
                                 </Typography>
                             </Grid>
                             <Grid item xs={12} md={3}>
-                                <Typography variant="caption" color="text.secondary">宸ュ叿鎴愬姛鐜�</Typography>
+                                <Typography variant="caption" color="text.secondary">{translate("ai.observe.summary.toolSuccessRate")}</Typography>
                                 <Typography variant="h5">{Number(stats.toolSuccessRate || 0).toFixed(2)}%</Typography>
                                 <Typography variant="body2" color="text.secondary">
-                                    璋冪敤 {stats.toolCallCount ?? 0} / 澶辫触 {stats.toolFailureCount ?? 0}
+                                    {translate("ai.observe.summary.toolCallFailure", { call: stats.toolCallCount ?? 0, failure: stats.toolFailureCount ?? 0 })}
                                 </Typography>
                             </Grid>
                         </Grid>
@@ -129,21 +131,22 @@
     );
 };
 
-const resolveStatusChip = (status) => {
+const resolveStatusChip = (status, translate) => {
     if (status === "COMPLETED") {
-        return { color: "success", label: "鎴愬姛" };
+        return { color: "success", label: translate("ai.observe.status.completed") };
     }
     if (status === "FAILED") {
-        return { color: "error", label: "澶辫触" };
+        return { color: "error", label: translate("ai.observe.status.failed") };
     }
     if (status === "ABORTED") {
-        return { color: "warning", label: "涓柇" };
+        return { color: "warning", label: translate("ai.observe.status.aborted") };
     }
     return { color: "default", label: status || "--" };
 };
 
 const AiCallLogDetailDialog = ({ record, open, onClose }) => {
     const notify = useNotify();
+    const translate = useTranslate();
     const [logs, setLogs] = useState([]);
     const [loading, setLoading] = useState(false);
 
@@ -161,7 +164,7 @@
             })
             .catch((error) => {
                 if (active) {
-                    notify(error?.message || "鑾峰彇 MCP 璋冪敤鏃ュ織澶辫触", { type: "error" });
+                    notify(error?.message || translate("ai.observe.detail.mcpLogsFailed"), { type: "error" });
                 }
             })
             .finally(() => {
@@ -180,35 +183,35 @@
 
     return (
         <Dialog open={open} onClose={onClose} fullWidth maxWidth="lg">
-            <DialogTitle>AI 璋冪敤璇︽儏</DialogTitle>
+            <DialogTitle>{translate("ai.observe.detail.title")}</DialogTitle>
             <DialogContent dividers>
                 <Grid container spacing={2}>
                     <Grid item xs={12} md={6}>
-                        <Typography variant="caption" color="text.secondary">璇锋眰ID</Typography>
+                        <Typography variant="caption" color="text.secondary">{translate("ai.observe.fields.requestId")}</Typography>
                         <Typography variant="body2">{record.requestId || "--"}</Typography>
                     </Grid>
                     <Grid item xs={12} md={3}>
-                        <Typography variant="caption" color="text.secondary">鐢ㄦ埛ID</Typography>
+                        <Typography variant="caption" color="text.secondary">{translate("ai.observe.fields.userId")}</Typography>
                         <Typography variant="body2">{record.userId || "--"}</Typography>
                     </Grid>
                     <Grid item xs={12} md={3}>
-                        <Typography variant="caption" color="text.secondary">浼氳瘽ID</Typography>
+                        <Typography variant="caption" color="text.secondary">{translate("ai.observe.fields.sessionId")}</Typography>
                         <Typography variant="body2">{record.sessionId || "--"}</Typography>
                     </Grid>
                     <Grid item xs={12} md={4}>
-                        <Typography variant="caption" color="text.secondary">Prompt</Typography>
+                        <Typography variant="caption" color="text.secondary">{translate("ai.common.prompt")}</Typography>
                         <Typography variant="body2">{record.promptName || "--"} / {record.promptCode || "--"}</Typography>
                     </Grid>
                     <Grid item xs={12} md={4}>
-                        <Typography variant="caption" color="text.secondary">妯″瀷</Typography>
+                        <Typography variant="caption" color="text.secondary">{translate("ai.common.model")}</Typography>
                         <Typography variant="body2">{record.model || "--"}</Typography>
                     </Grid>
                     <Grid item xs={12} md={4}>
-                        <Typography variant="caption" color="text.secondary">鐘舵��</Typography>
+                        <Typography variant="caption" color="text.secondary">{translate("common.field.status")}</Typography>
                         <Typography variant="body2">{record.status || "--"}</Typography>
                     </Grid>
                     <Grid item xs={12}>
-                        <Typography variant="caption" color="text.secondary">MCP 鎸傝浇</Typography>
+                        <Typography variant="caption" color="text.secondary">{translate("ai.observe.fields.mountedMcp")}</Typography>
                         <Typography variant="body2">{record.mountedMcpNames || "--"}</Typography>
                     </Grid>
                     {record.errorMessage && (
@@ -219,12 +222,12 @@
                     <Grid item xs={12}>
                         <Divider sx={{ my: 1 }} />
                         <Stack direction="row" justifyContent="space-between" alignItems="center" mb={1}>
-                            <Typography variant="h6">MCP 宸ュ叿璋冪敤鏃ュ織</Typography>
+                            <Typography variant="h6">{translate("ai.observe.detail.mcpLogs")}</Typography>
                             {loading && <CircularProgress size={20} />}
                         </Stack>
                         {!loading && !logs.length && (
                             <Typography variant="body2" color="text.secondary">
-                                褰撳墠璋冪敤娌℃湁浜х敓 MCP 宸ュ叿鏃ュ織銆�
+                                {translate("ai.observe.detail.noMcpLogs")}
                             </Typography>
                         )}
                         <Stack spacing={1.5}>
@@ -244,13 +247,11 @@
                                                 label={item.status || "--"}
                                             />
                                         </Stack>
-                                        <Typography variant="caption" color="text.secondary">杈撳叆鎽樿</Typography>
+                                        <Typography variant="caption" color="text.secondary">{translate("ai.observe.detail.inputSummary")}</Typography>
                                         <Typography variant="body2" sx={{ whiteSpace: "pre-wrap", wordBreak: "break-word" }}>
                                             {item.inputSummary || "--"}
                                         </Typography>
-                                        <Typography variant="caption" color="text.secondary" display="block" mt={1}>
-                                            杈撳嚭鎽樿 / 閿欒
-                                        </Typography>
+                                        <Typography variant="caption" color="text.secondary" display="block" mt={1}>{translate("ai.observe.detail.outputSummary")}</Typography>
                                         <Typography variant="body2" sx={{ whiteSpace: "pre-wrap", wordBreak: "break-word" }}>
                                             {item.outputSummary || item.errorMessage || "--"}
                                         </Typography>
@@ -262,13 +263,14 @@
                 </Grid>
             </DialogContent>
             <DialogActions>
-                <Button onClick={onClose}>鍏抽棴</Button>
+                <Button onClick={onClose}>{translate("ai.common.close")}</Button>
             </DialogActions>
         </Dialog>
     );
 };
 
 const AiCallLogCards = ({ onView }) => {
+    const translate = useTranslate();
     const { data, isLoading } = useListContext();
     const records = useMemo(() => (Array.isArray(data) ? data : []), [data]);
 
@@ -284,9 +286,9 @@
         return (
             <Box px={2} py={6}>
                 <Card variant="outlined" sx={{ p: 3, textAlign: "center", borderStyle: "dashed" }}>
-                    <Typography variant="subtitle1">鏆傛棤 AI 璋冪敤鏃ュ織</Typography>
+                    <Typography variant="subtitle1">{translate("ai.observe.list.emptyTitle")}</Typography>
                     <Typography variant="body2" color="text.secondary" mt={1}>
-                        鍙戣捣 AI 瀵硅瘽鍚庯紝杩欓噷浼氬睍绀鸿皟鐢ㄧ粺璁″拰瀹¤璁板綍銆�
+                        {translate("ai.observe.list.emptyDescription")}
                     </Typography>
                 </Card>
             </Box>
@@ -297,14 +299,14 @@
         <Box px={2} py={2}>
             <Grid container spacing={2}>
                 {records.map((record) => {
-                    const statusMeta = resolveStatusChip(record.status);
+                    const statusMeta = resolveStatusChip(record.status, translate);
                     return (
                         <Grid item xs={12} md={6} xl={4} key={record.id}>
                             <Card variant="outlined" sx={{ height: "100%", borderRadius: 3, boxShadow: "0 8px 24px rgba(15, 23, 42, 0.06)" }}>
                                 <CardContent sx={{ pb: 1.5 }}>
                                     <Stack direction="row" justifyContent="space-between" alignItems="flex-start" spacing={1}>
                                         <Box>
-                                            <Typography variant="h6">{record.promptName || "AI 瀵硅瘽"}</Typography>
+                                            <Typography variant="h6">{record.promptName || translate("ai.drawer.title")}</Typography>
                                             <Typography variant="body2" color="text.secondary">
                                                 {record.promptCode || "--"} / {record.model || "--"}
                                             </Typography>
@@ -312,31 +314,31 @@
                                         <Chip size="small" color={statusMeta.color} label={statusMeta.label} />
                                     </Stack>
                                     <Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap mt={1.5}>
-                                        <Chip size="small" variant="outlined" label={`鐢ㄦ埛 ${record.userId || "--"}`} />
-                                        <Chip size="small" variant="outlined" label={`鑰楁椂 ${record.elapsedMs ?? 0} ms`} />
-                                        <Chip size="small" variant="outlined" label={`Token ${record.totalTokens ?? 0}`} />
+                                        <Chip size="small" variant="outlined" label={translate("ai.observe.list.userValue", { value: record.userId || "--" })} />
+                                        <Chip size="small" variant="outlined" label={translate("ai.observe.list.elapsedValue", { value: record.elapsedMs ?? 0 })} />
+                                        <Chip size="small" variant="outlined" label={translate("ai.observe.list.tokenValue", { value: record.totalTokens ?? 0 })} />
                                     </Stack>
                                     <Divider sx={{ my: 1.5 }} />
-                                    <Typography variant="caption" color="text.secondary">璇锋眰ID</Typography>
+                                    <Typography variant="caption" color="text.secondary">{translate("ai.observe.fields.requestId")}</Typography>
                                     <Typography variant="body2" sx={{ wordBreak: "break-all" }}>{record.requestId || "--"}</Typography>
-                                    <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>
-                                        MCP / 宸ュ叿璋冪敤
-                                    </Typography>
+                                    <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>{translate("ai.observe.list.mcpToolCalls")}</Typography>
                                     <Typography variant="body2">
-                                        鎸傝浇 {record.mountedMcpCount ?? 0} 涓紝宸ュ叿鎴愬姛 {record.toolSuccessCount ?? 0}锛屽け璐� {record.toolFailureCount ?? 0}
+                                        {translate("ai.observe.list.mcpToolSummary", {
+                                            mcp: record.mountedMcpCount ?? 0,
+                                            success: record.toolSuccessCount ?? 0,
+                                            failure: record.toolFailureCount ?? 0,
+                                        })}
                                     </Typography>
                                     {record.errorMessage && (
                                         <>
-                                            <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>
-                                                閿欒
-                                            </Typography>
+                                            <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>{translate("ai.common.error")}</Typography>
                                             <Typography variant="body2">{record.errorMessage}</Typography>
                                         </>
                                     )}
                                 </CardContent>
                                 <CardActions sx={{ px: 2, pb: 2, pt: 0 }}>
                                     <Button size="small" startIcon={<VisibilityOutlinedIcon />} onClick={() => onView(record)}>
-                                        璇︽儏
+                                        {translate("ai.common.detail")}
                                     </Button>
                                 </CardActions>
                             </Card>
diff --git a/rsf-admin/src/page/system/aiMcpMount/AiMcpMountForm.jsx b/rsf-admin/src/page/system/aiMcpMount/AiMcpMountForm.jsx
index 7e1deee..b11f4d1 100644
--- a/rsf-admin/src/page/system/aiMcpMount/AiMcpMountForm.jsx
+++ b/rsf-admin/src/page/system/aiMcpMount/AiMcpMountForm.jsx
@@ -5,6 +5,7 @@
     SelectInput,
     TextInput,
     useNotify,
+    useTranslate,
 } from "react-admin";
 import { Alert, Button, Grid, Stack, Typography } from "@mui/material";
 import StatusSelectInput from "@/page/components/StatusSelectInput";
@@ -18,6 +19,7 @@
 
 const AiMcpDraftTestSection = ({ formData, readOnly }) => {
     const notify = useNotify();
+    const translate = useTranslate();
     const [loading, setLoading] = useState(false);
     const [result, setResult] = useState(null);
 
@@ -26,11 +28,11 @@
         try {
             const data = await validateDraftMcpConnectivity(formData);
             setResult(data);
-            notify(data?.message || "鑽夌杩為�氭�ф祴璇曞畬鎴�");
+            notify(data?.message || translate("ai.mcp.connectivity.success"));
         } catch (error) {
             const nextResult = {
                 healthStatus: "UNHEALTHY",
-                message: error?.message || "鑽夌杩為�氭�ф祴璇曞け璐�",
+                message: error?.message || translate("ai.mcp.connectivity.failed"),
             };
             setResult(nextResult);
             notify(nextResult.message, { type: "error" });
@@ -48,10 +50,10 @@
             <Grid item xs={12}>
                 <Stack direction="row" spacing={1} alignItems="center">
                     <Button variant="outlined" onClick={handleValidate} disabled={loading}>
-                        {loading ? "娴嬭瘯涓�..." : "淇濆瓨鍓嶆祴璇�"}
+                        {loading ? translate("ai.common.testing") : translate("ai.mcp.form.testBeforeSave")}
                     </Button>
                     <Typography variant="body2" color="text.secondary">
-                        鐢ㄥ綋鍓嶈崏绋块厤缃洿鎺ユ牎楠岃繛閫氭�э紝涓嶄細钀藉簱銆�
+                        {translate("ai.mcp.form.testDescription")}
                     </Typography>
                 </Stack>
             </Grid>
@@ -68,16 +70,19 @@
     );
 };
 
-const AiMcpMountForm = ({ readOnly = false }) => (
+const AiMcpMountForm = ({ readOnly = false }) => {
+    const translate = useTranslate();
+
+    return (
     <Grid container spacing={2} width={{ xs: "100%", xl: "80%" }}>
         <Grid item xs={12}>
-            <Typography variant="h6">MCP 鎸傝浇閰嶇疆</Typography>
+            <Typography variant="h6">{translate("ai.mcp.form.sections.main")}</Typography>
         </Grid>
         <Grid item xs={12} md={6}>
-            <TextInput source="name" label="鍚嶇О" fullWidth disabled={readOnly} />
+            <TextInput source="name" label="common.field.name" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={6}>
-            <SelectInput source="transportType" label="浼犺緭绫诲瀷" choices={transportChoices} fullWidth disabled={readOnly} />
+            <SelectInput source="transportType" label="ai.mcp.fields.transportType" choices={transportChoices} fullWidth disabled={readOnly} />
         </Grid>
         <FormDataConsumer>
             {({ formData }) => (
@@ -87,7 +92,7 @@
                             <Grid item xs={12}>
                                 <SelectInput
                                     source="builtinCode"
-                                    label="鍐呯疆 MCP"
+                                    label="ai.mcp.fields.builtinCode"
                                     choices={[
                                         { id: "RSF_WMS", name: "RSF_WMS" },
                                         { id: "RSF_WMS_STOCK", name: "RSF_WMS_STOCK" },
@@ -103,7 +108,7 @@
                     {formData.transportType === "SSE_HTTP" && (
                         <>
                             <Grid item xs={12}>
-                                <TextInput source="serverUrl" label="鏈嶅姟鍦板潃" fullWidth disabled={readOnly} />
+                                <TextInput source="serverUrl" label="ai.mcp.fields.serverUrl" fullWidth disabled={readOnly} />
                             </Grid>
                             <Grid item xs={12}>
                                 <TextInput source="endpoint" label="SSE Endpoint" fullWidth disabled={readOnly} />
@@ -116,7 +121,7 @@
                     {formData.transportType === "STDIO" && (
                         <>
                             <Grid item xs={12}>
-                                <TextInput source="command" label="鍛戒护" fullWidth disabled={readOnly} />
+                                <TextInput source="command" label="ai.mcp.fields.command" fullWidth disabled={readOnly} />
                             </Grid>
                             <Grid item xs={12}>
                                 <TextInput source="argsJson" label="Args JSON" fullWidth multiline minRows={4} disabled={readOnly} />
@@ -133,39 +138,40 @@
             <NumberInput source="requestTimeoutMs" label="Timeout(ms)" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={4}>
-            <NumberInput source="sort" label="鎺掑簭" fullWidth disabled={readOnly} />
+            <NumberInput source="sort" label="ai.mcp.fields.sort" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={4}>
             <StatusSelectInput disabled={readOnly} />
         </Grid>
         <Grid item xs={12}>
-            <TextInput source="memo" label="澶囨敞" fullWidth multiline minRows={3} disabled={readOnly} />
+            <TextInput source="memo" label="common.field.memo" fullWidth multiline minRows={3} disabled={readOnly} />
         </Grid>
         <FormDataConsumer>
             {({ formData }) => <AiMcpDraftTestSection formData={formData} readOnly={readOnly} />}
         </FormDataConsumer>
         <Grid item xs={12}>
-            <Typography variant="h6">杩愯鎬佷俊鎭�</Typography>
+            <Typography variant="h6">{translate("ai.mcp.form.sections.runtime")}</Typography>
         </Grid>
         <Grid item xs={12} md={4}>
-            <TextInput source="healthStatus" label="鍋ュ悍鐘舵��" fullWidth disabled />
+            <TextInput source="healthStatus" label="ai.mcp.fields.healthStatus" fullWidth disabled />
         </Grid>
         <Grid item xs={12} md={4}>
-            <TextInput source="lastInitElapsedMs" label="鏈�杩戝垵濮嬪寲鑰楁椂(ms)" fullWidth disabled />
+            <TextInput source="lastInitElapsedMs" label="ai.mcp.fields.lastInitElapsedMs" fullWidth disabled />
         </Grid>
         <Grid item xs={12} md={4}>
-            <TextInput source="lastTestTime$" label="鏈�杩戞祴璇曟椂闂�" fullWidth disabled />
+            <TextInput source="lastTestTime$" label="ai.mcp.fields.lastTestTime" fullWidth disabled />
         </Grid>
         <Grid item xs={12}>
-            <TextInput source="lastTestMessage" label="鏈�杩戞祴璇曠粨鏋�" fullWidth multiline minRows={3} disabled />
+            <TextInput source="lastTestMessage" label="ai.mcp.fields.lastTestMessage" fullWidth multiline minRows={3} disabled />
         </Grid>
         <Grid item xs={12} md={6}>
-            <TextInput source="updateBy" label="鏈�杩戞洿鏂颁汉" fullWidth disabled />
+            <TextInput source="updateBy" label="ai.common.lastUpdatedBy" fullWidth disabled />
         </Grid>
         <Grid item xs={12} md={6}>
-            <TextInput source="updateTime$" label="鏈�杩戞洿鏂版椂闂�" fullWidth disabled />
+            <TextInput source="updateTime$" label="ai.common.lastUpdatedAt" fullWidth disabled />
         </Grid>
     </Grid>
-);
+    );
+};
 
 export default AiMcpMountForm;
diff --git a/rsf-admin/src/page/system/aiMcpMount/AiMcpMountList.jsx b/rsf-admin/src/page/system/aiMcpMount/AiMcpMountList.jsx
index 16c5e85..634aa30 100644
--- a/rsf-admin/src/page/system/aiMcpMount/AiMcpMountList.jsx
+++ b/rsf-admin/src/page/system/aiMcpMount/AiMcpMountList.jsx
@@ -9,6 +9,7 @@
     useListContext,
     useNotify,
     useRefresh,
+    useTranslate,
 } from "react-admin";
 import {
     Box,
@@ -39,7 +40,7 @@
     <SearchInput source="condition" alwaysOn />,
     <SelectInput
         source="transportType"
-        label="浼犺緭绫诲瀷"
+        label="ai.mcp.fields.transportType"
         choices={[
             { id: "SSE_HTTP", name: "SSE_HTTP" },
             { id: "STDIO", name: "STDIO" },
@@ -48,7 +49,7 @@
     />,
     <SelectInput
         source="status"
-        label="鐘舵��"
+        label="common.field.status"
         choices={[
             { id: "1", name: "common.enums.statusTrue" },
             { id: "0", name: "common.enums.statusFalse" },
@@ -83,22 +84,23 @@
 };
 
 const transportGroups = [
-    { key: "BUILTIN", title: "鍐呯疆 MCP", description: "绯荤粺鍐呯疆宸ュ叿鎸傝浇锛岄�傚悎鐩存帴鏆撮湶骞冲彴鑳藉姏銆�" },
-    { key: "SSE_HTTP", title: "杩滅▼ SSE MCP", description: "閫氳繃杩滅▼ MCP Server 鎸傝浇澶栭儴宸ュ叿銆�" },
-    { key: "STDIO", title: "鏈湴 STDIO MCP", description: "閫氳繃鏈湴鍛戒护杩涚▼鎸傝浇澶栭儴 MCP銆�" },
+    { key: "BUILTIN", titleKey: "ai.mcp.groups.builtin.title", descriptionKey: "ai.mcp.groups.builtin.description" },
+    { key: "SSE_HTTP", titleKey: "ai.mcp.groups.sse.title", descriptionKey: "ai.mcp.groups.sse.description" },
+    { key: "STDIO", titleKey: "ai.mcp.groups.stdio.title", descriptionKey: "ai.mcp.groups.stdio.description" },
 ];
 
-const resolveHealthMeta = (record) => {
+const resolveHealthMeta = (record, translate) => {
     if (record.healthStatus === "HEALTHY") {
-        return { color: "success", label: "姝e父" };
+        return { color: "success", label: translate("ai.mcp.health.healthy") };
     }
     if (record.healthStatus === "UNHEALTHY") {
-        return { color: "error", label: "澶辫触" };
+        return { color: "error", label: translate("ai.mcp.health.unhealthy") };
     }
-    return { color: "default", label: "鏈祴璇�" };
+    return { color: "default", label: translate("ai.common.notTested") };
 };
 
 const AiMcpMountCards = ({ onView, onEdit, onDelete, onConnectivityTest, deleting, testingConnectivityId }) => {
+    const translate = useTranslate();
     const { data, isLoading } = useListContext();
     const records = useMemo(() => (Array.isArray(data) ? data : []), [data]);
     const groupedRecords = useMemo(() => {
@@ -120,9 +122,9 @@
         return (
             <Box px={2} py={6}>
                 <Card variant="outlined" sx={{ p: 3, textAlign: "center", borderStyle: "dashed" }}>
-                    <Typography variant="subtitle1">鏆傛棤 MCP 鎸傝浇</Typography>
+                    <Typography variant="subtitle1">{translate("ai.mcp.list.emptyTitle")}</Typography>
                     <Typography variant="body2" color="text.secondary" mt={1}>
-                        鍙互鏂板缓鍐呯疆 MCP銆佽繙绋� SSE 鎸傝浇鎴栨湰鍦� STDIO 鎸傝浇銆�
+                        {translate("ai.mcp.list.emptyDescription")}
                     </Typography>
                 </Card>
             </Box>
@@ -135,14 +137,14 @@
                 {groupedRecords.map((group) => (
                     <Box key={group.key}>
                         <Box mb={1.5}>
-                            <Typography variant="h6">{group.title}</Typography>
+                            <Typography variant="h6">{translate(group.titleKey)}</Typography>
                             <Typography variant="body2" color="text.secondary">
-                                {group.description}
+                                {translate(group.descriptionKey)}
                             </Typography>
                         </Box>
                         <Grid container spacing={2}>
                             {group.records.map((record) => {
-                                const healthMeta = resolveHealthMeta(record);
+                                const healthMeta = resolveHealthMeta(record, translate);
                                 return (
                                     <Grid item xs={12} md={6} xl={4} key={record.id}>
                                         <Card
@@ -167,39 +169,35 @@
                                                         <Chip
                                                             size="small"
                                                             color={record.statusBool ? "success" : "default"}
-                                                            label={record.statusBool ? "鍚敤" : "鍋滅敤"}
+                                                            label={translate(record.statusBool ? "ai.common.enabled" : "ai.common.disabled")}
                                                         />
                                                         <Chip size="small" color={healthMeta.color} label={healthMeta.label} />
                                                     </Stack>
                                                 </Stack>
                                                 <Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap mt={1.5}>
-                                                    <Chip size="small" variant="outlined" label={`鎺掑簭 ${record.sort ?? 0}`} />
+                                                    <Chip size="small" variant="outlined" label={translate("ai.mcp.list.sortValue", { value: record.sort ?? 0 })} />
                                                     <Chip size="small" variant="outlined" label={`${record.requestTimeoutMs ?? "--"} ms`} />
                                                     <Chip size="small" variant="outlined" label={`Init ${record.lastInitElapsedMs ?? "--"} ms`} />
                                                 </Stack>
                                                 <Divider sx={{ my: 1.5 }} />
-                                                <Typography variant="caption" color="text.secondary">鐩爣</Typography>
+                                                <Typography variant="caption" color="text.secondary">{translate("ai.common.target")}</Typography>
                                                 <Typography variant="body2" sx={{ mt: 0.5, wordBreak: "break-all" }}>
                                                     {truncateText(resolveTargetLabel(record), 120)}
                                                 </Typography>
-                                                <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>
-                                                    鏈�杩戞祴璇�
-                                                </Typography>
+                                                <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>{translate("ai.common.lastTest")}</Typography>
                                                 <Typography variant="body2">
-                                                    {record.lastTestTime$ ? `${record.lastTestTime$} 路 ${truncateText(record.lastTestMessage, 72)}` : "灏氭湭鎵ц杩為�氭�ф祴璇�"}
+                                                    {record.lastTestTime$ ? `${record.lastTestTime$} 路 ${truncateText(record.lastTestMessage, 72)}` : translate("ai.mcp.list.noConnectivityTest")}
                                                 </Typography>
-                                                <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>
-                                                    澶囨敞
-                                                </Typography>
+                                                <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>{translate("common.field.memo")}</Typography>
                                                 <Typography variant="body2">{truncateText(record.memo)}</Typography>
                                             </CardContent>
                                             <CardActions sx={{ px: 2, pb: 2, pt: 0, justifyContent: "space-between", alignItems: "flex-start" }}>
                                                 <Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap>
                                                     <Button size="small" startIcon={<VisibilityOutlinedIcon />} onClick={() => onView(record.id)}>
-                                                        璇︽儏
+                                                        {translate("ai.common.detail")}
                                                     </Button>
                                                     <Button size="small" startIcon={<EditOutlinedIcon />} onClick={() => onEdit(record.id)}>
-                                                        缂栬緫
+                                                        {translate("common.button.edit")}
                                                     </Button>
                                                     <Button
                                                         size="small"
@@ -207,7 +205,7 @@
                                                         onClick={() => onConnectivityTest(record)}
                                                         disabled={testingConnectivityId === record.id}
                                                     >
-                                                        {testingConnectivityId === record.id ? "娴嬭瘯涓�..." : "杩為�氭祴璇�"}
+                                                        {testingConnectivityId === record.id ? translate("ai.common.testing") : translate("ai.mcp.list.connectivityTest")}
                                                     </Button>
                                                 </Stack>
                                                 <Button
@@ -217,7 +215,7 @@
                                                     onClick={() => onDelete(record)}
                                                     disabled={deleting}
                                                 >
-                                                    鍒犻櫎
+                                                    {translate("ai.common.delete")}
                                                 </Button>
                                             </CardActions>
                                         </Card>
@@ -233,6 +231,7 @@
 };
 
 const AiMcpMountList = () => {
+    const translate = useTranslate();
     const notify = useNotify();
     const refresh = useRefresh();
     const [deleteOne, { isPending: deleting }] = useDelete();
@@ -243,7 +242,7 @@
     const closeDialog = () => setDialogState({ open: false, mode: "create", recordId: null });
 
     const handleDelete = (record) => {
-        if (!record?.id || !window.confirm(`纭鍒犻櫎鈥�${record.name}鈥濆悧锛焋)) {
+        if (!record?.id || !window.confirm(translate("ai.common.confirmDelete", { name: record.name }))) {
             return;
         }
         deleteOne(
@@ -251,11 +250,11 @@
             { id: record.id },
             {
                 onSuccess: () => {
-                    notify("鍒犻櫎鎴愬姛");
+                    notify(translate("ai.common.deleteSuccess"));
                     refresh();
                 },
                 onError: (error) => {
-                    notify(error?.message || "鍒犻櫎澶辫触", { type: "error" });
+                    notify(error?.message || translate("ai.common.deleteFailed"), { type: "error" });
                 },
             }
         );
@@ -268,19 +267,19 @@
         setTestingConnectivityId(record.id);
         try {
             const result = await testMcpConnectivity(record.id);
-            notify(result?.message || "杩為�氭�ф祴璇曞畬鎴�");
+            notify(result?.message || translate("ai.mcp.connectivity.success"));
             refresh();
         } catch (error) {
-            notify(error?.message || "杩為�氭�ф祴璇曞け璐�", { type: "error" });
+            notify(error?.message || translate("ai.mcp.connectivity.failed"), { type: "error" });
         } finally {
             setTestingConnectivityId(null);
         }
     };
 
     const dialogTitle = {
-        create: "鏂板缓 MCP 鎸傝浇",
-        edit: "缂栬緫 MCP 鎸傝浇",
-        show: "鏌ョ湅 MCP 鎸傝浇璇︽儏",
+        create: translate("ai.mcp.dialog.create"),
+        edit: translate("ai.mcp.dialog.edit"),
+        show: translate("ai.mcp.dialog.show"),
     }[dialogState.mode];
 
     return (
@@ -293,7 +292,7 @@
                     <TopToolbar>
                         <FilterButton />
                         <Button variant="contained" startIcon={<AddRoundedIcon />} onClick={() => openDialog("create")}>
-                            鏂板缓
+                            {translate("ai.common.new")}
                         </Button>
                         <MyExportButton />
                     </TopToolbar>
diff --git a/rsf-admin/src/page/system/aiMcpMount/AiMcpMountToolsPanel.jsx b/rsf-admin/src/page/system/aiMcpMount/AiMcpMountToolsPanel.jsx
index 96edb0a..1b6158b 100644
--- a/rsf-admin/src/page/system/aiMcpMount/AiMcpMountToolsPanel.jsx
+++ b/rsf-admin/src/page/system/aiMcpMount/AiMcpMountToolsPanel.jsx
@@ -1,4 +1,5 @@
 import React, { useEffect, useMemo, useState } from "react";
+import { useTranslate, useNotify } from "react-admin";
 import {
     Accordion,
     AccordionDetails,
@@ -18,10 +19,9 @@
 import PlayCircleOutlineOutlinedIcon from "@mui/icons-material/PlayCircleOutlineOutlined";
 import PreviewOutlinedIcon from "@mui/icons-material/PreviewOutlined";
 import ExpandMoreOutlinedIcon from "@mui/icons-material/ExpandMoreOutlined";
-import { useNotify } from "react-admin";
 import { previewMcpTools, testMcpConnectivity, testMcpTool } from "@/api/ai/mcpMount";
 
-const parseInputSchema = (inputSchema) => {
+const parseInputSchema = (inputSchema, translate) => {
     if (!inputSchema) {
         return { pretty: "", fields: [], required: [], error: "" };
     }
@@ -46,7 +46,7 @@
             pretty: inputSchema,
             fields: [],
             required: [],
-            error: `Input Schema 瑙f瀽澶辫触: ${error.message}`,
+            error: translate("ai.mcp.tools.schemaParseFailed", { message: error.message }),
         };
     }
 };
@@ -118,6 +118,7 @@
 
 const AiMcpMountToolsPanel = ({ mountId }) => {
     const notify = useNotify();
+    const translate = useTranslate();
     const [loading, setLoading] = useState(false);
     const [tools, setTools] = useState([]);
     const [error, setError] = useState("");
@@ -130,10 +131,10 @@
 
     const schemaInfoMap = useMemo(() => {
         return tools.reduce((result, tool) => {
-            result[tool.name] = parseInputSchema(tool.inputSchema);
+            result[tool.name] = parseInputSchema(tool.inputSchema, translate);
             return result;
         }, {});
-    }, [tools]);
+    }, [tools, translate]);
 
     useEffect(() => {
         if (!mountId) {
@@ -158,7 +159,7 @@
             setInputs({});
             setStructuredInputs({});
         } catch (requestError) {
-            setError(requestError.message || "鑾峰彇宸ュ叿鍒楄〃澶辫触");
+            setError(requestError.message || translate("ai.mcp.tools.loadFailed"));
         } finally {
             setLoading(false);
         }
@@ -169,9 +170,9 @@
         try {
             const result = await testMcpConnectivity(mountId);
             setConnectivity(result);
-            notify(result?.message || "杩為�氭�ф祴璇曞畬鎴�");
+            notify(result?.message || translate("ai.mcp.connectivity.success"));
         } catch (requestError) {
-            const message = requestError.message || "杩為�氭�ф祴璇曞け璐�";
+            const message = requestError.message || translate("ai.mcp.connectivity.failed");
             notify(message, { type: "error" });
         } finally {
             setTestingConnectivity(false);
@@ -210,7 +211,7 @@
     const handleTest = async (toolName) => {
         const inputJson = inputs[toolName];
         if (!inputJson || !inputJson.trim()) {
-            notify("璇疯緭鍏ュ伐鍏锋祴璇� JSON", { type: "warning" });
+            notify(translate("ai.mcp.tools.inputRequired"), { type: "warning" });
             return;
         }
         setTestingToolName(toolName);
@@ -223,9 +224,9 @@
                 ...prev,
                 [toolName]: result?.output || "",
             }));
-            notify(`宸ュ叿 ${toolName} 娴嬭瘯瀹屾垚`);
+            notify(translate("ai.mcp.tools.testSuccess", { name: toolName }));
         } catch (requestError) {
-            const message = requestError.message || "宸ュ叿娴嬭瘯澶辫触";
+            const message = requestError.message || translate("ai.mcp.tools.testFailed");
             setOutputs((prev) => ({
                 ...prev,
                 [toolName]: message,
@@ -239,7 +240,7 @@
     if (!mountId) {
         return (
             <Alert severity="info" sx={{ mt: 2 }}>
-                淇濆瓨鎸傝浇鍚庡嵆鍙瑙堝伐鍏峰苟鎵ц娴嬭瘯銆�
+                {translate("ai.mcp.tools.saveBeforePreview")}
             </Alert>
         );
     }
@@ -249,16 +250,16 @@
             <Accordion defaultExpanded={false} sx={{ borderRadius: 3, overflow: "hidden" }}>
                 <AccordionSummary expandIcon={<ExpandMoreOutlinedIcon />}>
                     <Box flex={1}>
-                        <Typography variant="h6">宸ュ叿棰勮涓庢祴璇�</Typography>
+                        <Typography variant="h6">{translate("ai.mcp.tools.title")}</Typography>
                         <Typography variant="body2" color="text.secondary">
-                            鏀寔杩為�氭�ф祴璇曘�佺粨鏋勫寲 Schema 棰勮鍜屾寜杈撳叆鍙傛暟鑷姩鐢熸垚娴嬭瘯琛ㄥ崟銆�
+                            {translate("ai.mcp.tools.description")}
                         </Typography>
                     </Box>
                 </AccordionSummary>
                 <AccordionDetails>
                     <Stack direction="row" justifyContent="space-between" alignItems="center" mb={1.5} flexWrap="wrap" useFlexGap>
                         <Button size="small" startIcon={<PreviewOutlinedIcon />} onClick={loadTools} disabled={loading}>
-                            鍒锋柊宸ュ叿
+                            {translate("ai.mcp.tools.refresh")}
                         </Button>
                         <Button
                             size="small"
@@ -267,7 +268,7 @@
                             onClick={handleConnectivityTest}
                             disabled={testingConnectivity}
                         >
-                            {testingConnectivity ? "娴嬭瘯涓�..." : "杩為�氭�ф祴璇�"}
+                            {testingConnectivity ? translate("ai.common.testing") : translate("ai.mcp.list.connectivityTest")}
                         </Button>
                     </Stack>
                     {!!connectivity && (
@@ -289,7 +290,7 @@
                         </Alert>
                     )}
                     {!loading && !error && !tools.length && (
-                        <Alert severity="info">褰撳墠鎸傝浇鏈В鏋愬嚭浠讳綍宸ュ叿銆�</Alert>
+                        <Alert severity="info">{translate("ai.mcp.tools.noTools")}</Alert>
                     )}
                     <Grid container spacing={2}>
                         {tools.map((tool) => {
@@ -303,11 +304,11 @@
                                                 <Box>
                                                     <Typography variant="subtitle1">{tool.name}</Typography>
                                                     <Typography variant="body2" color="text.secondary">
-                                                        {tool.description || "鏆傛棤鎻忚堪"}
+                                                        {tool.description || translate("ai.common.none")}
                                                     </Typography>
                                                     {!!tool.toolPurpose && (
                                                         <Typography variant="caption" color="text.secondary" display="block" mt={0.5}>
-                                                            鐢ㄩ��: {tool.toolPurpose}
+                                                            {translate("ai.mcp.tools.purpose", { value: tool.toolPurpose })}
                                                         </Typography>
                                                     )}
                                                 </Box>
@@ -318,7 +319,7 @@
                                                         </Typography>
                                                     )}
                                                     <Typography variant="caption" color="text.secondary">
-                                                        {schemaInfo.fields.length} 涓弬鏁�
+                                                        {translate("ai.mcp.tools.fieldCount", { count: schemaInfo.fields.length })}
                                                     </Typography>
                                                     <Typography variant="caption" color="text.secondary">
                                                         {tool.returnDirect ? "returnDirect" : "normal"}
@@ -331,13 +332,13 @@
                                                 <CardContent>
                                                     {!!tool.queryBoundary && (
                                                         <Alert severity="info" sx={{ mb: 2 }}>
-                                                            鏌ヨ杈圭晫: {tool.queryBoundary}
+                                                            {translate("ai.mcp.tools.queryBoundary", { value: tool.queryBoundary })}
                                                         </Alert>
                                                     )}
                                                     {!!tool.exampleQuestions?.length && (
                                                         <Alert severity="success" sx={{ mb: 2 }}>
                                                             <Typography variant="body2" fontWeight={700} mb={0.5}>
-                                                                绀轰緥鎻愰棶
+                                                                {translate("ai.mcp.tools.exampleQuestions")}
                                                             </Typography>
                                                             {tool.exampleQuestions.map((question) => (
                                                                 <Typography key={question} variant="body2">
@@ -352,7 +353,7 @@
                                                         </Alert>
                                                     )}
                                                     <TextField
-                                                        label="鏍煎紡鍖� Input Schema"
+                                                        label={translate("ai.mcp.tools.formattedSchema")}
                                                         value={schemaInfo.pretty || tool.inputSchema || ""}
                                                         fullWidth
                                                         multiline
@@ -391,7 +392,7 @@
                                                         </Grid>
                                                     )}
                                                     <TextField
-                                                        label="娴嬭瘯杈撳叆 JSON"
+                                                        label={translate("ai.mcp.tools.testInput")}
                                                         value={inputs[tool.name] || ""}
                                                         onChange={(event) => handleInputChange(tool.name, event.target.value)}
                                                         fullWidth
@@ -399,7 +400,7 @@
                                                         minRows={5}
                                                         maxRows={12}
                                                         sx={{ mt: 2 }}
-                                                        placeholder='渚嬪锛歿"code":"A01"}'
+                                                        placeholder={translate("ai.mcp.tools.testInputPlaceholder")}
                                                     />
                                                     <Stack direction="row" justifyContent="flex-end" mt={1.5}>
                                                         <Button
@@ -408,11 +409,11 @@
                                                             onClick={() => handleTest(tool.name)}
                                                             disabled={testingToolName === tool.name}
                                                         >
-                                                            {testingToolName === tool.name ? "娴嬭瘯涓�..." : "鎵ц娴嬭瘯"}
+                                                            {testingToolName === tool.name ? translate("ai.common.testing") : translate("ai.mcp.tools.executeTest")}
                                                         </Button>
                                                     </Stack>
                                                     <TextField
-                                                        label="娴嬭瘯缁撴灉"
+                                                        label={translate("ai.mcp.tools.testResult")}
                                                         value={outputs[tool.name] || ""}
                                                         fullWidth
                                                         multiline
diff --git a/rsf-admin/src/page/system/aiParam/AiParamForm.jsx b/rsf-admin/src/page/system/aiParam/AiParamForm.jsx
index 09eface..eabd8dd 100644
--- a/rsf-admin/src/page/system/aiParam/AiParamForm.jsx
+++ b/rsf-admin/src/page/system/aiParam/AiParamForm.jsx
@@ -6,6 +6,7 @@
     SelectInput,
     TextInput,
     useNotify,
+    useTranslate,
 } from "react-admin";
 import { Alert, Button, Grid, Stack, Typography } from "@mui/material";
 import StatusSelectInput from "@/page/components/StatusSelectInput";
@@ -17,6 +18,7 @@
 
 const AiParamValidateSection = ({ formData, readOnly }) => {
     const notify = useNotify();
+    const translate = useTranslate();
     const [loading, setLoading] = useState(false);
     const [result, setResult] = useState(null);
 
@@ -25,11 +27,11 @@
         try {
             const data = await validateAiParamDraft(formData);
             setResult(data);
-            notify(data?.message || "AI 鍙傛暟楠岃瘉鎴愬姛");
+            notify(data?.message || translate("ai.param.validate.success"));
         } catch (error) {
             const nextResult = {
                 status: "INVALID",
-                message: error?.message || "AI 鍙傛暟楠岃瘉澶辫触",
+                message: error?.message || translate("ai.param.validate.failed"),
             };
             setResult(nextResult);
             notify(nextResult.message, { type: "error" });
@@ -44,10 +46,10 @@
                 <Grid item xs={12}>
                     <Stack direction="row" spacing={1} alignItems="center">
                         <Button variant="outlined" onClick={handleValidate} disabled={loading}>
-                            {loading ? "楠岃瘉涓�..." : "淇濆瓨鍓嶉獙璇�"}
+                            {loading ? translate("ai.param.validate.loading") : translate("ai.param.validate.beforeSave")}
                         </Button>
                         <Typography variant="body2" color="text.secondary">
-                            浼氱洿鎺ユ牎楠屽綋鍓� Base URL銆丄PI Key 涓庢ā鍨嬫槸鍚﹀彲璋冪敤銆�
+                            {translate("ai.param.validate.description")}
                         </Typography>
                     </Stack>
                 </Grid>
@@ -65,72 +67,76 @@
     );
 };
 
-const AiParamForm = ({ readOnly = false }) => (
+const AiParamForm = ({ readOnly = false }) => {
+    const translate = useTranslate();
+
+    return (
     <Grid container spacing={2} width={{ xs: "100%", xl: "80%" }}>
         <Grid item xs={12}>
-            <Typography variant="h6">涓昏閰嶇疆</Typography>
+            <Typography variant="h6">{translate("ai.param.form.sections.main")}</Typography>
         </Grid>
         <Grid item xs={12} md={6}>
-            <TextInput source="name" label="鍚嶇О" fullWidth disabled={readOnly} />
+            <TextInput source="name" label="common.field.name" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={6}>
-            <SelectInput source="providerType" label="鎻愪緵鏂圭被鍨�" choices={providerChoices} fullWidth disabled={readOnly} />
+            <SelectInput source="providerType" label="ai.param.fields.providerType" choices={providerChoices} fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12}>
-            <TextInput source="baseUrl" label="Base URL" fullWidth disabled={readOnly} />
+            <TextInput source="baseUrl" label="ai.param.fields.baseUrl" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={6}>
-            <TextInput source="apiKey" label="API Key" fullWidth disabled={readOnly} />
+            <TextInput source="apiKey" label="ai.param.fields.apiKey" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={6}>
-            <TextInput source="model" label="妯″瀷" fullWidth disabled={readOnly} />
+            <TextInput source="model" label="ai.param.fields.model" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={3}>
-            <NumberInput source="temperature" label="Temperature" fullWidth disabled={readOnly} />
+            <NumberInput source="temperature" label="ai.param.fields.temperature" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={3}>
-            <NumberInput source="topP" label="Top P" fullWidth disabled={readOnly} />
+            <NumberInput source="topP" label="ai.param.fields.topP" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={3}>
-            <NumberInput source="maxTokens" label="Max Tokens" fullWidth disabled={readOnly} />
+            <NumberInput source="maxTokens" label="ai.param.fields.maxTokens" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={3}>
-            <NumberInput source="timeoutMs" label="Timeout(ms)" fullWidth disabled={readOnly} />
+            <NumberInput source="timeoutMs" label="ai.param.fields.timeoutMs" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={6}>
-            <BooleanInput source="streamingEnabled" label="鍚敤娴佸紡鍝嶅簲" disabled={readOnly} />
+            <BooleanInput source="streamingEnabled" label="ai.param.fields.streamingEnabled" disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={6}>
             <StatusSelectInput disabled={readOnly} />
         </Grid>
         <Grid item xs={12}>
-            <TextInput source="memo" label="澶囨敞" fullWidth multiline minRows={3} disabled={readOnly} />
+            <TextInput source="memo" label="common.field.memo" fullWidth multiline minRows={3} disabled={readOnly} />
         </Grid>
         <FormDataConsumer>
             {({ formData }) => <AiParamValidateSection formData={formData} readOnly={readOnly} />}
         </FormDataConsumer>
         <Grid item xs={12}>
-            <Typography variant="h6">杩愯涓庡璁′俊鎭�</Typography>
+            <Typography variant="h6">{translate("ai.param.form.sections.runtime")}</Typography>
         </Grid>
         <Grid item xs={12} md={3}>
-            <TextInput source="validateStatus" label="鏈�杩戞牎楠岀姸鎬�" fullWidth disabled />
+            <TextInput source="validateStatus" label="ai.param.fields.validateStatus" fullWidth disabled />
         </Grid>
         <Grid item xs={12} md={3}>
-            <TextInput source="lastValidateElapsedMs" label="鏈�杩戞牎楠岃�楁椂(ms)" fullWidth disabled />
+            <TextInput source="lastValidateElapsedMs" label="ai.param.fields.lastValidateElapsedMs" fullWidth disabled />
         </Grid>
         <Grid item xs={12} md={3}>
-            <TextInput source="lastValidateTime$" label="鏈�杩戞牎楠屾椂闂�" fullWidth disabled />
+            <TextInput source="lastValidateTime$" label="ai.param.fields.lastValidateTime" fullWidth disabled />
         </Grid>
         <Grid item xs={12} md={3}>
-            <TextInput source="updateBy" label="鏈�杩戞洿鏂颁汉" fullWidth disabled />
+            <TextInput source="updateBy" label="ai.common.lastUpdatedBy" fullWidth disabled />
         </Grid>
         <Grid item xs={12}>
-            <TextInput source="lastValidateMessage" label="鏈�杩戞牎楠岀粨鏋�" fullWidth multiline minRows={3} disabled />
+            <TextInput source="lastValidateMessage" label="ai.param.fields.lastValidateMessage" fullWidth multiline minRows={3} disabled />
         </Grid>
         <Grid item xs={12}>
-            <TextInput source="updateTime$" label="鏈�杩戞洿鏂版椂闂�" fullWidth disabled />
+            <TextInput source="updateTime$" label="ai.common.lastUpdatedAt" fullWidth disabled />
         </Grid>
     </Grid>
-);
+    );
+};
 
 export default AiParamForm;
diff --git a/rsf-admin/src/page/system/aiParam/AiParamList.jsx b/rsf-admin/src/page/system/aiParam/AiParamList.jsx
index 225fbd9..ebee4e6 100644
--- a/rsf-admin/src/page/system/aiParam/AiParamList.jsx
+++ b/rsf-admin/src/page/system/aiParam/AiParamList.jsx
@@ -10,6 +10,7 @@
     useListContext,
     useNotify,
     useRefresh,
+    useTranslate,
 } from "react-admin";
 import {
     Box,
@@ -35,11 +36,11 @@
 
 const filters = [
     <SearchInput source="condition" alwaysOn />,
-    <TextInput source="providerType" label="鎻愪緵鏂圭被鍨�" />,
-    <TextInput source="model" label="妯″瀷" />,
+    <TextInput source="providerType" label="ai.param.fields.providerType" />,
+    <TextInput source="model" label="ai.param.fields.model" />,
     <SelectInput
         source="status"
-        label="鐘舵��"
+        label="common.field.status"
         choices={[
             { id: "1", name: "common.enums.statusTrue" },
             { id: "0", name: "common.enums.statusFalse" },
@@ -64,6 +65,7 @@
 };
 
 const AiParamCards = ({ onView, onEdit, onDelete, deleting }) => {
+    const translate = useTranslate();
     const { data, isLoading } = useListContext();
     const records = useMemo(() => (Array.isArray(data) ? data : []), [data]);
 
@@ -79,9 +81,9 @@
         return (
             <Box px={2} py={6}>
                 <Card variant="outlined" sx={{ p: 3, textAlign: "center", borderStyle: "dashed" }}>
-                    <Typography variant="subtitle1">鏆傛棤 AI 鍙傛暟閰嶇疆</Typography>
+                    <Typography variant="subtitle1">{translate("ai.param.list.emptyTitle")}</Typography>
                     <Typography variant="body2" color="text.secondary" mt={1}>
-                        鍙互鍏堟柊寤轰竴涓� OpenAI 鍏煎妯″瀷鍙傛暟鍗$墖銆�
+                        {translate("ai.param.list.emptyDescription")}
                     </Typography>
                 </Card>
             </Box>
@@ -114,7 +116,7 @@
                                     <Chip
                                         size="small"
                                         color={record.statusBool ? "success" : "default"}
-                                        label={record.statusBool ? "鍚敤" : "鍋滅敤"}
+                                        label={translate(record.statusBool ? "ai.common.enabled" : "ai.common.disabled")}
                                     />
                                 </Stack>
                                 <Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap mt={1.5}>
@@ -123,7 +125,7 @@
                                         size="small"
                                         variant="outlined"
                                         color={record.streamingEnabled ? "info" : "default"}
-                                        label={record.streamingEnabled ? "娴佸紡鍝嶅簲" : "闈炴祦寮�"}
+                                        label={translate(record.streamingEnabled ? "ai.param.list.streaming" : "ai.param.list.nonStreaming")}
                                     />
                                 </Stack>
                                 <Divider sx={{ my: 1.5 }} />
@@ -151,18 +153,16 @@
                                         <Typography variant="body2">{record.timeoutMs ?? "--"} ms</Typography>
                                     </Grid>
                                 </Grid>
-                                <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>
-                                    澶囨敞
-                                </Typography>
+                                <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>{translate("common.field.memo")}</Typography>
                                 <Typography variant="body2">{truncateText(record.memo)}</Typography>
                             </CardContent>
                             <CardActions sx={{ px: 2, pb: 2, pt: 0, justifyContent: "space-between" }}>
                                 <Stack direction="row" spacing={1}>
                                     <Button size="small" startIcon={<VisibilityOutlinedIcon />} onClick={() => onView(record.id)}>
-                                        璇︽儏
+                                        {translate("ai.common.detail")}
                                     </Button>
                                     <Button size="small" startIcon={<EditOutlinedIcon />} onClick={() => onEdit(record.id)}>
-                                        缂栬緫
+                                        {translate("common.button.edit")}
                                     </Button>
                                 </Stack>
                                 <Button
@@ -172,7 +172,7 @@
                                     onClick={() => onDelete(record)}
                                     disabled={deleting}
                                 >
-                                    鍒犻櫎
+                                    {translate("ai.common.delete")}
                                 </Button>
                             </CardActions>
                         </Card>
@@ -184,6 +184,7 @@
 };
 
 const AiParamList = () => {
+    const translate = useTranslate();
     const notify = useNotify();
     const refresh = useRefresh();
     const [deleteOne, { isPending: deleting }] = useDelete();
@@ -193,7 +194,7 @@
     const closeDialog = () => setDialogState({ open: false, mode: "create", recordId: null });
 
     const handleDelete = (record) => {
-        if (!record?.id || !window.confirm(`纭鍒犻櫎鈥�${record.name}鈥濆悧锛焋)) {
+        if (!record?.id || !window.confirm(translate("ai.common.confirmDelete", { name: record.name }))) {
             return;
         }
         deleteOne(
@@ -201,20 +202,20 @@
             { id: record.id },
             {
                 onSuccess: () => {
-                    notify("鍒犻櫎鎴愬姛");
+                    notify(translate("ai.common.deleteSuccess"));
                     refresh();
                 },
                 onError: (error) => {
-                    notify(error?.message || "鍒犻櫎澶辫触", { type: "error" });
+                    notify(error?.message || translate("ai.common.deleteFailed"), { type: "error" });
                 },
             }
         );
     };
 
     const dialogTitle = {
-        create: "鏂板缓 AI 鍙傛暟",
-        edit: "缂栬緫 AI 鍙傛暟",
-        show: "鏌ョ湅 AI 鍙傛暟璇︽儏",
+        create: translate("ai.param.dialog.create"),
+        edit: translate("ai.param.dialog.edit"),
+        show: translate("ai.param.dialog.show"),
     }[dialogState.mode];
 
     return (
@@ -227,7 +228,7 @@
                     <TopToolbar>
                         <FilterButton />
                         <Button variant="contained" startIcon={<AddRoundedIcon />} onClick={() => openDialog("create")}>
-                            鏂板缓
+                            {translate("ai.common.new")}
                         </Button>
                         <MyExportButton />
                     </TopToolbar>
diff --git a/rsf-admin/src/page/system/aiPrompt/AiPromptForm.jsx b/rsf-admin/src/page/system/aiPrompt/AiPromptForm.jsx
index 5c6ad35..36051d7 100644
--- a/rsf-admin/src/page/system/aiPrompt/AiPromptForm.jsx
+++ b/rsf-admin/src/page/system/aiPrompt/AiPromptForm.jsx
@@ -3,6 +3,7 @@
     FormDataConsumer,
     TextInput,
     useNotify,
+    useTranslate,
 } from "react-admin";
 import { Alert, Button, Grid, Stack, TextField, Typography } from "@mui/material";
 import StatusSelectInput from "@/page/components/StatusSelectInput";
@@ -10,7 +11,8 @@
 
 const AiPromptPreviewSection = ({ formData }) => {
     const notify = useNotify();
-    const [input, setInput] = useState("璇峰府鎴戞�荤粨褰撳墠椤甸潰鑳藉仛浠�涔�");
+    const translate = useTranslate();
+    const [input, setInput] = useState(() => translate("ai.prompt.preview.defaultInput"));
     const [metadataText, setMetadataText] = useState("{\"path\":\"/system/aiPrompt\"}");
     const [preview, setPreview] = useState(null);
     const [loading, setLoading] = useState(false);
@@ -25,10 +27,10 @@
                 metadata,
             });
             setPreview(data);
-            notify("Prompt 棰勮瀹屾垚");
+            notify(translate("ai.prompt.preview.success"));
         } catch (error) {
             setPreview(null);
-            notify(error?.message || "Prompt 棰勮澶辫触", { type: "error" });
+            notify(error?.message || translate("ai.prompt.preview.failed"), { type: "error" });
         } finally {
             setLoading(false);
         }
@@ -37,11 +39,11 @@
     return (
         <>
             <Grid item xs={12}>
-                <Typography variant="h6">Prompt 棰勮</Typography>
+                <Typography variant="h6">{translate("ai.prompt.preview.title")}</Typography>
             </Grid>
             <Grid item xs={12}>
                 <TextField
-                    label="绀轰緥杈撳叆"
+                    label={translate("ai.prompt.preview.input")}
                     value={input}
                     onChange={(event) => setInput(event.target.value)}
                     fullWidth
@@ -51,7 +53,7 @@
             </Grid>
             <Grid item xs={12}>
                 <TextField
-                    label="绀轰緥鍏冩暟鎹� JSON"
+                    label={translate("ai.prompt.preview.metadata")}
                     value={metadataText}
                     onChange={(event) => setMetadataText(event.target.value)}
                     fullWidth
@@ -62,10 +64,10 @@
             <Grid item xs={12}>
                 <Stack direction="row" spacing={1} alignItems="center">
                     <Button variant="outlined" onClick={handlePreview} disabled={loading}>
-                        {loading ? "棰勮涓�..." : "棰勮娓叉煋"}
+                        {loading ? translate("ai.prompt.preview.loading") : translate("ai.prompt.preview.render")}
                     </Button>
                     <Typography variant="body2" color="text.secondary">
-                        鐢ㄥ綋鍓嶈〃鍗曞唴瀹规覆鏌� System Prompt 鍜� User Prompt銆�
+                        {translate("ai.prompt.preview.description")}
                     </Typography>
                 </Stack>
             </Grid>
@@ -73,12 +75,14 @@
                 <>
                     <Grid item xs={12}>
                         <Alert severity="success">
-                            宸茶В鏋愬彉閲忥細{(preview.resolvedVariables || []).join(", ") || "鏃�"}
+                            {translate("ai.prompt.preview.resolvedVariables", {
+                                value: (preview.resolvedVariables || []).join(", ") || translate("ai.common.none"),
+                            })}
                         </Alert>
                     </Grid>
                     <Grid item xs={12}>
                         <TextField
-                            label="娓叉煋鍚庣殑 System Prompt"
+                            label={translate("ai.prompt.preview.renderedSystemPrompt")}
                             value={preview.renderedSystemPrompt || ""}
                             fullWidth
                             multiline
@@ -88,7 +92,7 @@
                     </Grid>
                     <Grid item xs={12}>
                         <TextField
-                            label="娓叉煋鍚庣殑 User Prompt"
+                            label={translate("ai.prompt.preview.renderedUserPrompt")}
                             value={preview.renderedUserPrompt || ""}
                             fullWidth
                             multiline
@@ -102,45 +106,49 @@
     );
 };
 
-const AiPromptForm = ({ readOnly = false }) => (
+const AiPromptForm = ({ readOnly = false }) => {
+    const translate = useTranslate();
+
+    return (
     <Grid container spacing={2} width={{ xs: "100%", xl: "80%" }}>
         <Grid item xs={12}>
-            <Typography variant="h6">Prompt 閰嶇疆</Typography>
+            <Typography variant="h6">{translate("ai.prompt.form.sections.main")}</Typography>
         </Grid>
         <Grid item xs={12} md={6}>
-            <TextInput source="name" label="鍚嶇О" fullWidth disabled={readOnly} />
+            <TextInput source="name" label="common.field.name" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={6}>
-            <TextInput source="code" label="缂栫爜" fullWidth disabled={readOnly} />
+            <TextInput source="code" label="ai.prompt.fields.code" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12}>
-            <TextInput source="scene" label="鍦烘櫙" fullWidth disabled={readOnly} />
+            <TextInput source="scene" label="ai.prompt.fields.scene" fullWidth disabled={readOnly} />
         </Grid>
         <Grid item xs={12}>
-            <TextInput source="systemPrompt" label="System Prompt" fullWidth multiline minRows={6} disabled={readOnly} />
+            <TextInput source="systemPrompt" label="ai.prompt.fields.systemPrompt" fullWidth multiline minRows={6} disabled={readOnly} />
         </Grid>
         <Grid item xs={12}>
-            <TextInput source="userPromptTemplate" label="User Prompt Template" fullWidth multiline minRows={5} disabled={readOnly} />
+            <TextInput source="userPromptTemplate" label="ai.prompt.fields.userPromptTemplate" fullWidth multiline minRows={5} disabled={readOnly} />
         </Grid>
         <Grid item xs={12} md={6}>
             <StatusSelectInput disabled={readOnly} />
         </Grid>
         <Grid item xs={12}>
-            <TextInput source="memo" label="澶囨敞" fullWidth multiline minRows={3} disabled={readOnly} />
+            <TextInput source="memo" label="common.field.memo" fullWidth multiline minRows={3} disabled={readOnly} />
         </Grid>
         <FormDataConsumer>
             {({ formData }) => <AiPromptPreviewSection formData={formData} />}
         </FormDataConsumer>
         <Grid item xs={12}>
-            <Typography variant="h6">杩愯涓庡璁′俊鎭�</Typography>
+            <Typography variant="h6">{translate("ai.prompt.form.sections.runtime")}</Typography>
         </Grid>
         <Grid item xs={12} md={6}>
-            <TextInput source="updateBy" label="鏈�杩戞洿鏂颁汉" fullWidth disabled />
+            <TextInput source="updateBy" label="ai.common.lastUpdatedBy" fullWidth disabled />
         </Grid>
         <Grid item xs={12} md={6}>
-            <TextInput source="updateTime$" label="鏈�杩戞洿鏂版椂闂�" fullWidth disabled />
+            <TextInput source="updateTime$" label="ai.common.lastUpdatedAt" fullWidth disabled />
         </Grid>
     </Grid>
-);
+    );
+};
 
 export default AiPromptForm;
diff --git a/rsf-admin/src/page/system/aiPrompt/AiPromptList.jsx b/rsf-admin/src/page/system/aiPrompt/AiPromptList.jsx
index 236fa02..089af71 100644
--- a/rsf-admin/src/page/system/aiPrompt/AiPromptList.jsx
+++ b/rsf-admin/src/page/system/aiPrompt/AiPromptList.jsx
@@ -10,6 +10,7 @@
     useListContext,
     useNotify,
     useRefresh,
+    useTranslate,
 } from "react-admin";
 import {
     Box,
@@ -35,11 +36,11 @@
 
 const filters = [
     <SearchInput source="condition" alwaysOn />,
-    <TextInput source="code" label="缂栫爜" />,
-    <TextInput source="scene" label="鍦烘櫙" />,
+    <TextInput source="code" label="ai.prompt.fields.code" />,
+    <TextInput source="scene" label="ai.prompt.fields.scene" />,
     <SelectInput
         source="status"
-        label="鐘舵��"
+        label="common.field.status"
         choices={[
             { id: "1", name: "common.enums.statusTrue" },
             { id: "0", name: "common.enums.statusFalse" },
@@ -61,6 +62,7 @@
 };
 
 const AiPromptCards = ({ onView, onEdit, onDelete, deleting }) => {
+    const translate = useTranslate();
     const { data, isLoading } = useListContext();
     const records = useMemo(() => (Array.isArray(data) ? data : []), [data]);
 
@@ -76,9 +78,9 @@
         return (
             <Box px={2} py={6}>
                 <Card variant="outlined" sx={{ p: 3, textAlign: "center", borderStyle: "dashed" }}>
-                    <Typography variant="subtitle1">鏆傛棤 Prompt 閰嶇疆</Typography>
+                    <Typography variant="subtitle1">{translate("ai.prompt.list.emptyTitle")}</Typography>
                     <Typography variant="body2" color="text.secondary" mt={1}>
-                        鏂板缓涓�寮� Prompt 鍗$墖鍚庯紝AI 瀵硅瘽浼氬姩鎬佸姞杞借繖閲岀殑鍐呭銆�
+                        {translate("ai.prompt.list.emptyDescription")}
                     </Typography>
                 </Card>
             </Box>
@@ -111,29 +113,27 @@
                                     <Chip
                                         size="small"
                                         color={record.statusBool ? "success" : "default"}
-                                        label={record.statusBool ? "鍚敤" : "鍋滅敤"}
+                                        label={translate(record.statusBool ? "ai.common.enabled" : "ai.common.disabled")}
                                     />
                                 </Stack>
                                 <Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap mt={1.5}>
-                                    <Chip size="small" variant="outlined" label={`Scene: ${record.scene || "--"}`} />
+                                    <Chip size="small" variant="outlined" label={translate("ai.prompt.list.sceneValue", { value: record.scene || "--" })} />
                                 </Stack>
                                 <Divider sx={{ my: 1.5 }} />
-                                <Typography variant="caption" color="text.secondary">System Prompt</Typography>
+                                <Typography variant="caption" color="text.secondary">{translate("ai.prompt.fields.systemPrompt")}</Typography>
                                 <Typography variant="body2" sx={{ mt: 0.5 }}>
                                     {truncateText(record.systemPrompt)}
                                 </Typography>
-                                <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>
-                                    User Prompt Template
-                                </Typography>
+                                <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>{translate("ai.prompt.fields.userPromptTemplate")}</Typography>
                                 <Typography variant="body2">{truncateText(record.userPromptTemplate, 100)}</Typography>
                             </CardContent>
                             <CardActions sx={{ px: 2, pb: 2, pt: 0, justifyContent: "space-between" }}>
                                 <Stack direction="row" spacing={1}>
                                     <Button size="small" startIcon={<VisibilityOutlinedIcon />} onClick={() => onView(record.id)}>
-                                        璇︽儏
+                                        {translate("ai.common.detail")}
                                     </Button>
                                     <Button size="small" startIcon={<EditOutlinedIcon />} onClick={() => onEdit(record.id)}>
-                                        缂栬緫
+                                        {translate("common.button.edit")}
                                     </Button>
                                 </Stack>
                                 <Button
@@ -143,7 +143,7 @@
                                     onClick={() => onDelete(record)}
                                     disabled={deleting}
                                 >
-                                    鍒犻櫎
+                                    {translate("ai.common.delete")}
                                 </Button>
                             </CardActions>
                         </Card>
@@ -155,6 +155,7 @@
 };
 
 const AiPromptList = () => {
+    const translate = useTranslate();
     const notify = useNotify();
     const refresh = useRefresh();
     const [deleteOne, { isPending: deleting }] = useDelete();
@@ -164,7 +165,7 @@
     const closeDialog = () => setDialogState({ open: false, mode: "create", recordId: null });
 
     const handleDelete = (record) => {
-        if (!record?.id || !window.confirm(`纭鍒犻櫎鈥�${record.name}鈥濆悧锛焋)) {
+        if (!record?.id || !window.confirm(translate("ai.common.confirmDelete", { name: record.name }))) {
             return;
         }
         deleteOne(
@@ -172,20 +173,20 @@
             { id: record.id },
             {
                 onSuccess: () => {
-                    notify("鍒犻櫎鎴愬姛");
+                    notify(translate("ai.common.deleteSuccess"));
                     refresh();
                 },
                 onError: (error) => {
-                    notify(error?.message || "鍒犻櫎澶辫触", { type: "error" });
+                    notify(error?.message || translate("ai.common.deleteFailed"), { type: "error" });
                 },
             }
         );
     };
 
     const dialogTitle = {
-        create: "鏂板缓 Prompt",
-        edit: "缂栬緫 Prompt",
-        show: "鏌ョ湅 Prompt 璇︽儏",
+        create: translate("ai.prompt.dialog.create"),
+        edit: translate("ai.prompt.dialog.edit"),
+        show: translate("ai.prompt.dialog.show"),
     }[dialogState.mode];
 
     return (
@@ -198,7 +199,7 @@
                     <TopToolbar>
                         <FilterButton />
                         <Button variant="contained" startIcon={<AddRoundedIcon />} onClick={() => openDialog("create")}>
-                            鏂板缓
+                            {translate("ai.common.new")}
                         </Button>
                         <MyExportButton />
                     </TopToolbar>
diff --git a/rsf-admin/src/page/system/aiShared/AiConfigDialog.jsx b/rsf-admin/src/page/system/aiShared/AiConfigDialog.jsx
index ea5de3e..5b61e97 100644
--- a/rsf-admin/src/page/system/aiShared/AiConfigDialog.jsx
+++ b/rsf-admin/src/page/system/aiShared/AiConfigDialog.jsx
@@ -7,6 +7,7 @@
     Toolbar,
     useNotify,
     useRefresh,
+    useTranslate,
 } from "react-admin";
 import {
     Button,
@@ -16,9 +17,9 @@
     DialogTitle,
 } from "@mui/material";
 
-const DialogFormToolbar = ({ onClose }) => (
+const DialogFormToolbar = ({ onClose, translate }) => (
     <Toolbar sx={{ justifyContent: "space-between", px: 0 }}>
-        <Button onClick={onClose}>鍙栨秷</Button>
+        <Button onClick={onClose}>{translate("ai.common.cancel")}</Button>
         <SaveButton />
     </Toolbar>
 );
@@ -36,25 +37,26 @@
 }) => {
     const notify = useNotify();
     const refresh = useRefresh();
+    const translate = useTranslate();
 
     if (!open) {
         return null;
     }
 
     const handleSuccess = () => {
-        notify(mode === "create" ? "淇濆瓨鎴愬姛" : "鏇存柊鎴愬姛");
+        notify(translate(mode === "create" ? "ai.common.saveSuccess" : "ai.common.updateSuccess"));
         refresh();
         onClose();
     };
 
     const handleError = (error) => {
-        notify(error?.message || "鎿嶄綔澶辫触", { type: "error" });
+        notify(error?.message || translate("ai.common.operationFailed"), { type: "error" });
     };
 
     const formContent = (
         <SimpleForm
             defaultValues={mode === "create" ? defaultValues : undefined}
-            toolbar={mode === "show" ? false : <DialogFormToolbar onClose={onClose} />}
+            toolbar={mode === "show" ? false : <DialogFormToolbar onClose={onClose} translate={translate} />}
             sx={{
                 "& .RaSimpleForm-form": {
                     maxWidth: "100%",
@@ -89,7 +91,7 @@
             </DialogContent>
             {mode === "show" && (
                 <DialogActions>
-                    <Button onClick={onClose}>鍏抽棴</Button>
+                    <Button onClick={onClose}>{translate("ai.common.close")}</Button>
                 </DialogActions>
             )}
         </Dialog>
diff --git a/rsf-admin/src/page/system/aiShared/AiRuntimeSummary.jsx b/rsf-admin/src/page/system/aiShared/AiRuntimeSummary.jsx
index bf0a840..723ff59 100644
--- a/rsf-admin/src/page/system/aiShared/AiRuntimeSummary.jsx
+++ b/rsf-admin/src/page/system/aiShared/AiRuntimeSummary.jsx
@@ -1,8 +1,10 @@
 import React, { useEffect, useState } from "react";
+import { useTranslate } from "react-admin";
 import { Alert, Box, Card, CardContent, Chip, CircularProgress, Grid, Stack, Typography } from "@mui/material";
 import { getAiConfigSummary } from "@/api/ai/configCenter";
 
 const AiRuntimeSummary = ({ promptCode = "home.default" }) => {
+    const translate = useTranslate();
     const [summary, setSummary] = useState(null);
     const [loading, setLoading] = useState(true);
     const [error, setError] = useState("");
@@ -22,7 +24,7 @@
                 if (!active) {
                     return;
                 }
-                setError(err?.message || "鑾峰彇杩愯鎬佹憳瑕佸け璐�");
+                setError(err?.message || translate("ai.runtimeSummary.fetchFailed"));
             })
             .finally(() => {
                 if (active) {
@@ -46,9 +48,9 @@
                 <CardContent>
                     <Stack direction="row" justifyContent="space-between" alignItems="center" mb={2}>
                         <Box>
-                            <Typography variant="h6">褰撳墠杩愯鎬�</Typography>
+                            <Typography variant="h6">{translate("ai.runtimeSummary.title")}</Typography>
                             <Typography variant="body2" color="text.secondary">
-                                灞曠ず褰撳墠鐢熸晥鐨勬ā鍨嬨�丳rompt 涓� MCP 鎸傝浇淇℃伅銆�
+                                {translate("ai.runtimeSummary.description")}
                             </Typography>
                         </Box>
                         {loading && <CircularProgress size={24} />}
@@ -57,29 +59,32 @@
                     {!loading && !error && summary && (
                         <Grid container spacing={2}>
                             <Grid item xs={12} md={4}>
-                                <Typography variant="caption" color="text.secondary">褰撳墠妯″瀷</Typography>
+                                <Typography variant="caption" color="text.secondary">{translate("ai.runtimeSummary.currentModel")}</Typography>
                                 <Typography variant="body1">{summary.activeModel || "--"}</Typography>
                                 <Typography variant="body2" color="text.secondary">
                                     {summary.activeParamName || "--"}
                                 </Typography>
                                 <Stack direction="row" spacing={1} mt={1} flexWrap="wrap" useFlexGap>
-                                    <Chip size="small" label={`鏍¢獙 ${summary.activeParamValidateStatus || "--"}`} />
-                                    <Chip size="small" variant="outlined" label={summary.activeParamValidatedAt || "鏈牎楠�"} />
+                                    <Chip size="small" label={translate("ai.runtimeSummary.validateStatus", { status: summary.activeParamValidateStatus || "--" })} />
+                                    <Chip size="small" variant="outlined" label={summary.activeParamValidatedAt || translate("ai.common.notValidated")} />
                                 </Stack>
                             </Grid>
                             <Grid item xs={12} md={4}>
-                                <Typography variant="caption" color="text.secondary">褰撳墠 Prompt</Typography>
+                                <Typography variant="caption" color="text.secondary">{translate("ai.runtimeSummary.currentPrompt")}</Typography>
                                 <Typography variant="body1">{summary.promptName || "--"}</Typography>
                                 <Typography variant="body2" color="text.secondary">
                                     {summary.promptCode || "--"} / {summary.promptScene || "--"}
                                 </Typography>
                                 <Typography variant="body2" color="text.secondary" mt={1}>
-                                    鏈�杩戞洿鏂帮細{summary.activePromptUpdatedAt || "--"} / {summary.activePromptUpdatedBy || "--"}
+                                    {translate("ai.runtimeSummary.lastUpdated", {
+                                        time: summary.activePromptUpdatedAt || "--",
+                                        user: summary.activePromptUpdatedBy || "--",
+                                    })}
                                 </Typography>
                             </Grid>
                             <Grid item xs={12} md={4}>
-                                <Typography variant="caption" color="text.secondary">宸插惎鐢� MCP</Typography>
-                                <Typography variant="body1">{summary.enabledMcpCount ?? 0} 涓�</Typography>
+                                <Typography variant="caption" color="text.secondary">{translate("ai.runtimeSummary.enabledMcp")}</Typography>
+                                <Typography variant="body1">{translate("ai.runtimeSummary.enabledMcpCount", { count: summary.enabledMcpCount ?? 0 })}</Typography>
                                 <Stack direction="row" spacing={1} mt={1} flexWrap="wrap" useFlexGap>
                                     {(summary.enabledMcpNames || []).map((name) => (
                                         <Chip key={name} size="small" variant="outlined" label={name} />

--
Gitblit v1.9.1