Spaces:
Sleeping
Sleeping
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>BanglaFeel Translator</title> | |
<link rel="stylesheet" href="/static/style.css" /> | |
<link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500&family=Roboto:wght@400;500&display=swap" rel="stylesheet"> | |
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> | |
</head> | |
<body> | |
<div class="page-container"> | |
<header> | |
<h1>BanglaFeel Translator</h1> | |
<p class="subtitle">Translate Romanized Bangla to Bengali with ease</p> | |
</header> | |
<div class="translation-box"> | |
<div class="input-section"> | |
<div class="input-header"> | |
<label> | |
<span class="material-icons">language</span> | |
English | |
</label> | |
</div> | |
<textarea id="userInput" placeholder="Type or paste your text here..." maxlength="500"></textarea> | |
</div> | |
<div class="controls"> | |
<div class="left-controls"> | |
<button id="clearBtn" class="icon-btn" title="Clear text"> | |
<span class="material-icons">clear</span> | |
</button> | |
</div> | |
<div class="right-controls"> | |
<span class="char-count">0/500</span> | |
<button id="translateBtn" class="primary-btn"> | |
<span class="material-icons">translate</span> | |
Translate | |
</button> | |
</div> | |
</div> | |
<div class="output-section"> | |
<div class="output-header"> | |
<label> | |
<span class="material-icons">translate</span> | |
Bengali | |
</label> | |
<button id="copyBtn" class="icon-btn" title="Copy translation"> | |
<span class="material-icons">content_copy</span> | |
</button> | |
</div> | |
<div class="translation-result"> | |
<p id="translationResult"></p> | |
<div class="loading-spinner" style="display: none;"> | |
<div class="spinner"></div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
const userInput = document.getElementById('userInput'); | |
const charCount = document.querySelector('.char-count'); | |
const translateBtn = document.getElementById('translateBtn'); | |
const clearBtn = document.getElementById('clearBtn'); | |
const copyBtn = document.getElementById('copyBtn'); | |
const translationResult = document.getElementById('translationResult'); | |
const loadingSpinner = document.querySelector('.loading-spinner'); | |
// Character counter | |
userInput.addEventListener('input', function() { | |
charCount.textContent = `${this.value.length}/500`; | |
}); | |
// Clear button | |
clearBtn.addEventListener('click', function() { | |
userInput.value = ''; | |
translationResult.textContent = ''; | |
charCount.textContent = '0/500'; | |
}); | |
// Copy button | |
copyBtn.addEventListener('click', function() { | |
if (translationResult.textContent) { | |
navigator.clipboard.writeText(translationResult.textContent) | |
.then(() => { | |
copyBtn.innerHTML = '<span class="material-icons">check</span>'; | |
setTimeout(() => { | |
copyBtn.innerHTML = '<span class="material-icons">content_copy</span>'; | |
}, 2000); | |
}); | |
} | |
}); | |
// Translation | |
translateBtn.addEventListener('click', async function() { | |
const text = userInput.value.trim(); | |
if (!text) { | |
showToast('Please enter some text first.'); | |
return; | |
} | |
// Show loading state | |
loadingSpinner.style.display = 'flex'; | |
translateBtn.disabled = true; | |
translationResult.style.opacity = '0.5'; | |
try { | |
const response = await fetch('/translate', { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ text: text }) | |
}); | |
if (!response.ok) throw new Error(`Server error: ${response.status}`); | |
const data = await response.json(); | |
translationResult.textContent = data.translation; | |
translationResult.style.opacity = '1'; | |
} catch (error) { | |
console.error('Error:', error); | |
translationResult.textContent = 'An error occurred during translation.'; | |
showToast('Translation failed. Please try again.'); | |
} finally { | |
loadingSpinner.style.display = 'none'; | |
translateBtn.disabled = false; | |
} | |
}); | |
function showToast(message) { | |
const toast = document.createElement('div'); | |
toast.className = 'toast'; | |
toast.textContent = message; | |
document.body.appendChild(toast); | |
setTimeout(() => toast.remove(), 3000); | |
} | |
}); | |
</script> | |
</body> | |
</html> | |