feat: add translate selection (#1010)
* feat: add translate selection * chore: add default translate value * feat: optimize trigger translation shotcut and add TanslateLanguageVarious * fix * fix: add database migrate version
This commit is contained in:
parent
f3940159b3
commit
3d8748a61a
@ -1,5 +1,6 @@
|
||||
import { LoadingOutlined, TranslationOutlined } from '@ant-design/icons'
|
||||
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { fetchTranslate } from '@renderer/services/ApiService'
|
||||
import { getDefaultTopic, getDefaultTranslateAssistant } from '@renderer/services/AssistantService'
|
||||
import { getUserMessage } from '@renderer/services/MessagesService'
|
||||
@ -20,6 +21,7 @@ const TranslateButton: FC<Props> = ({ text, onTranslated, disabled, style, isLoa
|
||||
const { t } = useTranslation()
|
||||
const { translateModel } = useDefaultModel()
|
||||
const [isTranslating, setIsTranslating] = useState(false)
|
||||
const { targetLanguage } = useSettings()
|
||||
|
||||
const translateConfirm = () => {
|
||||
return window?.modal?.confirm({
|
||||
@ -49,7 +51,7 @@ const TranslateButton: FC<Props> = ({ text, onTranslated, disabled, style, isLoa
|
||||
|
||||
setIsTranslating(true)
|
||||
try {
|
||||
const assistant = getDefaultTranslateAssistant('english', text)
|
||||
const assistant = getDefaultTranslateAssistant(targetLanguage, text)
|
||||
const message = getUserMessage({
|
||||
assistant,
|
||||
topic: getDefaultTopic('default'),
|
||||
@ -75,7 +77,10 @@ const TranslateButton: FC<Props> = ({ text, onTranslated, disabled, style, isLoa
|
||||
}, [isLoading])
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('chat.input.translate')} arrow>
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={t('chat.input.translate', { target_language: t(`languages.${targetLanguage.toString()}`) })}
|
||||
arrow>
|
||||
<ToolbarButton onClick={handleTranslate} disabled={disabled || isTranslating} style={style} type="text">
|
||||
{isTranslating ? <LoadingOutlined spin /> : <TranslationOutlined />}
|
||||
</ToolbarButton>
|
||||
|
||||
@ -3,13 +3,14 @@ import {
|
||||
SendMessageShortcut,
|
||||
setSendMessageShortcut as _setSendMessageShortcut,
|
||||
setSidebarIcons,
|
||||
setTargetLanguage,
|
||||
setTheme,
|
||||
SettingsState,
|
||||
setTopicPosition,
|
||||
setTray,
|
||||
setWindowStyle
|
||||
} from '@renderer/store/settings'
|
||||
import { SidebarIcon, ThemeMode } from '@renderer/types'
|
||||
import { SidebarIcon, ThemeMode, TranslateLanguageVarious } from '@renderer/types'
|
||||
|
||||
export function useSettings() {
|
||||
const settings = useAppSelector((state) => state.settings)
|
||||
@ -30,6 +31,9 @@ export function useSettings() {
|
||||
setWindowStyle(windowStyle: 'transparent' | 'opaque') {
|
||||
dispatch(setWindowStyle(windowStyle))
|
||||
},
|
||||
setTargetLanguage(targetLanguage: TranslateLanguageVarious) {
|
||||
dispatch(setTargetLanguage(targetLanguage))
|
||||
},
|
||||
setTopicPosition(topicPosition: 'left' | 'right') {
|
||||
dispatch(setTopicPosition(topicPosition))
|
||||
},
|
||||
|
||||
@ -86,7 +86,7 @@
|
||||
"input.send": "Send",
|
||||
"input.settings": "Settings",
|
||||
"input.topics": " Topics ",
|
||||
"input.translate": "Translate to English",
|
||||
"input.translate": "Translate to {{target_language}}",
|
||||
"input.upload": "Upload image or document file",
|
||||
"input.web_search": "Enable web search",
|
||||
"input.knowledge_base": "Knowledge Base",
|
||||
@ -462,6 +462,12 @@
|
||||
"display.custom.css": "Custom CSS",
|
||||
"display.custom.css.placeholder": "/* Put custom CSS here */",
|
||||
"input.auto_translate_with_space": "Quickly translate with 3 spaces",
|
||||
"input.target_language": "Target language",
|
||||
"input.target_language.chinese": "Simplified Chinese",
|
||||
"input.target_language.chinese-traditional": "Traditional Chinese",
|
||||
"input.target_language.english": "English",
|
||||
"input.target_language.japanese": "Japanese",
|
||||
"input.target_language.russian": "Russian",
|
||||
"messages.divider": "Show divider between messages",
|
||||
"messages.input.paste_long_text_as_file": "Paste long text as file",
|
||||
"messages.input.send_shortcuts": "Send shortcuts",
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
"input.send": "送信",
|
||||
"input.settings": "設定",
|
||||
"input.topics": " トピック ",
|
||||
"input.translate": "英語に翻訳",
|
||||
"input.translate": "{{target_language}}に翻訳",
|
||||
"input.upload": "画像またはドキュメントをアップロード",
|
||||
"input.web_search": "ウェブ検索を有効にする",
|
||||
"input.knowledge_base": "ナレッジベース",
|
||||
@ -453,6 +453,12 @@
|
||||
"display.minApp.disabled": "非表示ミニプログラム",
|
||||
"display.minApp.empty": "非表示にしたいアプレットを左からここまでドラッグします",
|
||||
"input.auto_translate_with_space": "スペースを3回押して翻訳",
|
||||
"input.target_language": "目標言語",
|
||||
"input.target_language.chinese": "簡体字中国語",
|
||||
"input.target_language.chinese-traditional": "繁体字中国語",
|
||||
"input.target_language.english": "英語",
|
||||
"input.target_language.japanese": "日本語",
|
||||
"input.target_language.russian": "ロシア語",
|
||||
"messages.divider": "メッセージ間に区切り線を表示",
|
||||
"messages.input.paste_long_text_as_file": "長いテキストをファイルとして貼り付け",
|
||||
"messages.input.send_shortcuts": "送信ショートカット",
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
"input.send": "Отправить",
|
||||
"input.settings": "Настройки",
|
||||
"input.topics": " Топики ",
|
||||
"input.translate": "Перевести на английский",
|
||||
"input.translate": "Перевести на {{target_language}}",
|
||||
"input.upload": "Загрузить изображение или документ",
|
||||
"input.web_search": "Включить веб-поиск",
|
||||
"input.knowledge_base": "База знаний",
|
||||
@ -454,6 +454,12 @@
|
||||
"display.custom.css": "Пользовательский CSS",
|
||||
"display.custom.css.placeholder": "/* Здесь введите пользовательский CSS */",
|
||||
"input.auto_translate_with_space": "Быстрый перевод с помощью 3-х пробелов",
|
||||
"input.target_language": "Целевой язык",
|
||||
"input.target_language.chinese": "Китайский упрощенный",
|
||||
"input.target_language.chinese-traditional": "Китайский традиционный",
|
||||
"input.target_language.english": "Английский",
|
||||
"input.target_language.japanese": "Японский",
|
||||
"input.target_language.russianinput.translate": "Русский",
|
||||
"messages.divider": "Показывать разделитель между сообщениями",
|
||||
"messages.input.paste_long_text_as_file": "Вставлять длинный текст как файл",
|
||||
"messages.input.send_shortcuts": "Горячие клавиши для отправки",
|
||||
|
||||
@ -86,7 +86,7 @@
|
||||
"input.send": "发送",
|
||||
"input.settings": "设置",
|
||||
"input.topics": " 话题 ",
|
||||
"input.translate": "翻译成英文",
|
||||
"input.translate": "翻译成{{target_language}}",
|
||||
"input.upload": "上传图片或文档",
|
||||
"input.web_search": "开启网络搜索",
|
||||
"input.knowledge_base": "知识库",
|
||||
@ -460,6 +460,12 @@
|
||||
"display.custom.css": "自定义 CSS",
|
||||
"display.custom.css.placeholder": "/* 这里写自定义CSS */",
|
||||
"input.auto_translate_with_space": "快速敲击3次空格翻译",
|
||||
"input.target_language": "目标语言",
|
||||
"input.target_language.chinese": "简体中文",
|
||||
"input.target_language.chinese-traditional": "繁体中文",
|
||||
"input.target_language.english": "英文",
|
||||
"input.target_language.japanese": "日文",
|
||||
"input.target_language.russian": "俄文",
|
||||
"messages.divider": "消息分割线",
|
||||
"messages.input.paste_long_text_as_file": "长文本粘贴为文件",
|
||||
"messages.input.send_shortcuts": "发送快捷键",
|
||||
|
||||
@ -86,7 +86,7 @@
|
||||
"input.send": "發送",
|
||||
"input.settings": "設定",
|
||||
"input.topics": " 話題 ",
|
||||
"input.translate": "翻譯成英文",
|
||||
"input.translate": "翻譯成{{target_language}}",
|
||||
"input.upload": "上傳圖片或文檔",
|
||||
"input.web_search": "開啟網路搜索",
|
||||
"input.knowledge_base": "知識庫",
|
||||
@ -459,6 +459,12 @@
|
||||
"display.custom.css": "自定義 CSS",
|
||||
"display.custom.css.placeholder": "/* 這裡寫自定義 CSS */",
|
||||
"input.auto_translate_with_space": "快速敲擊3次空格翻譯",
|
||||
"input.target_language": "目標語言",
|
||||
"input.target_language.chinese": "簡體中文",
|
||||
"input.target_language.chinese-traditional": "繁體中文",
|
||||
"input.target_language.english": "英文",
|
||||
"input.target_language.japanese": "日文",
|
||||
"input.target_language.russian": "俄文",
|
||||
"messages.divider": "訊息間顯示分隔線",
|
||||
"messages.input.paste_long_text_as_file": "將長文本貼上為檔案",
|
||||
"messages.input.send_shortcuts": "發送快捷鍵",
|
||||
|
||||
@ -58,13 +58,13 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
|
||||
const [inputFocus, setInputFocus] = useState(false)
|
||||
const { assistant, addTopic, model, setModel, updateAssistant } = useAssistant(_assistant.id)
|
||||
const {
|
||||
targetLanguage,
|
||||
sendMessageShortcut,
|
||||
fontSize,
|
||||
pasteLongTextAsFile,
|
||||
pasteLongTextThreshold,
|
||||
showInputEstimatedTokens,
|
||||
clickAssistantToShowTopic,
|
||||
language,
|
||||
autoTranslateWithSpace,
|
||||
sidebarIcons
|
||||
} = useSettings()
|
||||
@ -152,7 +152,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
|
||||
|
||||
try {
|
||||
setIsTranslating(true)
|
||||
const translatedText = await translateText(text, 'english')
|
||||
const translatedText = await translateText(text, targetLanguage)
|
||||
translatedText && setText(translatedText)
|
||||
setTimeout(() => resizeTextArea(), 0)
|
||||
} catch (error) {
|
||||
@ -539,9 +539,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
|
||||
/>
|
||||
</ToolbarMenu>
|
||||
<ToolbarMenu>
|
||||
{!language.startsWith('en') && (
|
||||
<TranslateButton text={text} onTranslated={onTranslated} isLoading={isTranslating} />
|
||||
)}
|
||||
{generating && (
|
||||
<Tooltip placement="top" title={t('chat.input.pause')} arrow>
|
||||
<ToolbarButton type="text" onClick={onPause} style={{ marginRight: -2, marginTop: 1 }}>
|
||||
|
||||
@ -29,7 +29,7 @@ import {
|
||||
setShowInputEstimatedTokens,
|
||||
setShowMessageDivider
|
||||
} from '@renderer/store/settings'
|
||||
import { Assistant, AssistantSettings, ThemeMode } from '@renderer/types'
|
||||
import { Assistant, AssistantSettings, ThemeMode, TranslateLanguageVarious } from '@renderer/types'
|
||||
import { Col, InputNumber, Row, Select, Slider, Switch, Tooltip } from 'antd'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -59,6 +59,8 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
showInputEstimatedTokens,
|
||||
sendMessageShortcut,
|
||||
setSendMessageShortcut,
|
||||
targetLanguage,
|
||||
setTargetLanguage,
|
||||
pasteLongTextAsFile,
|
||||
renderInputMessageAsMarkdown,
|
||||
codeShowLineNumbers,
|
||||
@ -378,6 +380,25 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<SettingDivider />
|
||||
</>
|
||||
)}
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.input.target_language')}</SettingRowTitleSmall>
|
||||
<Select
|
||||
defaultValue={'english' as TranslateLanguageVarious}
|
||||
size="small"
|
||||
value={targetLanguage}
|
||||
menuItemSelectedIcon={<CheckOutlined />}
|
||||
options={[
|
||||
{ value: 'chinese', label: t('settings.input.target_language.chinese') },
|
||||
{ value: 'chinese-traditional', label: t('settings.input.target_language.chinese-traditional') },
|
||||
{ value: 'english', label: t('settings.input.target_language.english') },
|
||||
{ value: 'japanese', label: t('settings.input.target_language.japanese') },
|
||||
{ value: 'russian', label: t('settings.input.target_language.russian') }
|
||||
]}
|
||||
onChange={(value) => setTargetLanguage(value)}
|
||||
style={{ width: 135 }}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.input.send_shortcuts')}</SettingRowTitleSmall>
|
||||
<Select
|
||||
|
||||
@ -921,6 +921,10 @@ const migrateConfig = {
|
||||
enabled: false
|
||||
})
|
||||
return state
|
||||
},
|
||||
'63': (state: RootState) => {
|
||||
state.settings.targetLanguage = 'english'
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
import { TRANSLATE_PROMPT } from '@renderer/config/prompts'
|
||||
import { CodeStyleVarious, LanguageVarious, ThemeMode } from '@renderer/types'
|
||||
import { CodeStyleVarious, LanguageVarious, ThemeMode, TranslateLanguageVarious } from '@renderer/types'
|
||||
|
||||
export type SendMessageShortcut = 'Enter' | 'Shift+Enter' | 'Ctrl+Enter' | 'Command+Enter'
|
||||
|
||||
@ -21,6 +21,7 @@ export interface SettingsState {
|
||||
showTopics: boolean
|
||||
sendMessageShortcut: SendMessageShortcut
|
||||
language: LanguageVarious
|
||||
targetLanguage: TranslateLanguageVarious
|
||||
proxyMode: 'system' | 'custom' | 'none'
|
||||
proxyUrl?: string
|
||||
userName: string
|
||||
@ -73,6 +74,7 @@ const initialState: SettingsState = {
|
||||
showTopics: true,
|
||||
sendMessageShortcut: 'Enter',
|
||||
language: navigator.language as LanguageVarious,
|
||||
targetLanguage: 'english' as TranslateLanguageVarious,
|
||||
proxyMode: 'system',
|
||||
proxyUrl: undefined,
|
||||
userName: '',
|
||||
@ -139,6 +141,9 @@ const settingsSlice = createSlice({
|
||||
state.language = action.payload
|
||||
window.electron.ipcRenderer.send('miniwindow-reload')
|
||||
},
|
||||
setTargetLanguage: (state, action: PayloadAction<TranslateLanguageVarious>) => {
|
||||
state.targetLanguage = action.payload
|
||||
},
|
||||
setProxyMode: (state, action: PayloadAction<'system' | 'custom' | 'none'>) => {
|
||||
state.proxyMode = action.payload
|
||||
},
|
||||
@ -269,6 +274,7 @@ export const {
|
||||
toggleShowTopics,
|
||||
setSendMessageShortcut,
|
||||
setLanguage,
|
||||
setTargetLanguage,
|
||||
setProxyMode,
|
||||
setProxyUrl,
|
||||
setUserName,
|
||||
|
||||
@ -180,6 +180,8 @@ export enum ThemeMode {
|
||||
|
||||
export type LanguageVarious = 'zh-CN' | 'zh-TW' | 'en-US' | 'ru-RU' | 'ja-JP'
|
||||
|
||||
export type TranslateLanguageVarious = 'chinese' | 'chinese-traditional' | 'english' | 'japanese' | 'russian'
|
||||
|
||||
export type CodeStyleVarious = BuiltinTheme | 'auto'
|
||||
|
||||
export type WebDavConfig = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user