您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Перевод сообщений в чате с любого языка на русский!
// ==UserScript== // @name Перевод чата Twitch // @version 0.1-BETA // @description Перевод сообщений в чате с любого языка на русский! // @author MjKey // @match *://*.twitch.tv/* // @icon https://www.google.com/s2/favicons?sz=64&domain=twitch.tv // @copyright 2022, MjKey | MjKey.ru // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_registerMenuCommand // @require https://openuserjs.org/src/libs/sizzle/GM_config.js // @license MIT // @namespace https://greasyfork.org/users/519758 // ==/UserScript== // ==OpenUserJS== // @author MjKey // ==/OpenUserJS== /* global GM_config, GM_info, GM_registerMenuCommand */ (function() { 'use strict'; GM_config.init({ id: 'ttconf', title: GM_info.script.name + ' • Настройки', fields: { AUTOTRANSLATE: { label: 'Кнопка перевода', type: 'checkbox', default: true, title: 'ВКЛ/ВЫКЛ кнопку' }, FROMLANG: { label: 'На какой язык переводить (ru, nl, fr, ..)', type: 'text', default: "ru", title: 'В РАЗРАБОТКЕ' } } }) GM_registerMenuCommand('Настройки', () => { GM_config.open('ttconf') }) GM_registerMenuCommand('Поддержать автора', () => { window.open("https://mjkey.ru/#donate", '_blank').focus(); }) function httpPost(theUrl,theData, callback) { var xmlHttp = new XMLHttpRequest(); xmlHttp.open( "POST", theUrl, true ); // false for synchronous request xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xmlHttp.send( theData ); xmlHttp.onreadystatechange = function() { if (this.readyState != 4) return; callback(xmlHttp.responseText); } } function isEng(t){ if(!t || 0 === t.length || t.startsWith('!'))return false; if(!/[А-я]+/.test(t))return true; return t.match(/[А-я]/g).length < (t.length * 0.1); } function TranslateTo(text,to, callback){ httpPost('https://translate.googleapis.com/translate_a/single', 'client=gtx&sl=auto&tl='+to+'&dt=t&q='+encodeURIComponent(text), (x)=>{ var jsos = JSON.parse(x); callback({text:jsos[0][0][0],from:jsos[2]}); },true); } var ChatLanguage = "en"; const chatObserver = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.type == 'childList'){ if(mutation.target.matches('div.chat-scrollable-area__message-container')){ mutation.addedNodes.forEach(n => { var textns = n.querySelectorAll('span[class*="-fragment"]'); var textn = textns[0]; setTimeout(() => { if(textn){ var text = ''; textns.forEach(element => {text += element.innerText;}); if(isEng(text.trim()) && text.length > 1 && !text.startsWith('!') && GM_config.get("AUTOTRANSLATE")){ setTimeout(() => { var xnewSpan = document.createElement('span'); xnewSpan.classList.add("chat-line__message--deleted"); xnewSpan.classList.add("twitchtoolbox-wronglayout"); xnewSpan.style.cursor = 'pointer'; xnewSpan.innerHTML = '<div class="tw-inline tw-relative tw-tooltip-wrapper" style="float:right;"><div class="tw-align-center tw-inline-block"> ⌈🌐⌋</div></div>'; xnewSpan.title = text; xnewSpan.onclick = function(){ var translatedText = ''; var isChanged = false; textns.forEach(element => { element.alt = element.innerText; TranslateTo(element.innerText, GM_config.get("FROMLANG"),(x)=>{ translatedText += element.innerText = x.text || element.innerText; }); }); } textn.parentNode.prepend(xnewSpan); }, 0); } } }); }, 0); } } }) }) chatObserver.observe(document.documentElement, { attributes: true, childList: true, subtree: true }) // Thanks ScriptedEngineer (aka. Siptrixed) <3 })();