feat: implement comprehensive i18n internationalization support

- Add custom i18n infrastructure with TypeScript support
- Support Chinese (zh-CN) and English (en-US) languages
- Implement language switching with localStorage persistence
- Update all components with translation keys:
  * System info components (board-info-panel, board-index)
  * Display management components (display-state-index, display-state-card)
  * LED strip configuration components (led-strip-configuration, led-count-control-panel)
  * White balance component with detailed usage instructions
  * LED test component with test pattern descriptions
- Add comprehensive translation coverage for:
  * Navigation menus and page titles
  * Common UI elements (buttons, status, actions)
  * Hardware information and connection status
  * Display configuration options
  * LED strip settings and controls
  * White balance adjustment instructions and tips
  * LED test modes and descriptions
  * Error messages and status indicators
- Features:
  * Dynamic language switching without app restart
  * Type-safe translation keys with full TypeScript support
  * Modular design for easy language extension
  * Responsive UI updates using SolidJS reactivity
This commit is contained in:
2025-07-08 16:55:12 +08:00
parent 4a3d7681d6
commit 2c6b777fa6
16 changed files with 893 additions and 115 deletions

View File

@ -10,6 +10,7 @@ import { BiRegularReset } from 'solid-icons/bi';
import { BsFullscreen, BsFullscreenExit } from 'solid-icons/bs';
import { getCurrentWindow } from '@tauri-apps/api/window';
import transparentBg from '../../assets/transparent-grid-background.svg?url';
import { useLanguage } from '../../i18n/index';
const Value: Component<{ value: number }> = (props) => {
return (
@ -20,6 +21,7 @@ const Value: Component<{ value: number }> = (props) => {
};
export const WhiteBalance = () => {
const { t } = useLanguage();
const [isFullscreen, setIsFullscreen] = createSignal(false);
const [panelPosition, setPanelPosition] = createSignal({ x: 0, y: 0 });
const [isDragging, setIsDragging] = createSignal(false);
@ -170,19 +172,19 @@ export const WhiteBalance = () => {
{!isFullscreen() && (
<div class="space-y-6">
<div class="flex items-center justify-between">
<h1 class="text-2xl font-bold text-base-content"></h1>
<h1 class="text-2xl font-bold text-base-content">{t('whiteBalance.title')}</h1>
<div class="flex gap-2">
<button class="btn btn-outline btn-sm" onClick={toggleFullscreen} title="进入全屏">
<button class="btn btn-outline btn-sm" onClick={toggleFullscreen} title={t('common.fullscreen')}>
<BsFullscreen size={16} />
{t('common.fullscreen')}
</button>
<button class="btn btn-outline btn-sm" onClick={reset} title="重置到100%">
<button class="btn btn-outline btn-sm" onClick={reset} title={t('common.reset')}>
<BiRegularReset size={16} />
{t('common.reset')}
</button>
<button class="btn btn-primary btn-sm" onClick={exit} title="返回">
<button class="btn btn-primary btn-sm" onClick={exit} title={t('whiteBalance.back')}>
<VsClose size={16} />
{t('whiteBalance.back')}
</button>
</div>
</div>
@ -192,8 +194,8 @@ export const WhiteBalance = () => {
<div class="card bg-base-200 shadow-lg">
<div class="card-body p-4">
<div class="card-title text-base mb-3">
<span></span>
<div class="badge badge-info badge-outline"></div>
<span>{t('whiteBalance.colorTest')}</span>
<div class="badge badge-info badge-outline">{t('whiteBalance.clickToTest')}</div>
</div>
<div
class="aspect-square rounded-lg overflow-hidden border border-base-300"
@ -204,7 +206,7 @@ export const WhiteBalance = () => {
<TestColorsBg />
</div>
<div class="text-xs text-base-content/50 mt-2">
💡
💡 {t('whiteBalance.colorTestTip')}
</div>
</div>
</div>
@ -213,14 +215,14 @@ export const WhiteBalance = () => {
<div class="card bg-base-200 shadow-lg">
<div class="card-body p-4">
<div class="card-title text-base mb-3">
<span>RGB调节</span>
<div class="badge badge-secondary badge-outline"></div>
<span>{t('whiteBalance.rgbAdjustment')}</span>
<div class="badge badge-secondary badge-outline">{t('whiteBalance.realtimeAdjustment')}</div>
</div>
<div class="space-y-4">
<div class="form-control">
<label class="label">
<span class="label-text font-semibold text-red-500"> (R)</span>
<span class="label-text font-semibold text-red-500">{t('whiteBalance.redChannel')}</span>
<Value value={ledStripStore.colorCalibration.r} />
</label>
<ColorSlider
@ -237,7 +239,7 @@ export const WhiteBalance = () => {
<div class="form-control">
<label class="label">
<span class="label-text font-semibold text-green-500">绿 (G)</span>
<span class="label-text font-semibold text-green-500">{t('whiteBalance.greenChannel')}</span>
<Value value={ledStripStore.colorCalibration.g} />
</label>
<ColorSlider
@ -254,7 +256,7 @@ export const WhiteBalance = () => {
<div class="form-control">
<label class="label">
<span class="label-text font-semibold text-blue-500"> (B)</span>
<span class="label-text font-semibold text-blue-500">{t('whiteBalance.blueChannel')}</span>
<Value value={ledStripStore.colorCalibration.b} />
</label>
<ColorSlider
@ -271,7 +273,7 @@ export const WhiteBalance = () => {
<div class="form-control">
<label class="label">
<span class="label-text font-semibold text-amber-500"> (W)</span>
<span class="label-text font-semibold text-amber-500">{t('whiteBalance.whiteChannel')}</span>
<Value value={ledStripStore.colorCalibration.w} />
</label>
<ColorSlider
@ -291,37 +293,37 @@ export const WhiteBalance = () => {
<div class="collapse collapse-arrow bg-base-100 mt-4">
<input type="checkbox" />
<div class="collapse-title text-sm font-medium text-base-content/80">
💡 使
💡 {t('whiteBalance.usageInstructions')}
</div>
<div class="collapse-content text-xs text-base-content/70 space-y-3">
<div class="space-y-2">
<p class="font-semibold text-primary">🎯 使</p>
<p class="font-semibold text-primary">{t('whiteBalance.recommendedMethod')}</p>
<ol class="list-decimal list-inside space-y-1 ml-2">
<li>"全屏"</li>
<li></li>
<li>{t('whiteBalance.fullscreenTip')}</li>
<li>{t('whiteBalance.dragTip')}</li>
<li>RGB控制面板拖拽到合适位置</li>
<li>LED灯条颜色与屏幕边缘颜色</li>
</ol>
</div>
<div class="space-y-2">
<p class="font-semibold text-secondary">🔧 </p>
<p class="font-semibold text-secondary">{t('whiteBalance.adjustmentTips')}</p>
<ul class="list-disc list-inside space-y-1 ml-2">
<li><span class="text-red-500 font-medium"></span>R值LED会减少红色成分</li>
<li><span class="text-green-500 font-medium">绿</span>G值LED会减少绿色成分</li>
<li><span class="text-blue-500 font-medium"></span>B值LED会减少蓝色成分</li>
<li><span class="text-base-content font-medium"></span>B值R/G值</li>
<li><span class="text-base-content font-medium"></span>B值R/G值</li>
<li>{t('whiteBalance.redStrong')}</li>
<li>{t('whiteBalance.greenStrong')}</li>
<li>{t('whiteBalance.blueStrong')}</li>
<li>{t('whiteBalance.whiteYellow')}</li>
<li>{t('whiteBalance.whiteBlue')}</li>
</ul>
</div>
<div class="space-y-2">
<p class="font-semibold text-accent">📋 </p>
<p class="font-semibold text-accent">{t('whiteBalance.comparisonMethod')}</p>
<ul class="list-disc list-inside space-y-1 ml-2">
<li>LED白光与屏幕白色一致</li>
<li>LED颜色饱和度合适</li>
<li></li>
<li>"重置"</li>
<li>{t('whiteBalance.whiteComparison')}</li>
<li>{t('whiteBalance.colorComparison')}</li>
<li>{t('whiteBalance.environmentTest')}</li>
<li>{t('whiteBalance.resetNote')}</li>
</ul>
</div>
</div>
@ -356,10 +358,10 @@ export const WhiteBalance = () => {
>
<div class="flex items-center gap-2">
<span class="text-xs opacity-60"></span>
<span>RGB调节</span>
<div class="badge badge-secondary badge-outline"></div>
<span>{t('whiteBalance.rgbAdjustment')}</span>
<div class="badge badge-secondary badge-outline">{t('whiteBalance.draggable')}</div>
</div>
<button class="btn btn-ghost btn-xs cursor-pointer" onClick={toggleFullscreen} title="退出全屏">
<button class="btn btn-ghost btn-xs cursor-pointer" onClick={toggleFullscreen} title={t('whiteBalance.exitFullscreen')}>
<BsFullscreenExit size={14} />
</button>
</div>
@ -367,7 +369,7 @@ export const WhiteBalance = () => {
<div class="space-y-4">
<div class="form-control">
<label class="label">
<span class="label-text font-semibold text-red-500"> (R)</span>
<span class="label-text font-semibold text-red-500">{t('whiteBalance.redChannel')}</span>
<Value value={ledStripStore.colorCalibration.r} />
</label>
<ColorSlider
@ -384,7 +386,7 @@ export const WhiteBalance = () => {
<div class="form-control">
<label class="label">
<span class="label-text font-semibold text-green-500">绿 (G)</span>
<span class="label-text font-semibold text-green-500">{t('whiteBalance.greenChannel')}</span>
<Value value={ledStripStore.colorCalibration.g} />
</label>
<ColorSlider
@ -401,7 +403,7 @@ export const WhiteBalance = () => {
<div class="form-control">
<label class="label">
<span class="label-text font-semibold text-blue-500"> (B)</span>
<span class="label-text font-semibold text-blue-500">{t('whiteBalance.blueChannel')}</span>
<Value value={ledStripStore.colorCalibration.b} />
</label>
<ColorSlider
@ -418,7 +420,7 @@ export const WhiteBalance = () => {
<div class="form-control">
<label class="label">
<span class="label-text font-semibold text-amber-500"> (W)</span>
<span class="label-text font-semibold text-amber-500">{t('whiteBalance.whiteChannel')}</span>
<Value value={ledStripStore.colorCalibration.w} />
</label>
<ColorSlider
@ -435,25 +437,25 @@ export const WhiteBalance = () => {
<div class="form-control">
<label class="label">
<span class="label-text font-semibold text-base-content/70"> (W)</span>
<div class="badge badge-outline badge-sm"></div>
<span class="label-text font-semibold text-base-content/70">{t('whiteBalance.whiteChannel')}</span>
<div class="badge badge-outline badge-sm">{t('whiteBalance.notEnabled')}</div>
</label>
<ColorSlider class="from-yellow-50 to-cyan-50" disabled />
</div>
</div>
<div class="text-xs text-base-content/60 mt-3 p-2 bg-base-300/50 rounded">
💡 LED灯条RGB滑块使颜色一致
💡 {t('whiteBalance.fullscreenComparisonTip')}
</div>
<div class="flex gap-2 mt-4">
<button class="btn btn-outline btn-sm flex-1" onClick={reset} title="重置到100%">
<button class="btn btn-outline btn-sm flex-1" onClick={reset} title={t('common.reset')}>
<BiRegularReset size={14} />
{t('common.reset')}
</button>
<button class="btn btn-primary btn-sm flex-1" onClick={exit} title="返回">
<button class="btn btn-primary btn-sm flex-1" onClick={exit} title={t('whiteBalance.back')}>
<VsClose size={14} />
{t('whiteBalance.back')}
</button>
</div>
</div>