amine_dubs
commited on
Commit
·
54fb2f1
1
Parent(s):
443ca56
- backend/main.py +7 -17
- static/script.js +170 -187
backend/main.py
CHANGED
@@ -182,34 +182,24 @@ def translate_text(text, source_lang, target_lang):
|
|
182 |
return use_fallback_translation(text, source_lang, target_lang)
|
183 |
|
184 |
try:
|
185 |
-
# Get full language name for better
|
186 |
source_lang_name = LANGUAGE_MAP.get(source_lang, source_lang)
|
187 |
|
188 |
-
#
|
189 |
-
|
190 |
-
|
191 |
-
Focus on conveying the meaning elegantly using proper Balagha (Arabic eloquence).
|
192 |
-
Adapt any cultural references or idioms appropriately rather than translating literally.
|
193 |
-
Ensure the translation reads naturally to a native Arabic speaker.
|
194 |
-
|
195 |
-
Text to translate:
|
196 |
-
{text}"""
|
197 |
-
print("Using culturally-aware prompt for Arabic translation with Balagha focus")
|
198 |
-
else:
|
199 |
-
# For non-Arabic target languages, use standard approach
|
200 |
-
prompt = text
|
201 |
|
202 |
# Use a more reliable timeout approach with concurrent.futures
|
203 |
with concurrent.futures.ThreadPoolExecutor() as executor:
|
204 |
future = executor.submit(
|
205 |
lambda: translator(
|
206 |
-
|
207 |
-
max_length=768
|
208 |
)[0]["translation_text"]
|
209 |
)
|
210 |
|
211 |
try:
|
212 |
-
# Set a reasonable timeout
|
213 |
result = future.result(timeout=10)
|
214 |
|
215 |
# Post-process the result for Arabic cultural adaptation
|
|
|
182 |
return use_fallback_translation(text, source_lang, target_lang)
|
183 |
|
184 |
try:
|
185 |
+
# Get full language name for better cultural adaptation
|
186 |
source_lang_name = LANGUAGE_MAP.get(source_lang, source_lang)
|
187 |
|
188 |
+
# The Helsinki model doesn't need or work with the elaborate prompt
|
189 |
+
# Just send the text directly for translation
|
190 |
+
text_to_translate = text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
|
192 |
# Use a more reliable timeout approach with concurrent.futures
|
193 |
with concurrent.futures.ThreadPoolExecutor() as executor:
|
194 |
future = executor.submit(
|
195 |
lambda: translator(
|
196 |
+
text_to_translate,
|
197 |
+
max_length=768
|
198 |
)[0]["translation_text"]
|
199 |
)
|
200 |
|
201 |
try:
|
202 |
+
# Set a reasonable timeout
|
203 |
result = future.result(timeout=10)
|
204 |
|
205 |
# Post-process the result for Arabic cultural adaptation
|
static/script.js
CHANGED
@@ -1,217 +1,200 @@
|
|
1 |
// Wait for the DOM to be fully loaded before attaching event handlers
|
2 |
-
|
3 |
-
console.log('
|
4 |
|
5 |
-
// Get form elements
|
6 |
-
const textTranslationForm = document.
|
7 |
-
const docTranslationForm = document.
|
8 |
|
9 |
// Set up text translation form
|
10 |
if (textTranslationForm) {
|
11 |
console.log('Text translation form found');
|
12 |
-
textTranslationForm.onsubmit = handleTextTranslation;
|
13 |
-
} else {
|
14 |
-
console.error('Text translation form not found!');
|
15 |
-
}
|
16 |
-
|
17 |
-
// Set up document translation form
|
18 |
-
if (docTranslationForm) {
|
19 |
-
console.log('Document translation form found');
|
20 |
-
docTranslationForm.onsubmit = handleDocTranslation;
|
21 |
-
} else {
|
22 |
-
console.error('Document translation form not found!');
|
23 |
-
}
|
24 |
-
|
25 |
-
// Function to handle text translation
|
26 |
-
function handleTextTranslation(event) {
|
27 |
-
event.preventDefault();
|
28 |
-
console.log('Text translation form submitted');
|
29 |
-
|
30 |
-
// Clear previous results and errors
|
31 |
-
hideElement('text-result');
|
32 |
-
hideElement('error-message');
|
33 |
-
hideElement('debug-info');
|
34 |
-
|
35 |
-
// Get form elements
|
36 |
-
const textInputElement = document.getElementById('text-input');
|
37 |
-
const sourceLangElement = document.getElementById('source-lang-text');
|
38 |
-
const targetLangElement = document.getElementById('target-lang-text');
|
39 |
-
const loadingElement = document.getElementById('text-loading');
|
40 |
-
const debugElement = document.getElementById('debug-info');
|
41 |
-
|
42 |
-
// Debug which elements were found
|
43 |
-
let debug = 'Found elements: ';
|
44 |
-
debug += textInputElement ? 'text-input ✓ ' : 'text-input ✗ ';
|
45 |
-
debug += sourceLangElement ? 'source-lang-text ✓ ' : 'source-lang-text ✗ ';
|
46 |
-
debug += targetLangElement ? 'target-lang-text ✓ ' : 'target-lang-text ✗ ';
|
47 |
-
console.log(debug);
|
48 |
-
|
49 |
-
// Show debug info
|
50 |
-
if (debugElement) {
|
51 |
-
debugElement.textContent = debug;
|
52 |
-
debugElement.style.display = 'block';
|
53 |
-
}
|
54 |
-
|
55 |
-
// Check for missing elements
|
56 |
-
if (!textInputElement || !sourceLangElement || !targetLangElement) {
|
57 |
-
showError('One or more form elements are missing');
|
58 |
-
return;
|
59 |
-
}
|
60 |
-
|
61 |
-
// Get text input
|
62 |
-
const textInput = textInputElement.value ? textInputElement.value.trim() : '';
|
63 |
-
if (!textInput) {
|
64 |
-
showError('Please enter text to translate');
|
65 |
-
return;
|
66 |
-
}
|
67 |
-
|
68 |
-
// Get language selections
|
69 |
-
const sourceLang = sourceLangElement.value;
|
70 |
-
const targetLang = targetLangElement.value;
|
71 |
-
|
72 |
-
// Show loading indicator
|
73 |
-
if (loadingElement) {
|
74 |
-
loadingElement.style.display = 'block';
|
75 |
-
}
|
76 |
-
|
77 |
-
// Create request payload
|
78 |
-
const payload = {
|
79 |
-
text: textInput,
|
80 |
-
source_lang: sourceLang,
|
81 |
-
target_lang: targetLang
|
82 |
-
};
|
83 |
|
84 |
-
//
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
if (debugElement) {
|
101 |
-
debugElement.textContent
|
|
|
|
|
|
|
|
|
102 |
}
|
103 |
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
throw new Error('Invalid JSON response from server');
|
109 |
}
|
110 |
|
111 |
-
|
112 |
-
|
|
|
|
|
|
|
113 |
}
|
114 |
|
115 |
-
//
|
116 |
-
const
|
117 |
-
const
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
});
|
|
|
|
|
133 |
}
|
134 |
|
135 |
-
//
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
hideElement('doc-result');
|
142 |
-
hideElement('error-message');
|
143 |
-
|
144 |
-
// Get form elements
|
145 |
-
const fileInput = document.getElementById('doc-input');
|
146 |
-
const loadingIndicator = document.getElementById('doc-loading');
|
147 |
-
|
148 |
-
if (!fileInput || !fileInput.files || fileInput.files.length === 0) {
|
149 |
-
showError('Please select a document to upload');
|
150 |
-
return;
|
151 |
-
}
|
152 |
-
|
153 |
-
// Show loading indicator
|
154 |
-
if (loadingIndicator) {
|
155 |
-
loadingIndicator.style.display = 'block';
|
156 |
-
}
|
157 |
-
|
158 |
-
// Create form data
|
159 |
-
const formData = new FormData(docTranslationForm);
|
160 |
-
|
161 |
-
// Make API request
|
162 |
-
fetch('/translate/document', {
|
163 |
-
method: 'POST',
|
164 |
-
body: formData
|
165 |
-
})
|
166 |
-
.then(function(response) {
|
167 |
-
if (!response.ok) {
|
168 |
-
throw new Error(`Server returned ${response.status}`);
|
169 |
-
}
|
170 |
-
return response.json();
|
171 |
-
})
|
172 |
-
.then(function(data) {
|
173 |
-
if (!data.translated_text) {
|
174 |
-
throw new Error('No translation returned');
|
175 |
-
}
|
176 |
|
177 |
-
//
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
})
|
190 |
-
.catch(function(error) {
|
191 |
-
showError(error.message);
|
192 |
-
})
|
193 |
-
.finally(function() {
|
194 |
-
if (loadingIndicator) {
|
195 |
-
loadingIndicator.style.display = 'none';
|
196 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
});
|
|
|
|
|
198 |
}
|
199 |
|
200 |
// Helper function to show errors
|
201 |
function showError(message) {
|
202 |
-
const errorDiv = document.
|
203 |
if (errorDiv) {
|
204 |
errorDiv.textContent = 'Error: ' + message;
|
205 |
errorDiv.style.display = 'block';
|
206 |
}
|
207 |
console.error('Error:', message);
|
208 |
}
|
209 |
-
|
210 |
-
// Helper function to hide elements
|
211 |
-
function hideElement(id) {
|
212 |
-
const element = document.getElementById(id);
|
213 |
-
if (element) {
|
214 |
-
element.style.display = 'none';
|
215 |
-
}
|
216 |
-
}
|
217 |
-
});
|
|
|
1 |
// Wait for the DOM to be fully loaded before attaching event handlers
|
2 |
+
window.onload = function() {
|
3 |
+
console.log('Window fully loaded, initializing translation app');
|
4 |
|
5 |
+
// Get form elements using direct form access instead of getElementById
|
6 |
+
const textTranslationForm = document.querySelector('#text-translation-form');
|
7 |
+
const docTranslationForm = document.querySelector('#doc-translation-form');
|
8 |
|
9 |
// Set up text translation form
|
10 |
if (textTranslationForm) {
|
11 |
console.log('Text translation form found');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
+
// Use standard form submit event
|
14 |
+
textTranslationForm.addEventListener('submit', function(event) {
|
15 |
+
event.preventDefault();
|
16 |
+
console.log('Text translation form submitted');
|
17 |
+
|
18 |
+
// Clear previous results and errors
|
19 |
+
document.querySelectorAll('#text-result, #error-message, #debug-info').forEach(el => {
|
20 |
+
if (el) el.style.display = 'none';
|
21 |
+
});
|
22 |
+
|
23 |
+
// Get form elements directly from the form itself
|
24 |
+
const textInput = textTranslationForm.querySelector('#text-input');
|
25 |
+
const sourceLang = textTranslationForm.querySelector('#source-lang-text');
|
26 |
+
const targetLang = textTranslationForm.querySelector('#target-lang-text');
|
27 |
+
const loadingElement = document.querySelector('#text-loading');
|
28 |
+
const debugElement = document.querySelector('#debug-info');
|
29 |
+
|
30 |
+
// Log which elements were found
|
31 |
+
console.log('Elements found:', {
|
32 |
+
textInput: !!textInput,
|
33 |
+
sourceLang: !!sourceLang,
|
34 |
+
targetLang: !!targetLang
|
35 |
+
});
|
36 |
+
|
37 |
+
// Show debug info
|
38 |
if (debugElement) {
|
39 |
+
debugElement.textContent = `Form elements found:
|
40 |
+
text-input: ${!!textInput}
|
41 |
+
source-lang-text: ${!!sourceLang}
|
42 |
+
target-lang-text: ${!!targetLang}`;
|
43 |
+
debugElement.style.display = 'block';
|
44 |
}
|
45 |
|
46 |
+
// Check for missing elements
|
47 |
+
if (!textInput || !sourceLang || !targetLang) {
|
48 |
+
showError('Form elements not found. Please check the HTML structure.');
|
49 |
+
return;
|
|
|
50 |
}
|
51 |
|
52 |
+
// Get values
|
53 |
+
const text = textInput.value ? textInput.value.trim() : '';
|
54 |
+
if (!text) {
|
55 |
+
showError('Please enter text to translate');
|
56 |
+
return;
|
57 |
}
|
58 |
|
59 |
+
// Get language selections
|
60 |
+
const sourceLangValue = sourceLang.value;
|
61 |
+
const targetLangValue = targetLang.value;
|
62 |
+
|
63 |
+
// Show loading indicator
|
64 |
+
if (loadingElement) loadingElement.style.display = 'block';
|
65 |
+
|
66 |
+
// Create payload
|
67 |
+
const payload = {
|
68 |
+
text: text,
|
69 |
+
source_lang: sourceLangValue,
|
70 |
+
target_lang: targetLangValue
|
71 |
+
};
|
72 |
+
|
73 |
+
console.log('Sending payload:', payload);
|
74 |
+
|
75 |
+
// Send API request
|
76 |
+
fetch('/translate/text', {
|
77 |
+
method: 'POST',
|
78 |
+
headers: { 'Content-Type': 'application/json' },
|
79 |
+
body: JSON.stringify(payload)
|
80 |
+
})
|
81 |
+
.then(function(response) {
|
82 |
+
if (!response.ok) throw new Error('Server error: ' + response.status);
|
83 |
+
return response.text();
|
84 |
+
})
|
85 |
+
.then(function(responseText) {
|
86 |
+
console.log('Response received:', responseText);
|
87 |
+
|
88 |
+
// Try to parse JSON
|
89 |
+
let data;
|
90 |
+
try {
|
91 |
+
data = JSON.parse(responseText);
|
92 |
+
} catch (error) {
|
93 |
+
throw new Error('Invalid response from server');
|
94 |
+
}
|
95 |
+
|
96 |
+
// Check for translation
|
97 |
+
if (!data.translated_text) {
|
98 |
+
throw new Error('No translation returned');
|
99 |
+
}
|
100 |
+
|
101 |
+
// Show result
|
102 |
+
const resultBox = document.querySelector('#text-result');
|
103 |
+
const outputElement = document.querySelector('#text-output');
|
104 |
+
|
105 |
+
if (resultBox && outputElement) {
|
106 |
+
outputElement.textContent = data.translated_text;
|
107 |
+
resultBox.style.display = 'block';
|
108 |
+
}
|
109 |
+
})
|
110 |
+
.catch(function(error) {
|
111 |
+
showError(error.message || 'Translation failed');
|
112 |
+
console.error('Error:', error);
|
113 |
+
})
|
114 |
+
.finally(function() {
|
115 |
+
if (loadingElement) loadingElement.style.display = 'none';
|
116 |
+
});
|
117 |
});
|
118 |
+
} else {
|
119 |
+
console.error('Text translation form not found in the document!');
|
120 |
}
|
121 |
|
122 |
+
// Document translation handler
|
123 |
+
if (docTranslationForm) {
|
124 |
+
console.log('Document translation form found');
|
125 |
+
docTranslationForm.addEventListener('submit', function(event) {
|
126 |
+
event.preventDefault();
|
127 |
+
console.log('Document translation form submitted');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
+
// Clear previous results and errors
|
130 |
+
document.querySelectorAll('#doc-result, #error-message').forEach(el => {
|
131 |
+
if (el) el.style.display = 'none';
|
132 |
+
});
|
133 |
+
|
134 |
+
// Get form elements
|
135 |
+
const fileInput = docTranslationForm.querySelector('#doc-input');
|
136 |
+
const loadingIndicator = document.querySelector('#doc-loading');
|
137 |
+
|
138 |
+
if (!fileInput || !fileInput.files || fileInput.files.length === 0) {
|
139 |
+
showError('Please select a document to upload');
|
140 |
+
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
}
|
142 |
+
|
143 |
+
// Show loading indicator
|
144 |
+
if (loadingIndicator) loadingIndicator.style.display = 'block';
|
145 |
+
|
146 |
+
// Create form data
|
147 |
+
const formData = new FormData(docTranslationForm);
|
148 |
+
|
149 |
+
// Make API request
|
150 |
+
fetch('/translate/document', {
|
151 |
+
method: 'POST',
|
152 |
+
body: formData
|
153 |
+
})
|
154 |
+
.then(function(response) {
|
155 |
+
if (!response.ok) {
|
156 |
+
throw new Error(`Server returned ${response.status}`);
|
157 |
+
}
|
158 |
+
return response.json();
|
159 |
+
})
|
160 |
+
.then(function(data) {
|
161 |
+
if (!data.translated_text) {
|
162 |
+
throw new Error('No translation returned');
|
163 |
+
}
|
164 |
+
|
165 |
+
// Display result
|
166 |
+
const resultBox = document.querySelector('#doc-result');
|
167 |
+
const outputEl = document.querySelector('#doc-output');
|
168 |
+
const filenameEl = document.querySelector('#doc-filename');
|
169 |
+
const sourceLangEl = document.querySelector('#doc-source-lang');
|
170 |
+
|
171 |
+
if (resultBox && outputEl) {
|
172 |
+
if (filenameEl) filenameEl.textContent = data.original_filename || 'N/A';
|
173 |
+
if (sourceLangEl) sourceLangEl.textContent = data.detected_source_lang || 'N/A';
|
174 |
+
outputEl.textContent = data.translated_text;
|
175 |
+
resultBox.style.display = 'block';
|
176 |
+
}
|
177 |
+
})
|
178 |
+
.catch(function(error) {
|
179 |
+
showError(error.message);
|
180 |
+
})
|
181 |
+
.finally(function() {
|
182 |
+
if (loadingIndicator) {
|
183 |
+
loadingIndicator.style.display = 'none';
|
184 |
+
}
|
185 |
+
});
|
186 |
});
|
187 |
+
} else {
|
188 |
+
console.error('Document translation form not found in the document!');
|
189 |
}
|
190 |
|
191 |
// Helper function to show errors
|
192 |
function showError(message) {
|
193 |
+
const errorDiv = document.querySelector('#error-message');
|
194 |
if (errorDiv) {
|
195 |
errorDiv.textContent = 'Error: ' + message;
|
196 |
errorDiv.style.display = 'block';
|
197 |
}
|
198 |
console.error('Error:', message);
|
199 |
}
|
200 |
+
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|