// ==UserScript== // @name Language Switcher for Google™ // @author gb.ianni shunf4 // @namespace gb.ianni // @version 2.3.4 // @copyright Copyright 2015-2022 gb.ianni shunf4 // @description a port of Language Switcher for Google™ Chome extension (https://chrome.google.com/webstore/detail/language-switcher-for-goo/jbbappjmafnnhhalfbhdhiemchcgejcp) to userscript.js // @include *://www.google.com/* // @include *://www.google.ad/* // @include *://www.google.ae/* // @include *://www.google.com.af/* // @include *://www.google.com.ag/* // @include *://www.google.com.ai/* // @include *://www.google.am/* // @include *://www.google.co.ao/* // @include *://www.google.com.ar/* // @include *://www.google.as/* // @include *://www.google.at/* // @include *://www.google.com.au/* // @include *://www.google.az/* // @include *://www.google.ba/* // @include *://www.google.com.bd/* // @include *://www.google.be/* // @include *://www.google.bf/* // @include *://www.google.bg/* // @include *://www.google.com.bh/* // @include *://www.google.bi/* // @include *://www.google.bj/* // @include *://www.google.com.bn/* // @include *://www.google.com.bo/* // @include *://www.google.com.br/* // @include *://www.google.bs/* // @include *://www.google.co.bw/* // @include *://www.google.by/* // @include *://www.google.com.bz/* // @include *://www.google.ca/* // @include *://www.google.cd/* // @include *://www.google.cf/* // @include *://www.google.cg/* // @include *://www.google.ch/* // @include *://www.google.ci/* // @include *://www.google.co.ck/* // @include *://www.google.cl/* // @include *://www.google.cm/* // @include *://www.google.cn/* // @include *://www.google.com.co/* // @include *://www.google.co.cr/* // @include *://www.google.com.cu/* // @include *://www.google.cz/* // @include *://www.google.de/* // @include *://www.google.dj/* // @include *://www.google.dk/* // @include *://www.google.dm/* // @include *://www.google.com.do/* // @include *://www.google.dz/* // @include *://www.google.com.ec/* // @include *://www.google.ee/* // @include *://www.google.com.eg/* // @include *://www.google.es/* // @include *://www.google.com.et/* // @include *://www.google.fi/* // @include *://www.google.com.fj/* // @include *://www.google.fm/* // @include *://www.google.fr/* // @include *://www.google.ga/* // @include *://www.google.ge/* // @include *://www.google.gg/* // @include *://www.google.com.gh/* // @include *://www.google.com.gi/* // @include *://www.google.gl/* // @include *://www.google.gm/* // @include *://www.google.gp/* // @include *://www.google.gr/* // @include *://www.google.com.gt/* // @include *://www.google.gy/* // @include *://www.google.com.hk/* // @include *://www.google.hn/* // @include *://www.google.hr/* // @include *://www.google.ht/* // @include *://www.google.hu/* // @include *://www.google.co.id/* // @include *://www.google.ie/* // @include *://www.google.co.il/* // @include *://www.google.im/* // @include *://www.google.co.in/* // @include *://www.google.iq/* // @include *://www.google.is/* // @include *://www.google.it/* // @include *://www.google.je/* // @include *://www.google.com.jm/* // @include *://www.google.jo/* // @include *://www.google.co.jp/* // @include *://www.google.co.ke/* // @include *://www.google.com.kh/* // @include *://www.google.ki/* // @include *://www.google.kg/* // @include *://www.google.co.kr/* // @include *://www.google.com.kw/* // @include *://www.google.kz/* // @include *://www.google.la/* // @include *://www.google.com.lb/* // @include *://www.google.li/* // @include *://www.google.lk/* // @include *://www.google.co.ls/* // @include *://www.google.lt/* // @include *://www.google.lu/* // @include *://www.google.lv/* // @include *://www.google.com.ly/* // @include *://www.google.co.ma/* // @include *://www.google.md/* // @include *://www.google.me/* // @include *://www.google.mg/* // @include *://www.google.mk/* // @include *://www.google.ml/* // @include *://www.google.mn/* // @include *://www.google.ms/* // @include *://www.google.com.mt/* // @include *://www.google.mu/* // @include *://www.google.mv/* // @include *://www.google.mw/* // @include *://www.google.com.mx/* // @include *://www.google.com.my/* // @include *://www.google.co.mz/* // @include *://www.google.com.na/* // @include *://www.google.com.nf/* // @include *://www.google.com.ng/* // @include *://www.google.com.ni/* // @include *://www.google.ne/* // @include *://www.google.nl/* // @include *://www.google.no/* // @include *://www.google.com.np/* // @include *://www.google.nr/* // @include *://www.google.nu/* // @include *://www.google.co.nz/* // @include *://www.google.com.om/* // @include *://www.google.com.pa/* // @include *://www.google.com.pe/* // @include *://www.google.com.ph/* // @include *://www.google.com.pk/* // @include *://www.google.pl/* // @include *://www.google.pn/* // @include *://www.google.com.pr/* // @include *://www.google.ps/* // @include *://www.google.pt/* // @include *://www.google.com.py/* // @include *://www.google.com.qa/* // @include *://www.google.ro/* // @include *://www.google.ru/* // @include *://www.google.rw/* // @include *://www.google.com.sa/* // @include *://www.google.com.sb/* // @include *://www.google.sc/* // @include *://www.google.se/* // @include *://www.google.com.sg/* // @include *://www.google.sh/* // @include *://www.google.si/* // @include *://www.google.sk/* // @include *://www.google.com.sl/* // @include *://www.google.sn/* // @include *://www.google.sm/* // @include *://www.google.st/* // @include *://www.google.com.sv/* // @include *://www.google.td/* // @include *://www.google.tg/* // @include *://www.google.co.th/* // @include *://www.google.com.tj/* // @include *://www.google.tk/* // @include *://www.google.tl/* // @include *://www.google.tm/* // @include *://www.google.tn/* // @include *://www.google.to/* // @include *://www.google.com.tr/* // @include *://www.google.tt/* // @include *://www.google.com.tw/* // @include *://www.google.co.tz/* // @include *://www.google.com.ua/* // @include *://www.google.co.ug/* // @include *://www.google.co.uk/* // @include *://www.google.com.uy/* // @include *://www.google.co.uz/* // @include *://www.google.com.vc/* // @include *://www.google.co.ve/* // @include *://www.google.vg/* // @include *://www.google.co.vi/* // @include *://www.google.com.vn/* // @include *://www.google.vu/* // @include *://www.google.ws/* // @include *://www.google.rs/* // @include *://www.google.co.za/* // @include *://www.google.co.zm/* // @include *://www.google.co.zw/* // @downloadURL none // ==/UserScript== var debug = false; cLog("Start"); // // Parses and puts in a hash map CGI URL parameters. // cLog("Window href:" + window.location.href); //debugLayer = { 'FORM3' : 1, 'PROF' : 1 }; debugLayer = { 'INJ': 1 }; var vars = null; function getUrlVars() { if (!vars) { vars = []; var hash; var positionQ = window.location.href.indexOf('?'); var positionS = window.location.href.indexOf('#'); if (positionQ > 0 && positionS > 0) position = Math.min(positionQ, positionS); else if (positionQ > 0) position = positionQ; else position = positionS; var hashes = window.location.href.slice(position + 1).split(/&|#/); for (var i = 0; i < hashes.length; i++) { cLog('VALUE:' + hashes[i]); hash = hashes[i].split('='); //vars.push(hash[0]); vars[hash[0]] = hash[1]; } // Possibly missing hl value is filled with languages value corresponding to TLD value if (!vars['hl']) vars['hl'] = domainsToLang[getTLD()]; // Possibly missing lr value is filled with languages value corresponding to TLD value if (!vars['lr']) vars['lr'] = "lang_" + domainsToLang[getTLD()]; } return vars; } function getTLD() { var tld = window.location.href.match(/\.(\w+?)(\/|$)/)[1]; cLog('TLD=' + tld); return tld; } cLog('TLD:' + getTLD()); // // Main // //var addPath = "/html/body/div/*/div/div[2]/div"; //var addPath = "/html/body/div/div/div[2]/div[@id='resultStats']"; //var addPath = "/html/body/div[@id='main']/div[@id='cnt']/div[@id='subform_ctrl']"; //var addSelector = '#resultStats'; var addPaths = ["//*[@id='resultStats']", "//*[@id='gbx1']"]; // // Add Possible Injection points below // // Places where to try injection of Language switcher box // var addSelectors = { "#resultStats": 1, "#slim_appbar": 1, "#extabar": 1, "#topabar": 1, ".med": 1, ".g": 1, ".appbar": 1 }; var addSelectors = [ ["#rhs > div:first-of-type", "addBeforeElem", ""], ["#appbar", "addAfterElem", "float:right;"], ]; var languageVars = ["hl", "#hl"]; var documentFormName = 'gbqf'; /* * Injected Code for querying as a different language */ var labels = ["en-US", "it", "fr", "de", "es", "cn/hk", "jp", "ru", "nl"]; //,"nl","ru","gr","jp","tr","cn","arb","il"); var languages = ["en", "it", "fr", "de", "es", "zh-CN", "ja", "ru", "nl"]; //,"nl","ru","el","ja","tr","zh-CN","ar","iw"); var domains = ["com", "it", "fr", "de", "es", "com.hk", "co.jp", "ru", "nl"]; var tlds = ["com", "it", "fr", "de", "es", "cn", "jp", "ru", "nl"]; var wikipediaDomains = ["en", "it", "fr", "de", "es", "zh", "ja", "ru", "nl"]; var domainsToLang = []; for (var i = 0; i < domains.length; i++) { domainsToLang[tlds[i]] = languages[i]; } var injectedObjectName = 'AGB_language_switcher'; var status = new Array(); var radioOn = "checked=\"checked\""; var radioOff = ""; for (var i = 0; i < labels.length; i++) { if ("lang_" + languages[i] != getUrlVars()["lr"]) status[languages[i]] = radioOff; else status[languages[i]] = radioOn; } cLog("GetURlVars=" + getUrlVars()); cLog("n_lang is=" + getUrlVars()["n_lang"]); cLog("hl is=" + getUrlVars()["hl"]); cLog("lr is=" + getUrlVars()["lr"]); cLog("q is=" + getUrlVars()["q"]); cLog("Languages[n_lang] is=" + status[getUrlVars()["hl"]]); var inject = "

