Spaces:
Sleeping
Sleeping
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Jawi Translator</title> | |
<link rel="stylesheet" href="styles.css"> | |
</head> | |
<body> | |
<header> | |
<div class="logo">Jawi Translator</div> | |
<!-- <nav> | |
<a href="#home">Home</a> | |
<a href="#about">About</a> | |
<a href="#contact">Contact Us</a> | |
</nav> --> | |
</header> | |
<main> | |
<section class="greeting"> | |
<h1>Salam!</h1> | |
<p>Kami akan membantu anda untuk terjemahkan diantara perkataan <span class="highlight">Jawi</span> dan <span class="highlight">Rumi</span>. Masukkan perkataan anda dan kami akan uruskan!</p> | |
</section> | |
<section class="translator"> | |
<div class="input-box"> | |
<textarea id="rumi-text" placeholder="Masukkan perkataan Rumi..."></textarea> | |
<div class="buttons"> | |
<button class="btn clear">Clear</button> | |
<button class="btn translate">Translate</button> | |
</div> | |
</div> | |
<div class="output-box"> | |
<textarea id="jawi-text" placeholder="Terjemahan Jawi akan diberikan di sini..." readonly></textarea> | |
<div class="buttons"> | |
<button class="btn copy">Copy</button> | |
</div> | |
</div> | |
</section> | |
</main> | |
<footer> | |
<p> | |
Aplikasi Terjemahan Jawi Dalam Talian ini dibangunkan untuk | |
membantu memartabatkan semula tulisan Jawi yang telah digunakan sejak sekian lama. | |
</p> | |
<p style="margin-top: 25px; color: #838383;">Copyright © Jawi Translator 2024</p> | |
</footer> | |
</body> | |
<!-- <script src="script.js"></script> --> | |
</html> | |
<script> | |
async function translateText(rumiText) { | |
try { | |
const response = await fetch('https://huggingface.co/spaces/GobLyne/Jawi-Translation/translate', { // Replace with your FastAPI server URL | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
body: JSON.stringify({ text: rumiText }), | |
}); | |
if (!response.ok) { | |
throw new Error('Failed to fetch translation'); | |
} | |
const data = await response.json(); | |
return data.translated_text; // Assuming the FastAPI response includes "translated_text" | |
} catch (error) { | |
console.error('Error:', error); | |
return 'Error: Unable to fetch translation'; | |
} | |
} | |
// DOM Elements | |
const rumiTextArea = document.getElementById("rumi-text"); | |
const jawiTextArea = document.getElementById("jawi-text"); | |
const clearButton = document.querySelector(".btn.clear"); | |
const translateButton = document.querySelector(".btn.translate"); | |
const copyButton = document.querySelector(".btn.copy"); | |
// Character limit counter | |
const charLimit = 120; | |
const charCounter = document.createElement("div"); | |
charCounter.style.marginTop = "10px"; | |
charCounter.style.color = "#838383"; | |
charCounter.textContent = `Characters: 0/${charLimit}`; | |
rumiTextArea.parentElement.appendChild(charCounter); | |
// Event Listeners | |
rumiTextArea.addEventListener("input", () => { | |
const inputText = rumiTextArea.value; | |
const charCount = inputText.length; | |
if (charCount > charLimit) { | |
rumiTextArea.value = inputText.slice(0, charLimit); | |
} | |
charCounter.textContent = `Characters: ${Math.min(charCount, charLimit)}/${charLimit}`; | |
}); | |
clearButton.addEventListener("click", () => { | |
rumiTextArea.value = ""; | |
jawiTextArea.value = ""; | |
charCounter.textContent = `Characters: 0/${charLimit}`; | |
}); | |
translateButton.addEventListener("click", async () => { | |
const rumiText = rumiTextArea.value.trim(); | |
if (!rumiText) { | |
alert("Sila masukkan teks Rumi untuk diterjemahkan."); | |
return; | |
} | |
jawiTextArea.value = "Translating..."; | |
try { | |
const translatedText = await translateText(rumiText); | |
jawiTextArea.value = translatedText; | |
} catch (error) { | |
jawiTextArea.value = "Error: Unable to translate the text. Please try again later."; | |
console.error("Translation error:", error); | |
} | |
}); | |
copyButton.addEventListener("click", () => { | |
if (jawiTextArea.value) { | |
jawiTextArea.select(); | |
document.execCommand("copy"); | |
// Display text pop-up inside the website | |
const popup = document.createElement("div"); | |
popup.textContent = "Teks telah disalin!"; | |
popup.style.position = "fixed"; | |
popup.style.bottom = "20px"; | |
popup.style.right = "20px"; | |
popup.style.backgroundColor = "#4CAF50"; | |
popup.style.color = "white"; | |
popup.style.padding = "10px"; | |
popup.style.borderRadius = "5px"; | |
popup.style.boxShadow = "0px 4px 6px rgba(0, 0, 0, 0.1)"; | |
popup.style.zIndex = "1000"; | |
document.body.appendChild(popup); | |
setTimeout(() => { | |
document.body.removeChild(popup); | |
}, 2000); | |
} else { | |
alert("Tiada teks untuk disalin."); | |
} | |
}); | |
</script> | |
<style> | |
/* General Reset */ | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
body { | |
height: 100%; | |
font-family: Arial, sans-serif; | |
line-height: 1.6; | |
background-color: #f8fcf9; | |
color: #333; | |
} | |
header { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
padding: 10px 20px; | |
background-color: #edf7f1; | |
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); | |
} | |
header .logo { | |
font-size: 1.5rem; | |
font-weight: bold; | |
font-family: 'Georgia', serif; | |
} | |
nav a { | |
margin: 0 10px; | |
text-decoration: none; | |
color: #838383; | |
font-weight: bold; | |
} | |
nav a:hover { | |
color: #007a5e; | |
} | |
main { | |
padding: 20px; | |
text-align: center; | |
} | |
.greeting h1 { | |
font-size: 2rem; | |
margin-left: 10px; | |
margin-right: 10px; | |
margin-bottom: 10px; | |
text-align: left; | |
} | |
.greeting p { | |
font-size: 1.2rem; | |
margin-left: 11px; | |
margin-right: 11px; | |
margin-bottom: 20px; | |
text-align: left; | |
color: #838383; | |
} | |
.highlight { | |
color: #007a5e; | |
font-weight: bold; | |
} | |
.translator { | |
display: flex; | |
justify-content: left; | |
flex-wrap: wrap; | |
margin-top: 30px; | |
margin-left: 13px; | |
margin-right: 13px; | |
} | |
.input-box { | |
width: 45%; | |
resize: none; | |
} | |
.output-box { | |
width: 45%; | |
resize: none; | |
margin-left: 25px; | |
} | |
textarea { | |
width: 100%; | |
height: 150px; | |
padding: 10px; | |
font-size: 1rem; | |
border: 1px solid #ccc; | |
border-radius: 8px; | |
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); | |
} | |
textarea:focus { | |
outline: none; | |
border-color: #007a5e; | |
} | |
.buttons { | |
display: flex; | |
flex-direction: row; | |
justify-content: right; | |
gap: 10px; | |
margin: 10px 0; | |
} | |
.btn { | |
padding: 10px 20px; | |
font-size: 1rem; | |
border: none; | |
border-radius: 5px; | |
cursor: pointer; | |
} | |
.btn.clear { | |
background-color: #ff6b6b; | |
color: white; | |
width: 100px; | |
justify-content: center; | |
} | |
.btn.clear:hover { | |
background-color: #e54848; | |
} | |
.btn.translate { | |
background-color: #007a5e; | |
color: white; | |
width: 100px; | |
justify-content: center; | |
} | |
.btn.translate:hover { | |
background-color: #005a42; | |
} | |
.btn.copy { | |
background-color: #ffc107; | |
color: white; | |
} | |
.btn.copy:hover { | |
background-color: #e0a800; | |
} | |
footer { | |
margin-top: 35px; | |
padding: 10px 20px; | |
text-align: center; | |
font-size: 0.9rem; | |
color: #555; | |
} | |
</style> |