mirror of
https://github.com/xmanrui/OpenClaw-bot-review.git
synced 2026-08-14 00:47:49 +00:00
1404 lines
58 KiB
TypeScript
1404 lines
58 KiB
TypeScript
"use client";
|
|
|
|
import { createContext, useContext, useState, useCallback, useEffect, ReactNode } from "react";
|
|
|
|
export type Locale = "vi" | "zh-TW" | "zh" | "en";
|
|
|
|
const translations: Record<Locale, Record<string, string>> = {
|
|
"zh-TW": {
|
|
// layout
|
|
"site.title": "OpenClaw Bot Dashboard",
|
|
"site.desc": "查看所有 OpenClaw 機器人設定",
|
|
|
|
// nav sidebar
|
|
"nav.overview": "總覽",
|
|
"nav.agents": "機器人",
|
|
"nav.models": "模型列表",
|
|
"nav.monitor": "監控",
|
|
"nav.sessions": "會話列表",
|
|
"nav.stats": "訊息統計",
|
|
"nav.pixelOffice": "像素辦公室",
|
|
"nav.config": "設定",
|
|
"nav.skills": "技能管理",
|
|
"nav.alerts": "警報中心",
|
|
"nav.experiments": "實驗功能",
|
|
"nav.expandSidebar": "展開側邊欄",
|
|
"nav.collapseSidebar": "收起側邊欄",
|
|
"nav.bugsOn": "Bugs On",
|
|
"nav.bugsOff": "Bugs Off",
|
|
"nav.bugsCount": "數量",
|
|
|
|
// R&D Council
|
|
"nav.rnd": "研發",
|
|
"nav.trending": "趨勢",
|
|
"nav.opportunity": "機會",
|
|
"nav.rdCouncil": "R&D 委員會",
|
|
"rdc.description": " AI 委員會 - 自動化決策與投資建議",
|
|
"rdc.active": "個項目",
|
|
"rdc.detected": "檢測於",
|
|
"rdc.estimated": "預測模型",
|
|
"rdc.scheduled": "排程",
|
|
"rdc.emergency": "緊急",
|
|
"rdc.debateSummary": " debates 摘要",
|
|
"rdc.disagreements": "爭議點",
|
|
"rdc.recommendation": "最終建議",
|
|
"rdc.passedReasoning": "通過原因",
|
|
"rdc.escalate": "快速上傳",
|
|
"rdc.schedule": "排程",
|
|
"rdc.escalateToCouncil": "快速上傳到委員會",
|
|
"rdc.whyEscalate": "為什麼要快速上傳?",
|
|
"rdc.priority": "優先級",
|
|
"rdc.normal": "正常",
|
|
"rdc.urgent": "緊急",
|
|
"rdc.comingSoon": "即將推出",
|
|
"rdc.latestMemo": "最新委員會备忘录",
|
|
"rdc.memoPreview": "新一期委員會會議已完成,請查看最新投資建議。",
|
|
"rdc.noItems": "暫無待處理項目",
|
|
|
|
// alerts page
|
|
"alerts.title": "警報中心",
|
|
"alerts.subtitle": "設定系統警報與通知",
|
|
"alerts.enableAlerts": "啟用警報",
|
|
"alerts.enableDesc": "開啟/關閉所有警報通知",
|
|
"alerts.receiveAgent": "接收警報的機器人",
|
|
"alerts.rules": "警報規則",
|
|
"alerts.rulesDesc": "設定哪些條件會觸發警報",
|
|
"alerts.triggered": "警報觸發 ({count})",
|
|
"alerts.checking": "正在檢查警報...",
|
|
"alerts.checkNow": "立即檢查",
|
|
"alerts.checkInterval": "檢查間隔",
|
|
|
|
// common
|
|
"common.loading": "思考中...",
|
|
"common.loadError": "載入失敗",
|
|
"common.backHome": "← 返回首頁",
|
|
"common.backOverview": "← 返回總覽",
|
|
"common.noData": "暫無資料",
|
|
"common.close": "關閉",
|
|
"common.test": "🧪 測試",
|
|
"common.testing": "⏳ 測試中...",
|
|
"common.justNow": "剛剛",
|
|
"common.minutesAgo": "分鐘前",
|
|
"common.hoursAgo": "小時前",
|
|
"common.daysAgo": "天前",
|
|
"common.manualRefresh": "手動重新整理",
|
|
"common.seconds": "秒",
|
|
"common.minute": "分鐘",
|
|
"common.minutes": "分鐘",
|
|
|
|
// home page
|
|
"home.title": "🐾 OpenClaw Bot Dashboard",
|
|
"home.agentCount": "個機器人",
|
|
"home.pageTitle": "OpenClaw 機器人",
|
|
"home.defaultModel": "預設模型",
|
|
"home.viewModels": "查看模型列表 →",
|
|
"home.skillMgmt": "🧩 技能管理",
|
|
"home.testAll": "測試已綁定模型",
|
|
"home.testingAll": "測試模型中...",
|
|
"home.testOk": "正常",
|
|
"home.testFail": "異常",
|
|
"home.updatedAt": "更新於",
|
|
"home.refreshManual": "🔄 手動重新整理",
|
|
"home.globalTrend": "📊 全域統計趨勢",
|
|
"home.totalInputToken": "總 Input Token",
|
|
"home.totalOutputToken": "總 Output Token",
|
|
"home.totalMessages": "總訊息數",
|
|
"home.tokenTrend": "🔢 Token 消耗趨勢",
|
|
"home.avgResponseTrend": "⏱️ 平均回應時間趨勢",
|
|
"home.groupTopology": "💬 群聊拓撲",
|
|
"home.fallbackModels": "🔄 Fallback 模型",
|
|
"home.feishuGroup": "飛書群",
|
|
"home.discordChannel": "Discord 頻道",
|
|
"home.bots": "個機器人",
|
|
"home.noResponseData": "暫無回應時間資料",
|
|
"home.testPlatforms": "測試平台連線",
|
|
"home.testingPlatforms": "測試平台中...",
|
|
"home.testSessions": "測試 Agent 會話",
|
|
"home.testingSessions": "測試會話中...",
|
|
"home.testDmSessions": "測試 DM Session",
|
|
"home.testingDmSessions": "測試中...",
|
|
"home.agentTaskTracking": "Agent 任務追蹤",
|
|
"home.agentTaskSubtasks": "子任務",
|
|
"home.agentTaskCron": "排程任務",
|
|
"home.agentTaskState.working": "執行中",
|
|
"home.agentTaskState.waiting": "等待中",
|
|
"home.agentTaskState.idle": "閒置",
|
|
"home.agentTaskNoSubtasks": "無進行中的子任務",
|
|
"home.agentTaskNoCron": "無排程任務活動",
|
|
"home.agentTaskCronState.running": "執行中",
|
|
"home.agentTaskCronState.success": "成功",
|
|
"home.agentTaskCronState.failed": "失敗",
|
|
"home.agentTaskCronFailures": "連續失敗",
|
|
"home.agentTaskCronNoSummary": "暫無摘要",
|
|
"home.agentTaskCronDuration": "耗時",
|
|
"home.agentTaskCronNextRun": "下次執行",
|
|
|
|
// agent card
|
|
"agent.model": "模型",
|
|
"agent.platform": "平台",
|
|
"agent.feishuAppId": "飛書 App ID",
|
|
"agent.sessionCount": "會話數",
|
|
"agent.messageCount": "訊息數",
|
|
"agent.tokenUsage": "Token 用量",
|
|
"agent.totalTokenTip": "總 Token 使用量",
|
|
"agent.stats": "統計",
|
|
"agent.lastActive": "最近活躍",
|
|
"agent.todayAvgResponse": "平均回應",
|
|
"agent.todayAvgResponseTip": "今日平均回應時間",
|
|
"agent.switchModel": "切換模型",
|
|
"agent.saveModel": "儲存並套用",
|
|
"agent.cancelModel": "取消",
|
|
"agent.modelSaving": "套用中...",
|
|
"agent.modelApplyHint": "儲存後會自動重新啟動 Gateway,以套用新模型。",
|
|
"agent.modelApplyFailed": "模型套用失敗",
|
|
"agent.currentUnknownModel": "目前模型(不在候選列表)",
|
|
|
|
// agent status
|
|
"agent.status.working": "工作中",
|
|
"agent.status.online": "線上",
|
|
"agent.status.idle": "閒置",
|
|
"agent.status.offline": "離線",
|
|
"agent.inUse": "使用中:",
|
|
"agent.openChat": "點擊開啟聊天頁面",
|
|
|
|
// platform
|
|
"platform.feishu": "📱 飛書",
|
|
"platform.yuanbao": "🤖 元宝",
|
|
"platform.discord": "🎮 Discord",
|
|
"platform.telegram": "✈️ Telegram",
|
|
"platform.whatsapp": "💬 WhatsApp",
|
|
"platform.qqbot": "🐧 QQBot",
|
|
"platform.wecom": "💼 企業微信",
|
|
|
|
// time range
|
|
"range.daily": "按日",
|
|
"range.weekly": "按週",
|
|
"range.monthly": "按月",
|
|
"range.total": "總計",
|
|
|
|
// refresh options
|
|
"refresh.manual": "手動重新整理",
|
|
"refresh.10s": "10 秒",
|
|
"refresh.30s": "30 秒",
|
|
"refresh.1m": "1 分鐘",
|
|
"refresh.5m": "5 分鐘",
|
|
"refresh.10m": "10 分鐘",
|
|
|
|
// models page
|
|
"models.title": "OpenClaw 接入模型列表",
|
|
"models.providerCount": "個 Provider",
|
|
"models.totalPrefix": "共",
|
|
"models.testAll": "🧪 測試全部模型",
|
|
"models.testingAll": "⏳ 測試中...",
|
|
"models.colModelId": "模型 ID",
|
|
"models.colName": "名稱",
|
|
"models.colAccessMode": "接入方式",
|
|
"models.accessModeApiKey": "api_key",
|
|
"models.accessModeAuth": "auth",
|
|
"models.colContext": "上下文視窗",
|
|
"models.colMaxOutput": "最大輸出",
|
|
"models.colInputType": "輸入類型",
|
|
"models.colReasoning": "推理",
|
|
"models.colInputToken": "Input Token",
|
|
"models.colOutputToken": "Output Token",
|
|
"models.colAvgResponse": "平均回應",
|
|
"models.colTest": "測試",
|
|
"models.noExplicitModels": "無顯式模型定義(透過 provider 名稱推斷)",
|
|
"models.defaultModel": "主模型",
|
|
"models.fallbackModels": "Fallback 模型",
|
|
|
|
// stats page
|
|
"stats.title": "訊息統計",
|
|
"stats.subtitle": "Token 消耗與回應時間分析",
|
|
"stats.totalInputToken": "總 Input Token",
|
|
"stats.totalOutputToken": "總 Output Token",
|
|
"stats.totalMessages": "總訊息數",
|
|
"stats.dataPeriod": "資料週期",
|
|
"stats.tokenConsumption": "🔢 Token 消耗",
|
|
"stats.avgResponseTime": "⏱️ 平均回應時間",
|
|
"stats.sessionList": "📋 會話列表",
|
|
"stats.home": "← 首頁",
|
|
"stats.missingAgent": "缺少 agent 參數",
|
|
"stats.noResponseData": "暫無回應時間資料",
|
|
"stats.selectAgent": "選擇一個機器人查看其訊息統計",
|
|
"stats.backToAgents": "← 返回機器人列表",
|
|
|
|
// sessions page
|
|
"sessions.title": "的會話列表",
|
|
"sessions.sessionCount": "個會話",
|
|
"sessions.totalToken": "總 Token",
|
|
"sessions.missingAgent": "缺少 agent 參數",
|
|
"sessions.type.main": "主會話",
|
|
"sessions.type.feishu-dm": "飛書私訊",
|
|
"sessions.type.feishu-group": "飛書群聊",
|
|
"sessions.type.discord-dm": "Discord 私訊",
|
|
"sessions.type.discord-channel": "Discord 頻道",
|
|
"sessions.type.telegram-dm": "Telegram 私訊",
|
|
"sessions.type.telegram-group": "Telegram 群聊",
|
|
"sessions.type.whatsapp-dm": "WhatsApp 私訊",
|
|
"sessions.type.whatsapp-group": "WhatsApp 群聊",
|
|
"sessions.type.cron": "排程任務",
|
|
"sessions.type.unknown": "未知",
|
|
"sessions.test": "測試",
|
|
"sessions.testing": "測試中...",
|
|
"sessions.testOk": "✅ 正常",
|
|
"sessions.testFail": "❌ 異常",
|
|
"sessions.testReply": "回覆",
|
|
"sessions.testTime": "耗時",
|
|
"sessions.context": "上下文",
|
|
"sessions.selectAgent": "選擇一個機器人查看其會話列表",
|
|
"sessions.testAll": "🧪 測試全部",
|
|
"sessions.testingAll": "⏳ 測試中...",
|
|
"sessions.testHint": "測試驗證 Agent 是否能回應,訊息不會出現在飛書/Discord 會話中",
|
|
"sessions.testAllResult": "測試完成",
|
|
"sessions.testAllOk": "通過",
|
|
"sessions.testAllFail": "失敗",
|
|
"sessions.backToAgents": "← 返回機器人列表",
|
|
|
|
// skills page
|
|
"skills.title": "🧩 技能管理",
|
|
"skills.count": "個技能",
|
|
"skills.builtin": "內建",
|
|
"skills.extension": "擴充",
|
|
"skills.custom": "自訂",
|
|
"skills.workspace": "工作區",
|
|
"skills.all": "全部",
|
|
"skills.search": "搜尋技能...",
|
|
"skills.showing": "顯示",
|
|
"skills.unit": "個",
|
|
"skills.noDesc": "無描述",
|
|
"skills.source.builtin": "內建",
|
|
"skills.source.custom": "自訂",
|
|
"skills.source.workspace": "工作區",
|
|
"skills.workspace.main": "主工作區",
|
|
"skills.workspaceFilter.all": "所有工作區",
|
|
"skills.viewSource": "查看 SKILL.md",
|
|
"skills.contentTitle": "SKILL.md 內容",
|
|
"skills.loadingContent": "正在載入技能內容...",
|
|
"skills.contentLoadFailed": "技能內容載入失敗",
|
|
|
|
// gateway status
|
|
"gateway.healthy": "Gateway 運作正常",
|
|
"gateway.unhealthy": "Gateway 異常",
|
|
"gateway.fetchError": "無法檢查 Gateway 狀態",
|
|
"gateway.noResponse": "Gateway 無回應",
|
|
"gateway.configChanged": "偵測到 openclaw.json 最近有變更,可能是設定錯誤導致。",
|
|
"gateway.configError": "設定檔可能有誤",
|
|
"gateway.configErrorDesc": "Gateway 無法啟動,可能是 openclaw.json 設定錯誤",
|
|
"gateway.restorePrev": "🔄 還原上一版設定",
|
|
"gateway.viewLogs": "📋 查看錯誤日誌",
|
|
"gateway.dismiss": "❌ 不處理",
|
|
"gateway.backupAvailable": "有可用備份",
|
|
"gateway.restoreBackup": "還原備份",
|
|
"gateway.restoring": "還原中…",
|
|
"gateway.restoreSuccess": "✅ 已還原,正在重啟 Gateway…",
|
|
"gateway.restoreFailed": "❌ 還原失敗",
|
|
"gateway.noBackups": "沒有可用的備份",
|
|
"gateway.backupRecommended": "建議",
|
|
"gateway.backupSuspect": "可能損毀",
|
|
"gateway.reloadCountdown": "秒後自動重新整理…",
|
|
"gateway.reloadNow": "立即重新整理",
|
|
"gateway.reloadHint": "重新整理後,可點選機器人卡片上的「測試」確認是否正常運作",
|
|
"gateway.configCorruptHint": "設定檔可能損毀,請使用上方 Gateway 面板還原備份",
|
|
|
|
// pixel office
|
|
"pixelOffice.title": "OpenClaw Agents 辦公室",
|
|
"pixelOffice.editMode": "編輯版面",
|
|
"pixelOffice.exitEdit": "退出編輯",
|
|
"pixelOffice.save": "儲存",
|
|
"pixelOffice.reset": "重設",
|
|
"pixelOffice.undo": "復原",
|
|
"pixelOffice.redo": "重做",
|
|
"pixelOffice.sound": "音效",
|
|
"pixelOffice.resetView": "重設視圖",
|
|
"pixelOffice.state.working": "工作中",
|
|
"pixelOffice.state.idle": "休息中",
|
|
"pixelOffice.state.offline": "下班了",
|
|
"pixelOffice.state.waiting": "等待中",
|
|
"pixelOffice.tempWorker": "臨時工",
|
|
"pixelOffice.tempWorker.source": "臨時工來源",
|
|
"pixelOffice.tempWorker.createdBy": "建立的 subagent",
|
|
"pixelOffice.broadcast.online": "上班了",
|
|
"pixelOffice.broadcast.offline": "下班了",
|
|
"pixelOffice.heatmap.title": "Agent 工作時間熱力圖",
|
|
"pixelOffice.heatmap.messages": "則訊息",
|
|
"pixelOffice.idleRank.title": "摸魚排行榜",
|
|
"pixelOffice.idleRank.online": "線上",
|
|
"pixelOffice.idleRank.active": "活躍",
|
|
"pixelOffice.idleRank.idle": "摸魚",
|
|
"pixelOffice.serverStatus.checking": "正在檢查伺服器狀態...",
|
|
"pixelOffice.serverStatus.healthy": "服務正常",
|
|
"pixelOffice.serverStatus.degraded": "服務退化",
|
|
"pixelOffice.serverStatus.down": "服務異常",
|
|
"pixelOffice.serverStatus.unknown": "狀態未知",
|
|
"pixelOffice.serverStatus.fetchFailed": "狀態檢查失敗",
|
|
"pixelOffice.gatewaySre.name": "值班工程師",
|
|
"pixelOffice.gatewaySre.statusLabel": "Gateway 狀態",
|
|
"pixelOffice.gatewaySre.responseMs": "檢查耗時",
|
|
"pixelOffice.gatewaySre.status.unknown": "監控中",
|
|
"pixelOffice.gatewaySre.status.healthy": "健康",
|
|
"pixelOffice.gatewaySre.status.degraded": "退化",
|
|
"pixelOffice.gatewaySre.status.down": "故障",
|
|
"pixelOffice.gatewaySre.tip.unknown": "正在等待閘道健康資料",
|
|
"pixelOffice.gatewaySre.tip.healthy": "Gateway healthy",
|
|
"pixelOffice.gatewaySre.tip.degraded": "Gateway degraded: latency high",
|
|
"pixelOffice.gatewaySre.tip.down": "Gateway down",
|
|
},
|
|
zh: {
|
|
// layout
|
|
"site.title": "OpenClaw Bot Dashboard",
|
|
"site.desc": "查看所有 OpenClaw 机器人配置",
|
|
|
|
// nav sidebar
|
|
"nav.overview": "总览",
|
|
"nav.agents": "机器人",
|
|
"nav.workspace": "Agent 工作台",
|
|
"nav.daily": "今日播报",
|
|
"nav.models": "模型列表",
|
|
"nav.monitor": "监控",
|
|
"nav.sessions": "会话列表",
|
|
"nav.stats": "消息统计",
|
|
"nav.pixelOffice": "像素办公室",
|
|
"nav.config": "配置",
|
|
"nav.skills": "技能管理",
|
|
"nav.alerts": "告警中心",
|
|
"nav.experiments": "实验功能",
|
|
"nav.expandSidebar": "展开侧边栏",
|
|
"nav.collapseSidebar": "收起侧边栏",
|
|
"nav.bugsOn": "Bugs On",
|
|
"nav.bugsOff": "Bugs Off",
|
|
"nav.bugsCount": "数量",
|
|
|
|
// R&D Council
|
|
"nav.rnd": "R&D",
|
|
"nav.trending": "Trending",
|
|
"nav.opportunity": "Opportunity",
|
|
"nav.rdCouncil": "R&D Council",
|
|
"nav.selfImprovement": "Self-Improvement",
|
|
"rdc.description": "AI Council - Automated Decision & Investment Recommendations",
|
|
"rdc.active": "个项目",
|
|
"rdc.detected": "检测于",
|
|
"rdc.estimated": "预测模型",
|
|
"rdc.scheduled": "排程",
|
|
"rdc.emergency": "紧急",
|
|
"rdc.debateSummary": "辩论摘要",
|
|
"rdc.disagreements": "争议点",
|
|
"rdc.recommendation": "最终建议",
|
|
"rdc.passedReasoning": "通过原因",
|
|
"rdc.escalate": "快速上传",
|
|
"rdc.schedule": "排程",
|
|
"rdc.escalateToCouncil": "快速上传到委员会",
|
|
"rdc.whyEscalate": "为什么快速上传?",
|
|
"rdc.priority": "优先级",
|
|
"rdc.normal": "正常",
|
|
"rdc.urgent": "紧急",
|
|
"rdc.comingSoon": "即将推出",
|
|
"rdc.latestMemo": "最新委员会备忘录",
|
|
"rdc.memoPreview": "新一期委员会会议已完成,请查看最新投资建议。",
|
|
"rdc.noItems": "暂无待处理项目",
|
|
"selfImprovement.subtitle": "协议审核、批准、拒绝或发送回AI建议",
|
|
"selfImprovement.terminal": "执行日志",
|
|
"selfImprovement.projects": "改进项目",
|
|
|
|
// alerts page
|
|
"alerts.title": "告警中心",
|
|
"alerts.subtitle": "配置系统告警和通知",
|
|
"alerts.enableAlerts": "启用告警",
|
|
"alerts.enableDesc": "开启/关闭所有告警通知",
|
|
"alerts.receiveAgent": "接收告警的机器人",
|
|
"alerts.rules": "告警规则",
|
|
"alerts.rulesDesc": "配置哪些条件会触发告警",
|
|
"alerts.triggered": "告警触发 ({count})",
|
|
"alerts.checking": "正在检查告警...",
|
|
"alerts.checkNow": "立即检查",
|
|
"alerts.checkInterval": "检查间隔",
|
|
|
|
// common
|
|
"common.loading": "思考中...",
|
|
"common.loadError": "加载失败",
|
|
"common.backHome": "← 返回首页",
|
|
"common.backOverview": "← 返回总览",
|
|
"common.noData": "暂无数据",
|
|
"common.close": "关闭",
|
|
"common.test": "🧪 测试",
|
|
"common.testing": "⏳ 测试中...",
|
|
"common.justNow": "刚刚",
|
|
"common.minutesAgo": "分钟前",
|
|
"common.hoursAgo": "小时前",
|
|
"common.daysAgo": "天前",
|
|
"common.manualRefresh": "手动刷新",
|
|
"common.seconds": "秒",
|
|
"common.minute": "分钟",
|
|
"common.minutes": "分钟",
|
|
|
|
// home page
|
|
"home.title": "🐾 OpenClaw Bot Dashboard",
|
|
"home.agentCount": "个机器人",
|
|
"home.pageTitle": "OpenClaw 机器人",
|
|
"home.defaultModel": "默认模型",
|
|
"home.viewModels": "查看模型列表 →",
|
|
"home.skillMgmt": "🧩 技能管理",
|
|
"home.testAll": "测试已绑定模型",
|
|
"home.testingAll": "测试模型中...",
|
|
"home.testOk": "正常",
|
|
"home.testFail": "异常",
|
|
"home.updatedAt": "更新于",
|
|
"home.refreshManual": "🔄 手动刷新",
|
|
"home.globalTrend": "📊 全局统计趋势",
|
|
"home.totalInputToken": "总 Input Token",
|
|
"home.totalOutputToken": "总 Output Token",
|
|
"home.totalMessages": "总消息数",
|
|
"home.tokenTrend": "🔢 Token 消耗趋势",
|
|
"home.avgResponseTrend": "⏱️ 平均响应时间趋势",
|
|
"home.groupTopology": "💬 群聊拓扑",
|
|
"home.fallbackModels": "🔄 Fallback 模型",
|
|
"home.feishuGroup": "飞书群",
|
|
"home.discordChannel": "Discord 频道",
|
|
"home.bots": "个机器人",
|
|
"home.noResponseData": "暂无响应时间数据",
|
|
"home.testPlatforms": "测试平台连通",
|
|
"home.testingPlatforms": "测试平台中...",
|
|
"home.testSessions": "测试 Agent 会话",
|
|
"home.testingSessions": "测试会话中...",
|
|
"home.testDmSessions": "测试 DM Session",
|
|
"home.testingDmSessions": "测试中...",
|
|
"home.agentTaskTracking": "Agent 任务追踪",
|
|
"home.agentTaskSubtasks": "子任务",
|
|
"home.agentTaskCron": "定时任务",
|
|
"home.agentTaskState.working": "执行中",
|
|
"home.agentTaskState.waiting": "等待中",
|
|
"home.agentTaskState.idle": "闲置",
|
|
"home.agentTaskNoSubtasks": "无进行中的子任务",
|
|
"home.agentTaskNoCron": "无定时任务活动",
|
|
"home.agentTaskCronState.running": "执行中",
|
|
"home.agentTaskCronState.success": "成功",
|
|
"home.agentTaskCronState.failed": "失败",
|
|
"home.agentTaskCronFailures": "连续失败",
|
|
"home.agentTaskCronNoSummary": "暂无摘要",
|
|
"home.agentTaskCronDuration": "耗时",
|
|
"home.agentTaskCronNextRun": "下次执行",
|
|
|
|
// agent card
|
|
"agent.model": "模型",
|
|
"agent.platform": "平台",
|
|
"agent.feishuAppId": "飞书 App ID",
|
|
"agent.sessionCount": "会话数",
|
|
"agent.messageCount": "消息数",
|
|
"agent.tokenUsage": "Token 用量",
|
|
"agent.totalTokenTip": "总 Token 使用量",
|
|
"agent.stats": "统计",
|
|
"agent.lastActive": "最近活跃",
|
|
"agent.todayAvgResponse": "平均响应",
|
|
"agent.todayAvgResponseTip": "今日平均响应时间",
|
|
"agent.switchModel": "切换模型",
|
|
"agent.saveModel": "保存并应用",
|
|
"agent.cancelModel": "取消",
|
|
"agent.modelSaving": "应用中...",
|
|
"agent.modelApplyHint": "保存后会自动重启 Gateway,以应用新模型。",
|
|
"agent.modelApplyFailed": "模型应用失败",
|
|
"agent.currentUnknownModel": "当前模型(不在候选列表)",
|
|
|
|
// agent status
|
|
"agent.status.working": "工作中",
|
|
"agent.status.online": "在线",
|
|
"agent.status.idle": "空闲",
|
|
"agent.status.offline": "离线",
|
|
"agent.inUse": "使用中:",
|
|
"agent.openChat": "点击打开聊天页面",
|
|
|
|
// platform
|
|
"platform.feishu": "📱 飞书",
|
|
"platform.yuanbao": "🤖 元宝",
|
|
"platform.discord": "🎮 Discord",
|
|
"platform.telegram": "✈️ Telegram",
|
|
"platform.whatsapp": "💬 WhatsApp",
|
|
"platform.qqbot": "🐧 QQBot",
|
|
"platform.wecom": "💼 企业微信",
|
|
|
|
// time range
|
|
"range.daily": "按天",
|
|
"range.weekly": "按周",
|
|
"range.monthly": "按月",
|
|
"range.total": "总计",
|
|
|
|
// refresh options
|
|
"refresh.manual": "手动刷新",
|
|
"refresh.10s": "10 秒",
|
|
"refresh.30s": "30 秒",
|
|
"refresh.1m": "1 分钟",
|
|
"refresh.5m": "5 分钟",
|
|
"refresh.10m": "10 分钟",
|
|
|
|
// models page
|
|
"models.title": "OpenClaw接入模型列表",
|
|
"models.providerCount": "个 Provider",
|
|
"models.totalPrefix": "共",
|
|
"models.testAll": "🧪 测试全部模型",
|
|
"models.testingAll": "⏳ 测试中...",
|
|
"models.colModelId": "模型 ID",
|
|
"models.colName": "名称",
|
|
"models.colAccessMode": "接入方式",
|
|
"models.accessModeApiKey": "api_key",
|
|
"models.accessModeAuth": "auth",
|
|
"models.colContext": "上下文窗口",
|
|
"models.colMaxOutput": "最大输出",
|
|
"models.colInputType": "输入类型",
|
|
"models.colReasoning": "推理",
|
|
"models.colInputToken": "Input Token",
|
|
"models.colOutputToken": "Output Token",
|
|
"models.colAvgResponse": "平均响应",
|
|
"models.colTest": "测试",
|
|
"models.noExplicitModels": "无显式模型定义(通过 provider 名称推断)",
|
|
"models.defaultModel": "主模型",
|
|
"models.fallbackModels": "Fallback 模型",
|
|
|
|
// stats page
|
|
"stats.title": "消息统计",
|
|
"stats.subtitle": "Token 消耗与响应时间分析",
|
|
"stats.totalInputToken": "总 Input Token",
|
|
"stats.totalOutputToken": "总 Output Token",
|
|
"stats.totalMessages": "总消息数",
|
|
"stats.dataPeriod": "数据周期",
|
|
"stats.tokenConsumption": "🔢 Token 消耗",
|
|
"stats.avgResponseTime": "⏱️ 平均响应时间",
|
|
"stats.sessionList": "📋 会话列表",
|
|
"stats.home": "← 首页",
|
|
"stats.missingAgent": "缺少 agent 参数",
|
|
"stats.noResponseData": "暂无响应时间数据",
|
|
"stats.selectAgent": "选择一个机器人查看其消息统计",
|
|
"stats.backToAgents": "← 返回机器人列表",
|
|
|
|
// sessions page
|
|
"sessions.title": "的会话列表",
|
|
"sessions.sessionCount": "个会话",
|
|
"sessions.totalToken": "总 Token",
|
|
"sessions.missingAgent": "缺少 agent 参数",
|
|
"sessions.type.main": "主会话",
|
|
"sessions.type.feishu-dm": "飞书私聊",
|
|
"sessions.type.feishu-group": "飞书群聊",
|
|
"sessions.type.discord-dm": "Discord 私聊",
|
|
"sessions.type.discord-channel": "Discord 频道",
|
|
"sessions.type.telegram-dm": "Telegram 私聊",
|
|
"sessions.type.telegram-group": "Telegram 群聊",
|
|
"sessions.type.whatsapp-dm": "WhatsApp 私聊",
|
|
"sessions.type.whatsapp-group": "WhatsApp 群聊",
|
|
"sessions.type.cron": "定时任务",
|
|
"sessions.type.unknown": "未知",
|
|
"sessions.test": "测试",
|
|
"sessions.testing": "测试中...",
|
|
"sessions.testOk": "✅ 正常",
|
|
"sessions.testFail": "❌ 异常",
|
|
"sessions.testReply": "回复",
|
|
"sessions.testTime": "耗时",
|
|
"sessions.context": "上下文",
|
|
"sessions.selectAgent": "选择一个机器人查看其会话列表",
|
|
"sessions.testAll": "🧪 测试全部",
|
|
"sessions.testingAll": "⏳ 测试中...",
|
|
"sessions.testHint": "测试验证 Agent 是否能响应,消息不会出现在飞书/Discord 会话中",
|
|
"sessions.testAllResult": "测试完成",
|
|
"sessions.testAllOk": "通过",
|
|
"sessions.testAllFail": "失败",
|
|
"sessions.backToAgents": "← 返回机器人列表",
|
|
|
|
// skills page
|
|
"skills.title": "🧩 技能管理",
|
|
"skills.count": "个技能",
|
|
"skills.builtin": "内置",
|
|
"skills.extension": "扩展",
|
|
"skills.custom": "自定义",
|
|
"skills.workspace": "工作区",
|
|
"skills.all": "全部",
|
|
"skills.search": "搜索技能...",
|
|
"skills.showing": "显示",
|
|
"skills.unit": "个",
|
|
"skills.noDesc": "无描述",
|
|
"skills.source.builtin": "内置",
|
|
"skills.source.custom": "自定义",
|
|
"skills.source.workspace": "工作区",
|
|
"skills.workspace.main": "主工作区",
|
|
"skills.workspaceFilter.all": "所有工作区",
|
|
"skills.viewSource": "查看 SKILL.md",
|
|
"skills.contentTitle": "SKILL.md 内容",
|
|
"skills.loadingContent": "正在加载技能内容...",
|
|
"skills.contentLoadFailed": "技能内容加载失败",
|
|
|
|
// gateway status
|
|
"gateway.healthy": "Gateway 运行正常",
|
|
"gateway.unhealthy": "Gateway 异常",
|
|
"gateway.fetchError": "无法检查 Gateway 状态",
|
|
"gateway.noResponse": "Gateway 无响应",
|
|
"gateway.configChanged": "检测到 openclaw.json 最近有变更,可能是配置错误导致。",
|
|
"gateway.configError": "配置文件可能有误",
|
|
"gateway.configErrorDesc": "Gateway 无法启动,可能是 openclaw.json 配置错误",
|
|
"gateway.restorePrev": "🔄 还原上一版配置",
|
|
"gateway.viewLogs": "📋 查看错误日志",
|
|
"gateway.dismiss": "❌ 不处理",
|
|
"gateway.backupAvailable": "有可用备份",
|
|
"gateway.restoreBackup": "还原备份",
|
|
"gateway.restoring": "还原中…",
|
|
"gateway.restoreSuccess": "✅ 已还原,正在重启 Gateway…",
|
|
"gateway.restoreFailed": "❌ 还原失败",
|
|
"gateway.noBackups": "没有可用的备份",
|
|
"gateway.backupRecommended": "建议",
|
|
"gateway.backupSuspect": "可能损坏",
|
|
"gateway.reloadCountdown": "秒后自动刷新…",
|
|
"gateway.reloadNow": "立即刷新",
|
|
"gateway.reloadHint": "刷新后,可点击机器人卡片上的「测试」确认是否正常运作",
|
|
"gateway.configCorruptHint": "配置文件可能损坏,请使用上方 Gateway 面板还原备份",
|
|
|
|
// pixel office
|
|
"pixelOffice.title": "OpenClaw Agents办公室",
|
|
"pixelOffice.editMode": "编辑布局",
|
|
"pixelOffice.exitEdit": "退出编辑",
|
|
"pixelOffice.save": "保存",
|
|
"pixelOffice.reset": "重置",
|
|
"pixelOffice.undo": "撤销",
|
|
"pixelOffice.redo": "重做",
|
|
"pixelOffice.sound": "音效",
|
|
"pixelOffice.resetView": "重置视图",
|
|
"pixelOffice.state.working": "工作中",
|
|
"pixelOffice.state.idle": "摸鱼中",
|
|
"pixelOffice.state.offline": "下班了",
|
|
"pixelOffice.state.waiting": "等待中",
|
|
"pixelOffice.tempWorker": "临时工",
|
|
"pixelOffice.tempWorker.source": "临时工来源",
|
|
"pixelOffice.tempWorker.createdBy": "创建的 subagent",
|
|
"pixelOffice.broadcast.online": "上班了",
|
|
"pixelOffice.broadcast.offline": "下班了",
|
|
"pixelOffice.heatmap.title": "Agent 工作时间热力图",
|
|
"pixelOffice.heatmap.messages": "条消息",
|
|
"pixelOffice.idleRank.title": "摸鱼排行榜",
|
|
"pixelOffice.idleRank.online": "在线",
|
|
"pixelOffice.idleRank.active": "活跃",
|
|
"pixelOffice.idleRank.idle": "摸鱼",
|
|
"pixelOffice.serverStatus.checking": "正在检查服务器状态...",
|
|
"pixelOffice.serverStatus.healthy": "服务正常",
|
|
"pixelOffice.serverStatus.degraded": "服务退化",
|
|
"pixelOffice.serverStatus.down": "服务异常",
|
|
"pixelOffice.serverStatus.unknown": "状态未知",
|
|
"pixelOffice.serverStatus.fetchFailed": "状态检查失败",
|
|
"pixelOffice.gatewaySre.name": "值班SRE",
|
|
"pixelOffice.gatewaySre.statusLabel": "Gateway状态",
|
|
"pixelOffice.gatewaySre.responseMs": "检查耗时",
|
|
"pixelOffice.gatewaySre.status.unknown": "监控中",
|
|
"pixelOffice.gatewaySre.status.healthy": "健康",
|
|
"pixelOffice.gatewaySre.status.degraded": "退化",
|
|
"pixelOffice.gatewaySre.status.down": "故障",
|
|
"pixelOffice.gatewaySre.tip.unknown": "正在等待网关健康数据",
|
|
"pixelOffice.gatewaySre.tip.healthy": "Gateway healthy",
|
|
"pixelOffice.gatewaySre.tip.degraded": "Gateway degraded: latency high",
|
|
"pixelOffice.gatewaySre.tip.down": "Gateway down",
|
|
},
|
|
en: {
|
|
// layout
|
|
"site.title": "OpenClaw Bot Dashboard",
|
|
"site.desc": "View all OpenClaw bot configurations",
|
|
|
|
// nav sidebar
|
|
"nav.overview": "Overview",
|
|
"nav.agents": "Bots",
|
|
"nav.workspace": "Agent Workspace",
|
|
"nav.daily": "Daily Report",
|
|
"nav.models": "Models",
|
|
"nav.monitor": "Monitor",
|
|
"nav.sessions": "Sessions",
|
|
"nav.stats": "Statistics",
|
|
"nav.pixelOffice": "Pixel Office",
|
|
"nav.config": "Config",
|
|
"nav.skills": "Skills",
|
|
"nav.alerts": "Alerts",
|
|
"nav.experiments": "Experiments",
|
|
"nav.expandSidebar": "Expand sidebar",
|
|
"nav.collapseSidebar": "Collapse sidebar",
|
|
"nav.bugsOn": "Bugs On",
|
|
"nav.bugsOff": "Bugs Off",
|
|
"nav.bugsCount": "Count",
|
|
|
|
// R&D Council
|
|
"nav.rnd": "R&D",
|
|
"nav.trending": "Trending",
|
|
"nav.opportunity": "Opportunity",
|
|
"nav.rdCouncil": "R&D Council",
|
|
"nav.selfImprovement": "Self-Improvement",
|
|
"rdc.description": "AI Council - Automated Decision & Investment Recommendations",
|
|
"rdc.active": "items",
|
|
"rdc.detected": "Detected",
|
|
"rdc.estimated": "Estimated Model",
|
|
"rdc.scheduled": "Scheduled",
|
|
"rdc.emergency": "Emergency",
|
|
"rdc.debateSummary": "Debate Summary",
|
|
"rdc.disagreements": "Disagreements",
|
|
"rdc.recommendation": "Recommendation",
|
|
"rdc.passedReasoning": "Passed Reasoning",
|
|
"rdc.escalate": "Escalate",
|
|
"rdc.schedule": "Schedule",
|
|
"rdc.escalateToCouncil": "Escalate to Council",
|
|
"rdc.whyEscalate": "Why escalate this?",
|
|
"rdc.priority": "Priority",
|
|
"rdc.normal": "Normal",
|
|
"rdc.urgent": "Urgent",
|
|
"rdc.comingSoon": "Coming Soon",
|
|
"rdc.latestMemo": "Latest Council Memo",
|
|
"rdc.memoPreview": "Council session completed. Check latest investment recommendations.",
|
|
"rdc.noItems": "No pending items",
|
|
"rdc.originTags.reactive": "📊 Reactive Analysis",
|
|
"rdc.originTags.efficiency": "⚙️ Efficiency Gap",
|
|
"rdc.originTags.infrastructure": "🏗️ Infrastructure Idea",
|
|
"rdc.originTags.pattern": "🔍 Pattern Detected",
|
|
"rdc.originTags.external": "🌐 External Opportunity",
|
|
"selfImprovement.subtitle": "Protocol to review, approve, reject, or send back AI recommendations",
|
|
"selfImprovement.terminal": "Execution Log",
|
|
|
|
// alerts page
|
|
"alerts.title": "Alert Center",
|
|
"alerts.subtitle": "Configure system alerts and notifications",
|
|
"alerts.enableAlerts": "Enable Alerts",
|
|
"alerts.enableDesc": "Turn on/off all alert notifications",
|
|
"alerts.receiveAgent": "Receive Alert Agent",
|
|
"alerts.rules": "Alert Rules",
|
|
"alerts.rulesDesc": "Configure which conditions trigger alerts",
|
|
"alerts.triggered": "Alerts Triggered ({count})",
|
|
"alerts.checking": "Checking alerts...",
|
|
"alerts.checkNow": "Check Now",
|
|
"alerts.checkInterval": "Check Interval",
|
|
|
|
// common
|
|
"common.loading": "thinking...",
|
|
"common.loadError": "Failed to load",
|
|
"common.backHome": "← Back to Home",
|
|
"common.backOverview": "← Back to Overview",
|
|
"common.noData": "No data",
|
|
"common.close": "Close",
|
|
"common.test": "🧪 Test",
|
|
"common.testing": "⏳ Testing...",
|
|
"common.justNow": "just now",
|
|
"common.minutesAgo": "min ago",
|
|
"common.hoursAgo": "hours ago",
|
|
"common.daysAgo": "days ago",
|
|
"common.manualRefresh": "Manual Refresh",
|
|
"common.seconds": "seconds",
|
|
"common.minute": "minute",
|
|
"common.minutes": "minutes",
|
|
|
|
// home page
|
|
"home.title": "🐾 OpenClaw Bot Dashboard",
|
|
"home.agentCount": "bots",
|
|
"home.pageTitle": "OpenClaw Bots",
|
|
"home.defaultModel": "Default model",
|
|
"home.viewModels": "View Models →",
|
|
"home.skillMgmt": "🧩 Skills",
|
|
"home.testAll": "Test Bound Models",
|
|
"home.testingAll": "Testing Models...",
|
|
"home.testOk": "OK",
|
|
"home.testFail": "Failed",
|
|
"home.updatedAt": "Updated at",
|
|
"home.refreshManual": "🔄 Manual Refresh",
|
|
"home.globalTrend": "📊 Global Statistics",
|
|
"home.totalInputToken": "Total Input Token",
|
|
"home.totalOutputToken": "Total Output Token",
|
|
"home.totalMessages": "Total Messages",
|
|
"home.tokenTrend": "🔢 Token Usage Trend",
|
|
"home.avgResponseTrend": "⏱️ Avg Response Time Trend",
|
|
"home.groupTopology": "💬 Group Chat Topology",
|
|
"home.fallbackModels": "🔄 Fallback Models",
|
|
"home.feishuGroup": "Feishu Group",
|
|
"home.discordChannel": "Discord Channel",
|
|
"home.bots": "bots",
|
|
"home.noResponseData": "No response time data",
|
|
"home.testPlatforms": "Test Platforms",
|
|
"home.testingPlatforms": "Testing Platforms...",
|
|
"home.testSessions": "Test Agent Sessions",
|
|
"home.testingSessions": "Testing Sessions...",
|
|
"home.testDmSessions": "Test DM Sessions",
|
|
"home.testingDmSessions": "Testing...",
|
|
"home.agentTaskTracking": "Agent Task Tracking",
|
|
"home.agentTaskSubtasks": "Subtasks",
|
|
"home.agentTaskCron": "Cron Jobs",
|
|
"home.agentTaskState.working": "Running",
|
|
"home.agentTaskState.waiting": "Waiting",
|
|
"home.agentTaskState.idle": "Idle",
|
|
"home.agentTaskNoSubtasks": "No active subtasks",
|
|
"home.agentTaskNoCron": "No cron activity",
|
|
"home.agentTaskCronState.running": "Running",
|
|
"home.agentTaskCronState.success": "Success",
|
|
"home.agentTaskCronState.failed": "Failed",
|
|
"home.agentTaskCronFailures": "Failures",
|
|
"home.agentTaskCronNoSummary": "No summary",
|
|
"home.agentTaskCronDuration": "Duration",
|
|
"home.agentTaskCronNextRun": "Next run",
|
|
|
|
// agent card
|
|
"agent.model": "Model",
|
|
"agent.platform": "Platform",
|
|
"agent.feishuAppId": "Feishu App ID",
|
|
"agent.sessionCount": "Sessions",
|
|
"agent.messageCount": "Messages",
|
|
"agent.tokenUsage": "Token Usage",
|
|
"agent.totalTokenTip": "Total token usage",
|
|
"agent.stats": "Stats",
|
|
"agent.lastActive": "Last Active",
|
|
"agent.todayAvgResponse": "Avg Response",
|
|
"agent.todayAvgResponseTip": "Today's average response time",
|
|
"agent.switchModel": "Switch Model",
|
|
"agent.saveModel": "Save & Apply",
|
|
"agent.cancelModel": "Cancel",
|
|
"agent.modelSaving": "Applying...",
|
|
"agent.modelApplyHint": "Saving will restart the Gateway automatically to apply the new model.",
|
|
"agent.modelApplyFailed": "Failed to apply model",
|
|
"agent.currentUnknownModel": "Current model (not in option list)",
|
|
|
|
// agent status
|
|
"agent.status.working": "Working",
|
|
"agent.status.online": "Online",
|
|
"agent.status.idle": "Idle",
|
|
"agent.status.offline": "Offline",
|
|
"agent.inUse": "Used by:",
|
|
"agent.openChat": "Click to open chat",
|
|
|
|
// platform
|
|
"platform.feishu": "📱 Feishu",
|
|
"platform.yuanbao": "🤖 Yuanbao",
|
|
"platform.discord": "🎮 Discord",
|
|
"platform.telegram": "✈️ Telegram",
|
|
"platform.whatsapp": "💬 WhatsApp",
|
|
"platform.qqbot": "🐧 QQBot",
|
|
"platform.wecom": "💼 WeCom",
|
|
|
|
// time range
|
|
"range.daily": "Daily",
|
|
"range.weekly": "Weekly",
|
|
"range.monthly": "Monthly",
|
|
"range.total": "Total",
|
|
|
|
// refresh options
|
|
"refresh.manual": "Manual Refresh",
|
|
"refresh.10s": "10s",
|
|
"refresh.30s": "30s",
|
|
"refresh.1m": "1 min",
|
|
"refresh.5m": "5 min",
|
|
"refresh.10m": "10 min",
|
|
|
|
// models page
|
|
"models.title": "OpenClaw Model List",
|
|
"models.providerCount": "Providers",
|
|
"models.totalPrefix": "",
|
|
"models.testAll": "🧪 Test All Models",
|
|
"models.testingAll": "⏳ Testing...",
|
|
"models.colModelId": "Model ID",
|
|
"models.colName": "Name",
|
|
"models.colAccessMode": "Access Mode",
|
|
"models.accessModeApiKey": "api_key",
|
|
"models.accessModeAuth": "auth",
|
|
"models.colContext": "Context Window",
|
|
"models.colMaxOutput": "Max Output",
|
|
"models.colInputType": "Input Type",
|
|
"models.colReasoning": "Reasoning",
|
|
"models.colInputToken": "Input Token",
|
|
"models.colOutputToken": "Output Token",
|
|
"models.colAvgResponse": "Avg Response",
|
|
"models.colTest": "Test",
|
|
"models.noExplicitModels": "No explicit model definitions (inferred from provider name)",
|
|
"models.defaultModel": "Default Model",
|
|
"models.fallbackModels": "Fallback Models",
|
|
|
|
// stats page
|
|
"stats.title": "Message Statistics",
|
|
"stats.subtitle": "Token usage and response time analysis",
|
|
"stats.totalInputToken": "Total Input Token",
|
|
"stats.totalOutputToken": "Total Output Token",
|
|
"stats.totalMessages": "Total Messages",
|
|
"stats.dataPeriod": "Data Period",
|
|
"stats.tokenConsumption": "🔢 Token Usage",
|
|
"stats.avgResponseTime": "⏱️ Avg Response Time",
|
|
"stats.sessionList": "📋 Sessions",
|
|
"stats.home": "← Home",
|
|
"stats.missingAgent": "Missing agent parameter",
|
|
"stats.noResponseData": "No response time data",
|
|
"stats.selectAgent": "Select an agent to view message statistics",
|
|
"stats.backToAgents": "← Back to agents",
|
|
|
|
// sessions page
|
|
"sessions.title": "Sessions",
|
|
"sessions.sessionCount": "sessions",
|
|
"sessions.totalToken": "Total Token",
|
|
"sessions.missingAgent": "Missing agent parameter",
|
|
"sessions.type.main": "Main",
|
|
"sessions.type.feishu-dm": "Feishu DM",
|
|
"sessions.type.feishu-group": "Feishu Group",
|
|
"sessions.type.discord-dm": "Discord DM",
|
|
"sessions.type.discord-channel": "Discord Channel",
|
|
"sessions.type.telegram-dm": "Telegram DM",
|
|
"sessions.type.telegram-group": "Telegram Group",
|
|
"sessions.type.whatsapp-dm": "WhatsApp DM",
|
|
"sessions.type.whatsapp-group": "WhatsApp Group",
|
|
"sessions.type.cron": "Cron Job",
|
|
"sessions.type.unknown": "Unknown",
|
|
"sessions.test": "Test",
|
|
"sessions.testing": "Testing...",
|
|
"sessions.testOk": "✅ OK",
|
|
"sessions.testFail": "❌ Failed",
|
|
"sessions.testReply": "Reply",
|
|
"sessions.testTime": "Time",
|
|
"sessions.context": "Context",
|
|
"sessions.selectAgent": "Select an agent to view its sessions",
|
|
"sessions.testAll": "🧪 Test All",
|
|
"sessions.testingAll": "⏳ Testing...",
|
|
"sessions.testHint": "Tests verify agent responsiveness only. Messages won't appear in Feishu/Discord chats.",
|
|
"sessions.testAllResult": "Test complete",
|
|
"sessions.testAllOk": "passed",
|
|
"sessions.testAllFail": "failed",
|
|
"sessions.backToAgents": "← Back to agents",
|
|
|
|
// skills page
|
|
"skills.title": "🧩 Skill Management",
|
|
"skills.count": "skills",
|
|
"skills.builtin": "Built-in",
|
|
"skills.extension": "Extension",
|
|
"skills.custom": "Custom",
|
|
"skills.workspace": "Workspace",
|
|
"skills.all": "All",
|
|
"skills.search": "Search skills...",
|
|
"skills.showing": "Showing",
|
|
"skills.unit": "",
|
|
"skills.noDesc": "No description",
|
|
"skills.source.builtin": "Built-in",
|
|
"skills.source.custom": "Custom",
|
|
"skills.source.workspace": "Workspace",
|
|
"skills.workspace.main": "Main workspace",
|
|
"skills.workspaceFilter.all": "All workspaces",
|
|
"skills.viewSource": "View SKILL.md",
|
|
"skills.contentTitle": "SKILL.md",
|
|
"skills.loadingContent": "Loading skill content...",
|
|
"skills.contentLoadFailed": "Failed to load skill content",
|
|
|
|
// gateway status
|
|
"gateway.healthy": "Gateway is running",
|
|
"gateway.unhealthy": "Gateway is down",
|
|
"gateway.fetchError": "Cannot check Gateway status",
|
|
"gateway.noResponse": "Gateway is not responding",
|
|
"gateway.configChanged": "openclaw.json was recently modified. This may be caused by a config error.",
|
|
"gateway.configError": "Config file may have errors",
|
|
"gateway.configErrorDesc": "Gateway failed to start, possibly due to openclaw.json config errors",
|
|
"gateway.restorePrev": "🔄 Restore previous config",
|
|
"gateway.viewLogs": "📋 View error logs",
|
|
"gateway.dismiss": "❌ Dismiss",
|
|
"gateway.backupAvailable": "Backup available",
|
|
"gateway.restoreBackup": "Restore backup",
|
|
"gateway.restoring": "Restoring…",
|
|
"gateway.restoreSuccess": "✅ Restored, restarting Gateway…",
|
|
"gateway.restoreFailed": "❌ Restore failed",
|
|
"gateway.noBackups": "No backups available",
|
|
"gateway.backupRecommended": "Recommended",
|
|
"gateway.backupSuspect": "Possibly corrupt",
|
|
"gateway.reloadCountdown": "s until auto-refresh…",
|
|
"gateway.reloadNow": "Refresh now",
|
|
"gateway.reloadHint": "After refresh, click the Test button on each bot card to verify it's working.",
|
|
"gateway.configCorruptHint": "Config may be corrupt. Use the Gateway panel above to restore a backup.",
|
|
|
|
// pixel office
|
|
"pixelOffice.title": "OpenClaw Agents Office",
|
|
"pixelOffice.editMode": "Edit Layout",
|
|
"pixelOffice.exitEdit": "Exit Edit",
|
|
"pixelOffice.save": "Save",
|
|
"pixelOffice.reset": "Reset",
|
|
"pixelOffice.undo": "Undo",
|
|
"pixelOffice.redo": "Redo",
|
|
"pixelOffice.sound": "Sound",
|
|
"pixelOffice.resetView": "Reset View",
|
|
"pixelOffice.state.working": "Working",
|
|
"pixelOffice.state.idle": "Idle",
|
|
"pixelOffice.state.offline": "Offline",
|
|
"pixelOffice.state.waiting": "Waiting",
|
|
"pixelOffice.tempWorker": "Temp",
|
|
"pixelOffice.tempWorker.source": "Temp Worker Source",
|
|
"pixelOffice.tempWorker.createdBy": "created subagent",
|
|
"pixelOffice.broadcast.online": "is online",
|
|
"pixelOffice.broadcast.offline": "is offline",
|
|
"pixelOffice.heatmap.title": "Agent Activity Heatmap",
|
|
"pixelOffice.heatmap.messages": "messages",
|
|
"pixelOffice.idleRank.title": "Slacking Leaderboard",
|
|
"pixelOffice.idleRank.online": "Online",
|
|
"pixelOffice.idleRank.active": "Active",
|
|
"pixelOffice.idleRank.idle": "Slacking",
|
|
"pixelOffice.serverStatus.checking": "Checking server status...",
|
|
"pixelOffice.serverStatus.healthy": "Service healthy",
|
|
"pixelOffice.serverStatus.degraded": "Service degraded",
|
|
"pixelOffice.serverStatus.down": "Service down",
|
|
"pixelOffice.serverStatus.unknown": "Service status unknown",
|
|
"pixelOffice.serverStatus.fetchFailed": "Failed to check service status",
|
|
"pixelOffice.gatewaySre.name": "OnCall SRE",
|
|
"pixelOffice.gatewaySre.statusLabel": "Gateway status",
|
|
"pixelOffice.gatewaySre.responseMs": "Check latency",
|
|
"pixelOffice.gatewaySre.status.unknown": "Monitoring",
|
|
"pixelOffice.gatewaySre.status.healthy": "Healthy",
|
|
"pixelOffice.gatewaySre.status.degraded": "Degraded",
|
|
"pixelOffice.gatewaySre.status.down": "Down",
|
|
"pixelOffice.gatewaySre.tip.unknown": "Waiting for gateway health data",
|
|
"pixelOffice.gatewaySre.tip.healthy": "Gateway healthy",
|
|
"pixelOffice.gatewaySre.tip.degraded": "Gateway degraded: latency high",
|
|
"pixelOffice.gatewaySre.tip.down": "Gateway down",
|
|
},
|
|
vi: {
|
|
// layout
|
|
"site.title": "OpenClaw Bảng Điều Khiển Bot",
|
|
"site.desc": "Xem tất cả cấu hình bot OpenClaw",
|
|
|
|
// nav sidebar
|
|
"nav.overview": "Tổng quan",
|
|
"nav.agents": "Bot",
|
|
"nav.models": "Mô hình",
|
|
"nav.monitor": "Giám sát",
|
|
"nav.sessions": "Phiên hội thoại",
|
|
"nav.stats": "Thống kê",
|
|
"nav.pixelOffice": "Văn phòng Pixel",
|
|
"nav.config": "Cấu hình",
|
|
"nav.skills": "Kỹ năng",
|
|
"nav.alerts": "Cảnh báo",
|
|
"nav.experiments": "Thử nghiệm",
|
|
"nav.expandSidebar": "Mở rộng thanh bên",
|
|
"nav.collapseSidebar": "Thu gọn thanh bên",
|
|
"nav.bugsOn": "Bật Bugs",
|
|
"nav.bugsOff": "Tắt Bugs",
|
|
"nav.bugsCount": "Số lượng",
|
|
|
|
// alerts page
|
|
"alerts.title": "Trung tâm Cảnh báo",
|
|
"alerts.subtitle": "Cấu hình cảnh báo và thông báo hệ thống",
|
|
"alerts.enableAlerts": "Bật cảnh báo",
|
|
"alerts.enableDesc": "Bật/tắt tất cả thông báo cảnh báo",
|
|
"alerts.receiveAgent": "Bot nhận cảnh báo",
|
|
"alerts.rules": "Quy tắc cảnh báo",
|
|
"alerts.rulesDesc": "Cấu hình điều kiện kích hoạt cảnh báo",
|
|
"alerts.triggered": "Cảnh báo đã kích hoạt ({count})",
|
|
"alerts.checking": "Đang kiểm tra cảnh báo...",
|
|
"alerts.checkNow": "Kiểm tra ngay",
|
|
"alerts.checkInterval": "Tần suất kiểm tra",
|
|
|
|
// common
|
|
"common.loading": "Đang suy nghĩ...",
|
|
"common.loadError": "Tải thất bại",
|
|
"common.backHome": "← Về trang chủ",
|
|
"common.backOverview": "← Về tổng quan",
|
|
"common.noData": "Không có dữ liệu",
|
|
"common.close": "Đóng",
|
|
"common.test": "🧪 Kiểm thử",
|
|
"common.testing": "⏳ Đang kiểm thử...",
|
|
"common.justNow": "vừa xong",
|
|
"common.minutesAgo": "phút trước",
|
|
"common.hoursAgo": "giờ trước",
|
|
"common.daysAgo": "ngày trước",
|
|
"common.manualRefresh": "Làm mới thủ công",
|
|
"common.seconds": "giây",
|
|
"common.minute": "phút",
|
|
"common.minutes": "phút",
|
|
|
|
// home page
|
|
"home.title": "🐾 OpenClaw Bảng Điều Khiển Bot",
|
|
"home.agentCount": "bot",
|
|
"home.pageTitle": "OpenClaw Bot",
|
|
"home.defaultModel": "Mô hình mặc định",
|
|
"home.viewModels": "Xem danh sách mô hình →",
|
|
"home.skillMgmt": "🧩 Quản lý kỹ năng",
|
|
"home.testAll": "Kiểm thử mô hình đã liên kết",
|
|
"home.testingAll": "Đang kiểm thử mô hình...",
|
|
"home.testOk": "Bình thường",
|
|
"home.testFail": "Bất thường",
|
|
"home.updatedAt": "Cập nhật lúc",
|
|
"home.refreshManual": "🔄 Làm mới thủ công",
|
|
"home.globalTrend": "📊 Thống kê tổng quan",
|
|
"home.totalInputToken": "Tổng Token đầu vào",
|
|
"home.totalOutputToken": "Tổng Token đầu ra",
|
|
"home.totalMessages": "Tổng số tin nhắn",
|
|
"home.tokenTrend": "🔢 Xu hướng tiêu thụ Token",
|
|
"home.avgResponseTrend": "⏱️ Xu hướng thời gian phản hồi TB",
|
|
"home.groupTopology": "💬 Cấu trúc nhóm chat",
|
|
"home.fallbackModels": "🔄 Mô hình dự phòng",
|
|
"home.feishuGroup": "Nhóm Feishu",
|
|
"home.discordChannel": "Kênh Discord",
|
|
"home.bots": "bot",
|
|
"home.noResponseData": "Chưa có dữ liệu thời gian phản hồi",
|
|
"home.testPlatforms": "Kiểm thử nền tảng",
|
|
"home.testingPlatforms": "Đang kiểm thử nền tảng...",
|
|
"home.testSessions": "Kiểm thử phiên Agent",
|
|
"home.testingSessions": "Đang kiểm thử phiên...",
|
|
"home.testDmSessions": "Kiểm thử phiên DM",
|
|
"home.testingDmSessions": "Đang kiểm thử...",
|
|
"home.agentTaskTracking": "Theo dõi tác vụ Agent",
|
|
"home.agentTaskSubtasks": "Tác vụ con",
|
|
"home.agentTaskCron": "Tác vụ định kỳ",
|
|
"home.agentTaskState.working": "Đang chạy",
|
|
"home.agentTaskState.waiting": "Đang chờ",
|
|
"home.agentTaskState.idle": "Rảnh rỗi",
|
|
"home.agentTaskNoSubtasks": "Không có tác vụ con đang hoạt động",
|
|
"home.agentTaskNoCron": "Không có hoạt động định kỳ",
|
|
"home.agentTaskCronState.running": "Đang chạy",
|
|
"home.agentTaskCronState.success": "Thành công",
|
|
"home.agentTaskCronState.failed": "Thất bại",
|
|
"home.agentTaskCronFailures": "Thất bại liên tiếp",
|
|
"home.agentTaskCronNoSummary": "Chưa có tóm tắt",
|
|
"home.agentTaskCronDuration": "Thời lượng",
|
|
"home.agentTaskCronNextRun": "Lần chạy tiếp",
|
|
|
|
// agent card
|
|
"agent.model": "Mô hình",
|
|
"agent.platform": "Nền tảng",
|
|
"agent.feishuAppId": "Feishu App ID",
|
|
"agent.sessionCount": "Số phiên",
|
|
"agent.messageCount": "Số tin nhắn",
|
|
"agent.tokenUsage": "Token sử dụng",
|
|
"agent.totalTokenTip": "Tổng Token đã dùng",
|
|
"agent.stats": "Thống kê",
|
|
"agent.lastActive": "Hoạt động lần cuối",
|
|
"agent.todayAvgResponse": "Phản hồi TB",
|
|
"agent.todayAvgResponseTip": "Thời gian phản hồi trung bình hôm nay",
|
|
"agent.switchModel": "Đổi mô hình",
|
|
"agent.saveModel": "Lưu & Áp dụng",
|
|
"agent.cancelModel": "Hủy",
|
|
"agent.modelSaving": "Đang áp dụng...",
|
|
"agent.modelApplyHint": "Sau khi lưu, Gateway sẽ tự động khởi động lại để áp dụng mô hình mới.",
|
|
"agent.modelApplyFailed": "Áp dụng mô hình thất bại",
|
|
"agent.currentUnknownModel": "Mô hình hiện tại (không có trong danh sách)",
|
|
|
|
// agent status
|
|
"agent.status.working": "Đang làm việc",
|
|
"agent.status.online": "Trực tuyến",
|
|
"agent.status.idle": "Rảnh rỗi",
|
|
"agent.status.offline": "Ngoại tuyến",
|
|
"agent.inUse": "Đang dùng:",
|
|
"agent.openChat": "Nhấn để mở trang chat",
|
|
|
|
// platform
|
|
"platform.feishu": "📱 Feishu",
|
|
"platform.yuanbao": "🤖 Yuanbao",
|
|
"platform.discord": "🎮 Discord",
|
|
"platform.telegram": "✈️ Telegram",
|
|
"platform.whatsapp": "💬 WhatsApp",
|
|
"platform.qqbot": "🐧 QQBot",
|
|
"platform.wecom": "💼 WeCom",
|
|
|
|
// time range
|
|
"range.daily": "Theo ngày",
|
|
"range.weekly": "Theo tuần",
|
|
"range.monthly": "Theo tháng",
|
|
|
|
// refresh options
|
|
"refresh.manual": "Làm mới thủ công",
|
|
"refresh.10s": "10 giây",
|
|
"refresh.30s": "30 giây",
|
|
"refresh.1m": "1 phút",
|
|
"refresh.5m": "5 phút",
|
|
"refresh.10m": "10 phút",
|
|
|
|
// models page
|
|
"models.title": "Danh sách mô hình OpenClaw",
|
|
"models.providerCount": "Nhà cung cấp",
|
|
"models.totalPrefix": "Tổng",
|
|
"models.testAll": "🧪 Kiểm thử tất cả mô hình",
|
|
"models.testingAll": "⏳ Đang kiểm thử...",
|
|
"models.colModelId": "ID Mô hình",
|
|
"models.colName": "Tên",
|
|
"models.colAccessMode": "Phương thức truy cập",
|
|
"models.accessModeApiKey": "api_key",
|
|
"models.accessModeAuth": "auth",
|
|
"models.colContext": "Cửa sổ ngữ cảnh",
|
|
"models.colMaxOutput": "Đầu ra tối đa",
|
|
"models.colInputType": "Loại đầu vào",
|
|
"models.colReasoning": "Suy luận",
|
|
"models.colInputToken": "Token đầu vào",
|
|
"models.colOutputToken": "Token đầu ra",
|
|
"models.colAvgResponse": "Phản hồi TB",
|
|
"models.colTest": "Kiểm thử",
|
|
"models.noExplicitModels": "Không có định nghĩa mô hình rõ ràng (suy ra từ tên provider)",
|
|
"models.defaultModel": "Mô hình chính",
|
|
"models.fallbackModels": "Mô hình dự phòng",
|
|
|
|
// stats page
|
|
"stats.title": "Thống kê tin nhắn",
|
|
"stats.subtitle": "Phân tích tiêu thụ Token và thời gian phản hồi",
|
|
"stats.totalInputToken": "Tổng Token đầu vào",
|
|
"stats.totalOutputToken": "Tổng Token đầu ra",
|
|
"stats.totalMessages": "Tổng số tin nhắn",
|
|
"stats.dataPeriod": "Chu kỳ dữ liệu",
|
|
"stats.tokenConsumption": "🔢 Tiêu thụ Token",
|
|
"stats.avgResponseTime": "⏱️ Thời gian phản hồi TB",
|
|
"stats.sessionList": "📋 Danh sách phiên",
|
|
"stats.home": "← Trang chủ",
|
|
"stats.missingAgent": "Thiếu tham số agent",
|
|
"stats.noResponseData": "Chưa có dữ liệu thời gian phản hồi",
|
|
"stats.selectAgent": "Chọn một bot để xem thống kê tin nhắn",
|
|
"stats.backToAgents": "← Quay lại danh sách bot",
|
|
|
|
// sessions page
|
|
"sessions.title": "Danh sách phiên của",
|
|
"sessions.sessionCount": "phiên",
|
|
"sessions.totalToken": "Tổng Token",
|
|
"sessions.missingAgent": "Thiếu tham số agent",
|
|
"sessions.type.main": "Phiên chính",
|
|
"sessions.type.feishu-dm": "Feishu tin nhắn riêng",
|
|
"sessions.type.feishu-group": "Feishu nhóm",
|
|
"sessions.type.discord-dm": "Discord tin nhắn riêng",
|
|
"sessions.type.discord-channel": "Discord kênh",
|
|
"sessions.type.telegram-dm": "Telegram tin nhắn riêng",
|
|
"sessions.type.telegram-group": "Telegram nhóm",
|
|
"sessions.type.whatsapp-dm": "WhatsApp tin nhắn riêng",
|
|
"sessions.type.whatsapp-group": "WhatsApp nhóm",
|
|
"sessions.type.cron": "Tác vụ định kỳ",
|
|
"sessions.type.unknown": "Không xác định",
|
|
"sessions.test": "Kiểm thử",
|
|
"sessions.testing": "Đang kiểm thử...",
|
|
"sessions.testOk": "✅ Bình thường",
|
|
"sessions.testFail": "❌ Bất thường",
|
|
"sessions.testReply": "Phản hồi",
|
|
"sessions.testTime": "Thời gian",
|
|
"sessions.context": "Ngữ cảnh",
|
|
"sessions.selectAgent": "Chọn một bot để xem danh sách phiên",
|
|
"sessions.testAll": "🧪 Kiểm thử tất cả",
|
|
"sessions.testingAll": "⏳ Đang kiểm thử...",
|
|
"sessions.testHint": "Kiểm thử chỉ xác minh khả năng phản hồi của Agent. Tin nhắn sẽ không hiển thị trong Feishu/Discord.",
|
|
"sessions.testAllResult": "Kiểm thử hoàn tất",
|
|
"sessions.testAllOk": "Đạt",
|
|
"sessions.testAllFail": "Thất bại",
|
|
"sessions.backToAgents": "← Quay lại danh sách bot",
|
|
|
|
// skills page
|
|
"skills.title": "🧩 Quản lý kỹ năng",
|
|
"skills.count": "kỹ năng",
|
|
"skills.builtin": "Tích hợp",
|
|
"skills.extension": "Mở rộng",
|
|
"skills.custom": "Tùy chỉnh",
|
|
"skills.all": "Tất cả",
|
|
"skills.search": "Tìm kiếm kỹ năng...",
|
|
"skills.showing": "Đang hiển thị",
|
|
"skills.unit": "cái",
|
|
"skills.noDesc": "Không có mô tả",
|
|
"skills.source.builtin": "Tích hợp",
|
|
"skills.source.custom": "Tùy chỉnh",
|
|
"skills.viewSource": "Xem SKILL.md",
|
|
"skills.contentTitle": "Nội dung SKILL.md",
|
|
"skills.loadingContent": "Đang tải nội dung kỹ năng...",
|
|
"skills.contentLoadFailed": "Tải nội dung kỹ năng thất bại",
|
|
|
|
// gateway status
|
|
"gateway.healthy": "Gateway hoạt động bình thường",
|
|
"gateway.unhealthy": "Gateway bất thường",
|
|
"gateway.fetchError": "Không thể kiểm tra trạng thái Gateway",
|
|
|
|
// pixel office
|
|
"pixelOffice.title": "Văn phòng OpenClaw Agents",
|
|
"pixelOffice.editMode": "Chỉnh sửa bố cục",
|
|
"pixelOffice.exitEdit": "Thoát chỉnh sửa",
|
|
"pixelOffice.save": "Lưu",
|
|
"pixelOffice.reset": "Đặt lại",
|
|
"pixelOffice.undo": "Hoàn tác",
|
|
"pixelOffice.redo": "Làm lại",
|
|
"pixelOffice.sound": "Âm thanh",
|
|
"pixelOffice.resetView": "Đặt lại giao diện",
|
|
"pixelOffice.state.working": "Đang làm việc",
|
|
"pixelOffice.state.idle": "Đang rảnh",
|
|
"pixelOffice.state.offline": "Ngoại tuyến",
|
|
"pixelOffice.state.waiting": "Đang chờ",
|
|
"pixelOffice.tempWorker": "Tạm thời",
|
|
"pixelOffice.tempWorker.source": "Nguồn nhân viên tạm",
|
|
"pixelOffice.tempWorker.createdBy": "đã tạo subagent",
|
|
"pixelOffice.broadcast.online": "đã lên mạng",
|
|
"pixelOffice.broadcast.offline": "đã ngoại tuyến",
|
|
"pixelOffice.heatmap.title": "Biểu đồ nhiệt hoạt động Agent",
|
|
"pixelOffice.heatmap.messages": "tin nhắn",
|
|
"pixelOffice.idleRank.title": "Bảng xếp hạng lười biếng",
|
|
"pixelOffice.idleRank.online": "Trực tuyến",
|
|
"pixelOffice.idleRank.active": "Hoạt động",
|
|
"pixelOffice.idleRank.idle": "Nghỉ ngơi",
|
|
"pixelOffice.serverStatus.checking": "Đang kiểm tra trạng thái máy chủ...",
|
|
"pixelOffice.serverStatus.healthy": "Dịch vụ bình thường",
|
|
"pixelOffice.serverStatus.degraded": "Dịch vụ suy giảm",
|
|
"pixelOffice.serverStatus.down": "Dịch vụ gặp sự cố",
|
|
"pixelOffice.serverStatus.unknown": "Trạng thái không xác định",
|
|
"pixelOffice.serverStatus.fetchFailed": "Kiểm tra trạng thái thất bại",
|
|
"pixelOffice.gatewaySre.name": "Kỹ sư trực ca",
|
|
"pixelOffice.gatewaySre.statusLabel": "Trạng thái Gateway",
|
|
"pixelOffice.gatewaySre.responseMs": "Thời gian kiểm tra",
|
|
"pixelOffice.gatewaySre.status.unknown": "Đang giám sát",
|
|
"pixelOffice.gatewaySre.status.healthy": "Khỏe mạnh",
|
|
"pixelOffice.gatewaySre.status.degraded": "Suy giảm",
|
|
"pixelOffice.gatewaySre.status.down": "Sự cố",
|
|
"pixelOffice.gatewaySre.tip.unknown": "Đang chờ dữ liệu sức khỏe gateway",
|
|
"pixelOffice.gatewaySre.tip.healthy": "Gateway hoạt động tốt",
|
|
"pixelOffice.gatewaySre.tip.degraded": "Gateway suy giảm: độ trễ cao",
|
|
"pixelOffice.gatewaySre.tip.down": "Gateway gặp sự cố",
|
|
},
|
|
};
|
|
|
|
interface I18nContextType {
|
|
locale: Locale;
|
|
setLocale: (l: Locale) => void;
|
|
t: (key: string) => string;
|
|
}
|
|
|
|
const I18nContext = createContext<I18nContextType>({
|
|
locale: "vi",
|
|
setLocale: () => {},
|
|
t: (key) => key,
|
|
});
|
|
|
|
function detectBrowserLocale(): Locale {
|
|
const langs = navigator.languages?.length ? navigator.languages : [navigator.language];
|
|
for (const lang of langs) {
|
|
const l = lang.toLowerCase();
|
|
if (l.startsWith('zh-tw') || l.startsWith('zh-hant') || l.startsWith('zh-hk') || l.startsWith('zh-mo')) return 'zh-TW';
|
|
if (l.startsWith('zh')) return 'zh';
|
|
if (l.startsWith('en')) return 'en';
|
|
}
|
|
return 'zh';
|
|
}
|
|
|
|
export function I18nProvider({ children }: { children: ReactNode }) {
|
|
const [locale, setLocaleState] = useState<Locale>("vi");
|
|
|
|
useEffect(() => {
|
|
const saved = localStorage.getItem("locale") as Locale;
|
|
if (saved && (saved === "vi" || saved === "zh-TW" || saved === "zh" || saved === "en")) {
|
|
setLocaleState(saved);
|
|
} else {
|
|
setLocaleState(detectBrowserLocale());
|
|
}
|
|
}, []);
|
|
|
|
const setLocale = useCallback((l: Locale) => {
|
|
setLocaleState(l);
|
|
if (typeof window !== "undefined") {
|
|
localStorage.setItem("locale", l);
|
|
}
|
|
}, []);
|
|
|
|
const t = useCallback(
|
|
(key: string) => translations[locale]?.[key] ?? translations.vi[key] ?? translations.zh[key] ?? key,
|
|
[locale]
|
|
);
|
|
|
|
return (
|
|
<I18nContext.Provider value={{ locale, setLocale, t }}>
|
|
{children}
|
|
</I18nContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useI18n() {
|
|
return useContext(I18nContext);
|
|
}
|
|
|
|
export function LanguageSwitcher() {
|
|
const { locale, setLocale } = useI18n();
|
|
return (
|
|
<select
|
|
value={locale}
|
|
onChange={(e) => setLocale(e.target.value as Locale)}
|
|
className="px-3 py-1.5 rounded-lg bg-[var(--card)] border border-[var(--border)] text-xs font-medium hover:border-[var(--accent)] transition cursor-pointer text-[var(--text)]"
|
|
>
|
|
<option value="vi">Tiếng Việt</option>
|
|
<option value="zh-TW">繁體中文</option>
|
|
<option value="zh">简体中文</option>
|
|
<option value="en">English</option>
|
|
</select>
|
|
);
|
|
}
|