Created
July 11, 2024 10:26
-
-
Save JohnRSim/12cbd6751c8c76ae7c79b3627b33dd87 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Translation Manager</title> | |
<style> | |
/* Modal styles */ | |
.modal { | |
display: none; | |
position: fixed; | |
z-index: 1; | |
left: 0; | |
top: 0; | |
width: 100%; | |
height: 100%; | |
overflow: auto; | |
background-color: rgba(0,0,0,0.4); | |
} | |
.modal-content { | |
background-color: #fefefe; | |
margin: 15% auto; | |
padding: 20px; | |
border: 1px solid #888; | |
width: 80%; | |
} | |
.close { | |
color: #aaa; | |
float: right; | |
font-size: 28px; | |
font-weight: bold; | |
} | |
.close:hover, | |
.close:focus { | |
color: black; | |
text-decoration: none; | |
cursor: pointer; | |
} | |
.highlight { | |
background-color: yellow; | |
cursor: pointer; | |
} | |
</style> | |
</head> | |
<body> | |
<button id="enableTranslationModeButton">Enable Translation Mode</button> | |
<div id="translationModal" class="modal"> | |
<div class="modal-content"> | |
<span class="close">×</span> | |
<h2>Edit Translation</h2> | |
<p>Original: <span id="originalText"></span></p> | |
<p>Translation: <input type="text" id="translationInput" /></p> | |
<button id="saveTranslationButton">Save</button> | |
</div> | |
</div> | |
<script> | |
// Function to collect all text nodes | |
function getTextNodes(element) { | |
let textNodes = []; | |
function recursiveCollect(node) { | |
if (node.nodeType === Node.TEXT_NODE) { | |
if (node.nodeValue.trim() !== "") { | |
textNodes.push(node); | |
} | |
} else { | |
node.childNodes.forEach(recursiveCollect); | |
} | |
} | |
recursiveCollect(element); | |
return textNodes; | |
} | |
// Retrieve translations from local storage or use default | |
const storedTranslations = localStorage.getItem('translations'); | |
const translations = storedTranslations ? JSON.parse(storedTranslations) : {}; | |
// Function to replace text nodes with translated text | |
function replaceTextNodes(textNodes, translations) { | |
textNodes.forEach(node => { | |
const originalText = node.nodeValue.trim(); | |
if (translations[originalText]) { | |
node.nodeValue = translations[originalText]; | |
} | |
}); | |
} | |
// Function to update the translations object with new strings that need translating | |
function updateTranslations(textNodes, translations) { | |
let updated = false; | |
textNodes.forEach(node => { | |
const originalText = node.nodeValue.trim(); | |
if (!translations.hasOwnProperty(originalText)) { | |
translations[originalText] = ""; | |
updated = true; | |
} | |
}); | |
if (updated) { | |
localStorage.setItem('translations', JSON.stringify(translations)); | |
} | |
} | |
// Function to clear highlights and remove event listeners | |
function clearHighlights() { | |
highlightedElements.forEach(element => { | |
element.classList.remove('highlight'); | |
element.removeEventListener('click', handleTextClick); | |
}); | |
highlightedElements = []; | |
} | |
// Collect all text nodes in the body | |
let textNodes = getTextNodes(document.body); | |
// Update the translations object with new strings that need translating | |
updateTranslations(textNodes, translations); | |
// Replace the text nodes with translated text from the JSON object | |
replaceTextNodes(textNodes, translations); | |
let translationModeEnabled = false; | |
const enableTranslationModeButton = document.getElementById('enableTranslationModeButton'); | |
let highlightedElements = []; | |
// Add event listener to enable/disable translation mode | |
enableTranslationModeButton.addEventListener('click', () => { | |
translationModeEnabled = !translationModeEnabled; | |
if (translationModeEnabled) { | |
enableTranslationModeButton.textContent = 'Disable Translation Mode'; | |
textNodes = getTextNodes(document.body); // Re-collect text nodes | |
textNodes.forEach(node => { | |
const parent = node.parentElement; | |
if (parent && !parent.classList.contains('highlight') && !parent.closest('.modal')) { | |
parent.classList.add('highlight'); | |
parent.addEventListener('click', handleTextClick); | |
highlightedElements.push(parent); | |
} | |
}); | |
} else { | |
enableTranslationModeButton.textContent = 'Enable Translation Mode'; | |
clearHighlights(); | |
} | |
}); | |
let selectedTextNode = null; | |
// Handle text element click | |
function handleTextClick(event) { | |
// Ensure the click did not happen within the modal | |
if (event.target.closest('.modal')) { | |
return; | |
} | |
const originalText = event.target.dataset.originalText || event.target.textContent.trim(); | |
selectedTextNode = event.target; | |
selectedTextNode.dataset.originalText = originalText; | |
document.getElementById('originalText').textContent = originalText; | |
document.getElementById('translationInput').value = translations[originalText] || ""; | |
document.getElementById('translationModal').style.display = 'block'; | |
} | |
// Add event listener to close button to close the modal | |
document.querySelector('.close').addEventListener('click', () => { | |
document.getElementById('translationModal').style.display = 'none'; | |
}); | |
// Add event listener to save button to save the translation | |
document.getElementById('saveTranslationButton').addEventListener('click', () => { | |
const originalText = document.getElementById('originalText').textContent.trim(); | |
const translation = document.getElementById('translationInput').value.trim(); | |
if (translation) { | |
translations[originalText] = translation; | |
selectedTextNode.textContent = translation; | |
} else { | |
delete translations[originalText]; | |
selectedTextNode.textContent = originalText; | |
} | |
localStorage.setItem('translations', JSON.stringify(translations)); | |
document.getElementById('translationModal').style.display = 'none'; | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment