AI Translation on crowdin

add extra buttons to translate with AI on crowdin, support DeepL X and OpenAI

  1. // ==UserScript==
  2. // @name AI Translation on crowdin
  3. // @description add extra buttons to translate with AI on crowdin, support DeepL X and OpenAI
  4. // @namespace https://crowdin.com/
  5. // @version 0.3.2
  6. // @author bowencool
  7. // @license MIT
  8. // @supportURL https://github.com/bowencool/Tampermonkey-Scripts/issues
  9. // @match https://crowdin.com/translate/*
  10. // @icon https://www.google.com/s2/favicons?sz=64&domain=crowdin.com
  11. // @run-at document-end
  12. // @require https://cdn.jsdelivr.net/gh/bowencool/Tampermonkey-Scripts@f59cc91442dd34eb28e0d270486da5c7ac8d2d50/shared/waitForElementToExist.js
  13. // @grant GM_xmlhttpRequest
  14. // ==/UserScript==
  15.  
  16. async function main() {
  17. const sourceContainer = await waitForElementToExist(
  18. "#source_phrase_container"
  19. );
  20.  
  21. const button = document.createElement("button");
  22. button.innerText = "DeepL Translate";
  23. button.classList.add("btn");
  24.  
  25. button.addEventListener("click", () => {
  26. const sourceText = sourceContainer.innerText;
  27. // console.log(sourceText);
  28. if (!sourceText) return;
  29. button.setAttribute("disabled", "true");
  30. const targetContainer = document.querySelector("#translation");
  31. // console.log(targetContainer);
  32. // you need to deploy https://hub.docker.com/r/zu1k/deepl to use this api
  33. fetch("http://deeplx.localhost:8080/translate", {
  34. method: "POST",
  35. body: JSON.stringify({
  36. text: sourceText,
  37. source_lang: "auto",
  38. target_lang: "ZH",
  39. }),
  40. })
  41. .then((res) => res.json())
  42. .then((res) => {
  43. //console.log(res)
  44. targetContainer.value = res.data;
  45. targetContainer.dispatchEvent(new Event("input", { bubbles: true }));
  46. button.removeAttribute("disabled");
  47. });
  48. });
  49.  
  50. const button2 = document.createElement("button");
  51. button2.innerText = "OpenAI Translate";
  52. button2.classList.add("btn");
  53. button2.style.marginLeft = "10px";
  54.  
  55. button2.addEventListener("click", () => {
  56. const sourceText = sourceContainer?.innerText;
  57. // console.log(sourceText);
  58. if (!sourceText) return;
  59. button2.setAttribute("disabled", "true");
  60. const targetContainer = document.querySelector("#translation");
  61.  
  62. // you need to login https://key-rental.bowen.cool/login to use this api
  63. fetch("https://key-rental-api.bowen.cool/openai/v1/chat/completions", {
  64. method: "POST",
  65. mode: "cors",
  66. credentials: "include",
  67. body: JSON.stringify({
  68. model: "gpt-3.5-turbo",
  69. messages: [
  70. { role: "user", content: "Translate to Chinese:\n" + sourceText },
  71. ],
  72. }),
  73. })
  74. .then((res) => res.json())
  75. .then((res) => {
  76. //console.log(res)
  77. const text = res.choices[0].message.content;
  78. targetContainer.value = text;
  79. targetContainer.dispatchEvent(new Event("input", { bubbles: true }));
  80. button2.removeAttribute("disabled");
  81. });
  82. });
  83.  
  84. sourceContainer.before(button);
  85. sourceContainer.before(button2);
  86. console.log("inserted");
  87. }
  88.  
  89. main();