document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const sourceText = document.getElementById('sourceText');
const targetText = document.getElementById('targetText');
const sourceLanguage = document.getElementById('sourceLanguage');
const targetLanguage = document.getElementById('targetLanguage');
const translateBtn = document.getElementById('translateBtn');
const swapLanguages = document.getElementById('swapLanguages');
const detectLanguage = document.getElementById('detectLanguage');
const clearSource = document.getElementById('clearSource');
const copyTranslation = document.getElementById('copyTranslation');
const speakTranslation = document.getElementById('speakTranslation');
const sourceWordCounter = document.getElementById('sourceWordCounter');
const historyTable = document.getElementById('historyTable');
const alertContainer = document.querySelector('.alert-container');
// Word limit
const WORD_LIMIT = 250;
// Translation API endpoint (using LibreTranslate)
// Note: You may need to set up your own instance or use a different API
const TRANSLATE_API_URL = 'https://libretranslate.de/translate';
const DETECT_API_URL = 'https://libretranslate.de/detect';
// Translation history
let translationHistory = JSON.parse(localStorage.getItem('translationHistory')) || [];
// Initialize the history table
updateHistoryTable();
// Event Listeners
sourceText.addEventListener('input', updateWordCounter);
translateBtn.addEventListener('click', translateText);
swapLanguages.addEventListener('click', swapLanguagesHandler);
detectLanguage.addEventListener('click', detectLanguageHandler);
clearSource.addEventListener('click', clearSourceHandler);
copyTranslation.addEventListener('click', copyTranslationHandler);
speakTranslation.addEventListener('click', speakTranslationHandler);
// Auto-detect language if "Detect Language" is selected and text is entered
sourceText.addEventListener('blur', function() {
if (sourceLanguage.value === 'auto' && sourceText.value.trim()) {
detectLanguageHandler();
}
});
// Functions
function updateWordCounter() {
const text = sourceText.value.trim();
const wordCount = text ? text.split(/\s+/).length : 0;
sourceWordCounter.textContent = `${wordCount}/${WORD_LIMIT} words`;
if (wordCount > WORD_LIMIT) {
sourceWordCounter.classList.add('limit-reached');
showAlert('Word limit exceeded. Please reduce your text to 250 words or less.', 'danger');
} else {
sourceWordCounter.classList.remove('limit-reached');
}
}
async function translateText() {
const text = sourceText.value.trim();
const sourceLang = sourceLanguage.value;
const targetLang = targetLanguage.value;
if (!text) {
showAlert('Please enter text to translate.', 'warning');
return;
}
const wordCount = text.split(/\s+/).length;
if (wordCount > WORD_LIMIT) {
showAlert(`Please limit your text to ${WORD_LIMIT} words or less.`, 'danger');
return;
}
try {
translateBtn.disabled = true;
translateBtn.innerHTML = ' Translating...';
// If auto-detection is selected, detect the language first
let actualSourceLang = sourceLang;
if (sourceLang === 'auto') {
actualSourceLang = await detectLanguageFromAPI(text);
sourceLanguage.value = actualSourceLang;
}
// Call the translation API
const translatedText = await callTranslateAPI(text, actualSourceLang, targetLang);
targetText.value = translatedText;
// Add to history
const translationItem = {
id: Date.now(),
sourceText: text,
translatedText: translatedText,
sourceLang: sourceLang === 'auto' ? 'auto-detected' : getLanguageName(sourceLang),
targetLang: getLanguageName(targetLang),
timestamp: new Date().toLocaleString()
};
translationHistory.unshift(translationItem);
if (translationHistory.length > 5) {
translationHistory.pop();
}
localStorage.setItem('translationHistory', JSON.stringify(translationHistory));
updateHistoryTable();
showAlert('Translation successful!', 'success');
} catch (error) {
console.error('Translation error:', error);
showAlert('Translation failed. Please try again later.', 'danger');
} finally {
translateBtn.disabled = false;
translateBtn.innerHTML = ' Translate';
}
}
async function callTranslateAPI(text, sourceLang, targetLang) {
const response = await fetch(TRANSLATE_API_URL, {
method: 'POST',
body: JSON.stringify({
q: text,
source: sourceLang,
target: targetLang,
format: 'text'
}),
headers: { 'Content-Type': 'application/json' }
});
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
const data = await response.json();
return data.translatedText;
}
async function detectLanguageFromAPI(text) {
const response = await fetch(DETECT_API_URL, {
method: 'POST',
body: JSON.stringify({
q: text
}),
headers: { 'Content-Type': 'application/json' }
});
if (!response.ok) {
throw new Error(`Detection API request failed with status ${response.status}`);
}
const data = await response.json();
// Return the language code with the highest confidence
return data[0].language;
}
async function detectLanguageHandler() {
const text = sourceText.value.trim();
if (!text) {
showAlert('Please enter text to detect language.', 'warning');
return;
}
try {
detectLanguage.disabled = true;
detectLanguage.innerHTML = ' Detecting...';
const detectedLang = await detectLanguageFromAPI(text);
sourceLanguage.value = detectedLang;
showAlert(`Detected language: ${getLanguageName(detectedLang)}`, 'success');
} catch (error) {
console.error('Language detection error:', error);
showAlert('Language detection failed. Please try again later.', 'danger');
} finally {
detectLanguage.disabled = false;
detectLanguage.innerHTML = ' Detect Language';
}
}
function swapLanguagesHandler() {
const tempLang = sourceLanguage.value;
sourceLanguage.value = targetLanguage.value;
targetLanguage.value = tempLang;
const tempText = sourceText.value;
sourceText.value = targetText.value;
targetText.value = tempText;
updateWordCounter();
}
function clearSourceHandler() {
sourceText.value = '';
targetText.value = '';
updateWordCounter();
}
function copyTranslationHandler() {
if (!targetText.value.trim()) {
showAlert('No translation to copy.', 'warning');
return;
}
targetText.select();
document.execCommand('copy');
// Show feedback
const originalText = copyTranslation.innerHTML;
copyTranslation.innerHTML = ' Copied!';
setTimeout(() => {
copyTranslation.innerHTML = originalText;
}, 2000);
showAlert('Translation copied to clipboard!', 'success');
}
function speakTranslationHandler() {
if (!targetText.value.trim()) {
showAlert('No translation to speak.', 'warning');
return;
}
const utterance = new SpeechSynthesisUtterance(targetText.value);
utterance.lang = targetLanguage.value;
speechSynthesis.speak(utterance);
}
// ... (rest of the functions remain the same as in the original code)
// Keep the updateHistoryTable(), getLanguageName(), and showAlert() functions
// exactly as they were in the original code
});