Skip to content

Commit 01398d2

Browse files
committed
Function: Translation Page now will call AI Provider
1 parent e080850 commit 01398d2

File tree

10 files changed

+127
-29
lines changed

10 files changed

+127
-29
lines changed

src/components/chat/ChatMessageArea.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -527,11 +527,11 @@ export const ChatMessageArea: React.FC<ChatMessageAreaProps> = ({
527527
<div className='flex flex-row items-center h-full gap-2'>
528528
{/* File upload button */}
529529
{onSendMessageWithFiles && (
530-
<FileUploadButton
531-
onFilesSelected={handleFilesSelected}
532-
disabled={isLoading || isCurrentlyStreaming}
533-
/>
534-
)}
530+
<FileUploadButton
531+
onFilesSelected={handleFilesSelected}
532+
disabled={isLoading || isCurrentlyStreaming}
533+
/>
534+
)}
535535
</div>
536536

537537
{/* Web search element */}

src/components/layout/Sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const Sidebar: React.FC<SidebarProps> = ({
3636
<div className="w-[68px] h-full bg-main-background-color flex flex-col">
3737

3838
{/* Navigation buttons */}
39-
<div className="flex flex-col items-center flex-1 pt-2">
39+
<div className="flex flex-col items-center flex-1 gap-1 pt-2">
4040
<button
4141
className={`w-12 h-12 rounded-lg flex items-center justify-center transition-all duration-200 ${
4242
getActivePage() === 'chat'

src/components/pages/TranslationPage.tsx

Lines changed: 111 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import React, { useState, useEffect } from 'react';
22
import { SettingsService, SETTINGS_CHANGE_EVENT } from '../../services/settings-service';
33
import { Orbit, Languages, ArrowRight } from 'lucide-react';
44
import { useTranslation } from 'react-i18next';
5+
import { v4 as uuidv4 } from 'uuid';
6+
import { Message, MessageRole } from '../../types/chat';
7+
import { AIService } from '../../services/ai-service';
8+
import { StreamControlHandler } from '../../services/streaming-control';
9+
import { MessageHelper } from '../../services/message-helper';
510

611
export const TranslationPage: React.FC = () => {
712
const { t } = useTranslation();
@@ -36,18 +41,115 @@ export const TranslationPage: React.FC = () => {
3641
setError(null);
3742

3843
try {
39-
// This would be replaced with actual translation logic
40-
// using a language model API
41-
setTimeout(() => {
42-
setTranslatedText(sourceText);
43-
setIsTranslating(false);
44-
}, 1000);
44+
const settingsService = SettingsService.getInstance();
45+
const provider = settingsService.getSelectedProvider();
46+
const model = settingsService.getSelectedModel();
47+
48+
// Create conversation ID (just for streaming handler, won't be stored)
49+
const tempConversationId = uuidv4();
50+
51+
// Create messages for translation
52+
const messages = createTranslationMessages(tempConversationId, sourceText, targetLanguage);
53+
54+
// Create placeholder message for streaming
55+
const placeholderMessage = MessageHelper.getPlaceholderMessage(model, provider, tempConversationId);
56+
placeholderMessage.fatherMessageId = messages[0].messageId;
57+
58+
// Create stream controller for handling the response
59+
const streamController = new StreamControlHandler(
60+
// We create a minimal conversation object just for the StreamControlHandler
61+
{
62+
conversationId: tempConversationId,
63+
folderId: '',
64+
title: 'Translation',
65+
firstMessageId: messages[0].messageId,
66+
messages: new Map([[placeholderMessage.messageId, placeholderMessage]]),
67+
createdAt: new Date(),
68+
updatedAt: new Date(),
69+
messageInput: ''
70+
},
71+
placeholderMessage,
72+
// On chunk callback
73+
(updatedConversation) => {
74+
const updatedMessage = updatedConversation.messages.get(placeholderMessage.messageId);
75+
if (updatedMessage) {
76+
setTranslatedText(MessageHelper.MessageContentToText(updatedMessage.content));
77+
}
78+
},
79+
// On finish callback
80+
(aiResponse) => {
81+
setIsTranslating(false);
82+
if (aiResponse) {
83+
setTranslatedText(MessageHelper.MessageContentToText(aiResponse.content));
84+
}
85+
}
86+
);
87+
88+
// Send to AI service
89+
await AIService.getInstance().getChatCompletion(
90+
messages,
91+
{
92+
model,
93+
provider,
94+
stream: true
95+
},
96+
streamController
97+
);
4598
} catch (err) {
4699
setError(err as Error);
47100
setIsTranslating(false);
48101
}
49102
};
50103

104+
// Create messages for translation
105+
const createTranslationMessages = (conversationId: string, text: string, targetLang: string): Message[] => {
106+
// Create a system message with translation instructions
107+
const systemMessage: Message = {
108+
messageId: uuidv4(),
109+
conversationId,
110+
role: 'system' as MessageRole,
111+
content: MessageHelper.pureTextMessage(
112+
`You are a translation assistant. Detect the source language of the text and translate it to ${getLanguageName(targetLang)}.
113+
Only return the translated text without any explanations, notes, or decorations.
114+
Do not include any text that is not in the original input.`
115+
),
116+
timestamp: new Date(),
117+
provider: SettingsService.getInstance().getSelectedProvider(),
118+
model: SettingsService.getInstance().getSelectedModel(),
119+
tokens: 0,
120+
fatherMessageId: null,
121+
childrenMessageIds: [],
122+
preferIndex: -1
123+
};
124+
125+
// Create the user message with text to translate
126+
const userMessage: Message = {
127+
messageId: uuidv4(),
128+
conversationId,
129+
role: 'user' as MessageRole,
130+
content: MessageHelper.pureTextMessage(text),
131+
timestamp: new Date(),
132+
provider: 'user',
133+
model: 'user',
134+
tokens: 0,
135+
fatherMessageId: systemMessage.messageId,
136+
childrenMessageIds: [],
137+
preferIndex: -1
138+
};
139+
140+
// Link messages
141+
systemMessage.childrenMessageIds.push(userMessage.messageId);
142+
systemMessage.preferIndex = 0;
143+
144+
return [systemMessage, userMessage];
145+
};
146+
147+
// Get language name from code
148+
const getLanguageName = (code: string): string => {
149+
const language = languages.find(lang => lang.code === code);
150+
return language ? language.name : code;
151+
};
152+
51153
// Languages for dropdown
52154
const languages = [
53155
{ code: 'auto', name: t('translation.autoDetect') },
@@ -83,17 +185,9 @@ export const TranslationPage: React.FC = () => {
83185
{t('translation.title')}
84186
</h1>
85187

86-
<select
87-
value={sourceLanguage}
88-
onChange={(e) => setSourceLanguage(e.target.value)}
89-
className="px-4 py-2 input-box"
90-
>
91-
{languages.map((lang) => (
92-
<option key={`source-${lang.code}`} value={lang.code}>
93-
{lang.name}
94-
</option>
95-
))}
96-
</select>
188+
<span className="text-sm text-light-hint">
189+
{t('translation.sourceLanguageWithAutoSelected')}
190+
</span>
97191
</div>
98192

99193
<button

src/locales/en/translation.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
},
3535
"translation": {
3636
"title": "Translation",
37-
"sourceLanguage": "Source Language",
37+
"sourceLanguageWithAutoSelected": "Source Language will be auto detected",
3838
"result": "Translation Result",
3939
"translateButton": "Translate",
4040
"translating": "Translating...",

src/locales/es/translation.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
},
3535
"translation": {
3636
"title": "Traducción",
37-
"sourceLanguage": "Idioma de Origen",
37+
"sourceLanguageWithAutoSelected": "El idioma de origen se detectará automáticamente",
3838
"result": "Resultado de la Traducción",
3939
"translateButton": "Traducir",
4040
"translating": "Traduciendo...",

src/locales/ja/translation.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
},
3535
"translation": {
3636
"title": "翻訳",
37-
"sourceLanguage": "ソース言語",
37+
"sourceLanguageWithAutoSelected": "ソース言語は自動で検出されます",
3838
"result": "翻訳結果",
3939
"translateButton": "翻訳",
4040
"translating": "翻訳中...",

src/locales/ko/translation.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
},
3535
"translation": {
3636
"title": "번역",
37-
"sourceLanguage": "원본 언어",
37+
"sourceLanguageWithAutoSelected": "원본 언어는 자동으로 감지됩니다",
3838
"result": "번역 결과",
3939
"translateButton": "번역",
4040
"translating": "번역 중...",

src/locales/zh-CN/translation.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
},
3535
"translation": {
3636
"title": "翻译",
37-
"sourceLanguage": "源语言",
37+
"sourceLanguageWithAutoSelected": "源语言将会自动识别",
3838
"result": "翻译结果",
3939
"translateButton": "翻译",
4040
"translating": "翻译中...",

src/locales/zh-TW/translation.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
},
3535
"translation": {
3636
"title": "翻譯",
37-
"sourceLanguage": "源語言",
37+
"sourceLanguageWithAutoSelected": "源語言將會自動偵測",
3838
"result": "翻譯結果",
3939
"translateButton": "翻譯",
4040
"translating": "翻譯中...",

src/styles/tensorblock-light.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,4 +598,8 @@
598598
.image-result-area:hover {
599599
border-color: var(--primary-300);
600600
}
601+
602+
.text-light-hint{
603+
color: var(--surface-400);
604+
}
601605
}

0 commit comments

Comments
 (0)