mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-07-12 16:01:56 +08:00
fix(audit): 复查第三波 — Hermes 安装向导 i18n 化漏网中文
第三轮逐文件复查发现 hermes/pages/setup.js 还有大量用户首屏可见的
中文硬编码(之前两轮主要扫 timer/cleanup/syntax/listener 类 bug)。
## 涉及修复
### setup.js phase 标签(5 处)
phase indicator 是用户最早看到的 UI 元素:
```
{ id: 'detect', label: '检测' } → t('engine.hermesPhaseDetect')
{ id: 'install', label: '安装' } → t('engine.hermesPhaseInstall')
{ id: 'configure', label: '配置' } → t('engine.hermesPhaseConfigure')
{ id: 'gateway', label: '启动' } → t('engine.hermesPhaseGateway')
{ id: 'complete', label: '完成' } → t('engine.hermesPhaseComplete')
```
英文用户原本看到的是 5 个汉字,现在按系统语言显示
Detect / Install / Configure / Start / Complete。
### setup.js Provider 分组标题(4 组)
configure 阶段渲染 provider 选择按钮时分组标题:
```
'国际 · API Key' → hermesProviderGroupIntl
'国内 · API Key' → hermesProviderGroupCn
'聚合 / 路由' → hermesProviderGroupAggregator
'OAuth 登录(需终端)' → hermesProviderGroupOAuth
'<provider>:需运行' → hermesProviderOAuthRunHint
```
### setup.js Provider 加载失败 fallback 文案
Web 模式下 provider 列表加载失败时的 12 行多行 hint,原本只有中文,
现已 11 语言 i18n。
### setup.js 检测异常日志 prefix
```js
logs.push(`检测错误: ${e}`) → `[detect error] ${e?.message || e}`
```
日志输出(用户在向导首屏可见)跟其他英文 prefix 一致,便于日志聚合。
## 新增 i18n key(engine 模块)
- hermesPhaseDetect / Install / Configure / Gateway / Complete
- hermesProviderGroupIntl / Cn / Aggregator / OAuth
- hermesProviderOAuthRunHint
- hermesProvidersLoadFallback
11 语言全覆盖(zh-CN / zh-TW / en / ja / ko / vi / es / pt / ru / fr / de)。
## 复查范围(第三轮)
- src-tauri/src/commands/*.rs unwrap 全 safe(regex / SystemTime / Mutex)
- src/lib/ humanize-error / engine-manager / ws-client / message-db / tts 全部健全
- src/components/ modal / toast 无问题
- scripts/dev-api.js 176 个 handler 无 duplicate / 关键命令全有
- src/pages/ 没发现新硬编码(之前的 i18n 覆盖到位)
- src/engines/hermes/pages/ setup.js 是唯一遗漏的中文重灾区,已修
## 验证
- npm run build:PASS(1.46s)
- 总计三轮复查共修 11 个 bug + 5 个 i18n 漏网
This commit is contained in:
@@ -67,11 +67,11 @@ export function render() {
|
||||
// --- 阶段指示器 ---
|
||||
function renderPhaseIndicator() {
|
||||
const phases = [
|
||||
{ id: 'detect', label: '检测' },
|
||||
{ id: 'install', label: '安装' },
|
||||
{ id: 'configure', label: '配置' },
|
||||
{ id: 'gateway', label: '启动' },
|
||||
{ id: 'complete', label: '完成' },
|
||||
{ id: 'detect', label: t('engine.hermesPhaseDetect') },
|
||||
{ id: 'install', label: t('engine.hermesPhaseInstall') },
|
||||
{ id: 'configure', label: t('engine.hermesPhaseConfigure') },
|
||||
{ id: 'gateway', label: t('engine.hermesPhaseGateway') },
|
||||
{ id: 'complete', label: t('engine.hermesPhaseComplete') },
|
||||
]
|
||||
const idx = phases.findIndex(p => p.id === phase)
|
||||
return `<div class="hermes-phases">${phases.map((p, i) => {
|
||||
@@ -420,7 +420,7 @@ export function render() {
|
||||
}
|
||||
draw()
|
||||
} catch (e) {
|
||||
logs.push(`检测错误: ${e}`)
|
||||
logs.push(`[detect error] ${e?.message || e}`)
|
||||
phase = 'install'
|
||||
draw()
|
||||
}
|
||||
@@ -686,7 +686,7 @@ export function render() {
|
||||
function renderGroupedProviderButtons() {
|
||||
if (!hermesProviders.length) {
|
||||
return `<div style="padding:10px 12px;background:var(--bg-tertiary);border-radius:var(--radius-sm,6px);color:var(--text-secondary);font-size:12px;line-height:1.6">
|
||||
未能加载 provider 列表。Web 模式下可手动填写下方 Base URL 与 API Key 完成配置。
|
||||
${t('engine.hermesProvidersLoadFallback')}
|
||||
</div>`
|
||||
}
|
||||
|
||||
@@ -708,19 +708,19 @@ function renderGroupedProviderButtons() {
|
||||
const parts = []
|
||||
|
||||
if (hermesGroups.apiKeyIntl.length) {
|
||||
parts.push(`<div style="${sectionStyle}"><div style="${titleStyle}">国际 · API Key</div><div style="${rowStyle}">${hermesGroups.apiKeyIntl.map(btn).join('')}</div></div>`)
|
||||
parts.push(`<div style="${sectionStyle}"><div style="${titleStyle}">${t('engine.hermesProviderGroupIntl')}</div><div style="${rowStyle}">${hermesGroups.apiKeyIntl.map(btn).join('')}</div></div>`)
|
||||
}
|
||||
if (hermesGroups.apiKeyCn.length) {
|
||||
parts.push(`<div style="${sectionStyle}"><div style="${titleStyle}">国内 · API Key</div><div style="${rowStyle}">${hermesGroups.apiKeyCn.map(btn).join('')}</div></div>`)
|
||||
parts.push(`<div style="${sectionStyle}"><div style="${titleStyle}">${t('engine.hermesProviderGroupCn')}</div><div style="${rowStyle}">${hermesGroups.apiKeyCn.map(btn).join('')}</div></div>`)
|
||||
}
|
||||
if (hermesGroups.aggregators.length) {
|
||||
parts.push(`<div style="${sectionStyle}"><div style="${titleStyle}">聚合 / 路由</div><div style="${rowStyle}">${hermesGroups.aggregators.map(btn).join('')}</div></div>`)
|
||||
parts.push(`<div style="${sectionStyle}"><div style="${titleStyle}">${t('engine.hermesProviderGroupAggregator')}</div><div style="${rowStyle}">${hermesGroups.aggregators.map(btn).join('')}</div></div>`)
|
||||
}
|
||||
if (hermesGroups.oauth.length) {
|
||||
const oauthItems = hermesGroups.oauth.map(p =>
|
||||
`<div style="font-size:11px;color:var(--text-tertiary);margin-right:10px"><code>${p.name}</code>:需运行 <code>${p.cliAuthHint}</code></div>`
|
||||
`<div style="font-size:11px;color:var(--text-tertiary);margin-right:10px"><code>${p.name}</code>:${t('engine.hermesProviderOAuthRunHint') || '需运行'} <code>${p.cliAuthHint}</code></div>`
|
||||
).join('')
|
||||
parts.push(`<div style="${sectionStyle}"><div style="${titleStyle}">OAuth 登录(需终端)</div><div style="display:flex;flex-wrap:wrap;gap:4px 0">${oauthItems}</div></div>`)
|
||||
parts.push(`<div style="${sectionStyle}"><div style="${titleStyle}">${t('engine.hermesProviderGroupOAuth')}</div><div style="display:flex;flex-wrap:wrap;gap:4px 0">${oauthItems}</div></div>`)
|
||||
}
|
||||
|
||||
return parts.join('')
|
||||
|
||||
Reference in New Issue
Block a user