Language Switcher for Google™

a port of Language Switcher for Google™ to userscript.js

当前为 2021-01-13 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Language Switcher for Google™
  3. // @author gb.ianni
  4. // @namespace gb.ianni
  5. // @version 2.2.1
  6. // @copyright Copyright 2015 gb.ianni
  7. // @description a port of Language Switcher for Google™ to userscript.js
  8. // @include *://www.google.com/*
  9. // @include *://www.google.ad/*
  10. // @include *://www.google.ae/*
  11. // @include *://www.google.com.af/*
  12. // @include *://www.google.com.ag/*
  13. // @include *://www.google.com.ai/*
  14. // @include *://www.google.am/*
  15. // @include *://www.google.co.ao/*
  16. // @include *://www.google.com.ar/*
  17. // @include *://www.google.as/*
  18. // @include *://www.google.at/*
  19. // @include *://www.google.com.au/*
  20. // @include *://www.google.az/*
  21. // @include *://www.google.ba/*
  22. // @include *://www.google.com.bd/*
  23. // @include *://www.google.be/*
  24. // @include *://www.google.bf/*
  25. // @include *://www.google.bg/*
  26. // @include *://www.google.com.bh/*
  27. // @include *://www.google.bi/*
  28. // @include *://www.google.bj/*
  29. // @include *://www.google.com.bn/*
  30. // @include *://www.google.com.bo/*
  31. // @include *://www.google.com.br/*
  32. // @include *://www.google.bs/*
  33. // @include *://www.google.co.bw/*
  34. // @include *://www.google.by/*
  35. // @include *://www.google.com.bz/*
  36. // @include *://www.google.ca/*
  37. // @include *://www.google.cd/*
  38. // @include *://www.google.cf/*
  39. // @include *://www.google.cg/*
  40. // @include *://www.google.ch/*
  41. // @include *://www.google.ci/*
  42. // @include *://www.google.co.ck/*
  43. // @include *://www.google.cl/*
  44. // @include *://www.google.cm/*
  45. // @include *://www.google.cn/*
  46. // @include *://www.google.com.co/*
  47. // @include *://www.google.co.cr/*
  48. // @include *://www.google.com.cu/*
  49. // @include *://www.google.cz/*
  50. // @include *://www.google.de/*
  51. // @include *://www.google.dj/*
  52. // @include *://www.google.dk/*
  53. // @include *://www.google.dm/*
  54. // @include *://www.google.com.do/*
  55. // @include *://www.google.dz/*
  56. // @include *://www.google.com.ec/*
  57. // @include *://www.google.ee/*
  58. // @include *://www.google.com.eg/*
  59. // @include *://www.google.es/*
  60. // @include *://www.google.com.et/*
  61. // @include *://www.google.fi/*
  62. // @include *://www.google.com.fj/*
  63. // @include *://www.google.fm/*
  64. // @include *://www.google.fr/*
  65. // @include *://www.google.ga/*
  66. // @include *://www.google.ge/*
  67. // @include *://www.google.gg/*
  68. // @include *://www.google.com.gh/*
  69. // @include *://www.google.com.gi/*
  70. // @include *://www.google.gl/*
  71. // @include *://www.google.gm/*
  72. // @include *://www.google.gp/*
  73. // @include *://www.google.gr/*
  74. // @include *://www.google.com.gt/*
  75. // @include *://www.google.gy/*
  76. // @include *://www.google.com.hk/*
  77. // @include *://www.google.hn/*
  78. // @include *://www.google.hr/*
  79. // @include *://www.google.ht/*
  80. // @include *://www.google.hu/*
  81. // @include *://www.google.co.id/*
  82. // @include *://www.google.ie/*
  83. // @include *://www.google.co.il/*
  84. // @include *://www.google.im/*
  85. // @include *://www.google.co.in/*
  86. // @include *://www.google.iq/*
  87. // @include *://www.google.is/*
  88. // @include *://www.google.it/*
  89. // @include *://www.google.je/*
  90. // @include *://www.google.com.jm/*
  91. // @include *://www.google.jo/*
  92. // @include *://www.google.co.jp/*
  93. // @include *://www.google.co.ke/*
  94. // @include *://www.google.com.kh/*
  95. // @include *://www.google.ki/*
  96. // @include *://www.google.kg/*
  97. // @include *://www.google.co.kr/*
  98. // @include *://www.google.com.kw/*
  99. // @include *://www.google.kz/*
  100. // @include *://www.google.la/*
  101. // @include *://www.google.com.lb/*
  102. // @include *://www.google.li/*
  103. // @include *://www.google.lk/*
  104. // @include *://www.google.co.ls/*
  105. // @include *://www.google.lt/*
  106. // @include *://www.google.lu/*
  107. // @include *://www.google.lv/*
  108. // @include *://www.google.com.ly/*
  109. // @include *://www.google.co.ma/*
  110. // @include *://www.google.md/*
  111. // @include *://www.google.me/*
  112. // @include *://www.google.mg/*
  113. // @include *://www.google.mk/*
  114. // @include *://www.google.ml/*
  115. // @include *://www.google.mn/*
  116. // @include *://www.google.ms/*
  117. // @include *://www.google.com.mt/*
  118. // @include *://www.google.mu/*
  119. // @include *://www.google.mv/*
  120. // @include *://www.google.mw/*
  121. // @include *://www.google.com.mx/*
  122. // @include *://www.google.com.my/*
  123. // @include *://www.google.co.mz/*
  124. // @include *://www.google.com.na/*
  125. // @include *://www.google.com.nf/*
  126. // @include *://www.google.com.ng/*
  127. // @include *://www.google.com.ni/*
  128. // @include *://www.google.ne/*
  129. // @include *://www.google.nl/*
  130. // @include *://www.google.no/*
  131. // @include *://www.google.com.np/*
  132. // @include *://www.google.nr/*
  133. // @include *://www.google.nu/*
  134. // @include *://www.google.co.nz/*
  135. // @include *://www.google.com.om/*
  136. // @include *://www.google.com.pa/*
  137. // @include *://www.google.com.pe/*
  138. // @include *://www.google.com.ph/*
  139. // @include *://www.google.com.pk/*
  140. // @include *://www.google.pl/*
  141. // @include *://www.google.pn/*
  142. // @include *://www.google.com.pr/*
  143. // @include *://www.google.ps/*
  144. // @include *://www.google.pt/*
  145. // @include *://www.google.com.py/*
  146. // @include *://www.google.com.qa/*
  147. // @include *://www.google.ro/*
  148. // @include *://www.google.ru/*
  149. // @include *://www.google.rw/*
  150. // @include *://www.google.com.sa/*
  151. // @include *://www.google.com.sb/*
  152. // @include *://www.google.sc/*
  153. // @include *://www.google.se/*
  154. // @include *://www.google.com.sg/*
  155. // @include *://www.google.sh/*
  156. // @include *://www.google.si/*
  157. // @include *://www.google.sk/*
  158. // @include *://www.google.com.sl/*
  159. // @include *://www.google.sn/*
  160. // @include *://www.google.sm/*
  161. // @include *://www.google.st/*
  162. // @include *://www.google.com.sv/*
  163. // @include *://www.google.td/*
  164. // @include *://www.google.tg/*
  165. // @include *://www.google.co.th/*
  166. // @include *://www.google.com.tj/*
  167. // @include *://www.google.tk/*
  168. // @include *://www.google.tl/*
  169. // @include *://www.google.tm/*
  170. // @include *://www.google.tn/*
  171. // @include *://www.google.to/*
  172. // @include *://www.google.com.tr/*
  173. // @include *://www.google.tt/*
  174. // @include *://www.google.com.tw/*
  175. // @include *://www.google.co.tz/*
  176. // @include *://www.google.com.ua/*
  177. // @include *://www.google.co.ug/*
  178. // @include *://www.google.co.uk/*
  179. // @include *://www.google.com.uy/*
  180. // @include *://www.google.co.uz/*
  181. // @include *://www.google.com.vc/*
  182. // @include *://www.google.co.ve/*
  183. // @include *://www.google.vg/*
  184. // @include *://www.google.co.vi/*
  185. // @include *://www.google.com.vn/*
  186. // @include *://www.google.vu/*
  187. // @include *://www.google.ws/*
  188. // @include *://www.google.rs/*
  189. // @include *://www.google.co.za/*
  190. // @include *://www.google.co.zm/*
  191. // @include *://www.google.co.zw/*
  192. // ==/UserScript==
  193.  
  194. var debug = false;
  195.  
  196. cLog("Start");
  197.  
  198. //
  199. // Parses and puts in a hash map CGI URL parameters.
  200. //
  201. cLog("Window href:"+window.location.href);
  202.  
  203. //debugLayer = { 'FORM3' : 1, 'PROF' : 1 };
  204. debugLayer = { 'INJ' : 1 };
  205.  
  206. var vars = null;
  207. function getUrlVars()
  208.  
  209. {
  210. if (!vars) {
  211. vars = [];
  212. var hash;
  213. var positionQ = window.location.href.indexOf('?');
  214. var positionS = window.location.href.indexOf('#');
  215.  
  216. if (positionQ > 0 && positionS > 0)
  217. position = Math.min(positionQ,positionS);
  218. else if (positionQ > 0)
  219. position = positionQ;
  220. else position = positionS;
  221.  
  222. var hashes = window.location.href.slice(position+1).split(/&|#/);
  223.  
  224. for(var i = 0; i < hashes.length; i++)
  225. {
  226. cLog('VALUE:'+hashes[i]);
  227. hash = hashes[i].split('=');
  228. //vars.push(hash[0]);
  229. vars[hash[0]] = hash[1];
  230.  
  231. }
  232. // Possibly missing hl value is filled with languages value corresponding to TLD value
  233. if (!vars['hl'])
  234. vars['hl'] = domainsToLang[getTLD()];
  235. // Possibly missing lr value is filled with languages value corresponding to TLD value
  236. if (!vars['lr'])
  237. vars['lr'] = "lang_" + domainsToLang[getTLD()];
  238. }
  239. return vars;
  240. }
  241.  
  242. function getTLD()
  243. {
  244. var tld = window.location.href.match(/\.(\w+?)(\/|$)/)[1];
  245. cLog('TLD='+tld);
  246. return tld;
  247. }
  248. cLog('TLD:'+getTLD());
  249.  
  250. //
  251. // Main
  252. //
  253.  
  254.  
  255. //var addPath = "/html/body/div/*/div/div[2]/div";
  256. //var addPath = "/html/body/div/div/div[2]/div[@id='resultStats']";
  257. //var addPath = "/html/body/div[@id='main']/div[@id='cnt']/div[@id='subform_ctrl']";
  258. //var addSelector = '#resultStats';
  259. var addPaths = [ "//*[@id='resultStats']", "//*[@id='gbx1']" ];
  260.  
  261. //
  262. // Add Possible Injection points below
  263. //
  264. // Places where to try injection of Language switcher box
  265. var addSelectors = { "#resultStats" : 1, "#slim_appbar" : 1, "#extabar" : 1, "#topabar" : 1, ".med" : 1, ".g" : 1, ".appbar" : 1};
  266. var languageVars = [ "hl", "#hl" ];
  267. var documentFormName = 'gbqf';
  268.  
  269. /*
  270. * Injected Code for querying as a different language
  271. */
  272. var labels = ["en-US", "it", "fr","de","es","cn/hk","jp","ru","nl"];
  273. //,"nl","ru","gr","jp","tr","cn","arb","il");
  274.  
  275. var languages = ["en","it","fr","de","es","zh-CN","ja","ru","nl"];
  276. //,"nl","ru","el","ja","tr","zh-CN","ar","iw");
  277.  
  278. var domains = ["com", "it", "fr", "de", "es", "com.hk", "co.jp","ru","nl"];
  279. var tlds = ["com", "it", "fr", "de", "es", "cn", "jp","ru","nl"];
  280.  
  281. var wikipediaDomains = ["en", "it","fr","de","es","zh","ja","ru","nl"];
  282.  
  283. var domainsToLang = [];
  284.  
  285. for (var i = 0; i < domains.length; i++)
  286. {
  287. domainsToLang[tlds[i]] = languages[i];
  288. }
  289.  
  290. var injectedObjectName = 'AGB_language_switcher';
  291.  
  292. var status = new Array();
  293.  
  294. var radioOn = "checked=\"checked\"";
  295. var radioOff = "";
  296.  
  297. for (var i = 0; i < labels.length; i++)
  298. {
  299. if ("lang_" + languages[i] != getUrlVars()["lr"] )
  300. status[languages[i]] = radioOff;
  301. else
  302. status[languages[i]] = radioOn;
  303. }
  304.  
  305. cLog("GetURlVars="+getUrlVars());
  306. cLog("n_lang is="+getUrlVars()["n_lang"]);
  307. cLog("hl is="+getUrlVars()["hl"]);
  308. cLog("lr is="+getUrlVars()["lr"]);
  309. cLog("q is="+getUrlVars()["q"]);
  310. cLog("Languages[n_lang] is="+status[getUrlVars()["hl"]]);
  311.  
  312.  
  313. var inject = "<div id='"+injectedObjectName+"' class='q qs', style='float:right'><br>Ask again on another local version: \
  314. <table width='100%' border='0' cellpadding='0' cellspacing='0' style='position:static'><td> \
  315. <table border='0' cellpadding='0' cellspacing='0'> \
  316. <tbody><tr><th scope='row' align='left'>Google:</th>";
  317.  
  318. //
  319. // Prepare code for radio buttons to be injected in Google page results
  320. //
  321.  
  322.  
  323.  
  324. for (var i = 0; i < languages.length; i++)
  325. {
  326. //var clicInject = "document."+documentFormName+".hl.value ='"+languages[i]+"'; document."+documentFormName+".submit(); ";
  327. cLog("Injecting "+domains[i]+" code");
  328. var clicInject =
  329. "console.log('clic"+domains[i]+"'); var a = window.location.href.slice(0); " +
  330. "console.log(a); a = a.replace(/google\\.(.*?)\\//,'google."+domains[i]+"/');" +
  331. "console.log(a); if (!a.match( /(\\?|\\&)hl=/ )) a = a + '&hl='; " +
  332. "console.log(a); if (!a.match( /(\\?|\\&)lr=/ )) a = a + '&lr='; " +
  333. "a = a.replace(/hl=(.*?)(&|$)/,'hl="+languages[i]+"$2'); " +
  334. "a = a.replace(/lr=(.*?)(&|$)/,'lr=lang_"+languages[i]+"$2'); " +
  335. "console.log(a); " +
  336. "window.location.href =a; " +
  337. "console.log('clac"+domains[i]+"');";
  338. var checked = ("lang_" + languages[i] == getUrlVars()["lr"]) && (tlds[i] == getTLD() || true);
  339.  
  340. inject += "<td nowrap valign='middle'><label for=il \
  341. onClick=\""+clicInject+"\" style=\"font-size:large;\"><input id='g_"+languages[i]+"' "+(checked ? ' checked ' :'')+"type=radio name=n_lang value='"+languages[i]+"'>"+labels[i]+"</label></td>";
  342. }
  343. inject += "<td>&nbsp;&nbsp;&nbsp;</td>";
  344. cLog("This is what I'm injecting:"+inject);
  345. /*
  346. function getClicFunction(i)
  347. {
  348. return function() { document[documentFormName].hl.value = languages[i]; document[documentFormName].submit(); };
  349. }
  350. for (var i = 0; i < languages.length; i++)
  351. {
  352. inject.append($('<td>').attr({ 'valign' : 'middle' })
  353. .append($('<input>').attr( { id : 'g_'+languages[i], type : 'radio', name : 'n_lang', value : languages[i]}
  354. )
  355. ));
  356. }
  357. */
  358. //
  359. // Adds Wikipedia radio buttons. Constructs xx.wikipedia.org for xx taken from wikipediaDomains[]
  360. //
  361. inject += "</tr><tr><th scope='row' align='left'>Wikipedia:</th>";
  362. var query = getUrlVars()["q"];
  363. for (var i = 0; i < languages.length; i++)
  364. {
  365. var clicWikiInject = "window.location = 'http://"+wikipediaDomains[i]+".wikipedia.org/?search="+query+"';";
  366.  
  367. inject += "<td nowrap valign='middle'><input id=g_w"+languages[i]+" type=radio name=n_lang value='w"+languages[i]+"' \
  368. onClick=\""+clicWikiInject+"\"><label for=il>"+labels[i]+"</label></td>";
  369.  
  370. }
  371. inject += "<td>&nbsp;&nbsp;&nbsp;</td></tr></tbody></table></td></table>";
  372.  
  373. tryInjection();
  374. document.addEventListener("DOMNodeInserted", function(event){
  375. var element = event.target;
  376. //cLog("Node INSERTED "+element.name);
  377. //if (element.className == 'med') {
  378. tryInjection();
  379. //}
  380. });
  381.  
  382. var alreadyInjected = false;
  383. function tryInjection()
  384. {
  385. if (alreadyInjected) return;
  386. var placeToInject = null;
  387. if (!document.getElementById(injectedObjectName)) {
  388. lLog("Starting injection","INJ");
  389.  
  390. for (var selector in addSelectors) {
  391. lLog("Attempting injection point: "+selector,"INJ");
  392. if (placeToInject = document.querySelectorAll(selector)[0])
  393. {
  394. lLog("Matched Selector:"+selector,"INJ"); break;
  395. }
  396. }
  397. lLog("Place to inject:"+placeToInject,"INJ");
  398. if (placeToInject)
  399. {
  400. //placeToInject.innerHTML = "<td>"+inject+"</td></div>" + placeToInject.innerHTML;
  401. document.querySelectorAll(selector).forEach(el => el.after(new DOMParser().parseFromString(inject, "text/html").body.firstChild));
  402. alreadyInjected = true;
  403. }
  404. lLog("Ending injection","INJ");
  405.  
  406. }
  407. else lLog("Looks like there is already a language_switcher here.","INJ2");
  408. }
  409.  
  410. function cLog(str)
  411. {
  412. if (debug) console.log(str);
  413. }
  414.  
  415. /**
  416. * main logging function
  417. * @param str String to be printed
  418. * @param level debugLayer triggering the printout. Will be printed only if level is in the currently active debugLayers
  419. */
  420.  
  421. function lLog(str, level) {
  422. //console.log("Logging:"+str);
  423. if (!isNaN(level))
  424. str += " USING NUMBERS FOR DEBUG LEVELS IS DEPRECATED - ";
  425. else if (level.match(/PROF/))
  426. {
  427. str = this.debug.getPace() + "\n" + str;
  428. };
  429. // console.log("mid Logging:"+this.debugLayer+" "+this.localLog);
  430.  
  431. if (debugLayer == level || debugLayer == "ALL" || (debugLayer instanceof Object && debugLayer[level]) )
  432. { cLog(str); }
  433. //console.log("end Logging:"+str);
  434.  
  435. };
  436.  
  437. //
  438. // XPath evaluation wrapping function.
  439. //
  440. function xpath(query,node) {
  441. return document.evaluate(query, node, null,
  442. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  443. }
  444.  
  445. //
  446. // Returns the first element of a given XPath query
  447. //
  448. function fXPath(query,node)
  449. {
  450. var elements = xpath(query,node);
  451. return elements.snapshotItem(0);
  452. }
  453.  
  454. //
  455. // Returns the last element of a given XPath query
  456. //
  457. function lXPath(query,node)
  458. {
  459. cLog("Asking for "+query);
  460. var elements = xpath(query,node);
  461. cLog("Elements are "+elements.snapshotLength);
  462. return elements.snapshotItem(elements.snapshotLength-1);
  463. }
  464.  
  465. //
  466. // 0-ize NaN and non-number strings
  467. //
  468. function normalize(str) {
  469. var temp = (str != null) ? parseInt(str) : 0;
  470. return (isNaN(temp)) ? 0 : temp;
  471. }

QingJ © 2025

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