From 3d8748a61a191087abbb10ad9ac1df26b6e9e137 Mon Sep 17 00:00:00 2001 From: Chen Tao <70054568+eeee0717@users.noreply.github.com> Date: Mon, 10 Feb 2025 13:19:46 +0800 Subject: [PATCH] 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 --- .../src/components/TranslateButton.tsx | 9 ++++++-- src/renderer/src/hooks/useSettings.ts | 6 ++++- src/renderer/src/i18n/locales/en-us.json | 8 ++++++- src/renderer/src/i18n/locales/ja-jp.json | 8 ++++++- src/renderer/src/i18n/locales/ru-ru.json | 8 ++++++- src/renderer/src/i18n/locales/zh-cn.json | 8 ++++++- src/renderer/src/i18n/locales/zh-tw.json | 8 ++++++- .../src/pages/home/Inputbar/Inputbar.tsx | 8 +++---- .../src/pages/home/Tabs/SettingsTab.tsx | 23 ++++++++++++++++++- src/renderer/src/store/migrate.ts | 4 ++++ src/renderer/src/store/settings.ts | 8 ++++++- src/renderer/src/types/index.ts | 2 ++ 12 files changed, 85 insertions(+), 15 deletions(-) diff --git a/src/renderer/src/components/TranslateButton.tsx b/src/renderer/src/components/TranslateButton.tsx index c338b1b5..8f53ac15 100644 --- a/src/renderer/src/components/TranslateButton.tsx +++ b/src/renderer/src/components/TranslateButton.tsx @@ -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 = ({ 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 = ({ 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 = ({ text, onTranslated, disabled, style, isLoa }, [isLoading]) return ( - + {isTranslating ? : } diff --git a/src/renderer/src/hooks/useSettings.ts b/src/renderer/src/hooks/useSettings.ts index 55b50984..302dc90c 100644 --- a/src/renderer/src/hooks/useSettings.ts +++ b/src/renderer/src/hooks/useSettings.ts @@ -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)) }, diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 1ff77199..1693dde0 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -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", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index d9715914..44b7000f 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -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": "送信ショートカット", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 7454a4e1..e23eb0d5 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -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": "Горячие клавиши для отправки", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 9860936b..7cd86ed0 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -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": "发送快捷键", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index e9289d2d..785f30fc 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -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": "發送快捷鍵", diff --git a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx index 34f58bb7..4f89b148 100644 --- a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx +++ b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx @@ -58,13 +58,13 @@ const Inputbar: FC = ({ 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 = ({ 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 = ({ assistant: _assistant, setActiveTopic }) => { /> - {!language.startsWith('en') && ( - - )} + {generating && ( diff --git a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx index 3168bf3e..9706070f 100644 --- a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx @@ -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) => { showInputEstimatedTokens, sendMessageShortcut, setSendMessageShortcut, + targetLanguage, + setTargetLanguage, pasteLongTextAsFile, renderInputMessageAsMarkdown, codeShowLineNumbers, @@ -378,6 +380,25 @@ const SettingsTab: FC = (props) => { )} + + {t('settings.input.target_language')} + { + state.settings.targetLanguage = 'english' + return state } } diff --git a/src/renderer/src/store/settings.ts b/src/renderer/src/store/settings.ts index 979c897f..d048ea6a 100644 --- a/src/renderer/src/store/settings.ts +++ b/src/renderer/src/store/settings.ts @@ -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) => { + 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, diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts index 20ab03c8..07ca3531 100644 --- a/src/renderer/src/types/index.ts +++ b/src/renderer/src/types/index.ts @@ -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 = {