From edc6d2551aa820a8cc1b23cf6d77df61dd34ca6e Mon Sep 17 00:00:00 2001 From: xun <3415431250@qq.com> Date: Mon, 1 Jun 2026 19:56:51 +0800 Subject: [PATCH] zh-cn --- .github/workflows/build.yml | 203 +++++++++ src/components/common/HashFileModal.jsx | 17 +- src/components/common/PermissionHelper.jsx | 52 ++- src/components/explorer/EmptyState.jsx | 21 +- src/components/explorer/FileList.jsx | 11 +- src/components/network/NetworkView.jsx | 43 +- src/components/search/SearchBar.jsx | 5 +- src/components/settings/SettingsPanel.jsx | 135 +++--- src/components/sidebar/Sidebar.jsx | 113 ++--- src/components/templates/TemplateList.jsx | 57 +-- src/components/thisPc/ThisPCView.jsx | 47 +-- src/locales/zh-CN.js | 459 +++++++++++++++++++++ src/providers/ContextMenuProvider.jsx | 115 +++--- 13 files changed, 974 insertions(+), 304 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 src/locales/zh-CN.js diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..e92d1e07 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,203 @@ +name: Build & Release + +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + platform: + description: '构建平台' + required: true + default: 'all' + type: choice + options: + - all + - windows + - macos + - linux + +permissions: + contents: write + +jobs: + build_windows: + runs-on: windows-latest + if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'windows' || startsWith(github.ref, 'refs/tags/') }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: x86_64-pc-windows-msvc + + - name: Cache Rust dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry/ + ~/.cargo/git/ + src-tauri/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Install Windows WebView2 + run: | + Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=2124703" -OutFile "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" + Start-Process "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" -ArgumentList "/silent /install" -Wait + + - name: Install Node.js dependencies + run: npm ci + + - name: Build Tauri app + run: npx tauri build + + - name: Upload Windows artifacts + uses: actions/upload-artifact@v4 + with: + name: windows-build + path: | + src-tauri/target/release/bundle/**/*.msi + src-tauri/target/release/bundle/**/*.exe + if-no-files-found: error + + build_macos: + runs-on: macos-latest + if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'macos' || startsWith(github.ref, 'refs/tags/') }} + strategy: + matrix: + target: [aarch64-apple-darwin, x86_64-apple-darwin] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Cache Rust dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry/ + ~/.cargo/git/ + src-tauri/target/ + key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.target }}-cargo- + + - name: Install Node.js dependencies + run: npm ci + + - name: Build Tauri app + run: npx tauri build --target ${{ matrix.target }} + + - name: Upload macOS artifacts + uses: actions/upload-artifact@v4 + with: + name: macos-${{ matrix.target }}-build + path: | + src-tauri/target/${{ matrix.target }}/release/bundle/**/*.dmg + src-tauri/target/${{ matrix.target }}/release/bundle/**/*.app + if-no-files-found: error + + build_linux: + runs-on: ubuntu-22.04 + if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'linux' || startsWith(github.ref, 'refs/tags/') }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache Rust dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry/ + ~/.cargo/git/ + src-tauri/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + libwebkit2gtk-4.1-dev \ + build-essential \ + curl \ + wget \ + file \ + libssl-dev \ + libgtk-3-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev \ + pkg-config + + - name: Install Node.js dependencies + run: npm ci + + - name: Build Tauri app + run: npx tauri build + + - name: Upload Linux artifacts + uses: actions/upload-artifact@v4 + with: + name: linux-build + path: | + src-tauri/target/release/bundle/**/*.deb + src-tauri/target/release/bundle/**/*.AppImage + src-tauri/target/release/bundle/**/*.rpm + if-no-files-found: error + + release: + needs: [build_windows, build_macos, build_linux] + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') + + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + files: | + artifacts/**/*.msi + artifacts/**/*.exe + artifacts/**/*.dmg + artifacts/**/*.deb + artifacts/**/*.AppImage + artifacts/**/*.rpm + draft: true + generate_release_notes: true diff --git a/src/components/common/HashFileModal.jsx b/src/components/common/HashFileModal.jsx index 9eee77b5..b23b9918 100644 --- a/src/components/common/HashFileModal.jsx +++ b/src/components/common/HashFileModal.jsx @@ -5,6 +5,7 @@ import { useFileSystem } from '../../providers/FileSystemProvider'; import { showError, showSuccess } from '../../utils/NotificationSystem'; import Modal from '../common/Modal'; import Button from '../common/Button'; +import zhCN from '../../locales/zh-CN.js'; /** * Modal component for generating a hash file for a selected file or directory @@ -63,11 +64,11 @@ const HashFileModal = ({ isOpen, onClose, item }) => { }); await loadDirectory(currentPath); - showSuccess(`Hash generated and saved to ${fileName}: ${hash.substring(0, 16)}...`); + showSuccess(zhCN.hash.hashGenerated.replace('{file}', fileName).replace('{hash}', hash.substring(0, 16))); onClose(); } catch (error) { console.error('Hash generation to file failed:', error); - showError(`Failed to generate hash file: ${error.message || error}`); + showError(`${zhCN.hash.hashGenerateFailed}: ${error.message || error}`); } finally { setIsGenerating(false); } @@ -97,7 +98,7 @@ const HashFileModal = ({ isOpen, onClose, item }) => { @@ -106,7 +107,7 @@ const HashFileModal = ({ isOpen, onClose, item }) => { onClick={onClose} disabled={isGenerating} > - Cancel + {zhCN.common.cancel} } @@ -122,7 +123,7 @@ const HashFileModal = ({ isOpen, onClose, item }) => {
{ onChange={handleChange} onKeyDown={handleKeyDown} className="input" - placeholder="Enter hash file name" + placeholder={zhCN.hash.hashFileNamePlaceholder} disabled={isGenerating} />
- The hash will be generated for "{item.name}" and saved to this file. + {zhCN.hash.hashFileHint.replace('{name}', item.name)}
diff --git a/src/components/common/PermissionHelper.jsx b/src/components/common/PermissionHelper.jsx index 7e6baeeb..7e1f00b3 100644 --- a/src/components/common/PermissionHelper.jsx +++ b/src/components/common/PermissionHelper.jsx @@ -4,6 +4,7 @@ import { open } from '@tauri-apps/plugin-dialog'; import Modal from './Modal'; import Button from './Button'; import { showSuccess, showError } from '../../utils/NotificationSystem'; +import zhCN from '../../locales/zh-CN.js'; /** * PermissionHelper - Component to help users grant necessary permissions or browse to folder @@ -22,7 +23,7 @@ const PermissionHelper = ({ isOpen, onClose, directoryPath, directoryName, onDir const hasAccess = await invoke('check_directory_access', { path: directoryPath }); setHasAccess(hasAccess); if (hasAccess) { - showSuccess(`Access granted to ${directoryName}!`); + showSuccess(zhCN.permission.accessGrantedMessage.replace('{name}', directoryName)); setTimeout(onClose, 1000); // Close modal after success } } catch (error) { @@ -45,7 +46,7 @@ const PermissionHelper = ({ isOpen, onClose, directoryPath, directoryName, onDir await invoke('request_full_disk_access'); } catch (error) { console.error('Failed to open System Preferences:', error); - showError('Unable to open System Preferences. Please open it manually.'); + showError(zhCN.permission.failedToOpenPreferences); } }; @@ -64,18 +65,18 @@ const PermissionHelper = ({ isOpen, onClose, directoryPath, directoryName, onDir selectedPath = await open({ directory: true, - title: `Browse to your ${directoryName} folder`, + title: zhCN.permission.browseToFolder.replace('{name}', directoryName), defaultPath: parentPath || undefined }); if (selectedPath) { - showSuccess(`Selected ${directoryName} folder: ${selectedPath}`); + showSuccess(zhCN.permission.browseToFolder.replace('{name}', directoryName) + ': ' + selectedPath); onDirectorySelected && onDirectorySelected(selectedPath); onClose(); } } catch (error) { console.error('Failed to open folder picker:', error); - showError('Failed to open folder picker. Please try again.'); + showError(zhCN.permission.failedToOpenPicker); } finally { setIsBrowsing(false); } @@ -85,28 +86,28 @@ const PermissionHelper = ({ isOpen, onClose, directoryPath, directoryName, onDir {hasAccess ? ( ) : ( <> )} @@ -125,36 +126,33 @@ const PermissionHelper = ({ isOpen, onClose, directoryPath, directoryName, onDir
{hasAccess ? (
-

Access Granted!

-

You now have access to your {directoryName} folder.

+

{zhCN.permission.accessGranted}!

+

{zhCN.permission.accessGrantedMessage.replace('{name}', directoryName)}

) : (
-

Permission Required

-

- This application needs permission to access your {directoryName} folder. -

+

{zhCN.permission.permissionRequired}

+

-

Options to access your {directoryName} folder:

+

{zhCN.permission.optionsToAccess.replace('{name}', directoryName)}

-
Option 1: Browse to folder (Recommended)
-

Click "Browse to Folder" to manually select your {directoryName} directory using the system folder picker.

+
{zhCN.permission.option1Title}
+

{zhCN.permission.option1Desc.replace('{name}', directoryName)}

-
Option 2: Grant system permission
+
{zhCN.permission.option2Title}
    -
  1. Click "Grant Permission" to open System Preferences
  2. -
  3. Go to Privacy & Security → Files and Folders
  4. -
  5. Find "Explr" in the list and enable access to "{directoryName}"
  6. -
  7. Return to this app and click "Try Again"
  8. +
  9. {zhCN.permission.option2Step1}
  10. +
  11. +
  12. +
  13. {zhCN.permission.option2Step4}
-

Note: This is a macOS security feature that protects your personal files. - Granting access allows this file explorer to browse your {directoryName} folder.

+

)} diff --git a/src/components/explorer/EmptyState.jsx b/src/components/explorer/EmptyState.jsx index f341b2f9..e644db9a 100644 --- a/src/components/explorer/EmptyState.jsx +++ b/src/components/explorer/EmptyState.jsx @@ -1,5 +1,6 @@ import React from 'react'; import './emptyState.css'; +import zhCN from '../../locales/zh-CN.js'; /** * Component for displaying various empty state messages @@ -15,28 +16,28 @@ const EmptyState = ({ type = 'empty-folder', searchTerm = null, title = null, me const emptyStates = { 'empty-folder': { icon: 'folder-empty', - title: 'This folder is empty', - message: 'Drag and drop files here or use the Create button to add content', + title: zhCN.emptyState.emptyFolder, + message: zhCN.emptyState.emptyFolderHint, }, 'no-results': { icon: 'search-empty', - title: `No results found${searchTerm ? ` for "${searchTerm}"` : ''}`, - message: 'Try different keywords or check your spelling', + title: searchTerm ? zhCN.emptyState.noResultsFor.replace('{term}', searchTerm) : zhCN.emptyState.noResults, + message: zhCN.emptyState.noResultsHint, }, 'no-favorites': { icon: 'star-empty', - title: 'No favorites yet', - message: 'Right-click on folders and files to add them to favorites', + title: zhCN.emptyState.noFavorites, + message: zhCN.emptyState.noFavoritesHint, }, 'no-templates': { icon: 'template-empty', - title: 'No templates', - message: 'You haven\'t saved any templates yet. Templates help you create files and folders with predefined structures.', + title: zhCN.emptyState.noTemplates, + message: zhCN.emptyState.noTemplatesHint, }, 'error': { icon: 'error', - title: 'Something went wrong', - message: 'Please try again or check your connection', + title: zhCN.emptyState.error, + message: zhCN.emptyState.errorHint, }, }; diff --git a/src/components/explorer/FileList.jsx b/src/components/explorer/FileList.jsx index e53863a1..23a029ef 100644 --- a/src/components/explorer/FileList.jsx +++ b/src/components/explorer/FileList.jsx @@ -6,6 +6,7 @@ import { showError } from '../../utils/NotificationSystem'; import FileItem from './FileItem'; import EmptyState from './EmptyState'; import './fileList.css'; +import zhCN from '../../locales/zh-CN.js'; /** * Component to display a list of files and directories @@ -464,7 +465,7 @@ const FileList = ({ data, isLoading, viewMode = 'grid', isSearching = false, sea
-

Loading...

+

{zhCN.fileList.loading}

); @@ -584,7 +585,7 @@ const FileList = ({ data, isLoading, viewMode = 'grid', isSearching = false, sea className={`file-list-column column-name ${sortConfig.key === 'name' ? `sorted-${sortConfig.direction}` : ''}`} onClick={() => handleSort('name')} > - Name + {zhCN.fileList.name} {sortConfig.key === 'name' && ( )} @@ -593,7 +594,7 @@ const FileList = ({ data, isLoading, viewMode = 'grid', isSearching = false, sea className={`file-list-column column-size ${sortConfig.key === 'size_in_bytes' ? `sorted-${sortConfig.direction}` : ''}`} onClick={() => handleSort('size_in_bytes')} > - Size + {zhCN.fileList.size} {sortConfig.key === 'size_in_bytes' && ( )} @@ -602,7 +603,7 @@ const FileList = ({ data, isLoading, viewMode = 'grid', isSearching = false, sea className={`file-list-column column-type ${sortConfig.key === 'type' ? `sorted-${sortConfig.direction}` : ''}`} onClick={() => handleSort('type')} > - Type + {zhCN.fileList.type} {sortConfig.key === 'type' && ( )} @@ -611,7 +612,7 @@ const FileList = ({ data, isLoading, viewMode = 'grid', isSearching = false, sea className={`file-list-column column-modified ${sortConfig.key === 'last_modified' ? `sorted-${sortConfig.direction}` : ''}`} onClick={() => handleSort('last_modified')} > - Modified + {zhCN.fileList.modified} {sortConfig.key === 'last_modified' && ( )} diff --git a/src/components/network/NetworkView.jsx b/src/components/network/NetworkView.jsx index 4f093d4d..798ce22d 100644 --- a/src/components/network/NetworkView.jsx +++ b/src/components/network/NetworkView.jsx @@ -5,6 +5,7 @@ import { useHistory } from '../../providers/HistoryProvider'; import { showSuccess, showError } from '../../utils/NotificationSystem'; import AddSftpConnectionView from '../sidebar/AddSftpConnectionView'; import './networkView.css'; +import zhCN from '../../locales/zh-CN.js'; /** * NetworkView component that displays available network connections @@ -53,9 +54,9 @@ const NetworkView = () => { key: 'fileExplorerSftpConnections', newValue: JSON.stringify(newConnections) })); - showSuccess(`SFTP connection "${conn.name}" added successfully`); + showSuccess(zhCN.network.connectionAdded.replace('{name}', conn.name)); } catch (err) { - showError('Failed to add SFTP connection'); + showError(zhCN.network.connectionFailed); } setIsAddSftpModalOpen(false); }; @@ -68,31 +69,31 @@ const NetworkView = () => { const sftpPath = createSftpUrl(connection, '.'); await loadDirectory(sftpPath); navigateTo(sftpPath); - showSuccess(`Connected to ${connection.name}`); + showSuccess(zhCN.network.connected.replace('{name}', connection.name)); } } catch (error) { console.error('Failed to connect to SFTP:', error); - showError(`Failed to connect to ${connection.name}: ${error.message || error}`); + showError(`${zhCN.network.connectionFailed}: ${error.message || error}`); } }; return (
-

Network

-

Manage and connect to remote servers

+

{zhCN.network.title}

+

{zhCN.network.subtitle}

-

SFTP Connections

+

{zhCN.network.sftpConnections}

@@ -102,14 +103,14 @@ const NetworkView = () => {
-

No SFTP connections

-

Add an SFTP connection to get started with remote file access

+

{zhCN.network.noConnections}

+

{zhCN.network.addConnectionToStart}

) : ( @@ -128,10 +129,10 @@ const NetworkView = () => {
@@ -141,15 +142,15 @@ const NetworkView = () => {
-

About Network Features

+

{zhCN.network.aboutNetwork}

-

Secure Connections

-

All SFTP connections use secure SSH protocols to protect your data during transfer.

+

{zhCN.network.secureConnections}

+

{zhCN.network.secureConnectionsDesc}

@@ -157,8 +158,8 @@ const NetworkView = () => {
-

File Operations

-

Perform all standard file operations on remote files just like local ones.

+

{zhCN.network.fileOperations}

+

{zhCN.network.fileOperationsDesc}

@@ -166,8 +167,8 @@ const NetworkView = () => {
-

Seamless Integration

-

Remote files appear alongside local files with full explorer functionality.

+

{zhCN.network.seamlessIntegration}

+

{zhCN.network.seamlessIntegrationDesc}

diff --git a/src/components/search/SearchBar.jsx b/src/components/search/SearchBar.jsx index bb1e932f..95879bf5 100644 --- a/src/components/search/SearchBar.jsx +++ b/src/components/search/SearchBar.jsx @@ -1,5 +1,6 @@ import React, { useState, useEffect, useRef } from 'react'; import './searchBar.css'; +import zhCN from '../../locales/zh-CN.js'; /** * SearchBar component - Provides a search input with expand/collapse functionality @@ -8,10 +9,10 @@ import './searchBar.css'; * @param {string} [props.value=''] - Initial value for the search input * @param {Function} [props.onChange] - Callback function when input value changes * @param {Function} [props.onSubmit] - Callback function when form is submitted - * @param {string} [props.placeholder='Search files and folders'] - Placeholder text for the input + * @param {string} [props.placeholder] - Placeholder text for the input * @returns {React.ReactElement} SearchBar component */ -const SearchBar = ({ value = '', onChange, onSubmit, placeholder = 'Search files and folders' }) => { +const SearchBar = ({ value = '', onChange, onSubmit, placeholder = zhCN.search.searchFilesAndFolders }) => { const [inputValue, setInputValue] = useState(value); const [isFocused, setIsFocused] = useState(false); const [isExpanded, setIsExpanded] = useState(true); // Always expanded diff --git a/src/components/settings/SettingsPanel.jsx b/src/components/settings/SettingsPanel.jsx index 212433ba..4e6df467 100644 --- a/src/components/settings/SettingsPanel.jsx +++ b/src/components/settings/SettingsPanel.jsx @@ -4,6 +4,7 @@ import { useSettings } from '../../providers/SettingsProvider'; import Modal from '../common/Modal'; import Button from '../common/Button'; import './settings.css'; +import zhCN from '../../locales/zh-CN.js'; /** * SettingsPanel component - Provides a comprehensive settings interface @@ -23,10 +24,10 @@ const SettingsPanel = ({ isOpen, onClose }) => { * @type {Array<{id: string, label: string, icon: string}>} */ const tabs = [ - { id: 'appearance', label: 'Appearance', icon: 'palette' }, - { id: 'behavior', label: 'Behavior', icon: 'settings' }, - { id: 'search', label: 'Search', icon: 'search' }, - { id: 'advanced', label: 'Advanced', icon: 'cog' } + { id: 'appearance', label: zhCN.settings.appearance, icon: 'palette' }, + { id: 'behavior', label: zhCN.settings.behavior, icon: 'settings' }, + { id: 'search', label: zhCN.settings.search, icon: 'search' }, + { id: 'advanced', label: zhCN.settings.advanced, icon: 'cog' } ]; /** @@ -34,8 +35,8 @@ const SettingsPanel = ({ isOpen, onClose }) => { * @type {Array<{id: boolean, label: string}>} */ const themes = [ - { id: false, label: 'Light' }, - { id: true, label: 'Dark' } + { id: false, label: zhCN.settings.light }, + { id: true, label: zhCN.settings.dark } ]; /** @@ -43,9 +44,9 @@ const SettingsPanel = ({ isOpen, onClose }) => { * @type {Array<{id: string, label: string}>} */ const viewModes = [ - { id: 'grid', label: 'Grid View' }, - { id: 'list', label: 'List View' }, - { id: 'details', label: 'Details View' } + { id: 'grid', label: zhCN.settings.gridView }, + { id: 'list', label: zhCN.settings.listView }, + { id: 'details', label: zhCN.settings.detailsView } ]; /** @@ -53,9 +54,9 @@ const SettingsPanel = ({ isOpen, onClose }) => { * @type {Array<{id: string, label: string}>} */ const fontSizes = [ - { id: 'Small', label: 'Small' }, - { id: 'Medium', label: 'Medium' }, - { id: 'Large', label: 'Large' } + { id: 'Small', label: zhCN.settings.small }, + { id: 'Medium', label: zhCN.settings.medium }, + { id: 'Large', label: zhCN.settings.large } ]; /** @@ -63,10 +64,10 @@ const SettingsPanel = ({ isOpen, onClose }) => { * @type {Array<{id: string, label: string}>} */ const sortOptions = [ - { id: 'Name', label: 'Name' }, - { id: 'Size', label: 'Size' }, - { id: 'Modified', label: 'Date Modified' }, - { id: 'Type', label: 'Type' } + { id: 'Name', label: zhCN.settings.sortByOptions.name }, + { id: 'Size', label: zhCN.settings.sortByOptions.size }, + { id: 'Modified', label: zhCN.settings.sortByOptions.modified }, + { id: 'Type', label: zhCN.settings.sortByOptions.type } ]; /** @@ -74,8 +75,8 @@ const SettingsPanel = ({ isOpen, onClose }) => { * @type {Array<{id: string, label: string}>} */ const sortDirections = [ - { id: 'Ascending', label: 'Ascending' }, - { id: 'Descending', label: 'Descending' } + { id: 'Ascending', label: zhCN.settings.ascending }, + { id: 'Descending', label: zhCN.settings.descending } ]; /** @@ -83,8 +84,8 @@ const SettingsPanel = ({ isOpen, onClose }) => { * @type {Array<{id: string, label: string}>} */ const doubleClickOptions = [ - { id: 'OpenFilesAndFolders', label: 'Open files and folders' }, - { id: 'SelectFilesAndFolders', label: 'Select files and folders' } + { id: 'OpenFilesAndFolders', label: zhCN.settings.openFilesAndFolders }, + { id: 'SelectFilesAndFolders', label: zhCN.settings.selectFilesAndFolders } ]; /** @@ -115,7 +116,7 @@ const SettingsPanel = ({ isOpen, onClose }) => { * @async */ const handleReset = async () => { - if (!confirm('Are you sure you want to reset all settings to default? This cannot be undone.')) { + if (!confirm(zhCN.settings.confirmResetSettings)) { return; } @@ -123,10 +124,10 @@ const SettingsPanel = ({ isOpen, onClose }) => { try { await resetSettings(); setLocalError(null); - alert('Settings have been reset to default.'); + alert(zhCN.settings.settingsResetSuccess); } catch (error) { console.error('Failed to reset settings:', error); - setLocalError('Failed to reset settings. Please try again.'); + setLocalError(zhCN.settings.settingsResetFailed); } finally { setIsResetting(false); } @@ -139,10 +140,10 @@ const SettingsPanel = ({ isOpen, onClose }) => { const handleClearSearchIndex = async () => { try { await invoke('clear_search_engine'); - alert('Search index has been cleared.'); + alert(zhCN.settings.searchIndexCleared); } catch (error) { console.error('Failed to clear search index:', error); - setLocalError('Failed to clear search index.'); + setLocalError('清除搜索索引失败'); } }; @@ -153,7 +154,7 @@ const SettingsPanel = ({ isOpen, onClose }) => { const renderAppearanceTab = () => (
-

Theme

+

{zhCN.settings.theme}

{themes.map(theme => (
-

Default View

+

{zhCN.settings.defaultView}

{viewModes.map(mode => (
-

Font Size

+

{zhCN.settings.fontSize}

{ className="color-picker" />
- Choose your preferred accent color for the interface. + {zhCN.settings.accentColorHint}
@@ -223,7 +224,7 @@ const SettingsPanel = ({ isOpen, onClose }) => { checked={settings.show_details_panel || false} onChange={(e) => updateSetting('show_details_panel', e.target.checked)} /> - Show details panel by default + {zhCN.settings.showDetailsPanel}
@@ -245,14 +246,14 @@ const SettingsPanel = ({ isOpen, onClose }) => { const renderBehaviorTab = () => (
-

File Operations

+

{zhCN.settings.fileOperations}

-

Default Sort

+

{zhCN.settings.defaultSort}

- + updateSetting('sort_direction', e.target.value)} @@ -306,7 +307,7 @@ const SettingsPanel = ({ isOpen, onClose }) => {
-

Double-click Behavior

+

{zhCN.settings.doubleClickBehavior}

{doubleClickOptions.map(option => (