您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Double-Click to Translate Twitch Chat Messages
- // ==UserScript==
- // @name Twitch Translate Chat Messages
- // @namespace http://userstyles.org
- // @description Double-Click to Translate Twitch Chat Messages
- // @author 636597
- // @include *://*.twitch.tv/*
- // @run-at document-start
- // @version 1.0
- // ==/UserScript==
- var enableTranslation = false;
- var destinationLanguage = "en";
- // You have to setup some coors enabled https site with
- // var GoogleTranslateBase = https://github.com/matheuss/google-translate-api
- // or use
- // var GoogleTranslateBase = "https://translation.googleapis.com/language/translate/v2";
- // https://console.cloud.google.com/apis/credentials
- var gapi_key = "";
- // Search for Occurrence *anywhere* in message
- var enableBlacklist = false;
- var blacklist_anywhere_words = [
- ];
- // Search for these exact words
- var blacklist_exact_words = [
- "BTTV!",
- "Prime" ,
- "Subscribe",
- "subscription",
- ];
- function searchBlacklist( wText ) {
- var lower = wText.toLowerCase();
- for ( var i = 0; i < blacklist_anywhere_words.length; ++i ) {
- if ( lower.indexOf( blacklist_anywhere_words[ i ] ) !== -1 ) {
- //console.log( "found anywhere" );
- //console.log( wText );
- return true;
- }
- }
- var x11 = wText.split( ":" )[ 1 ];
- if ( x11 ) {
- x11 = x11.split( " " );
- for ( var j = 0; j < x11.length; ++j ) {
- for ( var i = 0; i < blacklist_exact_words.length; ++i ) {
- if ( x11[ j ] === blacklist_exact_words[ i ] ) {
- //console.log( "found exact" );
- //console.log( wText );
- return true;
- }
- }
- }
- }
- return false;
- }
- function fixedEncodeURIComponent(str){
- return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
- }
- var TranslationActive = false;
- var gapi_key = "";
- var GoogleTranslateEnd = "&key=" + gapi_key;
- var TranB1 = "q=";
- var TranB2 = "&target=" + destinationLanguage;
- function translateText( text , dom_elem ) {
- if ( !text ) { return; }
- if ( !dom_elem ) { return; }
- text = text.trim();
- var query_string = TranB1 + fixedEncodeURIComponent( text ) + TranB2 + GoogleTranslateEnd;
- var anHttpRequest = new XMLHttpRequest();
- anHttpRequest.onreadystatechange = function() {
- if ( anHttpRequest.readyState == 4 && anHttpRequest.status == 200 ) {
- var response = anHttpRequest.responseText;
- console.log( response );
- var translation = JSON.parse( response );
- translation = translation[ "data" ][ "translations" ][ 0 ][ "translatedText" ];
- translation = translation.trim();
- var has_mention_fragment = false;
- var mention_frag_node = null;
- for ( var i = 0; i < dom_elem.childNodes.length; ++i ) {
- if ( dom_elem.childNodes[ i ].className === "mention-fragment" ) { has_mention_fragment = true; mention_frag_node = dom_elem.childNodes[ i ]; }
- var attr = dom_elem.childNodes[ i ].getAttribute( "data-a-target" );
- if ( attr === "chat-message-text" ) {
- dom_elem.childNodes[ i ].innerHTML = translation;
- dom_elem.setAttribute( "data-showTranslation" , "true" );
- dom_elem.setAttribute( "data-translatedText" , translation );
- dom_elem.setAttribute( "data-originalText" , text );
- }
- }
- if ( has_mention_fragment ) { dom_elem.removeChild( mention_frag_node ); }
- }
- };
- anHttpRequest.open( "POST", GoogleTranslateBase , true );
- anHttpRequest.setRequestHeader( "Content-Type" , "application/x-www-form-urlencoded; charset=UTF-8" );
- anHttpRequest.send( query_string );
- }
- var chat_element = null;
- var chat_observer = null;
- var observerConfig = {
- attributes: true,
- childList: true,
- characterData: true
- };
- function loadObserver() {
- chat_observer = new MutationObserver(function(mutations) {
- mutations.forEach(function( mutation , index ) {
- if ( mutation.type === "childList" ) {
- var addedNode = mutation.addedNodes[0];
- if( addedNode ) {
- var msg = addedNode.innerText;
- // Revert Back to Original
- if ( TranslationActive ) {
- addedNode.addEventListener( "dblclick" , function() {
- var that = this;
- var show_translation = addedNode.getAttribute( "data-showTranslation" );
- console.log( show_translation );
- if ( show_translation ) {
- if ( show_translation === "true" ) {
- //that.style.background = "red";
- console.log( "reverting" );
- console.log( "old text === " );
- var original_text = addedNode.getAttribute( "data-originalText" );
- //console.log( original_text );
- for ( var i = 0; i < addedNode.childNodes.length; ++i ) {
- if ( !addedNode.childNodes[ i ] ) { continue; }
- var attr = addedNode.childNodes[ i ].getAttribute( "data-a-target" );
- if ( attr === "chat-message-text" ) {
- addedNode.childNodes[ i ].innerText = original_text;
- break;
- }
- }
- addedNode.setAttribute( "data-showTranslation" , "false" );
- }
- else {
- //that.style.background = "green";
- addedNode.setAttribute( "data-showTranslation" , "true" );
- var already_translated = addedNode.getAttribute( "data-translatedText" );
- //console.log( "already_translated text === " );
- //console.log( already_translated );
- for ( var i = 0; i < addedNode.childNodes.length; ++i ) {
- if ( !addedNode.childNodes[ i ] ) { continue; }
- var attr = addedNode.childNodes[ i ].getAttribute( "data-a-target" );
- if ( attr === "chat-message-text" ) {
- addedNode.childNodes[ i ].innerHTML = already_translated;
- break;
- }
- }
- }
- }
- else {
- //that.style.background = "green";
- var start = msg.indexOf( ":" );
- var z1 = msg.substring( ( start + 1 ) );
- translateText( z1 , addedNode );
- }
- } , false );
- }
- if ( enableBlacklist ) {
- var remove = searchBlacklist( msg );
- // If Not Already Set to be Removed , Search Emotes
- if ( !remove ) {
- for ( var i = 0; i < addedNode.childNodes.length; ++i ) {
- if ( !addedNode.childNodes[ i ] ) { continue; }
- if ( !remove ) {
- var alt_text_target = addedNode.childNodes[ i ].getAttribute( "data-a-target" );
- if ( alt_text_target === "emote-name" ) {
- for ( var j = 0; j < addedNode.childNodes[ i ].childNodes.length; ++j ) {
- if ( !addedNode.childNodes[ i ].childNodes[ j ] ) { continue; }
- if ( !remove ) {
- if ( addedNode.childNodes[ i ].childNodes[ j ].alt ) {
- var test = searchBlacklist( addedNode.childNodes[ i ].childNodes[ j ].alt );
- if ( test ) {
- remove = true;
- break;
- }
- }
- }
- else { break; }
- }
- }
- }
- else { break; }
- }
- }
- if ( remove ) {
- if ( addedNode.parentNode ) {
- try {
- addedNode.setAttribute( "style", "visibility: hidden !important" );
- addedNode.setAttribute( "style", "height: 0 !important" );
- addedNode.setAttribute( "style", "padding: 0 !important" );
- addedNode.innerHTML = "";
- }
- catch( e ) { console.log( e ); }
- }
- }
- }
- }
- }
- });
- });
- if ( enableTranslation && gapi_key ) {
- TranslationActive = true;
- console.log( "Translation Option Loaded" );
- }
- if ( TranslationActive || enableBlacklist ) {
- if ( enableBlacklist ) {
- console.log( "Blacklist Option Loaded" );
- }
- chat_observer.observe( chat_element , observerConfig );
- }
- }
- (function() {
- var ready = setInterval(function(){
- var x1 = document.querySelectorAll( '[role="log"]' );
- if ( x1 ) { if ( x1[ 0 ] ) { chat_element = x1[0]; clearInterval( ready ); loadObserver(); } }
- } , 2 );
- })();