diff --git a/package.json b/package.json index 8963586..cd59434 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "license": "MIT", "dependencies": { + "@solid-primitives/i18n": "^2.2.1", "@solidjs/router": "^0.8.4", "@tauri-apps/api": "^2.6.0", "debug": "^4.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5ec6eee..9d1c48f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@solid-primitives/i18n': + specifier: ^2.2.1 + version: 2.2.1(solid-js@1.9.7) '@solidjs/router': specifier: ^0.8.4 version: 0.8.4(solid-js@1.9.7) @@ -424,6 +427,11 @@ packages: cpu: [x64] os: [win32] + '@solid-primitives/i18n@2.2.1': + resolution: {integrity: sha512-TnTnE2Ku11MGYZ1JzhJ8pYscwg1fr9MteoYxPwsfxWfh9Jp5K7RRJncJn9BhOHvNLwROjqOHZ46PT7sPHqbcXw==} + peerDependencies: + solid-js: ^1.6.12 + '@solidjs/router@0.8.4': resolution: {integrity: sha512-Gi/WVoVseGMKS1DBdT3pNAMgOzEOp6Q3dpgNd2mW9GUEnVocPmtyBjDvXwN6m7tjSGsqqfqJFXk7bm1hxabSRw==} peerDependencies: @@ -1282,6 +1290,10 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.44.1': optional: true + '@solid-primitives/i18n@2.2.1(solid-js@1.9.7)': + dependencies: + solid-js: 1.9.7 + '@solidjs/router@0.8.4(solid-js@1.9.7)': dependencies: solid-js: 1.9.7 diff --git a/src/App.tsx b/src/App.tsx index f2d812b..ec23a77 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -8,10 +8,12 @@ import { setLedStripStore } from './stores/led-strip.store'; import { LedStripConfigContainer } from './models/led-strip-config'; import { InfoIndex } from './components/info/info-index'; import { DisplayStateIndex } from './components/displays/display-state-index'; +import { useLanguage } from './i18n/index'; function App() { const location = useLocation(); const [previousPath, setPreviousPath] = createSignal(''); + const { t, locale, setLocale } = useLanguage(); // Monitor route changes and cleanup LED tests when leaving the test page createEffect(() => { @@ -57,26 +59,49 @@ function App() { - 环境光控制 + {t('nav.title')} diff --git a/src/components/displays/display-state-card.tsx b/src/components/displays/display-state-card.tsx index 6d4cb8f..8f57d02 100644 --- a/src/components/displays/display-state-card.tsx +++ b/src/components/displays/display-state-card.tsx @@ -1,5 +1,6 @@ import { Component, ParentComponent } from 'solid-js'; import { DisplayState } from '../../models/display-state.model'; +import { useLanguage } from '../../i18n/index'; type DisplayStateCardProps = { state: DisplayState; @@ -19,48 +20,49 @@ const Item: ParentComponent = (props) => { }; export const DisplayStateCard: Component = (props) => { + const { t } = useLanguage(); return (
- 显示器状态 -
实时
+ {t('displays.title')} +
{t('common.realtime')}
{/* 亮度信息 */}
-

亮度设置

+

{t('displays.brightnessSettings')}

- {props.state.brightness} - {props.state.max_brightness} - {props.state.min_brightness} + {props.state.brightness} + {props.state.max_brightness} + {props.state.min_brightness}
{/* 对比度信息 */}
-

对比度设置

+

{t('displays.contrastSettings')}

- {props.state.contrast} - {props.state.max_contrast} - {props.state.min_contrast} + {props.state.contrast} + {props.state.max_contrast} + {props.state.min_contrast}
{/* 模式信息 */}
-

模式设置

+

{t('displays.modeSettings')}

- {props.state.mode} - {props.state.max_mode} - {props.state.min_mode} + {props.state.mode} + {props.state.max_mode} + {props.state.min_mode}
{/* 更新时间 */}
- 最后更新: {props.state.last_modified_at.toLocaleString()} + {t('displays.lastModified')}: {props.state.last_modified_at.toLocaleString()}
diff --git a/src/components/displays/display-state-index.tsx b/src/components/displays/display-state-index.tsx index 4002388..307eb7c 100644 --- a/src/components/displays/display-state-index.tsx +++ b/src/components/displays/display-state-index.tsx @@ -4,11 +4,13 @@ import debug from 'debug'; import { invoke } from '@tauri-apps/api/core'; import { DisplayState, RawDisplayState } from '../../models/display-state.model'; import { DisplayStateCard } from './display-state-card'; +import { useLanguage } from '../../i18n/index'; const logger = debug('app:components:displays:display-state-index'); export const DisplayStateIndex: Component = () => { const [states, setStates] = createSignal([]); + const { t } = useLanguage(); createEffect(() => { const unlisten = listen('displays_changed', (ev) => { @@ -38,10 +40,10 @@ export const DisplayStateIndex: Component = () => { return (
-

显示器状态

+

{t('displays.title')}

-
显示器数量
+
{t('displays.displayCount')}
{states().length}
@@ -63,8 +65,8 @@ export const DisplayStateIndex: Component = () => { {states().length === 0 && (
🖥️
-

未检测到显示器

-

请检查显示器连接状态

+

{t('displays.noDisplaysFound')}

+

{t('displays.checkConnection')}

)}
diff --git a/src/components/info/board-index.tsx b/src/components/info/board-index.tsx index 35bdfed..1a21875 100644 --- a/src/components/info/board-index.tsx +++ b/src/components/info/board-index.tsx @@ -4,11 +4,13 @@ import { listen } from '@tauri-apps/api/event'; import debug from 'debug'; import { invoke } from '@tauri-apps/api/core'; import { BoardInfoPanel } from './board-info-panel'; +import { useLanguage } from '../../i18n/index'; const logger = debug('app:components:info:board-index'); export const BoardIndex: Component = () => { const [boards, setBoards] = createSignal([]); + const { t } = useLanguage(); createEffect(() => { const unlisten = listen('boards_changed', (ev) => { @@ -28,10 +30,10 @@ export const BoardIndex: Component = () => { return (
-

设备信息

+

{t('info.boardInfo')}

-
设备总数
+
{t('info.deviceCount')}
{boards().length}
@@ -53,8 +55,8 @@ export const BoardIndex: Component = () => { {boards().length === 0 && (
🔍
-

未发现设备

-

请检查设备连接状态

+

{t('info.noDevicesFound')}

+

{t('info.checkConnection')}

)}
diff --git a/src/components/info/board-info-panel.tsx b/src/components/info/board-info-panel.tsx index 3fd2218..2c30258 100644 --- a/src/components/info/board-info-panel.tsx +++ b/src/components/info/board-info-panel.tsx @@ -1,5 +1,6 @@ import { Component, ParentComponent, createMemo } from 'solid-js'; import { BoardInfo } from '../../models/board-info.model'; +import { useLanguage } from '../../i18n/index'; type ItemProps = { label: string; @@ -15,6 +16,7 @@ const Item: ParentComponent = (props) => { }; export const BoardInfoPanel: Component<{ board: BoardInfo }> = (props) => { + const { t } = useLanguage(); const ttl = createMemo(() => { if (props.board.connect_status !== 'Connected') { return '--'; @@ -60,10 +62,10 @@ export const BoardInfoPanel: Component<{ board: BoardInfo }> = (props) => {
{connectStatus()}
- {props.board.host} - {props.board.address} - {props.board.port} - {ttl()} + {props.board.host} + {props.board.address} + {props.board.port} + {ttl()}
diff --git a/src/components/led-strip-configuration/led-count-control-panel.tsx b/src/components/led-strip-configuration/led-count-control-panel.tsx index 3877120..73dc690 100644 --- a/src/components/led-strip-configuration/led-count-control-panel.tsx +++ b/src/components/led-strip-configuration/led-count-control-panel.tsx @@ -5,6 +5,7 @@ import { ledStripStore } from '../../stores/led-strip.store'; import { Borders } from '../../constants/border'; import { LedType } from '../../models/led-strip-config'; import { LedStripConfigurationContext } from '../../contexts/led-strip-configuration.context'; +import { useLanguage } from '../../i18n/index'; type LedCountControlItemProps = { displayId: number; @@ -14,6 +15,7 @@ type LedCountControlItemProps = { const LedCountControlItem: Component = (props) => { const [stripConfiguration, { setHoveredStripPart }] = useContext(LedStripConfigurationContext); + const { t } = useLanguage(); const config = createMemo(() => { return ledStripStore.strips.find( @@ -116,7 +118,7 @@ const LedCountControlItem: Component = (props) => { class="btn btn-xs btn-circle btn-outline flex-shrink-0 min-h-0 h-6 w-6" onClick={handleDecrease} disabled={!config() || (config()?.len || 0) <= 0} - title="减少LED数量" + title={t('ledConfig.decreaseLedCount')} > - @@ -139,7 +141,7 @@ const LedCountControlItem: Component = (props) => { class="btn btn-xs btn-circle btn-outline flex-shrink-0 min-h-0 h-6 w-6" onClick={handleIncrease} disabled={!config() || (config()?.len || 0) >= 1000} - title="增加LED数量" + title={t('ledConfig.increaseLedCount')} > + @@ -150,7 +152,7 @@ const LedCountControlItem: Component = (props) => { class="select select-xs w-full text-xs h-6 min-h-0" value={config()?.led_type || LedType.RGB} onChange={handleLedTypeChange} - title="LED类型" + title={t('ledConfig.ledType')} > @@ -167,20 +169,21 @@ type LedCountControlPanelProps = { export const LedCountControlPanel: Component = (props) => { const [localProps, rootProps] = splitProps(props, ['display']); + const { t } = useLanguage(); const borders: { border: Borders; label: string }[] = [ - { border: 'Top', label: '上' }, - { border: 'Bottom', label: '下' }, - { border: 'Left', label: '左' }, - { border: 'Right', label: '右' }, + { border: 'Top', label: t('ledConfig.top') }, + { border: 'Bottom', label: t('ledConfig.bottom') }, + { border: 'Left', label: t('ledConfig.left') }, + { border: 'Right', label: t('ledConfig.right') }, ]; return (
- LED数量控制 -
显示器 {localProps.display.id}
+ {t('ledConfig.ledCountControl')} +
{t('ledConfig.display')} {localProps.display.id}
@@ -196,7 +199,7 @@ export const LedCountControlPanel: Component = (props
- 💡 提示:点击 +/- 按钮或直接输入数值来调整LED数量(范围:0-1000) + 💡 {t('ledConfig.controlTip')}
diff --git a/src/components/led-strip-configuration/led-strip-configuration.tsx b/src/components/led-strip-configuration/led-strip-configuration.tsx index 9ec2e83..a6852b6 100644 --- a/src/components/led-strip-configuration/led-strip-configuration.tsx +++ b/src/components/led-strip-configuration/led-strip-configuration.tsx @@ -13,9 +13,11 @@ import { LedStripConfigurationContext, LedStripConfigurationContextType, } from '../../contexts/led-strip-configuration.context'; +import { useLanguage } from '../../i18n/index'; export const LedStripConfiguration = () => { + const { t } = useLanguage(); createEffect(() => { invoke('list_display_info').then((displays) => { const parsedDisplays = JSON.parse(displays); @@ -106,10 +108,10 @@ export const LedStripConfiguration = () => { return (
-

灯条配置

+

{t('ledConfig.title')}

-
显示器数量
+
{t('displays.displayCount')}
{displayStore.displays.length}
@@ -121,12 +123,12 @@ export const LedStripConfiguration = () => {
- 灯条排序 -
实时预览
+ {t('ledConfig.stripSorting')} +
{t('ledConfig.realtimePreview')}
- 💡 提示:拖拽灯条段落来调整顺序,双击可反转方向 + 💡 {t('ledConfig.sortingTip')}
@@ -135,8 +137,8 @@ export const LedStripConfiguration = () => {
- 显示器配置 -
可视化编辑
+ {t('ledConfig.displayConfiguration')} +
{t('ledConfig.visualEditor')}
@@ -146,7 +148,7 @@ export const LedStripConfiguration = () => {
- 💡 提示:悬停显示器查看详细信息,使用下方控制面板调整LED数量 + 💡 {t('ledConfig.displayTip')}
@@ -154,8 +156,8 @@ export const LedStripConfiguration = () => { {/* LED Count Control Panels */}
-

LED数量控制

-
实时调整
+

{t('ledConfig.ledCountControl')}

+
{t('ledConfig.realtimeAdjustment')}
{displayStore.displays.map((display) => ( diff --git a/src/components/led-strip-test/led-strip-test.tsx b/src/components/led-strip-test/led-strip-test.tsx index 25c3bf1..fc23b0c 100644 --- a/src/components/led-strip-test/led-strip-test.tsx +++ b/src/components/led-strip-test/led-strip-test.tsx @@ -1,6 +1,7 @@ import { createSignal, createEffect, For, Show, onCleanup } from 'solid-js'; import { invoke } from '@tauri-apps/api/core'; import { listen } from '@tauri-apps/api/event'; +import { useLanguage } from '../../i18n/index'; interface BoardInfo { fullname: string; @@ -24,6 +25,7 @@ interface TestEffectConfig { } export const LedStripTest = () => { + const { t } = useLanguage(); const [boards, setBoards] = createSignal([]); const [selectedBoard, setSelectedBoard] = createSignal(null); const [ledCount, setLedCount] = createSignal(60); @@ -100,23 +102,23 @@ export const LedStripTest = () => { // Test patterns const testPatterns: TestPattern[] = [ { - name: '流光效果', - description: '彩虹色流光,用于测试灯带方向', + name: t('ledTest.flowingRainbow'), + description: t('ledTest.flowingRainbowDesc'), effect_type: 'FlowingRainbow' }, { - name: '十个一组计数', - description: '每十个LED一组不同颜色,用于快速计算灯珠数量', + name: t('ledTest.groupCounting'), + description: t('ledTest.groupCountingDesc'), effect_type: 'GroupCounting' }, { - name: '单色扫描', - description: '单个LED依次点亮,用于精确测试每个LED位置', + name: t('ledTest.singleScan'), + description: t('ledTest.singleScanDesc'), effect_type: 'SingleScan' }, { - name: '呼吸灯', - description: '整条灯带呼吸效果,用于测试整体亮度', + name: t('ledTest.breathing'), + description: t('ledTest.breathingDesc'), effect_type: 'Breathing' } ]; diff --git a/src/components/white-balance/white-balance.tsx b/src/components/white-balance/white-balance.tsx index c965775..a1ba100 100644 --- a/src/components/white-balance/white-balance.tsx +++ b/src/components/white-balance/white-balance.tsx @@ -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() && (
-

白平衡调节

+

{t('whiteBalance.title')}

- - -
@@ -192,8 +194,8 @@ export const WhiteBalance = () => {
- 颜色测试 -
点击测试
+ {t('whiteBalance.colorTest')} +
{t('whiteBalance.clickToTest')}
{
- 💡 提示:点击颜色块进行单色测试,再次点击返回多色模式 + 💡 {t('whiteBalance.colorTestTip')}
@@ -213,14 +215,14 @@ export const WhiteBalance = () => {
- RGB调节 -
实时调节
+ {t('whiteBalance.rgbAdjustment')} +
{t('whiteBalance.realtimeAdjustment')}
{
{
{
{
- 💡 白平衡调节使用说明 + 💡 {t('whiteBalance.usageInstructions')}
-

🎯 推荐使用方法:

+

{t('whiteBalance.recommendedMethod')}

    -
  1. 点击上方"全屏"按钮进入全屏模式
  2. -
  3. 全屏模式下屏幕边缘会显示彩色条带
  4. +
  5. {t('whiteBalance.fullscreenTip')}
  6. +
  7. {t('whiteBalance.dragTip')}
  8. 将RGB控制面板拖拽到合适位置
  9. 对比LED灯条颜色与屏幕边缘颜色
-

🔧 调节技巧:

+

{t('whiteBalance.adjustmentTips')}

    -
  • 红色偏强:降低R值,LED会减少红色成分
  • -
  • 绿色偏强:降低G值,LED会减少绿色成分
  • -
  • 蓝色偏强:降低B值,LED会减少蓝色成分
  • -
  • 白色发黄:适当提高B值,降低R/G值
  • -
  • 白色发蓝:适当降低B值,提高R/G值
  • +
  • {t('whiteBalance.redStrong')}
  • +
  • {t('whiteBalance.greenStrong')}
  • +
  • {t('whiteBalance.blueStrong')}
  • +
  • {t('whiteBalance.whiteYellow')}
  • +
  • {t('whiteBalance.whiteBlue')}
-

📋 对比方法:

+

{t('whiteBalance.comparisonMethod')}

    -
  • 重点观察白色区域,确保LED白光与屏幕白色一致
  • -
  • 检查彩色区域,确保LED颜色饱和度合适
  • -
  • 在不同环境光下测试,确保效果稳定
  • -
  • 调节完成后可点击"重置"按钮恢复默认值
  • +
  • {t('whiteBalance.whiteComparison')}
  • +
  • {t('whiteBalance.colorComparison')}
  • +
  • {t('whiteBalance.environmentTest')}
  • +
  • {t('whiteBalance.resetNote')}
@@ -356,10 +358,10 @@ export const WhiteBalance = () => { >
⋮⋮ - RGB调节 -
可拖拽
+ {t('whiteBalance.rgbAdjustment')} +
{t('whiteBalance.draggable')}
-
@@ -367,7 +369,7 @@ export const WhiteBalance = () => {
{
{
{
{
- 💡 对比屏幕边缘颜色与LED灯条,调节RGB滑块使颜色一致 + 💡 {t('whiteBalance.fullscreenComparisonTip')}
- -
diff --git a/src/i18n/index.tsx b/src/i18n/index.tsx new file mode 100644 index 0000000..2719683 --- /dev/null +++ b/src/i18n/index.tsx @@ -0,0 +1,79 @@ +import { createSignal, createContext, useContext, ParentComponent, createEffect } from 'solid-js'; +import { Language, TranslationDict } from './types'; +import { zhCN } from './locales/zh-CN'; +import { enUS } from './locales/en-US'; + +// Available translations +const translations: Record = { + 'zh-CN': zhCN, + 'en-US': enUS, +}; + +// Create locale signal +const [locale, setLocale] = createSignal('zh-CN'); + +// Translation function +const t = (key: string): string => { + const keys = key.split('.'); + let value: any = translations[locale()]; + + for (const k of keys) { + if (value && typeof value === 'object' && k in value) { + value = value[k]; + } else { + return key; // Return key if translation not found + } + } + + return typeof value === 'string' ? value : key; +}; + +// Language context for managing language state +interface LanguageContextType { + locale: () => Language; + setLocale: (lang: Language) => void; + t: (key: string) => string; +} + +const LanguageContext = createContext(); + +// Language provider component +export const LanguageProvider: ParentComponent = (props) => { + // Load saved language preference from localStorage + createEffect(() => { + const savedLang = localStorage.getItem('app-language') as Language; + if (savedLang && (savedLang === 'zh-CN' || savedLang === 'en-US')) { + setLocale(savedLang); + } + }); + + // Save language preference when it changes + createEffect(() => { + localStorage.setItem('app-language', locale()); + }); + + const contextValue: LanguageContextType = { + locale, + setLocale, + t, + }; + + return ( + + {props.children} + + ); +}; + +// Hook to use language context +export const useLanguage = () => { + const context = useContext(LanguageContext); + if (!context) { + throw new Error('useLanguage must be used within a LanguageProvider'); + } + return context; +}; + +// Export types and utilities +export type { Language, TranslationDict }; +export { translations }; diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts new file mode 100644 index 0000000..b4d6196 --- /dev/null +++ b/src/i18n/locales/en-US.ts @@ -0,0 +1,211 @@ +import { TranslationDict } from '../types'; + +export const enUS: TranslationDict = { + nav: { + title: 'Ambient Light Control', + info: 'System Info', + displays: 'Display Info', + ledConfiguration: 'LED Configuration', + whiteBalance: 'White Balance', + ledTest: 'LED Test', + }, + + common: { + version: 'Version', + primary: 'Primary', + save: 'Save', + cancel: 'Cancel', + reset: 'Reset', + close: 'Close', + fullscreen: 'Fullscreen', + exitFullscreen: 'Exit Fullscreen', + loading: 'Loading...', + error: 'Error', + success: 'Success', + warning: 'Warning', + confirm: 'Confirm', + delete: 'Delete', + edit: 'Edit', + add: 'Add', + remove: 'Remove', + enable: 'Enable', + disable: 'Disable', + start: 'Start', + stop: 'Stop', + test: 'Test', + apply: 'Apply', + refresh: 'Refresh', + realtime: 'Real-time', + }, + + info: { + title: 'System Information', + boardInfo: 'Device Information', + systemInfo: 'System Information', + deviceName: 'Device Name', + ipAddress: 'IP Address', + macAddress: 'MAC Address', + firmwareVersion: 'Firmware Version', + hardwareVersion: 'Hardware Version', + uptime: 'Uptime', + status: 'Status', + connected: 'Connected', + disconnected: 'Disconnected', + lastSeen: 'Last Seen', + port: 'Port', + latency: 'Latency', + hostname: 'Hostname', + deviceCount: 'Device Count', + noDevicesFound: 'No Devices Found', + checkConnection: 'Please check device connection status', + }, + + displays: { + title: 'Display Status', + count: 'Display Count', + noDisplays: 'No displays detected', + checkConnection: 'Please check display connection', + displayInfo: 'Display Information', + resolution: 'Resolution', + refreshRate: 'Refresh Rate', + colorDepth: 'Color Depth', + isPrimary: 'Primary Display', + position: 'Position', + size: 'Size', + scaleFactor: 'Scale Factor', + lastModified: 'Last Modified', + displayCount: 'Display Count', + noDisplaysFound: 'No displays detected', + brightnessSettings: 'Brightness Settings', + currentBrightness: 'Current Brightness', + maxBrightness: 'Max Brightness', + minBrightness: 'Min Brightness', + contrastSettings: 'Contrast Settings', + currentContrast: 'Current Contrast', + maxContrast: 'Max Contrast', + minContrast: 'Min Contrast', + modeSettings: 'Mode Settings', + currentMode: 'Current Mode', + maxMode: 'Max Mode', + minMode: 'Min Mode', + }, + + ledConfig: { + title: 'LED Strip Configuration', + displaySelection: 'Display Selection', + ledStripConfig: 'LED Strip Configuration', + ledCount: 'LED Count', + ledType: 'LED Type', + position: 'Position', + top: 'Top', + bottom: 'Bottom', + left: 'Left', + right: 'Right', + preview: 'Preview', + configuration: 'Configuration', + sorter: 'Sorter', + moveUp: 'Move Up', + moveDown: 'Move Down', + reverse: 'Reverse', + rgb: 'RGB', + rgbw: 'RGBW', + segments: 'Segments', + totalLeds: 'Total LEDs', + saveConfig: 'Save Configuration', + loadConfig: 'Load Configuration', + stripSorting: 'LED Strip Sorting', + realtimePreview: 'Real-time Preview', + sortingTip: 'Tip: Drag LED strip segments to adjust order, double-click to reverse direction', + displayConfiguration: 'Display Configuration', + visualEditor: 'Visual Editor', + displayTip: 'Tip: Hover over displays for detailed information, use control panel below to adjust LED count', + ledCountControl: 'LED Count Control', + realtimeAdjustment: 'Real-time Adjustment', + decreaseLedCount: 'Decrease LED Count', + increaseLedCount: 'Increase LED Count', + display: 'Display', + controlTip: 'Tip: Click +/- buttons or input values directly to adjust LED count (Range: 0-1000)', + }, + + whiteBalance: { + title: 'White Balance Adjustment', + colorCalibration: 'Color Calibration', + redChannel: 'Red (R)', + greenChannel: 'Green (G)', + blueChannel: 'Blue (B)', + whiteChannel: 'White (W)', + brightness: 'Brightness', + temperature: 'Temperature', + resetToDefault: 'Reset to Default', + fullscreenMode: 'Fullscreen Mode', + normalMode: 'Normal Mode', + instructions: 'Instructions', + helpText: 'Adjust RGB values to match screen colors with actual LED strip colors', + compareColors: 'Compare Colors', + adjustValues: 'Adjust Values', + dragToMove: 'Drag to Move Panel', + back: 'Back', + colorTest: 'Color Test', + clickToTest: 'Click to Test', + colorTestTip: 'Tip: Click color blocks for single color test, click again to return to multi-color mode', + rgbAdjustment: 'RGB Adjustment', + realtimeAdjustment: 'Real-time Adjustment', + usageInstructions: 'White Balance Adjustment Instructions', + recommendedMethod: '🎯 Recommended Method:', + adjustmentTips: '🔧 Adjustment Tips:', + comparisonMethod: '📋 Comparison Method:', + fullscreenTip: 'Click "Fullscreen" button above to enter fullscreen mode', + dragTip: 'Color strips will be displayed at screen edges in fullscreen mode', + redStrong: 'Red too strong: Lower R value to reduce red component in LEDs', + greenStrong: 'Green too strong: Lower G value to reduce green component in LEDs', + blueStrong: 'Blue too strong: Lower B value to reduce blue component in LEDs', + whiteYellow: 'White appears yellow: Increase B value, decrease R/G values', + whiteBlue: 'White appears blue: Decrease B value, increase R/G values', + whiteComparison: 'Focus on white areas, ensure LED white light matches screen white', + colorComparison: 'Check color areas, ensure LED color saturation is appropriate', + environmentTest: 'Test under different ambient lighting to ensure stable results', + resetNote: 'Click "Reset" button to restore default values after adjustment', + fullscreenComparisonTip: 'Compare screen edge colors with LED strips, adjust RGB sliders to match colors', + draggable: 'Draggable', + exitFullscreen: 'Exit Fullscreen', + notEnabled: 'Not Enabled', + }, + + ledTest: { + title: 'LED Strip Test', + testEffects: 'Test Effects', + staticColor: 'Static Color', + rainbow: 'Rainbow', + breathing: 'Breathing', + wave: 'Wave', + chase: 'Chase', + twinkle: 'Twinkle', + fire: 'Fire', + speed: 'Speed', + brightness: 'Brightness', + color: 'Color', + startTest: 'Start Test', + stopTest: 'Stop Test', + testRunning: 'Test Running', + testStopped: 'Test Stopped', + selectEffect: 'Select Effect', + effectSettings: 'Effect Settings', + flowingRainbow: 'Flowing Rainbow', + flowingRainbowDesc: 'Rainbow flowing light for testing LED strip direction', + groupCounting: 'Group Counting', + groupCountingDesc: 'Different colors for every ten LEDs to quickly count LED quantity', + singleScan: 'Single Scan', + singleScanDesc: 'Light up each LED individually for precise position testing', + breathingDesc: 'Breathing effect for the entire LED strip to test overall brightness', + }, + + errors: { + failedToLoad: 'Failed to load', + failedToSave: 'Failed to save', + failedToConnect: 'Failed to connect', + invalidConfiguration: 'Invalid configuration', + deviceNotFound: 'Device not found', + networkError: 'Network error', + unknownError: 'Unknown error', + }, +}; diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts new file mode 100644 index 0000000..55177b8 --- /dev/null +++ b/src/i18n/locales/zh-CN.ts @@ -0,0 +1,211 @@ +import { TranslationDict } from '../types'; + +export const zhCN: TranslationDict = { + nav: { + title: '环境光控制', + info: '基本信息', + displays: '显示器信息', + ledConfiguration: '灯条配置', + whiteBalance: '白平衡', + ledTest: '灯带测试', + }, + + common: { + version: '版本', + primary: '主要', + save: '保存', + cancel: '取消', + reset: '重置', + close: '关闭', + fullscreen: '全屏', + exitFullscreen: '退出全屏', + loading: '加载中...', + error: '错误', + success: '成功', + warning: '警告', + confirm: '确认', + delete: '删除', + edit: '编辑', + add: '添加', + remove: '移除', + enable: '启用', + disable: '禁用', + start: '开始', + stop: '停止', + test: '测试', + apply: '应用', + refresh: '刷新', + realtime: '实时', + }, + + info: { + title: '基本信息', + boardInfo: '设备信息', + systemInfo: '系统信息', + deviceName: '设备名称', + ipAddress: 'IP地址', + macAddress: 'MAC地址', + firmwareVersion: '固件版本', + hardwareVersion: '硬件版本', + uptime: '运行时间', + status: '状态', + connected: '已连接', + disconnected: '已断开', + lastSeen: '最后连接', + port: '端口', + latency: '延迟', + hostname: '主机名', + deviceCount: '设备总数', + noDevicesFound: '未发现设备', + checkConnection: '请检查设备连接状态', + }, + + displays: { + title: '显示器状态', + count: '显示器数量', + noDisplays: '未检测到显示器', + checkConnection: '请检查显示器连接状态', + displayInfo: '显示器信息', + resolution: '分辨率', + refreshRate: '刷新率', + colorDepth: '色深', + isPrimary: '主显示器', + position: '位置', + size: '尺寸', + scaleFactor: '缩放比例', + lastModified: '最后修改', + displayCount: '显示器数量', + noDisplaysFound: '未检测到显示器', + brightnessSettings: '亮度设置', + currentBrightness: '当前亮度', + maxBrightness: '最大亮度', + minBrightness: '最小亮度', + contrastSettings: '对比度设置', + currentContrast: '当前对比度', + maxContrast: '最大对比度', + minContrast: '最小对比度', + modeSettings: '模式设置', + currentMode: '当前模式', + maxMode: '最大模式', + minMode: '最小模式', + }, + + ledConfig: { + title: '灯条配置', + displaySelection: '显示器选择', + ledStripConfig: '灯条配置', + ledCount: '灯珠数量', + ledType: '灯珠类型', + position: '位置', + top: '顶部', + bottom: '底部', + left: '左侧', + right: '右侧', + preview: '预览', + configuration: '配置', + sorter: '排序器', + moveUp: '上移', + moveDown: '下移', + reverse: '反转', + rgb: 'RGB', + rgbw: 'RGBW', + segments: '段数', + totalLeds: '总灯珠数', + saveConfig: '保存配置', + loadConfig: '加载配置', + stripSorting: '灯条排序', + realtimePreview: '实时预览', + sortingTip: '提示:拖拽灯条段落来调整顺序,双击可反转方向', + displayConfiguration: '显示器配置', + visualEditor: '可视化编辑', + displayTip: '提示:悬停显示器查看详细信息,使用下方控制面板调整LED数量', + ledCountControl: 'LED数量控制', + realtimeAdjustment: '实时调整', + decreaseLedCount: '减少LED数量', + increaseLedCount: '增加LED数量', + display: '显示器', + controlTip: '提示:点击 +/- 按钮或直接输入数值来调整LED数量(范围:0-1000)', + }, + + whiteBalance: { + title: '白平衡调节', + colorCalibration: '颜色校准', + redChannel: '红色 (R)', + greenChannel: '绿色 (G)', + blueChannel: '蓝色 (B)', + whiteChannel: '白色 (W)', + brightness: '亮度', + temperature: '色温', + resetToDefault: '重置为默认值', + fullscreenMode: '全屏模式', + normalMode: '普通模式', + instructions: '使用说明', + helpText: '调整RGB值以匹配屏幕颜色与LED灯条的实际颜色', + compareColors: '比较颜色', + adjustValues: '调整数值', + dragToMove: '拖拽移动面板', + back: '返回', + colorTest: '颜色测试', + clickToTest: '点击测试', + colorTestTip: '提示:点击颜色块进行单色测试,再次点击返回多色模式', + rgbAdjustment: 'RGB调节', + realtimeAdjustment: '实时调节', + usageInstructions: '白平衡调节使用说明', + recommendedMethod: '🎯 推荐使用方法:', + adjustmentTips: '🔧 调节技巧:', + comparisonMethod: '📋 对比方法:', + fullscreenTip: '点击上方"全屏"按钮进入全屏模式', + dragTip: '全屏模式下屏幕边缘会显示彩色条带', + redStrong: '红色偏强:降低R值,LED会减少红色成分', + greenStrong: '绿色偏强:降低G值,LED会减少绿色成分', + blueStrong: '蓝色偏强:降低B值,LED会减少蓝色成分', + whiteYellow: '白色发黄:适当提高B值,降低R/G值', + whiteBlue: '白色发蓝:适当降低B值,提高R/G值', + whiteComparison: '重点观察白色区域,确保LED白光与屏幕白色一致', + colorComparison: '检查彩色区域,确保LED颜色饱和度合适', + environmentTest: '在不同环境光下测试,确保效果稳定', + resetNote: '调节完成后可点击"重置"按钮恢复默认值', + fullscreenComparisonTip: '对比屏幕边缘颜色与LED灯条,调节RGB滑块使颜色一致', + draggable: '可拖拽', + exitFullscreen: '退出全屏', + notEnabled: '暂未启用', + }, + + ledTest: { + title: '灯带测试', + testEffects: '测试效果', + staticColor: '静态颜色', + rainbow: '彩虹', + breathing: '呼吸', + wave: '波浪', + chase: '追逐', + twinkle: '闪烁', + fire: '火焰', + speed: '速度', + brightness: '亮度', + color: '颜色', + startTest: '开始测试', + stopTest: '停止测试', + testRunning: '测试运行中', + testStopped: '测试已停止', + selectEffect: '选择效果', + effectSettings: '效果设置', + flowingRainbow: '流光效果', + flowingRainbowDesc: '彩虹色流光,用于测试灯带方向', + groupCounting: '十个一组计数', + groupCountingDesc: '每十个LED一组不同颜色,用于快速计算灯珠数量', + singleScan: '单色扫描', + singleScanDesc: '单个LED依次点亮,用于精确测试每个LED位置', + breathingDesc: '整条灯带呼吸效果,用于测试整体亮度', + }, + + errors: { + failedToLoad: '加载失败', + failedToSave: '保存失败', + failedToConnect: '连接失败', + invalidConfiguration: '配置无效', + deviceNotFound: '设备未找到', + networkError: '网络错误', + unknownError: '未知错误', + }, +}; diff --git a/src/i18n/types.ts b/src/i18n/types.ts new file mode 100644 index 0000000..517e8db --- /dev/null +++ b/src/i18n/types.ts @@ -0,0 +1,219 @@ +export type Language = 'zh-CN' | 'en-US'; + +export interface TranslationDict { + // Navigation + nav: { + title: string; + info: string; + displays: string; + ledConfiguration: string; + whiteBalance: string; + ledTest: string; + }; + + // Common UI elements + common: { + version: string; + primary: string; + save: string; + cancel: string; + reset: string; + close: string; + fullscreen: string; + exitFullscreen: string; + loading: string; + error: string; + success: string; + warning: string; + confirm: string; + delete: string; + edit: string; + add: string; + remove: string; + enable: string; + disable: string; + start: string; + stop: string; + test: string; + apply: string; + refresh: string; + realtime: string; + }; + + // Info page + info: { + title: string; + boardInfo: string; + systemInfo: string; + deviceName: string; + ipAddress: string; + macAddress: string; + firmwareVersion: string; + hardwareVersion: string; + uptime: string; + status: string; + connected: string; + disconnected: string; + lastSeen: string; + port: string; + latency: string; + hostname: string; + deviceCount: string; + noDevicesFound: string; + checkConnection: string; + }; + + // Display page + displays: { + title: string; + count: string; + noDisplays: string; + checkConnection: string; + displayInfo: string; + resolution: string; + refreshRate: string; + colorDepth: string; + isPrimary: string; + position: string; + size: string; + scaleFactor: string; + lastModified: string; + displayCount: string; + noDisplaysFound: string; + brightnessSettings: string; + currentBrightness: string; + maxBrightness: string; + minBrightness: string; + contrastSettings: string; + currentContrast: string; + maxContrast: string; + minContrast: string; + modeSettings: string; + currentMode: string; + maxMode: string; + minMode: string; + }; + + // LED Strip Configuration + ledConfig: { + title: string; + displaySelection: string; + ledStripConfig: string; + ledCount: string; + ledType: string; + position: string; + top: string; + bottom: string; + left: string; + right: string; + preview: string; + configuration: string; + sorter: string; + moveUp: string; + moveDown: string; + reverse: string; + rgb: string; + rgbw: string; + segments: string; + totalLeds: string; + saveConfig: string; + loadConfig: string; + stripSorting: string; + realtimePreview: string; + sortingTip: string; + displayConfiguration: string; + visualEditor: string; + displayTip: string; + ledCountControl: string; + realtimeAdjustment: string; + decreaseLedCount: string; + increaseLedCount: string; + display: string; + controlTip: string; + }; + + // White Balance + whiteBalance: { + title: string; + colorCalibration: string; + redChannel: string; + greenChannel: string; + blueChannel: string; + whiteChannel: string; + brightness: string; + temperature: string; + resetToDefault: string; + fullscreenMode: string; + normalMode: string; + instructions: string; + helpText: string; + compareColors: string; + adjustValues: string; + dragToMove: string; + back: string; + colorTest: string; + clickToTest: string; + colorTestTip: string; + rgbAdjustment: string; + realtimeAdjustment: string; + usageInstructions: string; + recommendedMethod: string; + adjustmentTips: string; + comparisonMethod: string; + fullscreenTip: string; + dragTip: string; + redStrong: string; + greenStrong: string; + blueStrong: string; + whiteYellow: string; + whiteBlue: string; + whiteComparison: string; + colorComparison: string; + environmentTest: string; + resetNote: string; + fullscreenComparisonTip: string; + draggable: string; + exitFullscreen: string; + notEnabled: string; + }; + + // LED Test + ledTest: { + title: string; + testEffects: string; + staticColor: string; + rainbow: string; + breathing: string; + wave: string; + chase: string; + twinkle: string; + fire: string; + speed: string; + brightness: string; + color: string; + startTest: string; + stopTest: string; + testRunning: string; + testStopped: string; + selectEffect: string; + effectSettings: string; + flowingRainbow: string; + flowingRainbowDesc: string; + groupCounting: string; + groupCountingDesc: string; + singleScan: string; + singleScanDesc: string; + breathingDesc: string; + }; + + // Error messages + errors: { + failedToLoad: string; + failedToSave: string; + failedToConnect: string; + invalidConfiguration: string; + deviceNotFound: string; + networkError: string; + unknownError: string; + }; +} diff --git a/src/index.tsx b/src/index.tsx index 57c5f41..2797cc0 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,12 +4,15 @@ import { render } from "solid-js/web"; import "./styles.css"; import App from "./App"; import { Router } from '@solidjs/router'; +import { LanguageProvider } from './i18n/index'; render( () => ( - - - + + + + + ), document.getElementById('root') as HTMLElement, );