feat(i18n): 系统更新功能多语言支持与缺失 key 补全

- 新增 systemUpdate 区块(zh-CN/zh-TW/en)覆盖系统更新页与版本提示
- zh-CN 补充 account.walletType
- SystemUpdate 页与 Layout 版本 tag 全部改为 useTranslation,移除硬编码中文

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
WrBug
2026-02-25 21:14:59 +08:00
co-authored by Cursor
parent 0740abcf16
commit f35bad78d4
5 changed files with 206 additions and 53 deletions
+2 -2
View File
@@ -293,7 +293,7 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
alignItems: 'center',
verticalAlign: 'middle'
}}
title={hasUpdate ? '有新版本可用,点击前往系统更新' : '当前已是最新版本'}
title={hasUpdate ? t('systemUpdate.versionTooltipNew') : t('systemUpdate.versionTooltipLatest')}
>
{getVersionInfo().gitTag || `v${getVersionText()}`}
</Tag>
@@ -415,7 +415,7 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
alignItems: 'center',
verticalAlign: 'middle'
}}
title={hasUpdate ? '有新版本可用,点击前往系统更新' : '当前已是最新版本'}
title={hasUpdate ? t('systemUpdate.versionTooltipNew') : t('systemUpdate.versionTooltipLatest')}
>
{getVersionInfo().gitTag || `v${getVersionText()}`}
</Tag>
+53 -3
View File
@@ -419,6 +419,40 @@
"saveFailed": "Failed to save auto redeem configuration"
}
},
"systemUpdate": {
"title": "System Update",
"currentVersion": "Current Version",
"ready": "Ready",
"hasNewVersion": "New version available: {{version}}",
"alreadyLatest": "You are on the latest version",
"checkFailed": "Failed to check for updates",
"confirmTitle": "Confirm Update",
"confirmContent1": "Update to version {{version}}?",
"confirmContent2": "The system will be temporarily unavailable during the update (about 30-60 seconds).",
"confirmContent3": "The page will refresh automatically when the update completes.",
"okText": "Update Now",
"cancelText": "Cancel",
"updateStarted": "Update started, please wait...",
"updateFailedWithMessage": "Update failed: {{message}}",
"updateSuccessRefresh": "Update successful! Page will refresh in 3 seconds...",
"needAdmin": "Admin permission required to perform update",
"startFailed": "Failed to start update",
"updating": "System is updating",
"updateFailedTitle": "Update Failed",
"checkUpdate": "Check for Updates",
"newVersionFound": "New Version Available",
"publishedAt": "Published At",
"releaseNotes": "Release Notes",
"upgradeNow": "Upgrade to v{{version}} Now",
"usageTitle": "Instructions",
"usage1": "Click \"Check for Updates\" to see if a new version is available",
"usage2": "Update takes about 30-60 seconds; the system will be temporarily unavailable",
"usage3": "The page will refresh automatically after a successful update",
"usage4": "If the update fails, the system will roll back to the current version",
"versionTooltipNew": "New version available, click to go to System Update",
"versionTooltipLatest": "You are on the latest version",
"prerelease": "Pre-release"
},
"builderApiKey": {
"title": "Builder API Key Configuration",
"alertTitle": "What is Builder API Key?",
@@ -1579,20 +1613,36 @@
"title": "Price Chart",
"btcTitle": "BTC Price Chart",
"marketTitle": "Market Price Chart",
"price": "BTC Price",
"priceChart": "Price Chart",
"price": "Price",
"openPrice": "Open",
"spread": "Spread",
"minSpreadLine": "Min Spread Line",
"maxSpreadLine": "Max Spread Line",
"marketUp": "Up",
"marketDown": "Down",
"time": "Time"
"time": "Time",
"latestPrice": "Latest",
"timeWindowStart": "Window Start",
"timeWindowEnd": "Window End"
},
"strategyInfo": {
"title": "Strategy Info",
"market": "Market",
"interval": "Interval",
"account": "Account",
"spreadMode": "Spread Mode"
"spreadMode": "Spread Mode",
"spreadDirection": "Spread Direction"
},
"periodSwitch": {
"mode": "Period Switch Mode",
"auto": "Auto",
"manual": "Manual",
"autoDesc": "Automatically switch to the latest period when it ends",
"manualDesc": "Keep complete data when period ends",
"switchToLatest": "Switch to Latest Period",
"periodEnded": "Current period has ended",
"newPeriodAvailable": "New period has started"
}
}
}
+54 -3
View File
@@ -92,6 +92,7 @@
"accountNamePlaceholder": "账户名称(可选)",
"accountIdRequired": "账户ID不能为空",
"walletAddress": "钱包地址",
"walletType": "钱包类型",
"proxyAddress": "代理钱包地址",
"apiCredentials": "API 凭证",
"apiKey": "API Key",
@@ -418,6 +419,40 @@
"saveFailed": "保存自动赎回配置失败"
}
},
"systemUpdate": {
"title": "系统更新",
"currentVersion": "当前版本",
"ready": "就绪",
"hasNewVersion": "发现新版本: {{version}}",
"alreadyLatest": "当前已是最新版本",
"checkFailed": "检查更新失败",
"confirmTitle": "确认更新",
"confirmContent1": "确定要更新到版本 {{version}} 吗?",
"confirmContent2": "更新过程中系统将暂时不可用(约30-60秒)。",
"confirmContent3": "更新完成后页面将自动刷新。",
"okText": "立即更新",
"cancelText": "取消",
"updateStarted": "更新已启动,请稍候...",
"updateFailedWithMessage": "更新失败: {{message}}",
"updateSuccessRefresh": "更新成功!页面将在3秒后刷新...",
"needAdmin": "需要管理员权限才能执行更新",
"startFailed": "启动更新失败",
"updating": "系统正在更新",
"updateFailedTitle": "更新失败",
"checkUpdate": "检查更新",
"newVersionFound": "发现新版本",
"publishedAt": "发布时间",
"releaseNotes": "更新内容",
"upgradeNow": "立即升级到 v{{version}}",
"usageTitle": "使用说明",
"usage1": "点击「检查更新」按钮检查是否有新版本",
"usage2": "更新过程约需30-60秒,期间系统将暂时不可用",
"usage3": "更新成功后页面将自动刷新",
"usage4": "如果更新失败,系统会自动回滚到当前版本",
"versionTooltipNew": "有新版本可用,点击前往系统更新",
"versionTooltipLatest": "当前已是最新版本",
"prerelease": "预发布"
},
"builderApiKey": {
"title": "Builder API Key 配置",
"alertTitle": "什么是 Builder API Key",
@@ -1578,20 +1613,36 @@
"title": "分时图",
"btcTitle": "BTC 分时图",
"marketTitle": "市场分时图",
"price": "BTC 价格",
"priceChart": "价格分时图",
"price": "价格",
"openPrice": "开盘价",
"spread": "价差",
"minSpreadLine": "最小价差线",
"maxSpreadLine": "最大价差线",
"marketUp": "Up",
"marketDown": "Down",
"time": "时间"
"time": "时间",
"latestPrice": "最新价",
"timeWindowStart": "区间开始",
"timeWindowEnd": "区间结束"
},
"strategyInfo": {
"title": "策略信息",
"market": "市场",
"interval": "周期",
"account": "账户",
"spreadMode": "价差模式"
"spreadMode": "价差模式",
"spreadDirection": "价差方向"
},
"periodSwitch": {
"mode": "周期切换模式",
"auto": "自动",
"manual": "手动",
"autoDesc": "周期结束时自动切换到最新周期",
"manualDesc": "周期结束时保留完整数据",
"switchToLatest": "切换到最新周期",
"periodEnded": "当前周期已结束",
"newPeriodAvailable": "新周期已开始"
}
}
}
+53 -3
View File
@@ -419,6 +419,40 @@
"saveFailed": "保存自動贖回配置失敗"
}
},
"systemUpdate": {
"title": "系統更新",
"currentVersion": "當前版本",
"ready": "就緒",
"hasNewVersion": "發現新版本: {{version}}",
"alreadyLatest": "當前已是最新版本",
"checkFailed": "檢查更新失敗",
"confirmTitle": "確認更新",
"confirmContent1": "確定要更新到版本 {{version}} 嗎?",
"confirmContent2": "更新過程中系統將暫時不可用(約30-60秒)。",
"confirmContent3": "更新完成後頁面將自動刷新。",
"okText": "立即更新",
"cancelText": "取消",
"updateStarted": "更新已啟動,請稍候...",
"updateFailedWithMessage": "更新失敗: {{message}}",
"updateSuccessRefresh": "更新成功!頁面將在3秒後刷新...",
"needAdmin": "需要管理員權限才能執行更新",
"startFailed": "啟動更新失敗",
"updating": "系統正在更新",
"updateFailedTitle": "更新失敗",
"checkUpdate": "檢查更新",
"newVersionFound": "發現新版本",
"publishedAt": "發佈時間",
"releaseNotes": "更新內容",
"upgradeNow": "立即升級到 v{{version}}",
"usageTitle": "使用說明",
"usage1": "點擊「檢查更新」按鈕檢查是否有新版本",
"usage2": "更新過程約需30-60秒,期間系統將暫時不可用",
"usage3": "更新成功後頁面將自動刷新",
"usage4": "如果更新失敗,系統會自動回滾到當前版本",
"versionTooltipNew": "有新版本可用,點擊前往系統更新",
"versionTooltipLatest": "當前已是最新版本",
"prerelease": "預發佈"
},
"builderApiKey": {
"title": "Builder API Key 配置",
"alertTitle": "什麼是 Builder API Key",
@@ -1579,20 +1613,36 @@
"title": "分時圖",
"btcTitle": "BTC 分時圖",
"marketTitle": "市場分時圖",
"price": "BTC 價格",
"priceChart": "價格分時圖",
"price": "價格",
"openPrice": "開盤價",
"spread": "價差",
"minSpreadLine": "最小價差線",
"maxSpreadLine": "最大價差線",
"marketUp": "Up",
"marketDown": "Down",
"time": "時間"
"time": "時間",
"latestPrice": "最新價",
"timeWindowStart": "區間開始",
"timeWindowEnd": "區間結束"
},
"strategyInfo": {
"title": "策略信息",
"market": "市場",
"interval": "週期",
"account": "賬戶",
"spreadMode": "價差模式"
"spreadMode": "價差模式",
"spreadDirection": "價差方向"
},
"periodSwitch": {
"mode": "週期切換模式",
"auto": "自動",
"manual": "手動",
"autoDesc": "週期結束時自動切換到最新週期",
"manualDesc": "週期結束時保留完整數據",
"switchToLatest": "切換到最新週期",
"periodEnded": "當前週期已結束",
"newPeriodAvailable": "新週期已開始"
}
}
}
+44 -42
View File
@@ -6,6 +6,7 @@ import {
CheckCircleOutlined,
ExclamationCircleOutlined
} from '@ant-design/icons'
import { useTranslation } from 'react-i18next'
import { apiClient } from '../services/api'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
@@ -29,13 +30,14 @@ interface UpdateStatus {
}
const SystemUpdate: React.FC = () => {
const { t, i18n } = useTranslation()
const [currentVersion, setCurrentVersion] = useState('')
const [updateChecking, setUpdateChecking] = useState(false)
const [updateInfo, setUpdateInfo] = useState<UpdateInfo | null>(null)
const [updateStatus, setUpdateStatus] = useState<UpdateStatus>({
updating: false,
progress: 0,
message: '就绪',
message: '',
error: null
})
@@ -62,7 +64,7 @@ const SystemUpdate: React.FC = () => {
setUpdateStatus({
updating: response.data.data.updating,
progress: response.data.data.progress || 0,
message: response.data.data.message || '就绪',
message: response.data.data.message || '',
error: response.data.data.error || null
})
}
@@ -83,15 +85,15 @@ const SystemUpdate: React.FC = () => {
setUpdateInfo(data.data)
if (data.data.hasUpdate) {
message.success(`发现新版本: ${data.data.latestVersion}`)
message.success(t('systemUpdate.hasNewVersion', { version: data.data.latestVersion }))
} else {
message.info('当前已是最新版本')
message.info(t('systemUpdate.alreadyLatest'))
}
} else {
message.error(data.message || '检查更新失败')
message.error(data.message || t('systemUpdate.checkFailed'))
}
} catch (error: any) {
message.error(error.message || '检查更新失败')
message.error(error.message || t('systemUpdate.checkFailed'))
} finally {
setUpdateChecking(false)
}
@@ -99,25 +101,25 @@ const SystemUpdate: React.FC = () => {
const handleExecuteUpdate = () => {
Modal.confirm({
title: '确认更新',
title: t('systemUpdate.confirmTitle'),
icon: <ExclamationCircleOutlined />,
content: (
<div>
<p> <strong>{updateInfo?.latestVersion}</strong> </p>
<p>30-60</p>
<p></p>
<p>{t('systemUpdate.confirmContent1', { version: updateInfo?.latestVersion })}</p>
<p>{t('systemUpdate.confirmContent2')}</p>
<p>{t('systemUpdate.confirmContent3')}</p>
</div>
),
okText: '立即更新',
okText: t('systemUpdate.okText'),
okType: 'primary',
cancelText: '取消',
cancelText: t('systemUpdate.cancelText'),
onOk: async () => {
try {
const response = await apiClient.post('/update/update', {})
const data = response.data
if (data.code === 0) {
message.success('更新已启动,请稍候...')
message.success(t('systemUpdate.updateStarted'))
// 开始轮询更新状态
const pollInterval = setInterval(async () => {
@@ -138,9 +140,9 @@ const SystemUpdate: React.FC = () => {
clearInterval(pollInterval)
if (statusData.data.error) {
message.error(`更新失败: ${statusData.data.error}`)
message.error(t('systemUpdate.updateFailedWithMessage', { message: statusData.data.error }))
} else if (statusData.data.progress === 100) {
message.success('更新成功!页面将在3秒后刷新...')
message.success(t('systemUpdate.updateSuccessRefresh'))
setTimeout(() => window.location.reload(), 3000)
}
}
@@ -153,19 +155,19 @@ const SystemUpdate: React.FC = () => {
// 5分钟后停止轮询
setTimeout(() => clearInterval(pollInterval), 5 * 60 * 1000)
} else if (data.code === 403) {
message.error('需要管理员权限才能执行更新')
message.error(t('systemUpdate.needAdmin'))
} else {
message.error(data.message || '启动更新失败')
message.error(data.message || t('systemUpdate.startFailed'))
}
} catch (error: any) {
message.error(error.message || '启动更新失败')
message.error(error.message || t('systemUpdate.startFailed'))
}
}
})
}
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleString('zh-CN')
return new Date(dateString).toLocaleString(i18n.language === 'zh-CN' ? 'zh-CN' : i18n.language === 'zh-TW' ? 'zh-TW' : 'en')
}
return (
@@ -173,7 +175,7 @@ const SystemUpdate: React.FC = () => {
title={
<Space>
<CloudUploadOutlined style={{ fontSize: '18px', color: '#1890ff' }} />
<span style={{ fontSize: '16px', fontWeight: 600 }}></span>
<span style={{ fontSize: '16px', fontWeight: 600 }}>{t('systemUpdate.title')}</span>
</Space>
}
style={{
@@ -195,7 +197,7 @@ const SystemUpdate: React.FC = () => {
}}>
<div>
<div style={{ fontSize: '13px', opacity: 0.9, marginBottom: '4px' }}>
{t('systemUpdate.currentVersion')}
</div>
<div style={{ fontSize: '20px', fontWeight: 600 }}>
v{currentVersion || 'unknown'}
@@ -208,16 +210,16 @@ const SystemUpdate: React.FC = () => {
{updateStatus.updating && (
<Alert
message={
<span style={{ fontSize: '15px', fontWeight: 500 }}></span>
<span style={{ fontSize: '15px', fontWeight: 500 }}>{t('systemUpdate.updating')}</span>
}
description={
<div style={{ marginTop: '12px' }}>
<div style={{
marginBottom: '12px',
fontSize: '14px',
color: '#595959'
color: '#595959'
}}>
{updateStatus.message}
{updateStatus.message || t('systemUpdate.ready')}
</div>
<Progress
percent={updateStatus.progress}
@@ -245,7 +247,7 @@ const SystemUpdate: React.FC = () => {
{updateStatus.error && (
<Alert
message={<span style={{ fontSize: '15px', fontWeight: 500 }}></span>}
message={<span style={{ fontSize: '15px', fontWeight: 500 }}>{t('systemUpdate.updateFailedTitle')}</span>}
description={
<div style={{
marginTop: '8px',
@@ -281,14 +283,14 @@ const SystemUpdate: React.FC = () => {
boxShadow: '0 2px 4px rgba(24, 144, 255, 0.2)'
}}
>
{t('systemUpdate.checkUpdate')}
</Button>
{updateInfo && !updateInfo.hasUpdate && (
<Alert
message={
<span style={{ fontSize: '15px', fontWeight: 500 }}>
{t('systemUpdate.alreadyLatest')}
</span>
}
type="success"
@@ -326,7 +328,7 @@ const SystemUpdate: React.FC = () => {
color: '#8c8c8c',
marginBottom: '6px'
}}>
{t('systemUpdate.newVersionFound')}
</div>
<Space size="small">
<Tag
@@ -341,15 +343,15 @@ const SystemUpdate: React.FC = () => {
v{updateInfo.latestVersion}
</Tag>
{updateInfo.prerelease && (
<Tag
color="orange"
style={{
<Tag
color="orange"
style={{
fontSize: '12px',
padding: '4px 12px',
borderRadius: '4px'
}}
>
Pre-release
{t('systemUpdate.prerelease')}
</Tag>
)}
</Space>
@@ -367,7 +369,7 @@ const SystemUpdate: React.FC = () => {
color: '#8c8c8c',
marginBottom: '4px'
}}>
{t('systemUpdate.publishedAt')}
</div>
<div style={{
fontSize: '14px',
@@ -385,7 +387,7 @@ const SystemUpdate: React.FC = () => {
marginBottom: '8px',
fontWeight: 500
}}>
{t('systemUpdate.releaseNotes')}
</div>
<div style={{
padding: '16px',
@@ -449,7 +451,7 @@ const SystemUpdate: React.FC = () => {
boxShadow: '0 4px 12px rgba(102, 126, 234, 0.4)'
}}
>
v{updateInfo.latestVersion}
{t('systemUpdate.upgradeNow', { version: updateInfo.latestVersion })}
</Button>
</div>
)}
@@ -458,20 +460,20 @@ const SystemUpdate: React.FC = () => {
{!updateStatus.updating && !(updateInfo && updateInfo.hasUpdate) && (
<Alert
message={
<span style={{ fontSize: '15px', fontWeight: 500 }}>使</span>
<span style={{ fontSize: '15px', fontWeight: 500 }}>{t('systemUpdate.usageTitle')}</span>
}
description={
<ul style={{
marginBottom: 0,
<ul style={{
marginBottom: 0,
paddingLeft: '20px',
fontSize: '14px',
color: '#595959',
lineHeight: '1.8'
}}>
<li>"检查更新"</li>
<li>30-60</li>
<li></li>
<li></li>
<li>{t('systemUpdate.usage1')}</li>
<li>{t('systemUpdate.usage2')}</li>
<li>{t('systemUpdate.usage3')}</li>
<li>{t('systemUpdate.usage4')}</li>
</ul>
}
type="info"