Skip to content

Instantly share code, notes, and snippets.

@sorrycc
Last active December 5, 2022 05:06
Show Gist options
  • Save sorrycc/10f67ac688dce5301d8a690d8143882a to your computer and use it in GitHub Desktop.
Save sorrycc/10f67ac688dce5301d8a690d8143882a to your computer and use it in GitHub Desktop.
Translator
function getContainer(root) {
root ||= document.body;
if (!root.innerText) return null;
const totalWords = root.innerText.match(/\S+/g).length;
let ps = root.querySelectorAll('p');
if (!ps.length) ps = root.querySelectorAll('div');
if (!ps.length) return null;
let container = null;
let maxWords = 0;
for (let p of ps) {
const numWords = p.innerText.match(/\S+/g).length;
if (numWords > maxWords) {
maxWords = numWords;
container = p;
}
}
let selectedWords = maxWords;
while (selectedWords / totalWords < 0.4 && container !== root) {
container = container.parentElement;
selectedWords = container.innerText.match(/\S+/g).length;
}
if (container.tagName === 'P') {
container = container.parentElement;
}
return container;
}
function getNodes(container) {
const nodes = [];
const blockTags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'p', 'ul'];
for (const blockTag of blockTags) {
const elements = container.querySelectorAll(blockTag);
for (const element of elements) {
nodes.push(element);
}
}
return nodes;
}
function copyNodes(nodes) {
const copiedNodes = [];
for (const node of nodes) {
const copiedNode = node.cloneNode(true);
// node.insertAfter(copiedNode);
if (node.nextSibling) {
node.parentNode.insertBefore(copiedNode, node.nextSibling);
} else {
node.parentNode.appendChild(copiedNode);
}
copiedNodes.push(copiedNode);
}
return copiedNodes;
}
const API_URL = 'http://localhost:8080/translate';
async function translate(text) {
const res = await fetch(API_URL, {
method: 'POST',
mode: 'cors',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
text,
source_lang: 'auto',
target_lang: 'ZH',
}),
});
if (res.status !== 200) {
throw new Error(`Translate failed, ${res.status} ${res.statusText}`);
}
const json = await res.json();
const { data } = json;
if (!data) {
throw new Error(`Translate failed, data is null`);
}
return data;
}
(async () => {
const container = getContainer();
if (!container) {
throw new Error('No container found');
}
const nodes = [];
nodes.push(...getNodes(container));
if (!nodes.length) {
throw new Error('No nodes found');
}
const titleNode = document.querySelector('h1');
if (titleNode && !nodes.includes(titleNode)) {
nodes.push(titleNode);
}
console.log('Translating...');
const textToTranslate = nodes.map(node => node.innerText).join('\n\n');
const translatedText = await translate(textToTranslate);
console.log('Translated, copying nodes...');
const copiedNodes = copyNodes(nodes);
const translatedNodes = translatedText.split('\n\n');
for (let i = 0; i < copiedNodes.length; i++) {
copiedNodes[i].innerHTML = `<font style="border-bottom:2px solid #72ECE9;vertical-align:inherit">${translatedNodes[i]}</font>`;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment