Phase 0.8 對應後端轉檔功能的 frontend UI。完整 state machine(idle / uploading /
queued / running / succeeded / failed / expired)+ XHR upload progress + polling +
half-auto result handling(加到模型庫 / 下載)。
新增 src/app/conversion/(11 元件 + 12 test files,~5,000 行 prod+test,310/310 tests 全綠):
- page.tsx:state router(mount → bootstrap → 依 store.uiState 切換 view)+ toast on
store.error(aborted / active_job_exists 不 toast,避免雙重提示)
- IdleForm.tsx + FileDropzone.tsx + ChipSelector.tsx:上傳表單(拖放 + .onnx/.tflite
format 驗證 + 500MB 大小限制 + KL520/630/720/730 chip 選擇 + ref images ≤100×10MB)
- UploadingView.tsx:XHR upload progress 0-100% + EWMA ETA(alpha=0.3 平滑,<5s 顯示
「即將完成」避抖動)+ beforeunload warning + AlertDialog 取消
- ProcessingView.tsx:StageIndicator 三段式(解析模型 → 量化編譯 → 編譯 NEF)+
Progress bar 三模式(queued / determinate / indeterminate)+ tab title `(轉檔中)` 防疊加 +
409 active_job_exists banner(switchedFromActiveJob flag)
- SuccessView.tsx + PromoteDialog.tsx:兩按鈕(加到模型庫 / 下載)視覺平衡不暗示預設答案 +
7 天 expires_at 倒數(mount 時 setTimeout 鎖過期那刻 + 60s tick)+ PromoteDialog 單欄位
name 驗證(≤100 字元 / 無 /\\)+ spinner-during-close 阻擋 + 409 already_imported 特殊
訊息 + toast.success router.push 跳模型清單
- FailedView.tsx:5 個 known error code 翻譯(UNSUPPORTED_FORMAT / INVALID_CHECKSUM /
QUANTIZATION_FAILED / MODEL_TOO_LARGE / QUOTA_EXCEEDED)+ unknown fallback +
3 個建議解決方法 + Job ID 前 8 字元(供回報)+ 「重新開始」
- ExpiredView.tsx:橘色 hero(過期不 alarming)+ source/chip 摘要 + 「重新轉檔」→
store.reset()
新增 src/stores/conversion-store.ts(Zustand store + 29 tests):
- 7 個 UI state machine(不允許跳階段)
- recursive setTimeout polling(running 5s / queued 10s / 5xx 指數退避 cap 30s)+
visibilitychange 暫停/恢復
- 不持久化 jobId(純靠 backend getActiveConversion() lazy rebuild ownership)
- AbortController 防 stale request + 取消上傳
- switchedFromActiveJob flag(409 自動切到既存 job + UI 顯示 banner)
- formDraft(chip / taskName 提到 store,failed→idle 後保留設定,file picker 重選;
File 物件不能序列化只留 local)
新增 src/lib/api/conversion.ts + types/conversion.ts(5 client 函式 + 22 tests):
- initConversion:XHR multipart + onUploadProgress + AbortSignal
- getActiveConversion / getConversion / promoteConversionToModels:標準 fetch
- getConversionDownloadURL:純函式,回 `/api/conversion/{job_id}/download` 給 anchor
download 觸發(server-side 302 → FAA,token 不過 frontend JS)
- ConversionAPIError(status, code, message, requestId?),code 統一全小寫對齊
conversion.error.<code> i18n key 命名
新增 src/lib/utils/eta.ts(EWMA 演算法純函式 + 19 tests):抽出 smoothSpeed /
estimateRemainingSeconds / instantSpeedBytesPerSec / computeEtaUpdate(test 友善)。
新增 src/app/conversion/e2e-conversion-flow.test.tsx(5 e2e flow tests):
- happy path .onnx + KL720 + 0 ref images(idle → upload → polling → succeeded → 加到模型庫)
- variant 5 ref images
- upload fail → retry(form 設定保留)
- polling 5xx 指數退避 → 恢復繼續
- expired job → ExpiredView → 重新轉檔
修改 sidebar.tsx:左側 nav 新增「轉檔」tab(Wand2 icon,模型庫之後)。
修改 i18n 字典:新增 ~150 個 conversion.* keys(中英雙語對齊)。
PRD §9 14 條功能驗收條件全達成(4 條整合驗收等 stage 部署)。
驗證:pnpm lint / test (310/310) / build 全綠。
對齊文件:
- .autoflow/02-prd/features/feature-converter-integration.md
- .autoflow/03-design/wireframes/wireframe-conversion.md
- .autoflow/03-design/flows/flow-conversion.md
- .autoflow/04-architecture/api/api-conversion.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
601 lines
30 KiB
TypeScript
601 lines
30 KiB
TypeScript
/**
|
||
* 繁體中文字典 — visionA Cloud
|
||
*
|
||
* 原則:
|
||
* - 扁平 key(`nav.dashboard`);新增 key 時請同步更新 en.ts,確保兩語系 key 集合一致。
|
||
* - 設計指引:繁中台灣用語;不過度使用「您」;錯誤訊息說清楚發生什麼 + 使用者能做什麼。
|
||
* - F4(Sidebar/Header)、F5(auth/session)基礎已建立;F6 批次加入 Dashboard / Devices / Models / Workspace / Settings。
|
||
*/
|
||
|
||
import type { Dictionary } from "../types";
|
||
|
||
export const zhHant: Dictionary = {
|
||
// ── 應用 ──
|
||
"app.title": "visionA Cloud",
|
||
"app.tagline": "將 local-tool 的使用體驗延伸到雲端",
|
||
|
||
// ── 通用 ──
|
||
"common.loading": "載入中…",
|
||
"common.error": "發生錯誤",
|
||
"common.cancel": "取消",
|
||
"common.confirm": "確認",
|
||
"common.save": "儲存",
|
||
"common.close": "關閉",
|
||
"common.retry": "重試",
|
||
"common.view": "檢視",
|
||
"common.manage": "管理",
|
||
"common.connect": "連接",
|
||
"common.disconnect": "中斷連線",
|
||
"common.delete": "刪除",
|
||
"common.edit": "編輯",
|
||
"common.back": "返回",
|
||
"common.na": "—",
|
||
|
||
// ── 側邊導航 ──
|
||
"nav.dashboard": "儀表板",
|
||
"nav.devices": "裝置",
|
||
"nav.models": "模型",
|
||
"nav.conversion": "轉檔",
|
||
"nav.workspace": "推論工作區",
|
||
"nav.clusters": "叢集",
|
||
"nav.settings": "設定",
|
||
|
||
// ── 雛形階段 banner ──
|
||
// Phase 0.7 stage deployment fix:OIDC 已接 Innovedus 帳號中心,文案不再寫「未實作身分驗證」
|
||
"banner.prototype":
|
||
"🚧 雛形版本 · 已接 Innovedus 帳號中心,但部分功能仍為 UI 示意;資料為示範資料",
|
||
"banner.prototype.short": "🚧 雛形版本(demo)",
|
||
"banner.prototype.ariaLabel": "雛形版本提示",
|
||
|
||
// ── Header ──
|
||
"header.toggleTheme": "切換主題",
|
||
"header.toggleLocale": "切換語言",
|
||
"header.userMenu.open": "開啟使用者選單",
|
||
"header.userMenu.profile": "帳號設定",
|
||
"header.userMenu.logout": "登出",
|
||
"header.userMenu.fallbackName": "使用者",
|
||
"header.breadcrumb.home": "首頁",
|
||
|
||
// ── Tunnel / 遠端狀態(燈號) ──
|
||
"tunnel.status.online": "已連線",
|
||
"tunnel.status.offline": "離線",
|
||
"tunnel.status.reconnecting": "重新連線中",
|
||
"tunnel.rttLabel": "延遲 {rtt}ms",
|
||
|
||
// ── 主題切換(next-themes) ──
|
||
"theme.light": "淺色",
|
||
"theme.dark": "深色",
|
||
"theme.system": "跟隨系統",
|
||
|
||
// ── 認證(Phase 0.6 OIDC redirect 模式) ──
|
||
// 設計重點:
|
||
// - 所有 email/password 表單時代的 key(auth.login.email/password/submit/...
|
||
// auth.register.email/password/...)已移除,改用 Member Center 統一帳號
|
||
// - 共用「登入 / 登出」字串收斂為 auth.action.signIn / auth.action.signOut,
|
||
// 避免 header dropdown 之類的非表單元件再借用 auth.login.submit
|
||
"auth.action.signIn": "登入",
|
||
"auth.action.signOut": "登出",
|
||
// Login 頁
|
||
"auth.login.title": "登入 visionA Cloud",
|
||
"auth.login.subtitle": "歡迎回到 visionA Cloud",
|
||
"auth.login.welcomeBack": "歡迎回來",
|
||
"auth.login.signInWithMC": "使用您的 Innovedus 帳號登入",
|
||
"auth.login.button": "登入",
|
||
"auth.login.noAccount": "還沒有帳號?",
|
||
"auth.login.registerLink": "前往註冊",
|
||
"auth.login.prototypeHint":
|
||
"Phase 0.6 雛形 — 登入會跳轉到 Innovedus 帳號中心完成驗證",
|
||
// Register 頁(Phase 0.6:visionA 不再自有註冊表單,改導向 Member Center)
|
||
"auth.register.title": "註冊 visionA",
|
||
"auth.register.description":
|
||
"visionA 使用 Innovedus 統一帳號系統。",
|
||
"auth.register.howTo":
|
||
"請至 Innovedus 帳號中心註冊,註冊完成後即可回到 visionA 登入。",
|
||
"auth.register.button": "前往 Innovedus 帳號中心",
|
||
"auth.register.disabledHint":
|
||
"尚未設定 Innovedus 帳號中心 URL,請聯絡系統管理員。",
|
||
"auth.register.alreadyHaveAccount": "已有帳號?",
|
||
"auth.register.loginLink": "登入",
|
||
|
||
// ── 首頁 / Dashboard ──
|
||
"home.welcome": "歡迎回來,{name}",
|
||
"home.placeholder":
|
||
"這裡之後會是 Dashboard(StatCard / ActivityTimeline / ConnectedDevicesList);F6 會從 local-tool 搬入。",
|
||
"dashboard.title": "儀表板",
|
||
"dashboard.subtitle": "管理你的雲端 Edge AI 資源",
|
||
"dashboard.models": "模型",
|
||
"dashboard.devices": "裝置",
|
||
"dashboard.connected": "線上裝置",
|
||
"dashboard.flashes": "已燒錄次數",
|
||
"dashboard.connectedDevices": "線上裝置",
|
||
"dashboard.noConnectedDevices": "目前沒有裝置線上。配對一台 Kneron 裝置開始雲端推論。",
|
||
"dashboard.recentActivity": "近期活動",
|
||
"dashboard.noActivity": "還沒有任何活動。配對裝置、上傳模型或跑一次推論後就會出現。",
|
||
"dashboard.quickActions": "快速操作",
|
||
"dashboard.browseModels": "瀏覽模型",
|
||
"dashboard.manageDevices": "管理裝置",
|
||
"dashboard.uploadModel": "上傳模型",
|
||
"dashboard.pairDevice": "配對裝置",
|
||
"dashboard.empty.title": "還沒有任何裝置",
|
||
"dashboard.empty.description": "配對你的第一台 Kneron 裝置,開始雲端推論之旅",
|
||
"dashboard.empty.action": "配對裝置",
|
||
"dashboard.activity.justNow": "剛剛",
|
||
"dashboard.activity.minutesAgo": "{n} 分鐘前",
|
||
"dashboard.activity.hoursAgo": "{n} 小時前",
|
||
"dashboard.activity.daysAgo": "{n} 天前",
|
||
|
||
// ── Devices ──
|
||
"devices.title": "裝置",
|
||
"devices.subtitle": "管理你的 Edge AI 裝置",
|
||
"devices.type": "類型",
|
||
"devices.firmware": "韌體",
|
||
"devices.flashedModel": "已燒錄模型",
|
||
"devices.openWorkspace": "開啟工作區",
|
||
"devices.addMore": "配對新裝置",
|
||
"devices.pairAction": "配對新裝置",
|
||
"devices.empty.title": "還沒有配對的裝置",
|
||
"devices.empty.description":
|
||
"在你的電腦上執行 local agent 並完成配對,就能從任何地方存取你的 Kneron 裝置",
|
||
"devices.empty.action": "配對第一台裝置",
|
||
"devices.empty.secondaryAction": "查看配對說明",
|
||
"devices.detail.id": "ID",
|
||
"devices.detail.type": "類型",
|
||
"devices.detail.firmware": "韌體",
|
||
"devices.detail.port": "連接埠",
|
||
"devices.detail.deviceInfo": "裝置資訊",
|
||
"devices.detail.modelStatus": "模型狀態",
|
||
"devices.detail.readyForInference": "已就緒,可開始推論",
|
||
"devices.detail.noModelFlashed": "尚未燒錄任何模型",
|
||
"devices.detail.pairedAt": "配對時間",
|
||
"devices.detail.hostName": "所在電腦",
|
||
"devices.detail.lastSeen": "最後心跳",
|
||
"devices.detail.offlineBanner.title": "此裝置目前離線",
|
||
"devices.detail.offlineBanner.description":
|
||
"部分操作無法使用,待 local agent 重新連線後自動恢復",
|
||
"devices.status.detected": "已偵測",
|
||
"devices.status.connecting": "連線中",
|
||
"devices.status.connected": "已連線",
|
||
"devices.status.flashing": "燒錄中",
|
||
"devices.status.inferencing": "推論中",
|
||
"devices.status.error": "錯誤",
|
||
"devices.status.disconnected": "未連接",
|
||
|
||
// ── Remote Device Badge(雲端 tunnel 狀態) ──
|
||
"remote.status.online": "在線",
|
||
"remote.status.offline": "離線",
|
||
"remote.status.reconnecting": "重新連線中",
|
||
"remote.status.error": "連線錯誤",
|
||
"remote.status.unknown": "未確認",
|
||
"remote.lastSeenNever": "從未連線",
|
||
"remote.lastSeen.justNow": "剛剛",
|
||
"remote.lastSeen.minutesAgo": "{n} 分鐘前",
|
||
"remote.lastSeen.hoursAgo": "{n} 小時前",
|
||
|
||
// ── Models ──
|
||
"models.title": "模型庫",
|
||
"models.subtitle": "管理雲端上的 Kneron 模型",
|
||
"models.size": "檔案大小",
|
||
"models.createdAt": "建立時間",
|
||
"models.status.uploading": "上傳中",
|
||
"models.status.scanning": "掃描中",
|
||
"models.status.ready": "可用",
|
||
"models.status.rejected": "檢測失敗",
|
||
"models.source.uploaded": "自行上傳",
|
||
"models.source.preset": "預設",
|
||
"models.source.converted": "已轉檔",
|
||
"models.filters.label": "模型篩選",
|
||
"models.filters.hardware": "硬體",
|
||
"models.filters.source": "來源",
|
||
"models.filters.all": "全部",
|
||
"models.empty.title": "還沒有任何模型",
|
||
"models.empty.description":
|
||
"上傳你的第一個 .nef 模型到雲端,就能部署到任何一台配對過的 Kneron 裝置",
|
||
"models.empty.action": "上傳第一個模型",
|
||
"models.detail.description": "說明",
|
||
"models.detail.version": "版本",
|
||
"models.detail.checksum": "校驗碼",
|
||
"models.detail.supportedChips": "支援晶片",
|
||
"models.detail.deployToDevice": "部署至裝置",
|
||
|
||
// ── Model Upload Dialog(flow-model-upload) ──
|
||
"models.upload.button": "上傳模型",
|
||
"models.upload.dialog.title": "上傳模型",
|
||
"models.upload.dropzone.hint": "支援格式:.nef · 最大 100 MB",
|
||
"models.upload.selectedFile": "選擇檔案",
|
||
"models.upload.field.name": "模型名稱",
|
||
"models.upload.field.version": "版本",
|
||
"models.upload.field.notes": "備註(選填)",
|
||
"models.upload.field.targetChip": "目標晶片",
|
||
"models.upload.action.cancel": "取消",
|
||
"models.upload.action.start": "開始上傳",
|
||
"models.upload.action.remove": "移除",
|
||
"models.upload.uploading.title": "上傳中",
|
||
"models.upload.uploading.hint": "請勿關閉此視窗或導航到其他頁面",
|
||
"models.upload.success.title": "上傳完成",
|
||
"models.upload.success.scanHint": "模型即將進入安全掃描,完成後可燒錄",
|
||
"models.upload.error.invalidType": "只支援 .nef 檔案,你選的是 {type}",
|
||
"models.upload.error.tooLarge": "檔案太大({size}),最大允許 100 MB",
|
||
"models.upload.error.requiredField": "{field} 為必填",
|
||
"models.upload.error.urlFailed": "伺服器忙碌,請稍後再試",
|
||
"models.upload.error.networkLost": "網路中斷,上傳已暫停",
|
||
"models.upload.toast.uploaded": "模型「{name}」已上傳",
|
||
|
||
// ── Workspace ──
|
||
"workspace.title": "推論工作區",
|
||
"workspace.subtitle": "選擇已線上的裝置開始推論",
|
||
"workspace.empty.title": "目前沒有線上裝置",
|
||
"workspace.empty.description": "請先配對並確認 local agent 已連上雲端",
|
||
"workspace.empty.action": "前往裝置管理",
|
||
"workspace.header.backToDevices": "返回裝置",
|
||
"workspace.header.title": "工作區",
|
||
"workspace.inference.start": "開始推論",
|
||
"workspace.inference.stop": "停止推論",
|
||
"workspace.placeholder.cameraComingSoon":
|
||
"Camera 推論介面預覽 — F8 會接上 MJPEG stream(透過 tunnel 從 local agent 中繼)",
|
||
"workspace.offline.title": "裝置已離線",
|
||
"workspace.offline.description": "與 {deviceName} 的連線中斷,推論已自動停止",
|
||
"workspace.offline.backToList": "返回裝置列表",
|
||
"workspace.tabs.camera": "Camera",
|
||
"workspace.tabs.image": "圖片(Phase 1)",
|
||
"workspace.tabs.video": "影片(Phase 1)",
|
||
"workspace.tabs.batch": "批次(Phase 1)",
|
||
|
||
// ── Settings ──
|
||
"settings.title": "設定",
|
||
"settings.subtitle": "管理偏好與雲端端點",
|
||
"settings.tabs.general": "一般",
|
||
"settings.tabs.advanced": "進階",
|
||
"settings.general.title": "偏好",
|
||
"settings.general.language": "語言",
|
||
"settings.general.theme": "主題",
|
||
"settings.general.themeHint": "跟隨系統偏好自動切換淺 / 深色",
|
||
"settings.advanced.title": "雲端端點",
|
||
"settings.advanced.apiEndpoint": "API Endpoint",
|
||
"settings.advanced.apiEndpointHint":
|
||
"正常使用者不需更改;開發時可切到 staging 或 localhost",
|
||
"settings.advanced.apiUrl": "目前 API URL",
|
||
"settings.advanced.wsUrl": "目前 WebSocket URL",
|
||
"settings.advanced.about": "關於",
|
||
"settings.advanced.version": "版本",
|
||
"settings.advanced.platform": "平台",
|
||
|
||
// ── Pairing(F7 新增)──
|
||
"pairing.title": "配對新裝置",
|
||
"pairing.subtitle": "讓你的 Kneron 裝置連上雲端,就能從任何地方遠端操作",
|
||
"pairing.token.title": "你的 Pairing Token",
|
||
"pairing.step1.description":
|
||
"複製下方 token,在 15 分鐘內貼到 local agent 完成配對",
|
||
"pairing.copy": "複製",
|
||
"pairing.copied": "已複製",
|
||
"pairing.regenerate": "重新產生",
|
||
"pairing.timeRemaining": "剩餘 {time}",
|
||
"pairing.generatedAt": "產生時間:{time}",
|
||
"pairing.token.expired.label": "此 token 已過期,請重新產生",
|
||
"pairing.regenerateConfirm.title": "確定要重新產生?",
|
||
"pairing.regenerateConfirm.description":
|
||
"舊 token 將立即失效,新 token 有效期 15 分鐘",
|
||
"pairing.security.warning": "這組 token 15 分鐘內有效,請立刻完成配對",
|
||
"pairing.security.oneTime": "token 是一次性使用,完成配對後自動失效",
|
||
"pairing.toast.copied": "Token 已複製到剪貼簿,15 分鐘內有效",
|
||
"pairing.toast.generateFailed": "無法產生 token,請重試",
|
||
"pairing.toast.expiringSoon": "Token 即將過期,請立刻完成或重新產生",
|
||
"pairing.toast.pairedSuccess": "裝置 {deviceName} 已成功配對",
|
||
"pairing.toast.cliCopied": "指令已複製到剪貼簿",
|
||
"pairing.device.unknown": "未知裝置",
|
||
"pairing.cli.title": "CLI 指令範例",
|
||
"pairing.cli.description":
|
||
"在你的電腦啟動 local agent,將 token 貼到指令的 --relay-token 參數",
|
||
"pairing.cli.copy": "複製指令",
|
||
"pairing.cli.hint":
|
||
"local agent 連上雲端後,本頁會自動偵測並跳轉到裝置列表",
|
||
"pairing.step3.waiting": "等待 local agent 連線…",
|
||
"pairing.step3.elapsed": "已等待 {time}(最長 3 分鐘)",
|
||
"pairing.step3.hints.running": "確認 local agent 已啟動",
|
||
"pairing.step3.hints.token": "確認 token 貼上時無缺字或多餘空白",
|
||
"pairing.step3.hints.network": "確認你的網路可連線到雲端",
|
||
"pairing.step3.success": "已成功連線!",
|
||
"pairing.step3.success.detected": "檢測到的裝置",
|
||
"pairing.step3.failure.timeout": "連線超時",
|
||
"pairing.step3.failure.reason":
|
||
"超過 3 分鐘沒收到 local agent 連線,可能是 local agent 尚未啟動",
|
||
"pairing.step3.failure.retry": "重新檢查",
|
||
|
||
// ── Account(Phase 0.6 OIDC)──
|
||
// 設計重點:
|
||
// - 個人資料一律唯讀;修改入口統一導到 Innovedus 帳號中心
|
||
// - 「刪除帳號」按鈕保留為 disabled 雛形,文案說明改在 Member Center 處理
|
||
"account.title": "帳號設定",
|
||
"account.subtitle": "個人資料由 Innovedus 帳號中心管理",
|
||
"account.profile.title": "個人資料",
|
||
"account.profile.userId": "使用者 ID",
|
||
"account.profile.email": "電子郵件",
|
||
"account.profile.name": "顯示名稱",
|
||
"account.profile.namePlaceholder": "—",
|
||
"account.profile.managedBy":
|
||
"個人資料由 Innovedus 帳號中心管理。如需修改,請至 Innovedus 帳號中心。",
|
||
"account.profile.editAtMemberCenter": "前往 Innovedus 帳號中心",
|
||
"account.profile.editDisabledHint":
|
||
"尚未設定 Innovedus 帳號中心 URL,請聯絡系統管理員。",
|
||
"account.session.title": "登入狀態",
|
||
"account.session.description":
|
||
"登出後會回到登入頁,下次需重新透過 Innovedus 帳號中心登入。",
|
||
"account.danger.title": "危險區",
|
||
"account.danger.description":
|
||
"帳號刪除請至 Innovedus 帳號中心處理,visionA 不直接執行此操作。",
|
||
"account.danger.deleteAccount": "刪除帳號",
|
||
"account.danger.deleteAccount.tooltip":
|
||
"請至 Innovedus 帳號中心處理。",
|
||
|
||
// ── Conversion / 轉檔(Phase 0.8 — feature-converter-integration)──
|
||
// 設計來源:.autoflow/03-design/wireframes/wireframe-conversion.md §11
|
||
// 對應 PRD:.autoflow/02-prd/features/feature-converter-integration.md
|
||
// 範圍:5 個 state(idle / uploading / processing / success / failed)+ 6 種錯誤碼翻譯 + 過期狀態
|
||
"conversion.title": "轉檔",
|
||
"conversion.subtitle":
|
||
"把 ONNX / TFLite 模型轉成 .nef,跑在 Kneron 邊緣裝置上",
|
||
|
||
// idle 空狀態
|
||
"conversion.idle.heading": "還沒有進行中的轉檔",
|
||
"conversion.idle.description":
|
||
"上傳一個 ONNX / TFLite 模型,選擇目標 Kneron 晶片,我們幫你產出可直接燒錄的 .nef 檔案",
|
||
"conversion.idle.cta": "開始轉檔",
|
||
"conversion.idle.formats": "支援 .onnx / .tflite · 最大 500 MB",
|
||
"conversion.idle.about.title": "關於轉檔",
|
||
"conversion.idle.about.line1": "一次只能跑一個轉檔任務(包含其他分頁)",
|
||
"conversion.idle.about.line2": "完成後 7 天內可下載結果,過期自動清除",
|
||
"conversion.idle.about.line3": "轉檔約耗時 1–10 分鐘,依模型大小而定",
|
||
|
||
// Upload Dialog
|
||
"conversion.upload.title": "開始轉檔",
|
||
"conversion.upload.description":
|
||
"上傳模型、選擇目標晶片,可選擇加上 reference images 提升精度",
|
||
"conversion.upload.source.label": "來源模型",
|
||
"conversion.upload.source.dropzone": "拖曳 .onnx / .tflite 到此處",
|
||
"conversion.upload.source.or": "或",
|
||
"conversion.upload.source.browse": "選擇檔案",
|
||
"conversion.upload.source.formatHint":
|
||
"支援格式:.onnx · .tflite · 最大 500 MB",
|
||
"conversion.upload.source.remove": "移除",
|
||
"conversion.upload.name.label": "任務名稱(選填)",
|
||
"conversion.upload.name.hint": "顯示用,不影響輸出檔名",
|
||
"conversion.upload.chip.label": "目標晶片",
|
||
"conversion.upload.refImages.label": "Reference images(選填)",
|
||
"conversion.upload.refImages.dropzone": "拖曳圖片到此處(選填)",
|
||
"conversion.upload.refImages.hint":
|
||
"加上 ref images 可提升量化後精度(最多 100 張,每張 ≤ 10 MB)",
|
||
"conversion.upload.refImages.summary":
|
||
"已選 {count} 張 ref images(共 {totalSize})",
|
||
"conversion.upload.refImages.removeAll": "移除全部",
|
||
"conversion.upload.cancel": "取消",
|
||
"conversion.upload.start": "開始轉檔",
|
||
"conversion.upload.error.noFile": "請選擇 .onnx 或 .tflite 檔案",
|
||
"conversion.upload.error.unsupported":
|
||
"不支援的格式,請改用 ONNX 或 TFLite",
|
||
"conversion.upload.error.modelTooLarge":
|
||
"模型超過 500 MB 上限,請改用較小的模型",
|
||
"conversion.upload.error.noChip": "請選擇目標晶片",
|
||
"conversion.upload.error.refTooLarge":
|
||
"{filename} 超過 10 MB,請移除或壓縮後再試",
|
||
"conversion.upload.error.refTooMany": "Reference images 上限 100 張",
|
||
|
||
// uploading 階段(Dialog 內)
|
||
"conversion.uploading.title": "上傳中",
|
||
"conversion.uploading.heading": "正在上傳到 visionA…",
|
||
"conversion.uploading.progress": "已上傳 {loaded} / {total} · 預估剩餘 {eta}",
|
||
"conversion.uploading.almostDone": "即將完成…",
|
||
"conversion.uploading.warning": "請勿關閉此分頁,否則上傳會中斷",
|
||
"conversion.uploading.cancel": "取消上傳",
|
||
"conversion.uploading.cancelConfirm": "上傳尚未完成,確定取消?",
|
||
"conversion.uploading.tabTitle": "visionA Cloud · 上傳中 ({pct}%)",
|
||
"conversion.uploading.toastCanceled": "已取消上傳",
|
||
"conversion.uploading.toastFailed": "上傳失敗:{reason}",
|
||
"conversion.uploading.toastStarted": "已開始轉檔(任務 #{shortJobId})",
|
||
// F-T9 sub-3 / M1:上傳失敗 toast hint
|
||
// M1 修補:File 物件不能保留在 store(不可序列化、跨 unmount 不安全),
|
||
// 失敗回 idle 後 chip / taskName 透過 store.formDraft 保留,但檔案需重選
|
||
"conversion.toast.retryHint": "您之前的設定(晶片 / 任務名稱)仍保留,請重新選擇檔案再試",
|
||
"conversion.toast.networkError": "網路錯誤,請檢查連線後重試",
|
||
// F-T5:ETA / 取消確認 / beforeunload(細節 keys)
|
||
"conversion.uploading.subtitle": "正在上傳模型到 visionA backend",
|
||
"conversion.uploading.eta.computing": "預估剩餘時間…",
|
||
"conversion.uploading.eta.almostDone": "即將完成…",
|
||
"conversion.uploading.eta.format": "預估剩餘 {eta}",
|
||
"conversion.uploading.progress.format": "{loaded} / {total}",
|
||
"conversion.uploading.info": "上傳完成後將開始轉檔(10–30 秒不等)",
|
||
"conversion.uploading.cancel.confirm.title": "取消轉檔?",
|
||
"conversion.uploading.cancel.confirm.message":
|
||
"上傳尚未完成,已上傳的進度會丟失。確定要取消嗎?",
|
||
"conversion.uploading.cancel.confirm.yes": "確定取消",
|
||
"conversion.uploading.cancel.confirm.no": "繼續上傳",
|
||
"conversion.uploading.warning.beforeunload":
|
||
"上傳尚未完成,離開將中斷上傳。",
|
||
"conversion.uploading.target": "目標晶片:{chip}",
|
||
"conversion.uploading.aria.cancel": "取消上傳",
|
||
"conversion.uploading.aria.progress": "上傳進度",
|
||
"conversion.uploading.aria.status": "已上傳 {pct}%,{eta}",
|
||
|
||
// processing 階段(轉檔進行中)
|
||
"conversion.processing.title": "轉檔",
|
||
"conversion.processing.cardHeading": "進行中",
|
||
"conversion.processing.statusBadge": "轉檔中",
|
||
"conversion.processing.startedAgo": "開始於 {time}",
|
||
"conversion.processing.stage1": "上傳完成",
|
||
"conversion.processing.stage2": "解析模型",
|
||
"conversion.processing.stage3": "編譯 NEF",
|
||
"conversion.processing.processing": "處理中…",
|
||
"conversion.processing.hint":
|
||
"通常需要 1–10 分鐘 · 你可以離開此頁面,回來時會自動更新進度",
|
||
"conversion.processing.background.title": "你可以放著不管",
|
||
"conversion.processing.background.l1":
|
||
"我們會在背景持續查詢進度(每 5–10 秒一次)",
|
||
"conversion.processing.background.l2": "完成後分頁標題會通知你",
|
||
"conversion.processing.background.l3":
|
||
"此頁面關掉也沒關係,回來時會自動恢復",
|
||
"conversion.processing.queueLong":
|
||
"目前排隊較久,你可以離開此頁稍後再回",
|
||
"conversion.processing.runLong": "轉檔耗時較長,仍在進行中",
|
||
"conversion.processing.pollFailed": "無法取得轉檔狀態,請重試",
|
||
"conversion.processing.bannerActive": "您離開前的轉檔仍在進行中",
|
||
"conversion.processing.bannerExisting":
|
||
"您已有一個轉檔正在進行中,已切換至該任務",
|
||
// F-T9 sub-2:banner dismiss 按鈕的 a11y label
|
||
"conversion.processing.bannerDismiss": "關閉提示",
|
||
|
||
// F-T6:ProcessingView(queued / running 共用 UI)
|
||
// 任務描述對應 converter `stage` enum(onnx / bie / nef)— 與既有 stage1/2/3
|
||
// (上傳完成 / 解析模型 / 編譯 NEF)的「使用者感知」三段不同;ProcessingView
|
||
// 採用 onnx / bie / nef 對應 converter 真實 stage。詳見任務說明 §wireframe §3.3。
|
||
"conversion.processing.subtitle": "正在轉檔,請保持頁面開啟",
|
||
"conversion.processing.queued": "排隊中⋯",
|
||
"conversion.processing.stage.onnx": "解析模型",
|
||
"conversion.processing.stage.bie": "量化編譯",
|
||
"conversion.processing.stage.nef": "編譯 NEF",
|
||
"conversion.processing.stage.status.completed": "完成",
|
||
"conversion.processing.stage.status.current": "進行中",
|
||
"conversion.processing.stage.status.pending": "待處理",
|
||
"conversion.processing.stage.aria.completed": "{name}(已完成)",
|
||
"conversion.processing.stage.aria.current": "{name}(進行中)",
|
||
"conversion.processing.stage.aria.pending": "{name}(待處理)",
|
||
"conversion.processing.eta.pending": "請耐心等候",
|
||
"conversion.processing.eta.computing": "剩餘時間估算中",
|
||
"conversion.processing.expiryHint":
|
||
"7 天後將自動清除任務,請完成下載或加到模型庫",
|
||
"conversion.processing.tabTitle.prefix": "(轉檔中) ",
|
||
"conversion.processing.aria.progressIndeterminate":
|
||
"轉檔進行中,剩餘時間未知",
|
||
"conversion.processing.aria.queueProgress": "排隊中,等待轉檔開始",
|
||
"conversion.processing.targetChipPrefix": "→",
|
||
|
||
// 已有 active job 提示(idle 頁也會用到)
|
||
"conversion.busy.title": "您已有一個轉檔正在進行中",
|
||
"conversion.busy.cta": "查看進度",
|
||
|
||
// success 結果
|
||
"conversion.success.heading": "轉檔完成",
|
||
"conversion.success.summary.chip": "目標晶片",
|
||
"conversion.success.summary.size": "輸出大小",
|
||
"conversion.success.summary.duration": "耗時",
|
||
"conversion.success.summary.checksum": "checksum",
|
||
"conversion.success.summary.jobId": "任務",
|
||
"conversion.success.nextStep": "接下來要做什麼?",
|
||
"conversion.success.import.title": "加到模型庫",
|
||
"conversion.success.import.description":
|
||
"之後可以從模型庫部署到任何 {chip} 裝置",
|
||
"conversion.success.import.cta": "加到模型庫",
|
||
"conversion.success.import.dialog.title": "加到模型庫",
|
||
"conversion.success.import.dialog.description":
|
||
"把這個轉檔結果加到模型庫,之後可以直接部署到 {chip} 裝置",
|
||
"conversion.success.import.dialog.nameLabel": "模型名稱",
|
||
"conversion.success.import.dialog.nameHint":
|
||
"顯示在模型庫中的名稱,最多 100 字元;不可包含 / 或 \\",
|
||
"conversion.success.import.dialog.nameError.required": "請輸入模型名稱",
|
||
"conversion.success.import.dialog.nameError.tooLong":
|
||
"模型名稱不可超過 100 字元",
|
||
"conversion.success.import.dialog.nameError.invalidChars":
|
||
"模型名稱不可包含 / 或 \\",
|
||
"conversion.success.import.dialog.descLabel": "描述(選填)",
|
||
"conversion.success.import.dialog.sourceLabel": "來源",
|
||
"conversion.success.import.dialog.sourceValue": "轉檔(job #{shortJobId})",
|
||
"conversion.success.import.dialog.confirm": "加到模型庫",
|
||
"conversion.success.import.dialog.cancel": "取消",
|
||
"conversion.success.import.processing": "處理中…",
|
||
"conversion.success.import.toastDone": "已加入模型庫",
|
||
"conversion.success.import.toastDoneAction": "前往模型庫 →",
|
||
"conversion.success.import.toastDup": "此任務已加入過模型庫",
|
||
"conversion.success.import.toastDupAction": "查看現有模型 →",
|
||
"conversion.success.import.statusDone": "✓ 已加入(前往查看 →)",
|
||
"conversion.success.import.errorGeneric":
|
||
"加到模型庫失敗,請稍後再試",
|
||
"conversion.success.import.aria.cta":
|
||
"加到模型庫(會開啟確認對話框)",
|
||
"conversion.success.download.title": "下載 .nef",
|
||
"conversion.success.description":
|
||
"{source} 已成功轉成 {chip} 可用的 .nef 檔",
|
||
"conversion.success.summary.outputFile": "輸出檔案",
|
||
"conversion.success.summary.notAvailable": "—",
|
||
"conversion.success.download.description": "存到本機自行使用",
|
||
"conversion.success.download.cta": "下載",
|
||
"conversion.success.download.preparing": "準備下載…",
|
||
"conversion.success.download.toastStart": "下載已開始",
|
||
"conversion.success.download.toastHint":
|
||
"若沒看到下載提示,請檢查瀏覽器設定",
|
||
"conversion.success.download.toastFail": "下載連結取得失敗",
|
||
"conversion.success.download.aria.cta": "下載 .nef 檔到本機",
|
||
"conversion.success.download.aria.disabled":
|
||
"下載連結已過期,請開始新轉檔",
|
||
"conversion.success.expiry":
|
||
"此轉檔結果將在 {time} 後自動清除,請在期限內完成處理",
|
||
"conversion.success.expiry.expired": "此轉檔結果已過期",
|
||
"conversion.success.expiry.remaining.daysHours": "{days} 天 {hours} 小時",
|
||
"conversion.success.expiry.remaining.daysOnly": "{days} 天",
|
||
"conversion.success.expiry.remaining.hoursMinutes":
|
||
"{hours} 小時 {minutes} 分鐘",
|
||
"conversion.success.expiry.remaining.hoursOnly": "{hours} 小時",
|
||
"conversion.success.expiry.remaining.minutes": "{minutes} 分鐘",
|
||
"conversion.success.startNew": "開始新轉檔",
|
||
|
||
// failed 結果
|
||
"conversion.failed.heading": "轉檔失敗",
|
||
"conversion.failed.errorCode": "錯誤代碼",
|
||
"conversion.failed.suggestionsTitle": "你可以試試:",
|
||
"conversion.failed.retry": "重新開始",
|
||
"conversion.failed.backToModels": "回模型庫",
|
||
"conversion.failed.contactSupport":
|
||
"若持續發生,請複製任務 ID 聯絡支援團隊",
|
||
"conversion.failed.copyJobId": "複製任務 ID",
|
||
"conversion.failed.toastJobIdCopied": "已複製任務 ID",
|
||
// F-T8 新增 — FailedView 用
|
||
"conversion.failed.aria.alert": "轉檔失敗通知",
|
||
"conversion.failed.jobIdLabel": "Job ID",
|
||
"conversion.failed.summary.failedSuffix": "(失敗)",
|
||
"conversion.failed.aria.retry": "回到起點,重新開始一次轉檔",
|
||
|
||
// 錯誤碼翻譯(對應 PRD §F5 + .autoflow/04-architecture/conversion.md)
|
||
"conversion.error.UNSUPPORTED_FORMAT.message":
|
||
"此模型格式目前不支援,請改用 ONNX / TFLite",
|
||
"conversion.error.UNSUPPORTED_FORMAT.suggestion1": "確認檔案副檔名",
|
||
"conversion.error.UNSUPPORTED_FORMAT.suggestion2": "用標準 export 工具",
|
||
"conversion.error.INVALID_CHECKSUM.message":
|
||
"檔案傳輸過程毀損,請重新上傳",
|
||
"conversion.error.INVALID_CHECKSUM.suggestion1": "重新開始上傳",
|
||
"conversion.error.QUANTIZATION_FAILED.message":
|
||
"模型內含不支援的運算子,無法量化到目標晶片",
|
||
"conversion.error.QUANTIZATION_FAILED.suggestion1": "簡化模型結構",
|
||
"conversion.error.QUANTIZATION_FAILED.suggestion2": "移除 Custom Op",
|
||
"conversion.error.QUANTIZATION_FAILED.suggestion3": "改用較小的 input shape",
|
||
"conversion.error.MODEL_TOO_LARGE.message": "模型超過 500 MB 上限",
|
||
"conversion.error.MODEL_TOO_LARGE.suggestion1": "改用較小模型",
|
||
"conversion.error.MODEL_TOO_LARGE.suggestion2": "嘗試 Pruning / Quantization",
|
||
"conversion.error.QUOTA_EXCEEDED.message": "系統暫時繁忙,請稍後再試",
|
||
"conversion.error.QUOTA_EXCEEDED.suggestion1": "等 5 分鐘後重試",
|
||
"conversion.error.unknown.message":
|
||
"轉檔失敗,請稍後重試。若持續發生請聯絡支援團隊",
|
||
"conversion.error.unknown.suggestion1": "複製任務 ID 回報給支援團隊",
|
||
|
||
// 已過期 / 找不到
|
||
"conversion.expired.heading": "此轉檔結果已過期",
|
||
"conversion.expired.description":
|
||
"轉檔結果保留期為 7 天,目前已超過保留期限並自動清除。",
|
||
// F-T9 sub-1:ExpiredView 補充說明 — 解釋為什麼過期 + 怎麼處理
|
||
"conversion.expired.subDescription":
|
||
"如需重新取得轉檔結果,請按下方按鈕重新提交一次。",
|
||
// F-T9 sub-1:ExpiredView a11y
|
||
"conversion.expired.aria.alert": "轉檔結果已過期通知",
|
||
"conversion.expired.aria.startNew": "重新開始一次轉檔",
|
||
"conversion.expired.startNew": "重新轉檔",
|
||
|
||
// mobile hint(≥ 500 MB 檔在手機上傳體驗差)
|
||
"conversion.mobileHint":
|
||
"Mobile 設備上傳大型模型可能不穩定,建議使用桌面版瀏覽器",
|
||
|
||
// ── Clusters(F7 新增 stub)──
|
||
"clusters.title": "叢集",
|
||
"clusters.subtitle": "把多台 Kneron 裝置組成平行推論叢集",
|
||
"clusters.create": "建立叢集",
|
||
"clusters.empty.title": "叢集推論 — Phase 1 推出",
|
||
"clusters.empty.description":
|
||
"Phase 1 會把多裝置平行推論、降級機制等 POC 能力搬進雲端版",
|
||
"clusters.phase1Badge": "Phase 1 推出",
|
||
"clusters.phase1Toast": "叢集建立功能 Phase 1 才支援",
|
||
};
|