diff --git a/dashboard/src/main.tsx b/dashboard/src/main.tsx index 242ab8e..a611162 100644 --- a/dashboard/src/main.tsx +++ b/dashboard/src/main.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import ReactDOM from 'react-dom/client'; import './styles.css'; @@ -89,6 +89,8 @@ function App() { const [terminalExpanded, setTerminalExpanded] = useState(false); const [terminalCollapsed, setTerminalCollapsed] = useState(false); const [sidebarCollapsed, setSidebarCollapsed] = useState(false); + const [language, setLanguage] = useState<'en' | 'zh'>('en'); + const [theme, setTheme] = useState<'light' | 'dark'>('light'); useEffect(() => { fetch('http://127.0.0.1:8788/services') @@ -107,6 +109,63 @@ function App() { const currentServices = services ?? mockServices; const selected = tabs.find((tab) => tab.id === selectedTab); + const labels = language === 'zh' + ? { + product: 'XWorkspace', + workspace: '工作空间', + collapse: '收起', + expand: '展开', + connected: '已连接', + agentsRunning: '个 Agent 运行中', + vaultReady: 'Vault 就绪', + homepageTitle: 'AI Workspace 控制面板', + homepageSubtitle: '在一个工作空间里统一组织 Runtime、Gateway 和本地 AI 服务。', + workspaceReady: '工作空间就绪', + activity: '服务活动', + coreServices: '核心服务', + serviceCards: '服务卡片', + today: '今天', + newTab: '新标签', + terminal: '终端', + maximize: '最大化', + restore: '还原', + themeLight: '浅色', + themeDark: '深色', + lang: '中/EN', + languageLabel: '语言', + themeLabel: '主题', + } + : { + product: 'XWorkspace', + workspace: 'Workspace', + collapse: 'Collapse', + expand: 'Expand', + connected: 'Connected', + agentsRunning: 'Agents Running', + vaultReady: 'Vault Ready', + homepageTitle: 'AI Workspace Control Plane', + homepageSubtitle: 'Runtime, gateway and local AI services are organized in one workspace.', + workspaceReady: 'Workspace Ready', + activity: 'Service Activity', + coreServices: 'Core Services', + serviceCards: 'Service Cards', + today: 'Today', + newTab: 'New Tab', + terminal: 'Terminal', + maximize: 'Maximize', + restore: 'Restore', + themeLight: 'Light', + themeDark: 'Dark', + lang: 'EN/中', + languageLabel: 'Language', + themeLabel: 'Theme', + }; + + const breadcrumbItems = [ + labels.product, + labels.workspace, + selected && selected.id !== 'workspace' ? selected.label : null, + ].filter(Boolean) as string[]; const summary = useMemo(() => { const runningServices = currentServices.filter((service) => service.state === 'Running').length; @@ -137,11 +196,11 @@ function App() { }; return ( -