Ask again on another local version: \
\ \ "; // // Prepare code for radio buttons to be injected in Google page results // var googleInjectFuncMap = {}; for (let i = 0; i < languages.length; i++) { googleInjectFuncMap["label_g_" + languages[i]] = function() { var a = window.location.href.slice(0); a = a.replace(/google\.(.*?)\//, 'google.' + domains[i] + '/'); if (!a.match(/(\?|\&)hl=/)) { a = a + '&hl='; } if (!a.match(/(\?|\&)lr=/)) { a = a + '&lr='; } a = a.replace(/hl=(.*?)(&|$)/, 'hl=' + languages[i] + '$2'); a = a.replace(/lr=(.*?)(&|$)/, 'lr=lang_' + languages[i] + '$2'); window.location.href = a; } //var clicInject = "document."+documentFormName+".hl.value ='"+languages[i]+"'; document."+documentFormName+".submit(); "; cLog("Injecting " + domains[i] + " code"); var checked = ("lang_" + languages[i] == getUrlVars()["lr"]) && (tlds[i] == getTLD() || true); inject += ""; } inject += ""; cLog("This is what I'm injecting:" + inject); /* function getClicFunction(i) { return function() { document[documentFormName].hl.value = languages[i]; document[documentFormName].submit(); }; } for (var i = 0; i < languages.length; i++) { inject.append($('"; var query = getUrlVars()["q"]; for (var i = 0; i < languages.length; i++) { var clicWikiInject = "window.location = 'http://" + wikipediaDomains[i] + ".wikipedia.org/?search=" + query + "';"; inject += ""; } inject += "
Google:   ').attr({ 'valign' : 'middle' }) .append($('').attr( { id : 'g_'+languages[i], type : 'radio', name : 'n_lang', value : languages[i]} ) )); } */ // // Adds Wikipedia radio buttons. Constructs xx.wikipedia.org for xx taken from wikipediaDomains[] // inject += "
Wikipedia:   
"; tryInjection(); document.addEventListener("DOMNodeInserted", function (event) { var element = event.target; //cLog("Node INSERTED "+element.name); //if (element.className == 'med') { tryInjection(); //} }); var alreadyInjected = false; function tryInjection() { if (alreadyInjected) return; var placeToInject = null; if (!document.getElementById(injectedObjectName)) { lLog("Starting injection", "INJ"); var selector; var insertMethod; var extraStyles; for (var pair of addSelectors) { selector = pair[0]; insertMethod = pair[1]; extraStyles = pair[2]; lLog("Attempting injection point: " + selector, "INJ"); if (placeToInject = document.querySelectorAll(selector)[0]) { lLog("Matched Selector:" + selector, "INJ"); break; } } lLog("Place to inject:" + placeToInject, "INJ"); if (placeToInject) { //placeToInject.innerHTML = ""+inject+"
" + placeToInject.innerHTML; // document.querySelectorAll("#appbar").forEach(el => { el.style.zIndex = 999 }); document.querySelectorAll(selector).forEach(el => { var mainElem = new DOMParser().parseFromString(inject, "text/html").body.firstChild; if (insertMethod === "addBeforeElem") { el.before(mainElem); } else { el.after(mainElem); } mainElem.setAttribute("style", extraStyles); }); for (var labelId in googleInjectFuncMap) { document.getElementById(labelId).onclick = googleInjectFuncMap[labelId]; } alreadyInjected = true; } lLog("Ending injection", "INJ"); } else lLog("Looks like there is already a language_switcher here.", "INJ2"); } function cLog(str) { if (debug) console.log(str); } /** * main logging function * @param str String to be printed * @param level debugLayer triggering the printout. Will be printed only if level is in the currently active debugLayers */ function lLog(str, level) { //console.log("Logging:"+str); if (!isNaN(level)) str += " USING NUMBERS FOR DEBUG LEVELS IS DEPRECATED - "; else if (level.match(/PROF/)) { str = this.debug.getPace() + "\n" + str; }; // console.log("mid Logging:"+this.debugLayer+" "+this.localLog); if (debugLayer == level || debugLayer == "ALL" || (debugLayer instanceof Object && debugLayer[level])) { cLog(str); } //console.log("end Logging:"+str); }; // // XPath evaluation wrapping function. // function xpath(query, node) { return document.evaluate(query, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); } // // Returns the first element of a given XPath query // function fXPath(query, node) { var elements = xpath(query, node); return elements.snapshotItem(0); } // // Returns the last element of a given XPath query // function lXPath(query, node) { cLog("Asking for " + query); var elements = xpath(query, node); cLog("Elements are " + elements.snapshotLength); return elements.snapshotItem(elements.snapshotLength - 1); } // // 0-ize NaN and non-number strings // function normalize(str) { var temp = (str != null) ? parseInt(str) : 0; return (isNaN(temp)) ? 0 : temp; }