first commit
This commit is contained in:
255
static/js/main.js
Normal file
255
static/js/main.js
Normal file
@@ -0,0 +1,255 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// DOM elements
|
||||
const sourceLanguage = document.getElementById('sourceLanguage');
|
||||
const targetLanguage = document.getElementById('targetLanguage');
|
||||
const swapButton = document.getElementById('swapLanguages');
|
||||
const sourceText = document.getElementById('sourceText');
|
||||
const translatedText = document.getElementById('translatedText');
|
||||
const recordSourceButton = document.getElementById('recordSource');
|
||||
const speakButton = document.getElementById('speak');
|
||||
const clearSourceButton = document.getElementById('clearSource');
|
||||
const copyTranslationButton = document.getElementById('copyTranslation');
|
||||
const translateButton = document.getElementById('translateButton');
|
||||
const statusMessage = document.getElementById('status');
|
||||
|
||||
// Audio recording variables
|
||||
let mediaRecorder;
|
||||
let audioChunks = [];
|
||||
let isRecording = false;
|
||||
|
||||
// Speech recognition setup
|
||||
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||||
const recognition = SpeechRecognition ? new SpeechRecognition() : null;
|
||||
|
||||
if (recognition) {
|
||||
recognition.continuous = false;
|
||||
recognition.interimResults = false;
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
swapButton.addEventListener('click', swapLanguages);
|
||||
translateButton.addEventListener('click', translateText);
|
||||
clearSourceButton.addEventListener('click', clearSource);
|
||||
copyTranslationButton.addEventListener('click', copyTranslation);
|
||||
|
||||
if (recognition) {
|
||||
recordSourceButton.addEventListener('click', toggleRecording);
|
||||
} else {
|
||||
recordSourceButton.textContent = "Speech API not supported";
|
||||
recordSourceButton.disabled = true;
|
||||
}
|
||||
|
||||
speakButton.addEventListener('click', speakTranslation);
|
||||
|
||||
// Functions (continued)
|
||||
function swapLanguages() {
|
||||
const tempLang = sourceLanguage.value;
|
||||
sourceLanguage.value = targetLanguage.value;
|
||||
targetLanguage.value = tempLang;
|
||||
|
||||
// Also swap the text if both fields have content
|
||||
if (sourceText.value && translatedText.value) {
|
||||
const tempText = sourceText.value;
|
||||
sourceText.value = translatedText.value;
|
||||
translatedText.value = tempText;
|
||||
}
|
||||
}
|
||||
|
||||
function clearSource() {
|
||||
sourceText.value = '';
|
||||
updateStatus('');
|
||||
}
|
||||
|
||||
function copyTranslation() {
|
||||
if (!translatedText.value) {
|
||||
updateStatus('Nothing to copy', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(translatedText.value)
|
||||
.then(() => {
|
||||
updateStatus('Copied to clipboard!', 'success');
|
||||
setTimeout(() => updateStatus(''), 2000);
|
||||
})
|
||||
.catch(err => {
|
||||
updateStatus('Failed to copy: ' + err, 'error');
|
||||
});
|
||||
}
|
||||
|
||||
async function translateText() {
|
||||
const source = sourceText.value.trim();
|
||||
if (!source) {
|
||||
updateStatus('Please enter or speak some text to translate', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
updateStatus('Translating...');
|
||||
translatedText.value = '';
|
||||
|
||||
try {
|
||||
const response = await fetch('/translate', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
sourceLanguage: sourceLanguage.value,
|
||||
targetLanguage: targetLanguage.value,
|
||||
text: source
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
translatedText.value = data.translation;
|
||||
updateStatus('Translation complete', 'success');
|
||||
setTimeout(() => updateStatus(''), 2000);
|
||||
} else {
|
||||
updateStatus(data.error || 'Translation failed', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
updateStatus('Network error: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleRecording() {
|
||||
if (!recognition) {
|
||||
updateStatus('Speech recognition not supported in this browser', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRecording) {
|
||||
stopRecording();
|
||||
} else {
|
||||
startRecording();
|
||||
}
|
||||
}
|
||||
|
||||
function startRecording() {
|
||||
sourceText.value = '';
|
||||
updateStatus('Listening...');
|
||||
|
||||
recognition.lang = getLanguageCode(sourceLanguage.value);
|
||||
recognition.onresult = function(event) {
|
||||
const transcript = event.results[0][0].transcript;
|
||||
sourceText.value = transcript;
|
||||
updateStatus('Recording completed', 'success');
|
||||
setTimeout(() => updateStatus(''), 2000);
|
||||
};
|
||||
|
||||
recognition.onerror = function(event) {
|
||||
updateStatus('Error in speech recognition: ' + event.error, 'error');
|
||||
stopRecording();
|
||||
};
|
||||
|
||||
recognition.onend = function() {
|
||||
stopRecording();
|
||||
};
|
||||
|
||||
try {
|
||||
recognition.start();
|
||||
isRecording = true;
|
||||
recordSourceButton.classList.add('recording');
|
||||
recordSourceButton.querySelector('.button-text').textContent = 'Stop';
|
||||
} catch (error) {
|
||||
updateStatus('Failed to start recording: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function stopRecording() {
|
||||
if (isRecording) {
|
||||
try {
|
||||
recognition.stop();
|
||||
} catch (error) {
|
||||
console.error('Error stopping recognition:', error);
|
||||
}
|
||||
|
||||
isRecording = false;
|
||||
recordSourceButton.classList.remove('recording');
|
||||
recordSourceButton.querySelector('.button-text').textContent = 'Record';
|
||||
}
|
||||
}
|
||||
|
||||
function speakTranslation() {
|
||||
const text = translatedText.value.trim();
|
||||
if (!text) {
|
||||
updateStatus('No translation to speak', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the browser's speech synthesis API
|
||||
const speech = new SpeechSynthesisUtterance(text);
|
||||
speech.lang = getLanguageCode(targetLanguage.value);
|
||||
speech.volume = 1;
|
||||
speech.rate = 1;
|
||||
speech.pitch = 1;
|
||||
|
||||
speech.onstart = function() {
|
||||
updateStatus('Speaking...');
|
||||
speakButton.disabled = true;
|
||||
};
|
||||
|
||||
speech.onend = function() {
|
||||
updateStatus('');
|
||||
speakButton.disabled = false;
|
||||
};
|
||||
|
||||
speech.onerror = function(event) {
|
||||
updateStatus('Speech synthesis error: ' + event.error, 'error');
|
||||
speakButton.disabled = false;
|
||||
};
|
||||
|
||||
window.speechSynthesis.speak(speech);
|
||||
}
|
||||
|
||||
function getLanguageCode(language) {
|
||||
// Map language names to BCP 47 language tags for speech recognition/synthesis
|
||||
const languageMap = {
|
||||
"arabic": "ar-SA",
|
||||
"armenian": "hy-AM",
|
||||
"azerbaijani": "az-AZ",
|
||||
"english": "en-US",
|
||||
"french": "fr-FR",
|
||||
"georgian": "ka-GE",
|
||||
"kazakh": "kk-KZ",
|
||||
"mandarin": "zh-CN",
|
||||
"persian": "fa-IR",
|
||||
"portuguese": "pt-PT",
|
||||
"russian": "ru-RU",
|
||||
"turkish": "tr-TR",
|
||||
"uzbek": "uz-UZ"
|
||||
};
|
||||
|
||||
return languageMap[language] || 'en-US';
|
||||
}
|
||||
|
||||
function updateStatus(message, type = '') {
|
||||
statusMessage.textContent = message;
|
||||
statusMessage.className = 'status-message';
|
||||
|
||||
if (type) {
|
||||
statusMessage.classList.add(type);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for microphone and speech support when page loads
|
||||
function checkSupportedFeatures() {
|
||||
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
||||
updateStatus('Microphone access is not supported in this browser', 'error');
|
||||
recordSourceButton.disabled = true;
|
||||
}
|
||||
|
||||
if (!window.SpeechRecognition && !window.webkitSpeechRecognition) {
|
||||
updateStatus('Speech recognition is not supported in this browser', 'error');
|
||||
recordSourceButton.disabled = true;
|
||||
}
|
||||
|
||||
if (!window.speechSynthesis) {
|
||||
updateStatus('Speech synthesis is not supported in this browser', 'error');
|
||||
speakButton.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
checkSupportedFeatures();
|
||||
});
|
Reference in New Issue
Block a user