Translate Buttons for beta.character.ai

Adds a translate buttons for character messages in the chat for beta.character.ai

目前为 2022-12-24 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Translate Buttons for beta.character.ai
  3. // @namespace TranslateButtonsForBetaCharacterAI
  4. // @description Adds a translate buttons for character messages in the chat for beta.character.ai
  5. // @version 2.0.1
  6. // @author CriDos
  7. // @icon https://www.google.com/s2/favicons?sz=64&domain=beta.character.ai
  8. // @match https://beta.character.ai/chat?char=*
  9. // @grant GM_xmlhttpRequest
  10. // @run-at document-end
  11. // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15. 'use strict';
  16.  
  17. console.log(`Translate Buttons initializing...`);
  18.  
  19. let debug = false;
  20.  
  21. setInterval(addTranslateButtons, 1000);
  22.  
  23. function addTranslateButtons() {
  24. var charMessages = document.getElementsByClassName("char-msg");
  25. for (var i = 0; i < charMessages.length; i++) {
  26. const msgNode = charMessages[i];
  27.  
  28. const parentMsgMarkdown = msgNode.parentElement;
  29. if (parentMsgMarkdown.isAutoTranslate) {
  30. continue;
  31. }
  32. parentMsgMarkdown.isAutoTranslate = true;
  33.  
  34. setInterval(async () => {
  35. await translateNode(msgNode);
  36. }, 500);
  37. }
  38. }
  39.  
  40. async function translateNode(node) {
  41. const translateClassName = "translate-markdown";
  42. const parentMsgMarkdown = node.parentElement;
  43.  
  44. const msgMarkdownContent = $(node).html();
  45. if (node.storeContent == msgMarkdownContent) {
  46. return;
  47. }
  48. node.storeContent = msgMarkdownContent;
  49.  
  50. var translateNode = parentMsgMarkdown.querySelector(`.${translateClassName}`);
  51. if (translateNode == null) {
  52. translateNode = node.cloneNode(true);
  53. translateNode.classList.add(translateClassName);
  54. parentMsgMarkdown.insertBefore(translateNode, parentMsgMarkdown.firstChild);
  55. }
  56.  
  57. var msgMarkdownClone = node.cloneNode(true);
  58. msgMarkdownClone.classList.add(translateClassName);
  59. const msgMarkdownCloneContent = $(msgMarkdownClone).html();
  60. msgMarkdownClone = null;
  61.  
  62. $(translateNode).html(await translateText(msgMarkdownCloneContent, "en", navigator.language));
  63. }
  64.  
  65. async function translateText(text, sLang, tLang) {
  66. const url = `https://translate.googleapis.com/translate_a/single?client=gtx&format=text&sl=${sLang}&tl=${tLang}&dt=t&q=${encodeURIComponent(text)}`;
  67.  
  68. try {
  69. if (debug) {
  70. console.log(`preTranslate: ${text}`);
  71. }
  72.  
  73. const response = await doXHR(url);
  74. const responseText = JSON.parse(response.responseText);
  75.  
  76. let postTranslate = "";
  77. responseText[0].forEach(part => {
  78. postTranslate += part[0];
  79. });
  80.  
  81. if (debug) {
  82. console.log(`postTranslate: ${postTranslate}`);
  83. }
  84.  
  85. return postTranslate;
  86. } catch (error) {
  87. console.error(error);
  88. }
  89. }
  90.  
  91. async function doXHR(url) {
  92. return new Promise((resolve, reject) => {
  93. const xhr = new XMLHttpRequest();
  94. xhr.open("GET", url);
  95. xhr.onload = () => resolve(xhr);
  96. xhr.onerror = () => reject(xhr.statusText);
  97. xhr.send();
  98. });
  99. }