Skip to content

Instantly share code, notes, and snippets.

@4i8
Last active August 1, 2023 02:10
Show Gist options
  • Save 4i8/6136fbfe0dec4345081d54f3cfc52044 to your computer and use it in GitHub Desktop.
Save 4i8/6136fbfe0dec4345081d54f3cfc52044 to your computer and use it in GitHub Desktop.
The provided code adds a convenient "Copy" button to the CrowdIn translation section, streamlining the process of copying texts. It allows you to quickly copy text content without having to manually select and copy. Simply click the "Copy" button next to the desired text, and it will be copied to your clipboard.

example

- Open the translation section on [CrowdIn](https://crowdin.com/).
- Press F12 to open the developer console. or use [tampermonkey](http://tampermonkey.net)
- Paste the code in the console and hit Enter.
- A "Copy" button will appear next to each text and A "Copy All" add in navbar
- Click the "Copy" button to copy the respective text to your clipboard.
- If you want to use GPT prompt for translation, include your desired prompt within the parentheses on the last line of the code. If not, leave the parentheses empty. - This script enhances the translation workflow, making it easier and faster to copy content, saving valuable time. Enjoy a smoother translation experience with this handy utility!

"Your prompt"; To enable GPT prompt
Copied example text:

"Copied text"
Your prompt

""; just copy
Copied example text:

Copied text
// ==UserScript==
// @name CrowdinScript
// @namespace CrowdinScript
// @version 0.2
// @description try to take over the world! (By Arth)
// @author Arth(https://github.com/4i8)
// @match https://crowdin.com/translate/*
// @match https://*.crowdin.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=crowdin.com
// @grant none
// ==/UserScript==
(function () {
"use strict";
//By Arth
/**
* @variable
* @constants
*/
const Prompt_Copy = ""; // keep empty to disable GPT prompt
const Prompt_CopyAll = ""; // keep empty to disable GPT prompt for copy all
const EventListeners = ["next_page", "prev_page", "click", "keydown"];
const Elements_CopyAll = [
`<li>
<button
style="color:#ffffff;display: flex;flex-direction: row;font-size: 11px;padding: 6px 8px 3px 8px;background-color:#DA5E5A;"
class="btn btn-secondary"
>
Copy All
</button>
</li>`,
`<li>
<button
style="color:#ffffff;display: flex;flex-direction: row;font-size: 11px;padding: 6px 8px 3px 8px; background-color:#201737;"
class="btn btn-secondary"
>
Copy All
</button>
</li>
`,
];
/**
* @function
*/
function addElement(htmlContent) {
const dummyContainer = document.createElement("div");
dummyContainer.innerHTML = htmlContent;
return dummyContainer.firstChild;
}
async function copyContent(text) {
await navigator.clipboard.writeText(text);
}
function waitForLoading() {
return new Promise(function (resolve) {
const I = setInterval(function () {
let d = document.getElementById("loading_block").style.display;
if (d == "none") {
clearInterval(I);
resolve(true);
d = null;
}
}, 1000);
});
}
function addCopyButtons(prompt) {
document.querySelectorAll(".untranslated_phrase").forEach((i, index) => {
var status = false;
if (i instanceof Node) {
for (const childNode of i.childNodes) {
if (childNode.nodeName === "BUTTON") {
status = true;
break;
}
}
}
if (status) return;
if (i?.childNodes[1]?.className === "btn btn-primary") return;
let text = !prompt
? i.textContent.replace(/Copied!$|Copy$/, "")
: `"${i.textContent.replace(/Copied!$|Copy$/, "")}"\n${prompt}`;
i.appendChild(
addElement(
`<button style="margin-top: 7px; display: flex; flex-direction: row;" class="btn btn-primary">Copy</button>`
)
).addEventListener("click", (a) => {
navigator.permissions
.query({ name: "clipboard-write" })
.then(async (result) => {
if (result.state == "granted" || result.state == "prompt") {
a.target.textContent = "Copied!";
a.target.style.backgroundColor = "#198754";
setTimeout(() => {
a.target.textContent = "Copy";
a.target.disabled = false;
a.target.style.backgroundColor = null;
a.target.classList = "btn btn-primary";
}, 1000);
await copyContent(text);
} else {
alert("You need to grant permission to copy the text");
}
});
});
});
}
/**
* @main
*/
waitForLoading().then(() => {
addCopyButtons(Prompt_Copy);
Elements_CopyAll.forEach((i, index) => {
document
.getElementById("editor-menu")
.appendChild(addElement(i))
.addEventListener("click", (a) => {
navigator.permissions
.query({ name: "clipboard-write" })
.then(async (result) => {
if (result.state == "granted" || result.state == "prompt") {
setTimeout(() => {
a.target.textContent = "Copy All";
a.target.disabled = false;
a.target.style.backgroundColor =
index === 0 ? "#DA5E5A" : "#201737";
a.target.classList = "btn btn-secondary";
}, 1000);
if (index === 0) {
let items = [
...document.querySelectorAll(".untranslated_phrase"),
];
if (!items?.length) return;
a.target.textContent = "Copied!";
a.target.style.backgroundColor = "#198754";
$.jGrowl("Copy All UnTranslated Strings", {
life: 1400,
});
await copyContent(
items
.map(
(i, index) =>
`${index + 1}-` +
i.textContent.replace(/Copied!$|Copy$/, "")
)
.join("\n") + `\n${Prompt_CopyAll}`
);
} else {
let items = [...document.querySelectorAll(".source-string")];
if (!items?.length) return;
a.target.textContent = "Copied!";
a.target.style.backgroundColor = "#198754";
$.jGrowl("Copy All Source Strings", {
life: 1400,
});
await copyContent(
items
.map(
(i, index) =>
`${index + 1}-` +
i.textContent.replace(/Copied!$|Copy$/, "")
)
.join("\n") + `\n${Prompt_CopyAll}`
);
}
} else {
alert("You need to grant permission to copy UnTranslated text");
}
});
});
});
});
EventListeners.forEach((i) => {
document.addEventListener(i, async () => {
if (i === "keydown") {
waitForLoading().then(() => {
addCopyButtons(Prompt_Copy);
});
} else {
waitForLoading().then(() => {
addCopyButtons(Prompt_Copy);
document.querySelectorAll(".translated_phrase").forEach((i) => {
var status = false;
if (i instanceof Node) {
for (const childNode of i.childNodes) {
if (childNode.nodeName === "BUTTON") {
status = true;
break;
}
}
if (!status) return;
i.removeChild(i.children[0]);
}
});
});
}
});
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment