refactor(translate): move auto detection method to preferences

Move auto detection method configuration from local state to preference store
Remove unused auto detection types from renderer types
Add zod schema for auto detection method validation
This commit is contained in:
icarus 2025-10-14 22:03:21 +08:00
parent 9a67ac9018
commit dbfece3590
5 changed files with 15 additions and 48 deletions

View File

@ -397,6 +397,8 @@ export interface PreferenceSchemas {
'topic.tab.show_time': boolean 'topic.tab.show_time': boolean
// redux/translate/settings // redux/translate/settings
'translate.settings.auto_copy': boolean 'translate.settings.auto_copy': boolean
// indexedDB/translate
'translate.settings.auto_detection_method': PreferenceTypes.AutoDetectionMethod
// redux/settings/customCss // redux/settings/customCss
'ui.custom_css': string 'ui.custom_css': string
// redux/settings/navbarPosition // redux/settings/navbarPosition
@ -657,6 +659,7 @@ export const DefaultPreferences: PreferenceSchemas = {
'topic.tab.show': true, 'topic.tab.show': true,
'topic.tab.show_time': false, 'topic.tab.show_time': false,
'translate.settings.auto_copy': false, 'translate.settings.auto_copy': false,
'translate.settings.auto_detection_method': 'franc',
'ui.custom_css': '', 'ui.custom_css': '',
'ui.navbar.position': 'top', 'ui.navbar.position': 'top',
'ui.sidebar.icons.invisible': [], 'ui.sidebar.icons.invisible': [],

View File

@ -1,3 +1,5 @@
import * as z from 'zod'
import type { PreferenceSchemas } from './preferenceSchemas' import type { PreferenceSchemas } from './preferenceSchemas'
export type PreferenceDefaultScopeType = PreferenceSchemas['default'] export type PreferenceDefaultScopeType = PreferenceSchemas['default']
@ -85,3 +87,9 @@ export type ChatMessageNavigationMode = 'none' | 'buttons' | 'anchor'
export type MultiModelMessageStyle = 'horizontal' | 'vertical' | 'fold' | 'grid' export type MultiModelMessageStyle = 'horizontal' | 'vertical' | 'fold' | 'grid'
export type MultiModelGridPopoverTrigger = 'hover' | 'click' export type MultiModelGridPopoverTrigger = 'hover' | 'click'
const AutoDetectionMethodSchema = z.enum(['franc', 'llm', 'auto'])
export type AutoDetectionMethod = z.infer<typeof AutoDetectionMethodSchema>
export const isAutoDetectionMethod = (method: string): method is AutoDetectionMethod => {
return AutoDetectionMethodSchema.safeParse(method).success
}

View File

@ -22,13 +22,7 @@ import { estimateTextTokens } from '@renderer/services/TokenService'
import { saveTranslateHistory, translateText } from '@renderer/services/TranslateService' import { saveTranslateHistory, translateText } from '@renderer/services/TranslateService'
// import { setTranslateAbortKey, setTranslating as setTranslatingAction } from '@renderer/store/runtime' // import { setTranslateAbortKey, setTranslating as setTranslatingAction } from '@renderer/store/runtime'
import type { FileMetadata, SupportedOcrFile } from '@renderer/types' import type { FileMetadata, SupportedOcrFile } from '@renderer/types'
import { import { isSupportedOcrFile, type Model, type TranslateHistory, type TranslateLanguage } from '@renderer/types'
type AutoDetectionMethod,
isSupportedOcrFile,
type Model,
type TranslateHistory,
type TranslateLanguage
} from '@renderer/types'
import { getFileExtension, isTextFile, runAsyncFunction } from '@renderer/utils' import { getFileExtension, isTextFile, runAsyncFunction } from '@renderer/utils'
import { abortCompletion } from '@renderer/utils/abortController' import { abortCompletion } from '@renderer/utils/abortController'
import { isAbortError } from '@renderer/utils/error' import { isAbortError } from '@renderer/utils/error'
@ -91,7 +85,6 @@ const TranslatePage: FC = () => {
const [detectedLanguage, setDetectedLanguage] = useState<TranslateLanguage | null>(null) const [detectedLanguage, setDetectedLanguage] = useState<TranslateLanguage | null>(null)
const [sourceLanguage, setSourceLanguage] = useState<TranslateLanguage | 'auto'>(_sourceLanguage) const [sourceLanguage, setSourceLanguage] = useState<TranslateLanguage | 'auto'>(_sourceLanguage)
const [targetLanguage, setTargetLanguage] = useState<TranslateLanguage>(_targetLanguage) const [targetLanguage, setTargetLanguage] = useState<TranslateLanguage>(_targetLanguage)
const [autoDetectionMethod, setAutoDetectionMethod] = useState<AutoDetectionMethod>('franc')
const [isProcessing, setIsProcessing] = useState(false) const [isProcessing, setIsProcessing] = useState(false)
// ref // ref
@ -374,29 +367,9 @@ const TranslatePage: FC = () => {
const markdownSetting = await db.settings.get({ id: 'translate:markdown:enabled' }) const markdownSetting = await db.settings.get({ id: 'translate:markdown:enabled' })
setEnableMarkdown(markdownSetting ? markdownSetting.value : false) setEnableMarkdown(markdownSetting ? markdownSetting.value : false)
const autoDetectionMethodSetting = await db.settings.get({ id: 'translate:detect:method' })
if (autoDetectionMethodSetting) {
setAutoDetectionMethod(autoDetectionMethodSetting.value)
} else {
setAutoDetectionMethod('franc')
db.settings.put({ id: 'translate:detect:method', value: 'franc' })
}
}) })
}, [getLanguageByLangcode]) }, [getLanguageByLangcode])
// 控制设置同步
const updateAutoDetectionMethod = async (method: AutoDetectionMethod) => {
try {
await db.settings.put({ id: 'translate:detect:method', value: method })
setAutoDetectionMethod(method)
} catch (e) {
logger.error('Failed to update auto detection method setting.', e as Error)
window.toast.error(t('translate.error.detect.update_setting') + formatErrorMessage(e))
}
}
// 控制Enter触发翻译 // 控制Enter触发翻译
const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => { const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
const isEnterPressed = e.key === 'Enter' const isEnterPressed = e.key === 'Enter'
@ -802,8 +775,6 @@ const TranslatePage: FC = () => {
bidirectionalPair={bidirectionalPair} bidirectionalPair={bidirectionalPair}
setBidirectionalPair={setBidirectionalPair} setBidirectionalPair={setBidirectionalPair}
translateModel={translateModel} translateModel={translateModel}
autoDetectionMethod={autoDetectionMethod}
setAutoDetectionMethod={updateAutoDetectionMethod}
/> />
</Container> </Container>
) )

View File

@ -3,7 +3,7 @@ import { usePreference } from '@data/hooks/usePreference'
import LanguageSelect from '@renderer/components/LanguageSelect' import LanguageSelect from '@renderer/components/LanguageSelect'
import db from '@renderer/databases' import db from '@renderer/databases'
import useTranslate from '@renderer/hooks/useTranslate' import useTranslate from '@renderer/hooks/useTranslate'
import type { AutoDetectionMethod, Model, TranslateLanguage } from '@renderer/types' import type { Model, TranslateLanguage } from '@renderer/types'
import { Modal, Radio, Space } from 'antd' import { Modal, Radio, Space } from 'antd'
import type { FC } from 'react' import type { FC } from 'react'
import { memo, useEffect, useState } from 'react' import { memo, useEffect, useState } from 'react'
@ -24,8 +24,6 @@ const TranslateSettings: FC<{
bidirectionalPair: [TranslateLanguage, TranslateLanguage] bidirectionalPair: [TranslateLanguage, TranslateLanguage]
setBidirectionalPair: (value: [TranslateLanguage, TranslateLanguage]) => void setBidirectionalPair: (value: [TranslateLanguage, TranslateLanguage]) => void
translateModel: Model | undefined translateModel: Model | undefined
autoDetectionMethod: AutoDetectionMethod
setAutoDetectionMethod: (method: AutoDetectionMethod) => void
}> = ({ }> = ({
visible, visible,
onClose, onClose,
@ -36,14 +34,13 @@ const TranslateSettings: FC<{
enableMarkdown, enableMarkdown,
setEnableMarkdown, setEnableMarkdown,
bidirectionalPair, bidirectionalPair,
setBidirectionalPair, setBidirectionalPair
autoDetectionMethod,
setAutoDetectionMethod
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const [localPair, setLocalPair] = useState<[TranslateLanguage, TranslateLanguage]>(bidirectionalPair) const [localPair, setLocalPair] = useState<[TranslateLanguage, TranslateLanguage]>(bidirectionalPair)
const { getLanguageByLangcode } = useTranslate() const { getLanguageByLangcode } = useTranslate()
const [autoCopy, setAutoCopy] = usePreference('translate.settings.auto_copy') const [autoCopy, setAutoCopy] = usePreference('translate.settings.auto_copy')
const [autoDetectionMethod, setAutoDetectionMethod] = usePreference('translate.settings.auto_detection_method')
useEffect(() => { useEffect(() => {
setLocalPair(bidirectionalPair) setLocalPair(bidirectionalPair)

View File

@ -507,18 +507,6 @@ export type CustomTranslateLanguage = {
emoji: string emoji: string
} }
export const AutoDetectionMethods = {
franc: 'franc',
llm: 'llm',
auto: 'auto'
} as const
export type AutoDetectionMethod = keyof typeof AutoDetectionMethods
export const isAutoDetectionMethod = (method: string): method is AutoDetectionMethod => {
return Object.hasOwn(AutoDetectionMethods, method)
}
// by fullex @ data refactor // by fullex @ data refactor
// export type SidebarIcon = // export type SidebarIcon =
// | 'assistants' // | 'assistants'