Greasy Fork镜像 支持简体中文。

在线翻译

复制粘贴点击翻译即可,可以机器发声翻译之后的文本,也可以复制翻译之后的内容

  1. // ==UserScript==
  2. // @name 在线翻译
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description 复制粘贴点击翻译即可,可以机器发声翻译之后的文本,也可以复制翻译之后的内容
  6. // @license MIT
  7. // @author acxgdxy
  8. // @match *://*/*
  9. // @icon https://th.bing.com/th/id/R.81c41e9a6ac6aefdef1845b4d9bc2b99?rik=S6L5yItkn5R%2bjQ&riu=http%3a%2f%2fimg1.3png.com%2f81c41e9a6ac6aefdef1845b4d9bc2b994130.png&ehk=MctCYYmO6W8AyE9wQ2OUUUYnRhZEn4EloBRBfkvfVYE%3d&risl=&pid=ImgRaw&r=0
  10. // @grant none
  11. // ==/UserScript==
  12. let body = document.getElementsByTagName('body')[0];
  13. let head = document.getElementsByTagName('head')[0];
  14. let link = document.createElement('link');
  15. link.rel = 'stylesheet';
  16. link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css';
  17.  
  18.  
  19. const styles = `
  20. /* Import Google Font - Poppins */
  21.  
  22. @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
  23. *{
  24. font-family: 'Poppins', sans-serif;
  25. }
  26. .acxgdxy-container{
  27. position: fixed;
  28. right: 10px;
  29. top: 50%;
  30. transform: translateY(-50%);
  31. max-width: 300px;
  32. width: 100%;
  33. padding: 30px;
  34. background: #70717e;
  35. border-radius: 7px;
  36. box-shadow: 0 10px 20px rgba(0,0,0,0.01);
  37. z-index: 100;
  38. }
  39. .acxgdxy-wrapper{
  40. border-radius: 5px;
  41. border: 1px solid #ccc;
  42. }
  43. .acxgdxy-wrapper .acxgdxy-text-input{
  44. display: flex;
  45. border-bottom: 1px solid #ccc;
  46. }
  47. .acxgdxy-text-input .acxgdxy-to-text{
  48. border-radius: 0px;
  49. border-left: 1px solid #ccc;
  50. }
  51. .acxgdxy-text-input textarea{
  52. height: 200px;
  53. width: 100%;
  54. border: none;
  55. outline: none;
  56. resize: none;
  57. background: none;
  58. font-size: 18px;
  59. padding: 10px 15px;
  60. border-radius: 5px;
  61. }
  62. .acxgdxy-text-input textarea::placeholder{
  63. color: #b7b6b6;
  64. }
  65. .acxgdxy-text-input {
  66. position: relative;
  67. }
  68. .acxgdxy-controls{
  69. display: flex;
  70. align-items: center;
  71. justify-content: space-between;
  72. }
  73. .acxgdxy-controls{
  74. list-style: none;
  75. padding: 12px 15px;
  76. }
  77.  
  78. .acxgdxy-icons {
  79. display: flex;
  80. position: absolute;
  81. height: 20px;
  82. bottom: 0;
  83. right: 0;
  84. }
  85. .acxgdxy-icons i {
  86. height: 10px;
  87. width: 50px;
  88. }
  89. .acxgdxy-controls .acxgdxy-row{
  90. width: 38%;
  91. }
  92. .acxgdxy-controls .acxgdxy-row .acxgdxy-icons i{
  93. width: 50px;
  94. color: #adadad;
  95. font-size: 14px;
  96. cursor: pointer;
  97. transition: transform 0.2s ease;
  98. justify-content: center;
  99. }
  100. .acxgdxy-controls .acxgdxy-row .acxgdxy-from{
  101. padding-right: 15px;
  102. border-right: 1px solid #ccc;
  103. }
  104. .acxgdxy-controls .acxgdxy-row.acxgdxy-to{
  105. padding-left: 10px;
  106. /*border-left: 1px solid #ccc;*/
  107. }
  108. .acxgdxy-controls .acxgdxy-row select{
  109. color: #333;
  110. border: none;
  111. outline: none;
  112. font-size: 13px;
  113. background: none;
  114. /*padding-left: 5px;*/
  115. }
  116. .acxgdxy-text-input textarea::-webkit-scrollbar{
  117. width: 4px;
  118. }
  119. .acxgdxy-controls .acxgdxy-row select::-webkit-scrollbar{
  120. width: 8px;
  121. }
  122. .acxgdxy-text-input textarea::-webkit-scrollbar-track,
  123. .acxgdxy-controls .acxgdxy-row select::-webkit-scrollbar-track{
  124. background: #fff;
  125. }
  126. .acxgdxy-text-input textarea::-webkit-scrollbar-thumb{
  127. background: #ddd;
  128. border-radius: 8px;
  129. }
  130. .acxgdxy-controls .acxgdxy-row select::-webkit-scrollbar-thumb{
  131. background: #999;
  132. border-radius: 8px;
  133. /*border-right: 2px solid #ffffff;*/
  134. }
  135. .acxgdxy-controls .acxgdxy-exchange{
  136. color: #adadad;
  137. cursor: pointer;
  138. font-size: 16px;
  139. transition: transform 0.2s ease;
  140. }
  141. .acxgdxy-controls i:active{
  142. transform: scale(0.9);
  143. }
  144. .acxgdxy-container button{
  145. width: 100%;
  146. padding: 14px;
  147. outline: none;
  148. border: none;
  149. color: #fff;
  150. cursor: pointer;
  151. margin-top: 20px;
  152. font-size: 17px;
  153. border-radius: 5px;
  154. background: #5372F0;
  155. }
  156.  
  157. @media (max-width: 660px){
  158. .acxgdxy-container{
  159. padding: 20px;
  160. }
  161. .acxgdxy-wrapper .acxgdxy-text-input{
  162. flex-direction: column;
  163. }
  164. .acxgdxy-text-input .acxgdxy-to-text{
  165. border-left: 0px;
  166. border-top: 1px solid #ccc;
  167. }
  168. .acxgdxy-text-input textarea{
  169. height: 200px;
  170. }
  171. .acxgdxy-controls .acxgdxy-row .acxgdxy-icons{
  172. display: none;
  173. }
  174. .acxgdxy-container button{
  175. padding: 13px;
  176. font-size: 16px;
  177. }
  178. .acxgdxy-controls .acxgdxy-row select{
  179. font-size: 16px;
  180. }
  181. .acxgdxy-controls .acxgdxy-exchange{
  182. font-size: 14px;
  183. }
  184. }
  185.  
  186. `;
  187. let style = document.createElement('style');
  188.  
  189. function build() {
  190. style.type = 'text/css';
  191. style.appendChild(document.createTextNode(styles));
  192. let select = document.createElement('div');
  193. select.innerHTML = `<div class="acxgdxy-container">
  194. <div class="acxgdxy-wrapper">
  195. <div class="acxgdxy-text-input">
  196. <textarea spellcheck="false" class="acxgdxy-from-text" placeholder="输入文本(enter)"></textarea>
  197. <textarea spellcheck="false" readonly disabled class="acxgdxy-to-text" placeholder="翻译结果(result)"></textarea>
  198. <div class="acxgdxy-icons">
  199. <i class="fas fa-volume-up to"></i>
  200. <i class="fas fa-copy to"></i>
  201. </div>
  202. </div>
  203. <ul class="acxgdxy-controls">
  204. <li class="acxgdxy-row acxgdxy-from">
  205. <select class="acxgdxy-select"></select>
  206. </li>
  207. <li class="acxgdxy-exchange"><i class="fas fa-exchange-alt"></i></li>
  208. <li class="acxgdxy-row acxgdxy-to">
  209. <select class="acxgdxy-select"></select>
  210. </li>
  211. </ul>
  212. </div>
  213. <button class="acxgdxy-button">点击翻译文本(click to translate!)</button>
  214. </div>`;
  215. body.appendChild(select);
  216. head.appendChild(style);
  217. head.appendChild(link);
  218. }
  219.  
  220.  
  221. // <!-- ref https://www.codingnepalweb.com/language-translator-app-html-css-javascript/ -->
  222. function mywork() {
  223. // <!-- ref https://www.codingnepalweb.com/language-translator-app-html-css-javascript/ -->
  224. const fromText = document.querySelector(".acxgdxy-from-text"),
  225. toText = document.querySelector(".acxgdxy-to-text"),
  226. exchageIcon = document.querySelector(".acxgdxy-exchange"),
  227. selectTag = document.getElementsByClassName('acxgdxy-select'),
  228. icons = document.querySelectorAll(".acxgdxy-icons"),
  229. translateBtn = document.getElementsByClassName('acxgdxy-button')[0];
  230. // console.log(typeof selectTag);
  231. const countries = {
  232.  
  233. "zh": " Chinese",
  234. "de-DE": "German",
  235. "en-GB": "English",
  236. "es-ES": "Spanish",
  237. "it-IT": "Italian",
  238. "ja-JP": "Japanese",
  239. "la-VA": "Latin",
  240. "ru-RU": "Russian",
  241. }
  242. let Array = Object.keys(selectTag);
  243. Array.forEach((id) => {
  244. let tag = selectTag[id];
  245. for (let country_code in countries) {
  246. let selected = id == 0 ? country_code == "en-GB" ? "selected" : "" : country_code == "zh" ? "selected" : "";
  247. let option = `<option ${selected} value="${country_code}">${countries[country_code]}</option>`;
  248. tag.insertAdjacentHTML("beforeend", option);
  249. // console.log(country_code);
  250. }
  251. })
  252.  
  253.  
  254. exchageIcon.addEventListener("click", () => {
  255. let tempText = fromText.value,
  256. tempLang = selectTag[0].value;
  257. fromText.value = toText.value;
  258. toText.value = tempText;
  259. selectTag[0].value = selectTag[1].value;
  260. selectTag[1].value = tempLang;
  261. });
  262.  
  263. fromText.addEventListener("keyup", () => {
  264. if (!fromText.value) {
  265. toText.value = "";
  266. }
  267. });
  268.  
  269. translateBtn.addEventListener("click", () => {
  270. let text = fromText.value.trim(),
  271. translateFrom = selectTag[0].value,
  272. translateTo = selectTag[1].value;
  273. if (!text) return;
  274. toText.setAttribute("placeholder", "Translating...");
  275. // https://api.mymemory.translated.net/get?q=Hello World!&langpair=en|it
  276. let apiUrl = `https://api.mymemory.translated.net/get?q=${text}&langpair=${translateFrom}|${translateTo}`;
  277. fetch(apiUrl).then(res => res.json()).then(data => {
  278. toText.value = data.responseData.translatedText;
  279. data.matches.forEach(data => {
  280. if (data.id === 0) {
  281. toText.value = data.translation;
  282. }
  283. });
  284. toText.setAttribute("placeholder", "Translation");
  285. });
  286. });
  287.  
  288. icons.forEach(icon => {
  289. icon.addEventListener("click", ({target}) => {
  290. if (!fromText.value || !toText.value) return;
  291. if (target.classList.contains("fa-copy")) {
  292. if (target.classList["acxgdxy-from"]) {
  293. navigator.clipboard.writeText(fromText.value);
  294. } else {
  295. navigator.clipboard.writeText(toText.value);
  296. }
  297. } else {
  298. let utterance;
  299. if (target.classList["acxgdxy-from"]) {
  300. utterance = new SpeechSynthesisUtterance(fromacxgdxy - Text.value);
  301. utterance.lang = selectTag[0].value;
  302. } else {
  303. utterance = new SpeechSynthesisUtterance(toText.value);
  304. utterance.lang = selectTag[1].value;
  305. }
  306. speechSynthesis.speak(utterance);
  307. }
  308. });
  309. });
  310.  
  311. }
  312.  
  313. (function() {
  314. 'use strict';
  315. build();
  316. mywork();
  317. // Your code here...
  318. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址