jim800121chen 50a3f73acd feat(local-tool): 品牌視覺設計 + 內建模型首次啟動 seed
#8 首次啟動 seed 內建模型:
- app.go 新增 seedUserDataDir() 在 server spawn 之前執行
- 若 user data-dir 缺 models.json,從 locateBundleDataDir() 複製
  models.json + nef/ 預置模型過去
- 新增 locateBundleDataDir() / copyFile() / copyDirRecursive() helper
- user 第一次開 app 會看到 8 個 Kneron 預置 .nef 模型(kl520×5 + kl720×3)

#5 #6 #7 品牌視覺:
- 新增 branding/ 目錄存放設計資產與生成工具
  - logo.svg(向量原始稿)
  - icon-{16,...,1024}.png(10 種尺寸)
  - icon.ico(Windows 多解析度 ICO,PNG-in-ICO 格式)
  - icon.icns(macOS)
  - tools/gen_icon.go + gen_ico.go(純 Go 生成工具,未來調整 logo 用)
  - README.md + 色票表
- 部署:
  - visiona-local/build/appicon.png → Wails build 會嵌入 exe
  - visiona-local/frontend/icon.png → splash 使用
  - frontend/src/app/favicon.ico + icon.png → Next.js App Router favicon
- splash page 升級:加 logo icon + 品牌名 visionA Local + tagline Edge AI Workspace
- Wails window title: "visionA Local — Edge AI Workspace"
- wails.json productName: "visionA Local"
- Next.js metadata title + icons
- i18n: en/zh-TW 把殘留的 "Edge AI 平台" 字串改為 visionA Local 品牌
- .iss: SetupIconFile 指向 branding/icon.ico + UninstallDisplayIcon +
  ArchitecturesAllowed 改 x64compatible 修掉之前的 deprecation warning

品牌色票:
- 主色 #4F7EFF(電子藍)
- 輔色 #6EF3C5(mint 點綴)
- 深色背景漸層 #1A1F36 → #0E1222
- 警示 #FF6B6B

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 04:42:41 +08:00

428 lines
15 KiB
TypeScript

