feat: added translation functionality and chinese support
This commit is contained in:
parent
fb564733e4
commit
79f6d598ab
70
src/renderer/src/components/TranslateButton.tsx
Normal file
70
src/renderer/src/components/TranslateButton.tsx
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { TranslationOutlined } from '@ant-design/icons'
|
||||||
|
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
||||||
|
import { fetchTranslate } from '@renderer/services/ApiService'
|
||||||
|
import { getDefaultTopic, getDefaultTranslateAssistant } from '@renderer/services/AssistantService'
|
||||||
|
import { getUserMessage } from '@renderer/services/MessagesService'
|
||||||
|
import { Button } from 'antd'
|
||||||
|
import { FC, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
text?: string
|
||||||
|
onTranslated: (translatedText: string) => void
|
||||||
|
disabled?: boolean
|
||||||
|
style?: React.CSSProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
const TranslateButton: FC<Props> = ({ text, onTranslated, disabled, style }) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { translateModel } = useDefaultModel()
|
||||||
|
const [isTranslating, setIsTranslating] = useState(false)
|
||||||
|
|
||||||
|
const handleTranslate = async () => {
|
||||||
|
if (!text?.trim()) return
|
||||||
|
|
||||||
|
if (!translateModel) {
|
||||||
|
window.message.error({
|
||||||
|
content: t('translate.error.not_configured'),
|
||||||
|
key: 'translate-message'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先复制原文到剪贴板
|
||||||
|
await navigator.clipboard.writeText(text)
|
||||||
|
|
||||||
|
setIsTranslating(true)
|
||||||
|
try {
|
||||||
|
const assistant = getDefaultTranslateAssistant('english', text)
|
||||||
|
const message = getUserMessage({
|
||||||
|
assistant,
|
||||||
|
topic: getDefaultTopic('default'),
|
||||||
|
type: 'text'
|
||||||
|
})
|
||||||
|
|
||||||
|
const translatedText = await fetchTranslate({ message, assistant })
|
||||||
|
onTranslated(translatedText)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Translation failed:', error)
|
||||||
|
window.message.error({
|
||||||
|
content: t('translate.error.failed'),
|
||||||
|
key: 'translate-message'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
setIsTranslating(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
icon={<TranslationOutlined />}
|
||||||
|
onClick={handleTranslate}
|
||||||
|
disabled={disabled || isTranslating}
|
||||||
|
loading={isTranslating}
|
||||||
|
style={style}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TranslateButton
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import i18n from 'i18next'
|
import i18n from 'i18next'
|
||||||
import { initReactI18next } from 'react-i18next'
|
import { initReactI18next } from 'react-i18next'
|
||||||
|
|
||||||
import enUS from './en-us.json'
|
import enUS from './locales/en-us.json'
|
||||||
import zhCN from './zh-cn.json'
|
import zhCN from './locales/zh-cn.json'
|
||||||
import zhTW from './zh-tw.json'
|
import zhTW from './locales/zh-tw.json'
|
||||||
|
|
||||||
const resources = {
|
const resources = {
|
||||||
'en-US': enUS,
|
'en-US': enUS,
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
|
|
||||||
@ -8,6 +8,7 @@ import ImageSize16_9 from '@renderer/assets/images/paintings/image-size-16-9.svg
|
|||||||
import { Navbar, NavbarCenter, NavbarRight } from '@renderer/components/app/Navbar'
|
import { Navbar, NavbarCenter, NavbarRight } from '@renderer/components/app/Navbar'
|
||||||
import { VStack } from '@renderer/components/Layout'
|
import { VStack } from '@renderer/components/Layout'
|
||||||
import Scrollbar from '@renderer/components/Scrollbar'
|
import Scrollbar from '@renderer/components/Scrollbar'
|
||||||
|
import TranslateButton from '@renderer/components/TranslateButton'
|
||||||
import { TEXT_TO_IMAGES_MODELS } from '@renderer/config/models'
|
import { TEXT_TO_IMAGES_MODELS } from '@renderer/config/models'
|
||||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
import { usePaintings } from '@renderer/hooks/usePaintings'
|
import { usePaintings } from '@renderer/hooks/usePaintings'
|
||||||
@ -386,6 +387,12 @@ const PaintingsPage: FC = () => {
|
|||||||
/>
|
/>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<ToolbarMenu>
|
<ToolbarMenu>
|
||||||
|
<TranslateButton
|
||||||
|
text={textareaRef.current?.resizableTextArea?.textArea?.value}
|
||||||
|
onTranslated={(translatedText) => updatePaintingState({ prompt: translatedText })}
|
||||||
|
disabled={isLoading}
|
||||||
|
style={{ marginRight: 6 }}
|
||||||
|
/>
|
||||||
<SendMessageButton sendMessage={onGenerate} disabled={isLoading} />
|
<SendMessageButton sendMessage={onGenerate} disabled={isLoading} />
|
||||||
</ToolbarMenu>
|
</ToolbarMenu>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { isLocalAi } from '@renderer/config/env'
|
|||||||
import db from '@renderer/databases'
|
import db from '@renderer/databases'
|
||||||
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
||||||
import { fetchTranslate } from '@renderer/services/ApiService'
|
import { fetchTranslate } from '@renderer/services/ApiService'
|
||||||
import { getDefaultAssistant } from '@renderer/services/AssistantService'
|
import { getDefaultTranslateAssistant } from '@renderer/services/AssistantService'
|
||||||
import { Assistant, Message } from '@renderer/types'
|
import { Assistant, Message } from '@renderer/types'
|
||||||
import { runAsyncFunction, uuid } from '@renderer/utils'
|
import { runAsyncFunction, uuid } from '@renderer/utils'
|
||||||
import { Button, Select, Space } from 'antd'
|
import { Button, Select, Space } from 'antd'
|
||||||
@ -104,9 +104,7 @@ const TranslatePage: FC = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const assistant: Assistant = getDefaultAssistant()
|
const assistant: Assistant = getDefaultTranslateAssistant(targetLanguage, text)
|
||||||
assistant.model = translateModel
|
|
||||||
assistant.prompt = `Translate from input language to ${targetLanguage}, provide the translation result directly without any explanation, keep original format. If the target language is the same as the source language, do not translate. The text to be translated is as follows:\n\n ${text}`
|
|
||||||
|
|
||||||
const message: Message = {
|
const message: Message = {
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
|
|||||||
@ -19,6 +19,14 @@ export function getDefaultAssistant(): Assistant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getDefaultTranslateAssistant(targetLanguage: string, text: string): Assistant {
|
||||||
|
const translateModel = getTranslateModel()
|
||||||
|
const assistant: Assistant = getDefaultAssistant()
|
||||||
|
assistant.model = translateModel
|
||||||
|
assistant.prompt = `Translate from input language to ${targetLanguage}, provide the translation result directly without any explanation, keep original format. If the target language is the same as the source language, do not translate. The text to be translated is as follows:\n\n ${text}`
|
||||||
|
return assistant
|
||||||
|
}
|
||||||
|
|
||||||
export function getDefaultAssistantSettings() {
|
export function getDefaultAssistantSettings() {
|
||||||
return store.getState().assistants.defaultAssistant.settings
|
return store.getState().assistants.defaultAssistant.settings
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user