您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
View a google search result in two languages side by side for comparison and language learning.
当前为
// ==UserScript== // @name google multilang search view en/zh // @name:zh 谷歌多语言搜索 en/zh // @namespace [email protected] // @author [email protected] // @version 0.0.2 // @description View a google search result in two languages side by side for comparison and language learning. // @description:zh 以并列多语言视角浏览谷歌搜索结果 // @match https://*.google.com/search?* // @match https://*.google.com*/search?* // @match https://*.google.com.hk/search?* // @match https://*.google.com.tw/search?* // @grant none // @run-at document-start // @license GPL-3.0+ // @supportURL https://github.com/snomiao/userscript.js/issues // @contributionURL https://snomiao.com/donate // @grant GM_getValue // @grant GM_setValue // ==/UserScript== const introURL = 'https://rapidapi.com/microsoft-azure-org-microsoft-cognitive-services/api/microsoft-translator-text/'; const intro = ` [Microsoft Translator Text API Documentation (microsoft-azure-org-microsoft-cognitive-services) | RapidAPI]( ${introURL} ) 1. Open ${introURL} 2. Sign up or login 3. Click Subscribe to Test 4. Copy your API key 4. Come back and paste here 5. OK `.trim(); (async function () { if (parent !== window) return iframeHeightSenderSetup(); iframeHeightReceiverSetup(); // const rapidAPIKey = (globalThis.rapidAPIKey = await rapidAPIKeyLoad()); if (!rapidAPIKey) throw new Error('no rapid api key'); const searchLinks = await getMultiLangSearchLinks(); replacePageWIthMultiLang(searchLinks); })(); function replacePageWIthMultiLang(searchLinks) { const iframes = searchLinks.map((src) => `<iframe src="${src}"></iframe>`); const style = `<style> body{margin: 0; display: flex; flex-direction: row;} iframe{flex: auto;height: 100vh;overflow: hidden;border: none;} </style>`; document.body.innerHTML = `${style}${iframes}`; } function iframeHeightReceiverSetup() { const setHeight = (height = 0) => height && [...document.querySelectorAll('iframe[src]')].map( (e) => (e.style.height = Math.max( Number(String(e.style.height).replace(/\D+/g, '') || 0), height ) + 'px') ); window.addEventListener('message', (e) => setHeight(e.data?.height), false); } function iframeHeightSenderSetup() { iframeScrollbarRemove(); const sendHeight = () => parent.postMessage?.({ height: document.body.scrollHeight }, '*'); window.addEventListener('resize', sendHeight, false); window.addEventListener('load', sendHeight, false); sendHeight(); } function iframeScrollbarRemove() { document.body.style.margin = '-18px auto 0'; } async function getMultiLangSearchLinks() { const url = new URL(location.href); const query = url.searchParams.get('q') || ''; const result = await bingTranslate(query); const searchLinks = result.flatMap((e) => e.translations.map((t) => { const u2 = new URL(url.href); return u2.searchParams.set('q', t.text), u2.href; }) ); return searchLinks; } async function bingTranslate(text = 'hello, world') { const body = JSON.stringify([{ Text: text }]); const exampleResponse = [ { detectedLanguage: { language: 'en', score: 1, }, translations: [ { text: '我真的很想把你的车开几个圈。', to: 'zh-Hans', }, { text: 'I would really like to drive your car around the block a few times.', to: 'en', }, ], }, ]; const ak = await rakGet(); if (!ak) throw new Error('no rapid api key is found'); const response = await fetch( 'https://microsoft-translator-text.p.rapidapi.com/translate?to%5B0%5D=zh%2Cen&api-version=3.0&profanityAction=NoAction&textType=plain', { method: 'POST', headers: { 'content-type': 'application/json', 'X-RapidAPI-Key': ak, 'X-RapidAPI-Host': 'microsoft-translator-text.p.rapidapi.com', }, body, } ) .then((r) => r.json()) .catch(async (e) => await rapidAPIKeyLoadNew('error: ' + e.message)); return response; } async function rapidAPIKeyLoad() { return (await rakGet()) || (await rapidAPIKeyLoadNew()); } async function rapidAPIKeyLoadNew(msg = '') { return ( window.open(introURL, '_blank'), await rakSet(prompt((msg + '\n' + intro).trim(), await rakGet()) || ''), await rakGet() ); } async function rakGet() { return ( (await globalThis.GM_getValue?.('rapidAPIKey', '')) || localStorage.getItem('rapidAPIKey') )?.replace(/^null$/, ''); } async function rakSet(v = '') { return ( (await (globalThis.GM_setValue && ((await globalThis.GM_setValue('rapidAPIKey', v || '')) || true))) || localStorage.setItem('rapidAPIKey', v || '') || true ); }