mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-28 13:31:32 +08:00
fix: ui/ux
This commit is contained in:
parent
4310d42bd5
commit
86d7e0240b
@ -1766,6 +1766,7 @@
|
||||
"close": "Close",
|
||||
"closed": "Translation closed",
|
||||
"copied": "Translation content copied",
|
||||
"detected.language": "Detected Language",
|
||||
"empty": "Translation content is empty",
|
||||
"not.found": "Translation content not found",
|
||||
"confirm": {
|
||||
|
||||
@ -1798,7 +1798,8 @@
|
||||
"tooltip.newline": "改行",
|
||||
"menu": {
|
||||
"description": "對當前輸入框內容進行翻譯"
|
||||
}
|
||||
},
|
||||
"detected.language": "検出された言語"
|
||||
},
|
||||
"tray": {
|
||||
"quit": "終了",
|
||||
|
||||
@ -1791,14 +1791,15 @@
|
||||
"model": "Настройки модели",
|
||||
"model_desc": "Модель, используемая для службы перевода",
|
||||
"bidirectional": "Настройки двунаправленного перевода",
|
||||
"directional_tip": "После включения поддерживается только двунаправленный перевод между исходным и целевым языками",
|
||||
"scroll_sync": "Настройки синхронизации прокрутки"
|
||||
"scroll_sync": "Настройки синхронизации прокрутки",
|
||||
"bidirectional_tip": "Если включено, перевод будет выполняться в обоих направлениях, исходный текст будет переведен на целевой язык и наоборот."
|
||||
},
|
||||
"title": "Перевод",
|
||||
"tooltip.newline": "Перевести",
|
||||
"menu": {
|
||||
"description": "Перевести содержимое текущего ввода"
|
||||
}
|
||||
},
|
||||
"detected.language": "Обнаруженный язык"
|
||||
},
|
||||
"tray": {
|
||||
"quit": "Выйти",
|
||||
|
||||
@ -1798,7 +1798,8 @@
|
||||
"scroll_sync": "滚动同步设置"
|
||||
},
|
||||
"title": "翻译",
|
||||
"tooltip.newline": "换行"
|
||||
"tooltip.newline": "换行",
|
||||
"detected.language": "检测到的语言"
|
||||
},
|
||||
"tray": {
|
||||
"quit": "退出",
|
||||
|
||||
@ -1798,7 +1798,8 @@
|
||||
"tooltip.newline": "換行",
|
||||
"menu": {
|
||||
"description": "對當前輸入框內容進行翻譯"
|
||||
}
|
||||
},
|
||||
"detected.language": "檢測到的語言"
|
||||
},
|
||||
"tray": {
|
||||
"quit": "結束",
|
||||
|
||||
@ -18,7 +18,7 @@ import {
|
||||
detectLanguage,
|
||||
determineTargetLanguage
|
||||
} from '@renderer/utils/translate'
|
||||
import { Button, Empty, Flex, Modal, Popconfirm, Select, Space, Switch, Tooltip } from 'antd'
|
||||
import { Button, Dropdown, Empty, Flex, Modal, Popconfirm, Select, Space, Switch, Tooltip } from 'antd'
|
||||
import TextArea, { TextAreaRef } from 'antd/es/input/TextArea'
|
||||
import dayjs from 'dayjs'
|
||||
import { useLiveQuery } from 'dexie-react-hooks'
|
||||
@ -214,7 +214,7 @@ const TranslatePage: FC = () => {
|
||||
const [isBidirectional, setIsBidirectional] = useState(false)
|
||||
const [bidirectionalPair, setBidirectionalPair] = useState<[string, string]>(['english', 'chinese'])
|
||||
const [settingsVisible, setSettingsVisible] = useState(false)
|
||||
const [originalTargetLanguage, setOriginalTargetLanguage] = useState<string | null>(null)
|
||||
const [detectedLanguage, setDetectedLanguage] = useState<string | null>(null)
|
||||
const contentContainerRef = useRef<HTMLDivElement>(null)
|
||||
const textAreaRef = useRef<TextAreaRef>(null)
|
||||
const outputTextRef = useRef<HTMLDivElement>(null)
|
||||
@ -289,6 +289,8 @@ const TranslatePage: FC = () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const sourceLanguage = await detectLanguage(text)
|
||||
console.log('检测到的语言:', sourceLanguage)
|
||||
setDetectedLanguage(sourceLanguage)
|
||||
const result = determineTargetLanguage(sourceLanguage, targetLanguage, isBidirectional, bidirectionalPair)
|
||||
if (!result.success) {
|
||||
let errorMessage = ''
|
||||
@ -337,11 +339,6 @@ const TranslatePage: FC = () => {
|
||||
const toggleBidirectional = (value: boolean) => {
|
||||
setIsBidirectional(value)
|
||||
db.settings.put({ id: 'translate:bidirectional:enabled', value })
|
||||
|
||||
if (!value && originalTargetLanguage) {
|
||||
setTargetLanguage(originalTargetLanguage)
|
||||
setOriginalTargetLanguage(null)
|
||||
}
|
||||
}
|
||||
|
||||
const onCopy = () => {
|
||||
@ -450,70 +447,96 @@ const TranslatePage: FC = () => {
|
||||
<HistoryContainner $historyDrawerVisible={historyDrawerVisible}>
|
||||
<OperationBar>
|
||||
<span style={{ fontSize: 16 }}>{t('translate.history.title')}</span>
|
||||
<Popconfirm
|
||||
title={t('translate.history.clear')}
|
||||
description={t('translate.history.clear_description')}
|
||||
onConfirm={clearHistory}
|
||||
okText={t('settings.data.nutstore.new_folder.button.confirm')}
|
||||
cancelText={t('settings.data.nutstore.new_folder.button.cancel')}>
|
||||
<Button type="text" size="small" danger icon={<DeleteOutlined />}>
|
||||
{t('translate.history.clear')}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
{!isEmpty(translateHistory) && (
|
||||
<Popconfirm
|
||||
title={t('translate.history.clear')}
|
||||
description={t('translate.history.clear_description')}
|
||||
onConfirm={clearHistory}>
|
||||
<Button type="text" size="small" danger icon={<DeleteOutlined />}>
|
||||
{t('translate.history.clear')}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
)}
|
||||
</OperationBar>
|
||||
{translateHistory && translateHistory.length > 0 ? (
|
||||
{translateHistory && translateHistory.length ? (
|
||||
<HistoryList>
|
||||
{translateHistory.map((history) => (
|
||||
<HistoryListItem key={history.id} onClick={() => onHistoryItemClick(history)}>
|
||||
<HistoryListItemTitle>{history.sourceText}</HistoryListItemTitle>
|
||||
<Flex justify="space-between" style={{ marginTop: 5 }}>
|
||||
<HistoryListItemDate>{dayjs(history.createdAt).format('MM-DD HH:mm')}</HistoryListItemDate>
|
||||
<Button
|
||||
size="small"
|
||||
type="text"
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
deleteHistory(history.id)
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</HistoryListItem>
|
||||
{translateHistory.map((item) => (
|
||||
<Dropdown
|
||||
key={item.id}
|
||||
trigger={['contextMenu']}
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: 'delete',
|
||||
label: t('translate.history.delete'),
|
||||
icon: <DeleteOutlined />,
|
||||
danger: true,
|
||||
onClick: () => deleteHistory(item.id)
|
||||
}
|
||||
]
|
||||
}}>
|
||||
<HistoryListItem onClick={() => onHistoryItemClick(item)}>
|
||||
<Flex justify="space-between" vertical gap={4} style={{ width: '100%' }}>
|
||||
<HistoryListItemTitle>{item.sourceText}</HistoryListItemTitle>
|
||||
<HistoryListItemTitle>{item.targetText}</HistoryListItemTitle>
|
||||
<HistoryListItemDate>{dayjs(item.createdAt).format('MM/DD HH:mm')}</HistoryListItemDate>
|
||||
</Flex>
|
||||
</HistoryListItem>
|
||||
</Dropdown>
|
||||
))}
|
||||
</HistoryList>
|
||||
) : (
|
||||
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={t('translate.history.empty')} />
|
||||
<Flex justify="center" align="center" style={{ flex: 1 }}>
|
||||
<Empty description={t('translate.history.empty')} />
|
||||
</Flex>
|
||||
)}
|
||||
</HistoryContainner>
|
||||
|
||||
<InputContainer>
|
||||
<OperationBar>
|
||||
<div style={{ width: '100%', display: 'flex', justifyContent: 'flex-end', gap: '8px' }}>
|
||||
<Flex align="center" gap={20}>
|
||||
<Select
|
||||
showSearch
|
||||
value="auto"
|
||||
style={{ width: 180 }}
|
||||
optionFilterProp="label"
|
||||
disabled
|
||||
options={[
|
||||
{
|
||||
label: detectedLanguage
|
||||
? t(`languages.${detectedLanguage}`)
|
||||
: t('translate.detected.language'),
|
||||
value: 'auto'
|
||||
}
|
||||
]}
|
||||
/>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<Settings2 size={18} color="var(--color-icon)" />}
|
||||
icon={<Settings2 size={18} />}
|
||||
onClick={() => setSettingsVisible(true)}
|
||||
style={{ color: 'var(--color-text-2)', display: 'flex' }}
|
||||
/>
|
||||
<Tooltip
|
||||
mouseEnterDelay={0.5}
|
||||
styles={{ body: { fontSize: '12px' } }}
|
||||
title={
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
Enter: {t('translate.button.translate')}
|
||||
<br />
|
||||
Shift + Enter: {t('translate.tooltip.newline')}
|
||||
</div>
|
||||
}>
|
||||
<TranslateButton
|
||||
type="primary"
|
||||
loading={loading}
|
||||
onClick={onTranslate}
|
||||
disabled={!text.trim()}
|
||||
icon={<SendOutlined />}>
|
||||
{t('translate.button.translate')}
|
||||
</TranslateButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Flex>
|
||||
|
||||
<Tooltip
|
||||
mouseEnterDelay={0.5}
|
||||
styles={{ body: { fontSize: '12px' } }}
|
||||
title={
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
Enter: {t('translate.button.translate')}
|
||||
<br />
|
||||
Shift + Enter: {t('translate.tooltip.newline')}
|
||||
</div>
|
||||
}>
|
||||
<TranslateButton
|
||||
type="primary"
|
||||
loading={loading}
|
||||
onClick={onTranslate}
|
||||
disabled={!text.trim()}
|
||||
icon={<SendOutlined />}>
|
||||
{t('translate.button.translate')}
|
||||
</TranslateButton>
|
||||
</Tooltip>
|
||||
</OperationBar>
|
||||
|
||||
<Textarea
|
||||
|
||||
Loading…
Reference in New Issue
Block a user