网页翻译

给每个非中文的网页右下角(可以调整到左下角)添加一个google翻译图标,直接调用 Google 的翻译接口对非中文网页进行翻译

< 网页翻译についてのフィードバック

レート:良 – スクリプトは良好に動作する

§
投稿日: 2023/03/30

大佬,帮我看下我照抄你的代码,为什么不能运行呢,我看也没啥错误啊。 请指点一下。

// ==UserScript==
// @name         Simplified Chinese Toggle
// @namespace    https://gitee.com/Kaiter-Plus/TampermonkeyScript/tree/master/Translate
// @version      1.0
// @description  Toggle between Simplified Chinese and original webpage
// @author       Your Name
// @match        *://*/*
// @noframes
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_notification
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// ==/UserScript==

try {
(function() {
  'use strict';

  class TranslateToggle {
      constructor() {
          this.isTranslated = false;
          this.isEnabled = GM_getValue('isEnabled', false);
          this._initStyles();
          this._createEnableButton();
          this._bindEnableButton();

          if (this.isEnabled) {
              this._createToggleButton();
              this._bindToggleButton();
              this._excludeCodeTranslation();
          }
      }

    _initStyles() {
      GM_addStyle(`
        .toggleButton {
          position: fixed;
          top: 20px;
          right: 0;
          width: 2em;
          height: 2em;
          line-height: 2em;
          background: #fff;
          border: 1px solid #999;
          border-radius: 4px;
          text-align: center;
          font-size: 1.2em;
          color: #333;
          cursor: pointer;
          z-index: 999999;
          box-shadow: 1px 1px 3px 0 #999;
          user-select: none;
        }

        .toggleButton:hover {
          background: #f5f5f5;
        }

        .toggleButton:active {
          box-shadow: 1px 1px 3px 0 #888 inset;
        }
        .enableButton {
          position: fixed;
          top: 60px;
          right: 0;
          width: 6em;
          height: 2em;
          line-height: 2em;
          background: #fff;
          border: 1px solid #999;
          border-radius: 4px;
          text-align: center;
          font-size: 1.2em;
          color: #333;
          cursor: pointer;
          z-index: 999999;
          box-shadow: 1px 1px 3px 0 #999;
          user-select: none;
        }

        .enableButton:hover {
          background: #f5f5f5;
        }

        .enableButton:active {
          box-shadow: 1px 1px 3px 0 #888 inset;
        }
      `);
    }

      _loadGoogleTranslateLibrary() {
          window.googleTranslateElementInit = this._googleTranslateElementInit.bind(this);
          const script = document.createElement('script');
          script.src = 'https://translate.google.com/translate_a/element.js?&cb=googleTranslateElementInit';
          document.head.appendChild(script);
          console.log('Loading Google Translate Library');
      }

      _googleTranslateElementInit() {
          new window.google.translate.TranslateElement({
              pageLanguage: 'auto',
              includedLanguages: 'zh-CN',
              layout: window.google.translate.TranslateElement.FloatPosition.TOP_LEFT
          }, 'google_translate_element');
          console.log('Initializing Google Translate Element');
      }


      _createEnableButton() {
          this.enableButton = document.createElement('div');
          this.enableButton.className = 'notranslate enableButton';
          this.enableButton.innerText = '启用';
          document.body.appendChild(this.enableButton);
      }

      _bindEnableButton() {
          this.enableButton.onclick = () => {
              console.log('Enable button clicked');
              this.isEnabled = !this.isEnabled;
              GM_setValue('isEnabled', this.isEnabled);
              if (this.isEnabled) {
                  this._createToggleButton();
                  this._bindToggleButton();
                  this._loadGoogleTranslateLibrary();
                  this._excludeCodeTranslation();
              } else {
                  this.toggleButton.remove();
                  // Restore the page to the untranslated state
                  if (this.isTranslated) {
                      this._restoreOriginalPage();
                      this.isTranslated = false;
                  }
              }
          };
      }

    _createToggleButton() {
      this.toggleButton = document.createElement('div');
      this.toggleButton.className = 'notranslate toggleButton';
      this.toggleButton.innerText = this.isTranslated ? '原' : '简';
      document.body.appendChild(this.toggleButton);
    }

    _bindToggleButton() {
      this.toggleButton.onclick = () => {
          console.log('Toggle button clicked');
          if (!this.isTranslated) {
              this._translateToSimplifiedChinese();
          } else {
              this._restoreOriginalPage();
          }
          this.isTranslated = !this.isTranslated;
          this.toggleButton.innerText = this.isTranslated ? '原' : '简';
      };
    }

      _excludeCodeTranslation() {
          const codeSelectors = [
              '.bbCodeCode',
              'tt',
              'pre[translate="no"]',
              'pre',
              '.post_spoiler_show',
              '.c-article-section__content sub',
              '.c-article-section__content sup',
              '.c-article-equation',
              '.mathjax-tex'
          ];

          codeSelectors.forEach(selector => {
              const elements = document.querySelectorAll(selector);
              elements.forEach(element => {
                  if (!element.classList.contains('notranslate')) {
                      element.classList.add('notranslate');
                  }
              });
          });
      }

    _translateToSimplifiedChinese() {
        console.log('Translating to Simplified Chinese');
        const translateIframe = document.getElementById(':2.container') || document.getElementById(':1.container');
        if (translateIframe) {
            const translateDocument = translateIframe.contentWindow.document;
            translateDocument.querySelector('.goog-te-combo').value = 'zh-CN';
            translateDocument.querySelector('.goog-te-combo').dispatchEvent(new Event('change'));
        }
    }

    _restoreOriginalPage() {
      const recoverIframe = document.getElementById(':2.container') || document.getElementById(':1.container');
      if (recoverIframe) {
        const recoverDocument = recoverIframe.contentWindow.document;
        recoverDocument.getElementById(recoverIframe.id + '.restore').click();
      }
    }
  }

    // 在页面加载后等待一段时间,然后执行翻译操作
    window.setTimeout(() => {
        const translateToggle = new TranslateToggle();
        if (GM_getValue('isEnabled', false)) {
            translateToggle._loadGoogleTranslateLibrary();
            window.googleTranslateElementInit = translateToggle._googleTranslateElementInit.bind(translateToggle);
        }
    }, 5000);


})();

} catch (error) {
  console.error('An error occurred:', error);
}

Kaiter-Plus作者
§
投稿日: 2023/04/01

稍微看了下,其实最主要的问题还是脚本加载进来之后没有初始化。 你看下请求的地址后面是不是带了一个叫cb的参数,这个参数的值是可以随便写的,但是你写的参数的值必须定义一个函数。。 可以类比 JSONP,其实应该就是使用 JSONP 的实现。 你可以在 _translateToSimplifiedChinese 函数内调试,就会发现 translateIframe 为 null

Kaiter-Plus作者
§
投稿日: 2023/04/01

还有一个问题就是,如果你直接把方法定义在 window 上它也不会调用,目前不知道原因,这也是我使用创建 script 元素来初始化的原因

返信を投稿

返信を投稿するにはログインしてください。