// ==UserScript== // @name DeepL - Auto VN Translation Extension Helper // @version 1.2.9 // @grant GM.setClipboard // @match https://www.deepl.com/translator // @match https://www.deepl.com/en/translator // @description Watch for target language element class change, copy new value of textarea to clipboard each time change has been detected. // @author Zero_G // @icon https://www.deepl.com/img/logo/deepl-logo-blue.svg // @namespace Zero_G.autovntranslation // @downloadURL https://update.greasyfork.icu/scripts/476033/DeepL%20-%20Auto%20VN%20Translation%20Extension%20Helper.user.js // @updateURL https://update.greasyfork.icu/scripts/476033/DeepL%20-%20Auto%20VN%20Translation%20Extension%20Helper.meta.js // ==/UserScript== (function() { 'use strict'; // Filters to apply to translated text // These were originally here, so leaving them as is for compatibility to previous caches (as filtering should be done in setClipboardText) const filters = { // '' : /\"+|\'\'+/g, // Remove " or '' // '...' : /\.\.\.\.+/g // Change multiple dots (when there are more than 3 to '...' only) } var mutationObserver; // DeepL added a disconnect to all MutationObservers, as there is no way to check if a mutation was // disconnected, it will be checked if there was an active event every 10 seconds, if not, recreate the mutation var lastMutationTime = Date.now(); // Track last mutation event function startObserver() { // Observe the text div that contain the translation // But as the translated text appears in a
in a ::before css we need to watch
// for added nodes
const target = document.querySelector('#translation-target-heading')?.parentNode;
if (!target){
console.log("Auto VN script failed, can't attach ovserver because DeepL page changed");
return;
}
mutationObserver = new MutationObserver(callback);
mutationObserver.observe(target, {
childList: true,
subtree: true,
attributes: true
});
//console.log("MutationObserver started!");
}
// Initial observer setup
setTimeout(startObserver, 3000);
// Check if the observer is still working
function checkObserver() {
if (Date.now() - lastMutationTime > 10000) { // No events for 10 seconds?
//console.log("MutationObserver is inactive, restarting...");
mutationObserver.disconnect(); // Clean up old observer
startObserver();
} else {
//console.log("MutationObserver is still active");
}
setTimeout(checkObserver, 10000); // Run again in 10 seconds
}
// Start checking
setTimeout(checkObserver, 13000);
function callback(mutationsList) {
lastMutationTime = Date.now(); // Update timestamp when a mutation happens
//console.log("Mutation detected!", mutationsList);
mutationsList.forEach(mutation => {
if (mutation.type === 'childList' && // Irrelevant as we are already watching for childList only but meh
mutation.addedNodes.length !== 0 && // Looking for a mutation with an added node
mutation.removedNodes.length !== 0 && // This condition is to prevent a repeat
!mutation.addedNodes[0].innerHTML.includes('
(get as value doesn't work)
let text = '';
// Check for added elments/mutations of element type
for(let i in mutation.addedNodes){ let child = mutation.addedNodes[i] if(child.tagName == 'P'){ //console.log(child); text = child.textContent; } else if(child.tagName == 'DIV'){ text = child.textContent; } } // Apply filters for (const [key, value] of Object.entries(filters)) { text = text.replace(value, key); } // Copy to memory with GreaseMonkey special function (needs @grant) if(text) GM.setClipboard(text); } }) } })();