mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-10 07:19:02 +08:00
feat(translate): add bidirectional translation configuration in cache
Refactor bidirectional translation logic to use cache for state management Simplify language pair handling by using language codes directly
This commit is contained in:
parent
6cda7f891d
commit
9b7094ea4a
6
packages/shared/data/cache/cacheSchemas.ts
vendored
6
packages/shared/data/cache/cacheSchemas.ts
vendored
@ -32,6 +32,7 @@ export type UseCacheSchema = {
|
|||||||
'translate.output': string
|
'translate.output': string
|
||||||
'translate.detecting': boolean
|
'translate.detecting': boolean
|
||||||
'translate.translating': CacheValueTypes.CacheTranslating
|
'translate.translating': CacheValueTypes.CacheTranslating
|
||||||
|
'translate.bidirectional': CacheValueTypes.CacheTranslateBidirectional
|
||||||
|
|
||||||
// Test keys (for dataRefactorTest window)
|
// Test keys (for dataRefactorTest window)
|
||||||
// TODO: remove after testing
|
// TODO: remove after testing
|
||||||
@ -83,6 +84,11 @@ export const DefaultUseCache: UseCacheSchema = {
|
|||||||
'translate.output': '',
|
'translate.output': '',
|
||||||
'translate.detecting': false,
|
'translate.detecting': false,
|
||||||
'translate.translating': { isTranslating: false, abortKey: null },
|
'translate.translating': { isTranslating: false, abortKey: null },
|
||||||
|
'translate.bidirectional': {
|
||||||
|
enabled: false,
|
||||||
|
origin: 'en-us',
|
||||||
|
target: 'zh-cn'
|
||||||
|
},
|
||||||
|
|
||||||
// Test keys (for dataRefactorTest window)
|
// Test keys (for dataRefactorTest window)
|
||||||
// TODO: remove after testing
|
// TODO: remove after testing
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import type { MinAppType, Topic, WebSearchStatus } from '@types'
|
import type { MinAppType, Topic, TranslateLanguageCode, WebSearchStatus } from '@types'
|
||||||
import type { UpdateInfo } from 'builder-util-runtime'
|
import type { UpdateInfo } from 'builder-util-runtime'
|
||||||
|
|
||||||
export type CacheAppUpdateState = {
|
export type CacheAppUpdateState = {
|
||||||
@ -25,3 +25,8 @@ export type CacheTranslating =
|
|||||||
isTranslating: false
|
isTranslating: false
|
||||||
abortKey: null
|
abortKey: null
|
||||||
}
|
}
|
||||||
|
export type CacheTranslateBidirectional = {
|
||||||
|
enabled: boolean
|
||||||
|
origin: TranslateLanguageCode
|
||||||
|
target: TranslateLanguageCode
|
||||||
|
}
|
||||||
|
|||||||
@ -69,18 +69,15 @@ const TranslatePage: FC = () => {
|
|||||||
const [isDetecting, setIsDetecting] = useCache('translate.detecting')
|
const [isDetecting, setIsDetecting] = useCache('translate.detecting')
|
||||||
const [translatingState, setTranslatingState] = useCache('translate.translating')
|
const [translatingState, setTranslatingState] = useCache('translate.translating')
|
||||||
const { isTranslating, abortKey } = translatingState
|
const { isTranslating, abortKey } = translatingState
|
||||||
|
const [bidirectional, setBidirectional] = useCache('translate.bidirectional')
|
||||||
|
const { enabled: isBidirectional } = bidirectional
|
||||||
|
|
||||||
// states
|
// states
|
||||||
const [renderedMarkdown, setRenderedMarkdown] = useState<string>('')
|
const [renderedMarkdown, setRenderedMarkdown] = useState<string>('')
|
||||||
const [copied, setCopied] = useTemporaryValue(false, 2000)
|
const [copied, setCopied] = useTemporaryValue(false, 2000)
|
||||||
const [historyDrawerVisible, setHistoryDrawerVisible] = useState(false)
|
const [historyDrawerVisible, setHistoryDrawerVisible] = useState(false)
|
||||||
const [isScrollSyncEnabled, setIsScrollSyncEnabled] = useState(false)
|
const [isScrollSyncEnabled, setIsScrollSyncEnabled] = useState(false)
|
||||||
const [isBidirectional, setIsBidirectional] = useState(false)
|
|
||||||
const [enableMarkdown, setEnableMarkdown] = useState(false)
|
const [enableMarkdown, setEnableMarkdown] = useState(false)
|
||||||
const [bidirectionalPair, setBidirectionalPair] = useState<[TranslateLanguage, TranslateLanguage]>([
|
|
||||||
LanguagesEnum.enUS,
|
|
||||||
LanguagesEnum.zhCN
|
|
||||||
])
|
|
||||||
const [settingsVisible, setSettingsVisible] = useState(false)
|
const [settingsVisible, setSettingsVisible] = useState(false)
|
||||||
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)
|
||||||
@ -149,12 +146,11 @@ const TranslatePage: FC = () => {
|
|||||||
!text.trim() ||
|
!text.trim() ||
|
||||||
(sourceLanguage !== 'auto' && sourceLanguage.langCode === UNKNOWN.langCode) ||
|
(sourceLanguage !== 'auto' && sourceLanguage.langCode === UNKNOWN.langCode) ||
|
||||||
targetLanguage.langCode === UNKNOWN.langCode ||
|
targetLanguage.langCode === UNKNOWN.langCode ||
|
||||||
(isBidirectional &&
|
(isBidirectional && (bidirectional.origin === UNKNOWN.langCode || bidirectional.target === UNKNOWN.langCode)) ||
|
||||||
(bidirectionalPair[0].langCode === UNKNOWN.langCode || bidirectionalPair[1].langCode === UNKNOWN.langCode)) ||
|
|
||||||
isProcessing ||
|
isProcessing ||
|
||||||
isDetecting
|
isDetecting
|
||||||
)
|
)
|
||||||
}, [bidirectionalPair, isBidirectional, isDetecting, isProcessing, sourceLanguage, targetLanguage.langCode, text])
|
}, [bidirectional, isBidirectional, isDetecting, isProcessing, sourceLanguage, targetLanguage.langCode, text])
|
||||||
|
|
||||||
// 控制翻译按钮,翻译前进行校验
|
// 控制翻译按钮,翻译前进行校验
|
||||||
const onTranslate = useCallback(async () => {
|
const onTranslate = useCallback(async () => {
|
||||||
@ -184,7 +180,7 @@ const TranslatePage: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = determineTargetLanguage(actualSourceLanguage, targetLanguage, isBidirectional, bidirectionalPair)
|
const result = determineTargetLanguage(actualSourceLanguage.langCode, targetLanguage.langCode, bidirectional)
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
let errorMessage = ''
|
let errorMessage = ''
|
||||||
if (result.errorType === 'same_language') {
|
if (result.errorType === 'same_language') {
|
||||||
@ -197,7 +193,8 @@ const TranslatePage: FC = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const actualTargetLanguage = result.language as TranslateLanguage
|
const actualTargetLanguage = getLanguageByLangcode(result.language)
|
||||||
|
|
||||||
if (isBidirectional) {
|
if (isBidirectional) {
|
||||||
setTargetLanguage(actualTargetLanguage)
|
setTargetLanguage(actualTargetLanguage)
|
||||||
}
|
}
|
||||||
@ -230,7 +227,7 @@ const TranslatePage: FC = () => {
|
|||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
autoCopy,
|
autoCopy,
|
||||||
bidirectionalPair,
|
bidirectional,
|
||||||
couldTranslate,
|
couldTranslate,
|
||||||
getLanguageByLangcode,
|
getLanguageByLangcode,
|
||||||
isBidirectional,
|
isBidirectional,
|
||||||
@ -254,12 +251,6 @@ const TranslatePage: FC = () => {
|
|||||||
abortCompletion(abortKey)
|
abortCompletion(abortKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 控制双向翻译切换
|
|
||||||
const toggleBidirectional = (value: boolean) => {
|
|
||||||
setIsBidirectional(value)
|
|
||||||
db.settings.put({ id: 'translate:bidirectional:enabled', value })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 控制历史记录点击
|
// 控制历史记录点击
|
||||||
const onHistoryItemClick = (history: TranslateHistory) => {
|
const onHistoryItemClick = (history: TranslateHistory) => {
|
||||||
setText(history.sourceText)
|
setText(history.sourceText)
|
||||||
@ -334,32 +325,6 @@ const TranslatePage: FC = () => {
|
|||||||
sourceLang &&
|
sourceLang &&
|
||||||
setSourceLanguage(sourceLang.value === 'auto' ? sourceLang.value : getLanguageByLangcode(sourceLang.value))
|
setSourceLanguage(sourceLang.value === 'auto' ? sourceLang.value : getLanguageByLangcode(sourceLang.value))
|
||||||
|
|
||||||
const bidirectionalPairSetting = await db.settings.get({ id: 'translate:bidirectional:pair' })
|
|
||||||
if (bidirectionalPairSetting) {
|
|
||||||
const langPair = bidirectionalPairSetting.value
|
|
||||||
let source: undefined | TranslateLanguage
|
|
||||||
let target: undefined | TranslateLanguage
|
|
||||||
|
|
||||||
if (Array.isArray(langPair) && langPair.length === 2 && langPair[0] !== langPair[1]) {
|
|
||||||
source = getLanguageByLangcode(langPair[0])
|
|
||||||
target = getLanguageByLangcode(langPair[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source && target) {
|
|
||||||
setBidirectionalPair([source, target])
|
|
||||||
} else {
|
|
||||||
const defaultPair: [TranslateLanguage, TranslateLanguage] = [LanguagesEnum.enUS, LanguagesEnum.zhCN]
|
|
||||||
setBidirectionalPair(defaultPair)
|
|
||||||
db.settings.put({
|
|
||||||
id: 'translate:bidirectional:pair',
|
|
||||||
value: [defaultPair[0].langCode, defaultPair[1].langCode]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const bidirectionalSetting = await db.settings.get({ id: 'translate:bidirectional:enabled' })
|
|
||||||
setIsBidirectional(bidirectionalSetting ? bidirectionalSetting.value : false)
|
|
||||||
|
|
||||||
const scrollSyncSetting = await db.settings.get({ id: 'translate:scroll:sync' })
|
const scrollSyncSetting = await db.settings.get({ id: 'translate:scroll:sync' })
|
||||||
setIsScrollSyncEnabled(scrollSyncSetting ? scrollSyncSetting.value : false)
|
setIsScrollSyncEnabled(scrollSyncSetting ? scrollSyncSetting.value : false)
|
||||||
|
|
||||||
@ -383,8 +348,8 @@ const TranslatePage: FC = () => {
|
|||||||
|
|
||||||
// 获取目标语言显示
|
// 获取目标语言显示
|
||||||
const getLanguageDisplay = () => {
|
const getLanguageDisplay = () => {
|
||||||
try {
|
if (isBidirectional) {
|
||||||
if (isBidirectional) {
|
try {
|
||||||
return (
|
return (
|
||||||
<Flex className="min-w-40 items-center">
|
<Flex className="min-w-40 items-center">
|
||||||
<BidirectionalLanguageDisplay>
|
<BidirectionalLanguageDisplay>
|
||||||
@ -392,10 +357,14 @@ const TranslatePage: FC = () => {
|
|||||||
</BidirectionalLanguageDisplay>
|
</BidirectionalLanguageDisplay>
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error getting language display:', error as Error)
|
||||||
|
setBidirectional({
|
||||||
|
enabled: true,
|
||||||
|
origin: LanguagesEnum.enUS.langCode,
|
||||||
|
target: LanguagesEnum.zhCN.langCode
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
logger.error('Error getting language display:', error as Error)
|
|
||||||
setBidirectionalPair([LanguagesEnum.enUS, LanguagesEnum.zhCN])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -766,12 +735,8 @@ const TranslatePage: FC = () => {
|
|||||||
onClose={() => setSettingsVisible(false)}
|
onClose={() => setSettingsVisible(false)}
|
||||||
isScrollSyncEnabled={isScrollSyncEnabled}
|
isScrollSyncEnabled={isScrollSyncEnabled}
|
||||||
setIsScrollSyncEnabled={setIsScrollSyncEnabled}
|
setIsScrollSyncEnabled={setIsScrollSyncEnabled}
|
||||||
isBidirectional={isBidirectional}
|
|
||||||
setIsBidirectional={toggleBidirectional}
|
|
||||||
enableMarkdown={enableMarkdown}
|
enableMarkdown={enableMarkdown}
|
||||||
setEnableMarkdown={setEnableMarkdown}
|
setEnableMarkdown={setEnableMarkdown}
|
||||||
bidirectionalPair={bidirectionalPair}
|
|
||||||
setBidirectionalPair={setBidirectionalPair}
|
|
||||||
translateModel={translateModel}
|
translateModel={translateModel}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { Button, ColFlex, Flex, HelpTooltip, RowFlex, Switch, Tooltip } from '@cherrystudio/ui'
|
import { Button, ColFlex, Flex, HelpTooltip, RowFlex, Switch, Tooltip } from '@cherrystudio/ui'
|
||||||
|
import { useCache } from '@data/hooks/useCache'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
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 type { Model } 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 } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import TranslateSettingsPopup from '../settings/TranslateSettingsPopup/TranslateSettingsPopup'
|
import TranslateSettingsPopup from '../settings/TranslateSettingsPopup/TranslateSettingsPopup'
|
||||||
@ -17,35 +17,15 @@ const TranslateSettings: FC<{
|
|||||||
onClose: () => void
|
onClose: () => void
|
||||||
isScrollSyncEnabled: boolean
|
isScrollSyncEnabled: boolean
|
||||||
setIsScrollSyncEnabled: (value: boolean) => void
|
setIsScrollSyncEnabled: (value: boolean) => void
|
||||||
isBidirectional: boolean
|
|
||||||
setIsBidirectional: (value: boolean) => void
|
|
||||||
enableMarkdown: boolean
|
enableMarkdown: boolean
|
||||||
setEnableMarkdown: (value: boolean) => void
|
setEnableMarkdown: (value: boolean) => void
|
||||||
bidirectionalPair: [TranslateLanguage, TranslateLanguage]
|
|
||||||
setBidirectionalPair: (value: [TranslateLanguage, TranslateLanguage]) => void
|
|
||||||
translateModel: Model | undefined
|
translateModel: Model | undefined
|
||||||
}> = ({
|
}> = ({ visible, onClose, isScrollSyncEnabled, setIsScrollSyncEnabled, enableMarkdown, setEnableMarkdown }) => {
|
||||||
visible,
|
|
||||||
onClose,
|
|
||||||
isScrollSyncEnabled,
|
|
||||||
setIsScrollSyncEnabled,
|
|
||||||
isBidirectional,
|
|
||||||
setIsBidirectional,
|
|
||||||
enableMarkdown,
|
|
||||||
setEnableMarkdown,
|
|
||||||
bidirectionalPair,
|
|
||||||
setBidirectionalPair
|
|
||||||
}) => {
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [localPair, setLocalPair] = useState<[TranslateLanguage, TranslateLanguage]>(bidirectionalPair)
|
|
||||||
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')
|
const [autoDetectionMethod, setAutoDetectionMethod] = usePreference('translate.settings.auto_detection_method')
|
||||||
|
const [bidirectional, setBidirectional] = useCache('translate.bidirectional')
|
||||||
useEffect(() => {
|
const { enabled: isBidirectional } = bidirectional
|
||||||
setLocalPair(bidirectionalPair)
|
|
||||||
}, [bidirectionalPair, visible])
|
|
||||||
|
|
||||||
const onMoreSetting = () => {
|
const onMoreSetting = () => {
|
||||||
onClose()
|
onClose()
|
||||||
TranslateSettingsPopup.show()
|
TranslateSettingsPopup.show()
|
||||||
@ -146,7 +126,7 @@ const TranslateSettings: FC<{
|
|||||||
isSelected={isBidirectional}
|
isSelected={isBidirectional}
|
||||||
color="primary"
|
color="primary"
|
||||||
onValueChange={(isSelected) => {
|
onValueChange={(isSelected) => {
|
||||||
setIsBidirectional(isSelected)
|
setBidirectional({ ...bidirectional, enabled: isSelected })
|
||||||
// 双向翻译设置不需要持久化,它只是界面状态
|
// 双向翻译设置不需要持久化,它只是界面状态
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -156,36 +136,32 @@ const TranslateSettings: FC<{
|
|||||||
<Flex className="items-center justify-between gap-2.5">
|
<Flex className="items-center justify-between gap-2.5">
|
||||||
<LanguageSelect
|
<LanguageSelect
|
||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
value={localPair[0].langCode}
|
value={bidirectional.origin}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
const newPair: [TranslateLanguage, TranslateLanguage] = [getLanguageByLangcode(value), localPair[1]]
|
if (value === bidirectional.target) {
|
||||||
if (newPair[0] === newPair[1]) {
|
|
||||||
window.toast.warning(t('translate.language.same'))
|
window.toast.warning(t('translate.language.same'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setLocalPair(newPair)
|
setBidirectional({
|
||||||
setBidirectionalPair(newPair)
|
...bidirectional,
|
||||||
db.settings.put({
|
origin: value,
|
||||||
id: 'translate:bidirectional:pair',
|
target: bidirectional.target
|
||||||
value: [newPair[0].langCode, newPair[1].langCode]
|
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span>⇆</span>
|
<span>⇆</span>
|
||||||
<LanguageSelect
|
<LanguageSelect
|
||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
value={localPair[1].langCode}
|
value={bidirectional.target}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
const newPair: [TranslateLanguage, TranslateLanguage] = [localPair[0], getLanguageByLangcode(value)]
|
if (bidirectional.origin === value) {
|
||||||
if (newPair[0] === newPair[1]) {
|
|
||||||
window.toast.warning(t('translate.language.same'))
|
window.toast.warning(t('translate.language.same'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setLocalPair(newPair)
|
setBidirectional({
|
||||||
setBidirectionalPair(newPair)
|
...bidirectional,
|
||||||
db.settings.put({
|
origin: bidirectional.origin,
|
||||||
id: 'translate:bidirectional:pair',
|
target: value
|
||||||
value: [newPair[0].langCode, newPair[1].langCode]
|
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import type { Assistant, TranslateLanguage, TranslateLanguageCode } from '@rende
|
|||||||
import type { Chunk } from '@renderer/types/chunk'
|
import type { Chunk } from '@renderer/types/chunk'
|
||||||
import { ChunkType } from '@renderer/types/chunk'
|
import { ChunkType } from '@renderer/types/chunk'
|
||||||
import { LANG_DETECT_PROMPT } from '@shared/config/prompts'
|
import { LANG_DETECT_PROMPT } from '@shared/config/prompts'
|
||||||
|
import type { CacheTranslateBidirectional } from '@shared/data/cache/cacheValueTypes'
|
||||||
import { franc } from 'franc-min'
|
import { franc } from 'franc-min'
|
||||||
import type { RefObject } from 'react'
|
import type { RefObject } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
@ -128,60 +129,68 @@ const detectLanguageByFranc = (inputText: string): TranslateLanguageCode => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取双向翻译的目标语言
|
* Determine the target language for bidirectional translation.
|
||||||
* @param sourceLanguage 检测到的源语言
|
* When the source language matches one side of the pair, the opposite side is returned.
|
||||||
* @param languagePair 配置的语言对
|
* @param sourceLanguage The detected source language code
|
||||||
* @returns 目标语言
|
* @param languagePair The configured bidirectional language pair
|
||||||
|
* @returns The target language code to translate into
|
||||||
*/
|
*/
|
||||||
export const getTargetLanguageForBidirectional = (
|
export const getTargetLanguageForBidirectional = (
|
||||||
sourceLanguage: TranslateLanguage,
|
sourceLanguage: TranslateLanguageCode,
|
||||||
languagePair: [TranslateLanguage, TranslateLanguage]
|
languagePair: CacheTranslateBidirectional
|
||||||
): TranslateLanguage => {
|
): TranslateLanguageCode => {
|
||||||
if (sourceLanguage.langCode === languagePair[0].langCode) {
|
const { origin, target } = languagePair
|
||||||
return languagePair[1]
|
if (sourceLanguage === origin) {
|
||||||
} else if (sourceLanguage.langCode === languagePair[1].langCode) {
|
return target
|
||||||
return languagePair[0]
|
} else if (sourceLanguage === target) {
|
||||||
|
return origin
|
||||||
}
|
}
|
||||||
return languagePair[0] !== sourceLanguage ? languagePair[0] : languagePair[1]
|
return origin !== sourceLanguage ? origin : target
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查源语言是否在配置的语言对中
|
* Check if the source language is within the configured language pair
|
||||||
* @param sourceLanguage 检测到的源语言
|
* @param sourceLanguage The detected source language code
|
||||||
* @param languagePair 配置的语言对
|
* @param languagePair The configured bidirectional language pair
|
||||||
* @returns 是否在语言对中
|
* @returns true if the source language is in the pair, false otherwise
|
||||||
*/
|
*/
|
||||||
export const isLanguageInPair = (
|
export const isLanguageInPair = (
|
||||||
sourceLanguage: TranslateLanguage,
|
sourceLanguage: TranslateLanguageCode,
|
||||||
languagePair: [TranslateLanguage, TranslateLanguage]
|
languagePair: CacheTranslateBidirectional
|
||||||
): boolean => {
|
): boolean => {
|
||||||
return [languagePair[0].langCode, languagePair[1].langCode].includes(sourceLanguage.langCode)
|
return [languagePair.origin, languagePair.target].includes(sourceLanguage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DetermineTargetLanguageReturn =
|
||||||
|
| { success: true; language: TranslateLanguageCode; errorType?: never }
|
||||||
|
| {
|
||||||
|
success: false
|
||||||
|
errorType: 'same_language' | 'not_in_pair'
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 确定翻译的目标语言
|
* Determine the target language for translation
|
||||||
* @param sourceLanguage 检测到的源语言
|
* @param sourceLanguage The detected source language code
|
||||||
* @param targetLanguage 用户设置的目标语言
|
* @param targetLanguage The user-set target language code
|
||||||
* @param isBidirectional 是否开启双向翻译
|
* @param bidirectional The bidirectional translation configuration
|
||||||
* @param bidirectionalPair 双向翻译的语言对
|
* @returns An object indicating success or failure, including the target language code if successful, or an error type if failed
|
||||||
* @returns 处理结果对象
|
|
||||||
*/
|
*/
|
||||||
export const determineTargetLanguage = (
|
export const determineTargetLanguage = (
|
||||||
sourceLanguage: TranslateLanguage,
|
sourceLanguage: TranslateLanguageCode,
|
||||||
targetLanguage: TranslateLanguage,
|
targetLanguage: TranslateLanguageCode,
|
||||||
isBidirectional: boolean,
|
bidirectional: CacheTranslateBidirectional
|
||||||
bidirectionalPair: [TranslateLanguage, TranslateLanguage]
|
): DetermineTargetLanguageReturn => {
|
||||||
): { success: boolean; language?: TranslateLanguage; errorType?: 'same_language' | 'not_in_pair' } => {
|
const isBidirectional = bidirectional.enabled
|
||||||
if (isBidirectional) {
|
if (isBidirectional) {
|
||||||
if (!isLanguageInPair(sourceLanguage, bidirectionalPair)) {
|
if (!isLanguageInPair(sourceLanguage, bidirectional)) {
|
||||||
return { success: false, errorType: 'not_in_pair' }
|
return { success: false, errorType: 'not_in_pair' }
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
language: getTargetLanguageForBidirectional(sourceLanguage, bidirectionalPair)
|
language: getTargetLanguageForBidirectional(sourceLanguage, bidirectional)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sourceLanguage.langCode === targetLanguage.langCode) {
|
if (sourceLanguage === targetLanguage) {
|
||||||
return { success: false, errorType: 'same_language' }
|
return { success: false, errorType: 'same_language' }
|
||||||
}
|
}
|
||||||
return { success: true, language: targetLanguage }
|
return { success: true, language: targetLanguage }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user