import type { TranslationDict } from './types';
export const en: TranslationDict = {
common: {
save: 'Save',
cancel: 'Cancel',
delete: 'Delete',
back: 'Back',
close: 'Close',
done: 'Done',
retry: 'Retry',
connect: 'Connect',
disconnect: 'Disconnect',
manage: 'Manage',
view: 'View',
upload: 'Upload',
uploading: 'Uploading...',
loading: 'Loading...',
search: 'Search',
reset: 'Reset',
start: 'Start',
stop: 'Stop',
na: 'N/A',
custom: 'Custom',
},
nav: {
dashboard: 'Dashboard',
modelLibrary: 'Model Library',
devices: 'Devices',
workspace: 'Workspace',
settings: 'Settings',
appName: 'visionA Local',
version: 'visionA Local v0.1.0',
platformTitle: 'visionA Local — Edge AI Workspace',
serverConnected: 'Server Connected',
serverDisconnected: 'Server Disconnected',
},
workspace: {
title: 'Workspace',
subtitle: 'Select a device to begin',
noConnectedDevice: 'No connected device',
noConnectedDeviceDesc: 'Connect a device to start inference.',
goToDevices: 'Go to Devices',
},
dashboard: {
title: 'Dashboard',
subtitle: 'Overview of your visionA workspace',
models: 'Models',
devices: 'Devices',
connected: 'Connected',
flashes: 'Flashes',
quickActions: 'Quick Actions',
browseModels: 'Browse Models',
manageDevices: 'Manage Devices',
uploadModel: 'Upload Model',
recentActivity: 'Recent Activity',
noActivity: 'No activity recorded yet.',
connectedDevices: 'Connected Devices',
noConnectedDevices: 'No connected devices.',
justNow: 'Just now',
minutesAgo: '{n}m ago',
hoursAgo: '{n}h ago',
daysAgo: '{n}d ago',
},
devices: {
title: 'Devices',
subtitle: 'Manage your edge AI devices',
scan: 'Scan Devices',
scanning: 'Scanning...',
noDevices: 'No devices detected. Make sure mock mode is enabled or connect a device.',
type: 'Type',
firmware: 'Firmware',
flashedModel: 'Flashed Model',
status: {
detected: 'Detected',
connecting: 'Connecting',
connected: 'Connected',
flashing: 'Flashing',
inferencing: 'Inferring',
error: 'Error',
disconnected: 'Disconnected',
},
health: {
title: 'Device Health',
status: 'Status',
firmwareVersion: 'Firmware Version',
uptime: 'Uptime',
lastSeen: 'Last Seen',
},
connectionLog: {
title: 'Connection History',
noEvents: 'No connection events recorded.',
connected: 'Connected',
disconnected: 'Disconnected',
},
settings: {
title: 'Device Settings',
alias: 'Custom Name',
aliasPlaceholder: 'e.g., Lab Device #1',
notes: 'Notes',
notesPlaceholder: 'Add notes about this device...',
saveSettings: 'Save Settings',
settingsSaved: 'Device settings saved',
},
detail: {
deviceInfo: 'Device Info',
id: 'ID',
type: 'Type',
firmware: 'Firmware',
port: 'Port',
modelStatus: 'Model Status',
readyForInference: 'Device is ready for inference. Open the workspace to start.',
noModelFlashed: 'No model has been flashed to this device yet. Use the Flash Model button to deploy a model.',
openWorkspace: 'Open Workspace',
},
flash: {
flashModel: 'Flash Model',
flashToDevice: 'Flash Model to Device',
selectModel: 'Select a model',
hardwareIncompatible: 'Hardware Incompatible',
incompatibleDesc: 'This model does not support {device}.',
incompatibleCannotFlash: 'Incompatible \u2014 Cannot Flash',
startFlash: 'Start Flash',
flashFailed: 'Flash Failed',
preparingFlash: 'Preparing flash...',
flashComplete: 'Flash complete!',
},
},
models: {
title: 'Model Library',
subtitle: 'Browse and select AI models for deployment',
noModelsFound: 'No models found matching your criteria.',
compareModels: 'Compare Models',
exitCompare: 'Exit Compare',
uploadModel: 'Upload Model',
accuracy: 'Accuracy',
fps: 'FPS',
size: 'Size',
hardware: 'Hardware',
latency: 'Latency',
framework: 'Framework',
inputSize: 'Input Size',
quantization: 'Quantization',
version: 'Version',
author: 'Author',
license: 'License',
labels: 'Labels',
performance: 'Performance',
specifications: 'Specifications',
hardwareCompatibility: 'Hardware Compatibility',
metadata: 'Metadata',
deployToDevice: 'Deploy to Device',
deleteCustomModel: 'Delete Custom Model',
deleteConfirm: 'Are you sure you want to delete "{name}"? This action cannot be undone.',
comparison: {
title: 'Model Comparison',
metric: 'Metric',
selected: '{n} models selected',
compare: 'Compare',
clear: 'Clear',
taskType: 'Task Type',
modelSize: 'Model Size',
},
filters: {
searchPlaceholder: 'Search models...',
taskType: 'Task Type',
allTypes: 'All Types',
allHardware: 'All Hardware',
},
upload: {
title: 'Upload Custom Model',
modelFile: 'Model File (.nef) *',
clickToSelect: 'Click to select .nef file',
modelName: 'Model Name *',
modelNamePlaceholder: 'e.g., My Custom YOLOv5',
description: 'Description',
descriptionPlaceholder: 'Optional description',
taskType: 'Task Type *',
taskTypePlaceholder: 'Select task type',
objectDetection: 'Object Detection',
classification: 'Classification',
segmentation: 'Segmentation',
poseEstimation: 'Pose Estimation',
labels: 'Labels * (comma separated)',
labelsPlaceholder: 'e.g., person, car, dog, cat',
inputWidth: 'Input Width',
inputHeight: 'Input Height',
quantization: 'Quantization',
errors: {
noFile: 'Please select a .nef file',
noName: 'Model name is required',
noTaskType: 'Task type is required',
noLabels: 'At least one label is required',
uploadFailed: 'Upload failed. Please try again.',
},
},
},
camera: {
camera: 'Camera',
image: 'Image',
video: 'Video',
startCamera: 'Start Camera',
stopCamera: 'Stop Camera',
stopImage: 'Stop Image',
stopVideo: 'Stop Video',
stopBatch: 'Stop Batch',
selectImage: 'Select Image',
selectImages: 'Select Images',
selectVideo: 'Select Video',
uploadFile: 'Upload File',
pasteUrl: 'Paste URL',
urlPlaceholder: 'https://example.com/video.mp4',
urlHelpText: 'Supports YouTube, direct video URL (.mp4 etc.), and RTSP stream.',
jpgPng: 'JPG, PNG',
jpgPngMultiple: 'JPG, PNG (multiple)',
mp4AviMov: 'MP4, AVI, MOV',
noInputSource: 'No input source',
selectSourceHint: 'Select a camera, image, or video above',
uploadedImage: 'Uploaded Image',
videoPlayback: 'Video Playback',
cameraFeed: 'Camera Feed',
dropImagesHere: 'Drop images here',
batchProcessing: 'Processing',
batchImages: 'Batch Images',
noCameraDetected: 'No camera detected. Use image or video for inference.',
},
inference: {
confidenceFilter: 'Confidence Filter',
confidenceThreshold: 'Confidence Threshold',
classificationResults: 'Classification Results',
noResultsAboveThreshold: 'No results above threshold',
details: 'Details',
model: 'Model',
task: 'Task',
latency: 'Latency',
fps: 'FPS',
workspace: 'Workspace',
startInference: 'Start Inference',
stopInference: 'Stop Inference',
batchProgress: 'Batch Progress',
processed: 'Processed',
currentImage: 'Viewing',
totalImages: 'Total',
videoProgress: 'Video Progress',
frames: 'frames',
framesProcessed: 'Frames Processed',
},
settings: {
title: 'Settings',
subtitle: 'Application settings',
tabs: {
general: 'General',
hardware: 'Hardware',
models: 'Models',
advanced: 'Advanced',
},
general: {
title: 'General',
language: 'Language',
languageFollowSystem: 'Follow system',
languageFollowSystemLabel: 'Follow system ({detected})',
languageRestartHint: 'Language changes apply immediately in the app, but native OS menus may need a restart.',
theme: 'Theme',
themeFollowSystem: 'Follow system',
themeFollowSystemHint: 'Dark mode follows your system setting.',
themeCurrentLight: 'Currently: Light',
themeCurrentDark: 'Currently: Dark',
dataDirectory: 'Data Directory',
dataDirectoryHint: 'Logs, settings and custom models are stored here.',
},
hardware: {
title: 'Hardware',
runtimeMode: 'Runtime Mode',
runtimeModeMock: 'Mock (no hardware required)',
runtimeModeReal: 'Real Hardware',
runtimeModeHint: 'Switching runtime mode requires restarting the server.',
pythonMode: 'Python Runtime',
pythonModeAuto: 'Auto (prefer bundled)',
pythonModeBundled: 'Bundled (recommended)',
pythonModeSystem: 'System Python',
pythonModeHint: 'Read-only in this milestone. Switching will be available in a later release.',
serverPort: 'Server Port',
serverPortHint: 'Actual port the backend is listening on.',
},
models: {
title: 'Models',
presetModels: 'Preset Models',
presetModelsEmpty: 'No preset models available.',
presetModelsLoadFailed: 'Could not load model list.',
uploadPath: 'Upload Path',
uploadPathHint: 'Custom models you upload are stored here.',
},
advanced: {
title: 'Advanced',
viewLogs: 'View Server Logs',
viewLogsHint: 'Inspect recent server log entries.',
restartServer: 'Restart Server',
restartServerHint: 'All active inference sessions will stop. The UI reconnects automatically.',
about: 'About',
resetAll: 'Reset All Settings',
resetAllHint: 'Restore all preferences to their defaults. This does not delete data.',
},
serverConfig: 'Server Configuration',
backendUrl: 'Backend URL',
backendUrlPlaceholder: 'e.g., http://192.168.1.100:3721',
backendUrlHint: 'Leave empty for same-origin mode (frontend embedded in Go binary).',
backendUrlSaved: 'Backend URL updated',
saveBackendUrl: 'Save',
apiUrl: 'API URL',
wsUrl: 'WebSocket URL',
serverNote: 'Server addresses are configured at build time.',
appearance: 'Appearance',
theme: 'Theme',
themeLight: 'Light',
themeDark: 'Dark',
language: 'Language',
displayLanguage: 'Display Language',
languageZhTW: 'Traditional Chinese',
languageEn: 'English',
about: 'About',
versionLabel: 'Version',
platform: 'visionA Local — Edge AI Workspace',
resetToDefaults: 'Reset to Defaults',
resetSuccess: 'Settings restored to defaults',
serverLogs: {
title: 'Server Logs',
clear: 'Clear',
filter: 'Filter',
autoScroll: 'Auto-scroll',
noLogs: 'No log entries yet. Logs will appear as the server produces them.',
entries: 'entries',
},
serverStatus: {
title: 'Server Status',
uptimeLabel: 'Uptime',
goroutinesLabel: 'Goroutines',
heapAllocLabel: 'Heap Alloc',
sysMemLabel: 'System Mem',
gcCyclesLabel: 'GC Cycles',
nextGcLabel: 'Next GC',
versionLabel: 'Version',
buildTimeLabel: 'Build Time',
platformLabel: 'Platform',
goVersionLabel: 'Go Version',
depsTitle: 'Dependencies',
depAvailable: 'Available',
depNotFound: 'Not Found',
restart: 'Restart Server',
restarting: 'Restarting...',
waitingForServer: 'Waiting for server...',
serverBack: 'Server back online',
restartConfirmTitle: 'Restart Server?',
restartConfirmDesc: 'The server will restart. All active inference sessions will be stopped. The UI will reconnect automatically.',
restartConfirm: 'Restart',
offline: 'Server Offline',
offlineDesc: 'Cannot connect to the backend server. Make sure the server is running.',
backendAddress: 'Backend address',
reconnect: 'Reconnect',
reconnecting: 'Reconnecting...',
},
},
onboarding: {
welcome: 'Welcome to visionA Local!',
step1Title: 'Connect Your Device',
step1Desc: 'Plug in your Kneron USB Dongle and scan for devices. The platform will automatically detect supported hardware.',
step2Title: 'Choose an AI Model',
step2Desc: 'Browse the model library and flash a pre-trained model to your device. Models are optimized for edge inference.',
step3Title: 'Start Inference!',
step3Desc: 'Open the workspace, select a camera, image, or video, and run real-time AI inference on your edge device.',
next: 'Next',
previous: 'Previous',
getStarted: 'Get Started',
skipTour: 'Skip Tour',
},
emptyState: {
devicesTitle: 'No Devices Detected',
devicesDesc: 'Plug in your Kneron USB Dongle and click Scan to detect devices.',
devicesScan: 'Scan Devices',
modelsTitle: 'Explore AI Models',
modelsDesc: 'Browse pre-trained models or upload your own custom model.',
modelsBrowse: 'Browse Models',
modelsUpload: 'Upload Model',
},
tour: {
step1Title: 'Scan for Devices',
step1Desc: 'Click this button to scan for connected Kneron USB devices.',
step1Pending: 'Please click "Scan Devices" first. No devices detected yet.',
step2Title: 'Connect a Device',
step2Desc: 'Click Connect to establish a connection with the detected device.',
step2Pending: 'Please click "Connect" on a device first.',
step3Title: 'Manage Device',
step3Desc: 'Click Manage to view device details, flash models, and open the workspace.',
step3Pending: 'Please connect a device first to see the Manage button.',
step4Title: 'Flash a Model',
step4Desc: 'Select an AI model from the library and flash it to your device.',
step4Pending: 'Please flash a model to the device first.',
step5Title: 'Open Workspace',
step5Desc: 'Open the workspace to configure input sources and run inference.',
step5Pending: 'Please flash a model first — the workspace button will appear after.',
step6Title: 'Start Inference',
step6Desc: 'Select a camera or upload an image/video, then start real-time AI inference!',
step6Pending: 'Please start inference to complete the tour.',
next: 'Next',
prev: 'Previous',
done: 'Done',
exit: 'Exit Tour',
of: 'of',
helpTooltip: 'Start guided tour',
},
errors: {
serverDisconnected: 'Server connection lost',
serverReconnected: 'Server reconnected',
failedToLoadDevices: 'Failed to load device list',
deviceConnected: 'Device connected',
deviceDisconnected: 'Device disconnected',
modelUploadSuccess: 'Model uploaded successfully',
modelUploadFailed: 'Upload failed, please check network connection',
modelDeleted: 'Model deleted',
modelDeleteFailed: 'Delete failed',
cannotStopStream: 'Cannot stop stream',
imageUploadFailed: 'Image upload failed',
videoUploadFailed: 'Video upload failed',
cannotOpenVideoUrl: 'Cannot open video URL',
batchUploadFailed: 'Batch image upload failed',
unexpectedError: 'An unexpected error occurred',
},
};