插件
Chrome 翻译扩展项目总结与文档
chrome翻译插件代码
本文档使用 MrDoc 发布
-
+
首页
chrome翻译插件代码
下面是两个文件中得代码,全部复制进去即可。 manifest.json ``` { "name": "有道翻译", "description": "选中英文文本自动翻译", "version": "1.0", "manifest_version": 3, "permissions": ["activeTab"], "content_scripts": [{ "matches": ["<all_urls>"], "js": ["content.js"], "run_at": "document_end", "all_frames": true }], "icons": { "16": "icons/icon16.png" } } ``` content.js ``` console.log('🚀 网页翻译扩展开始执行'); // 在页面上显示扩展状态 const statusDiv = document.createElement('div'); statusDiv.id = 'translator-status'; statusDiv.style.cssText = `position: fixed; top: 10px; left: 10px; background: #4CAF50; color: white; padding: 8px 12px; border-radius: 4px; z-index: 99999; font-family: Arial, sans-serif; font-size: 12px; display: none;`; statusDiv.textContent = '网页翻译已加载'; document.body.appendChild(statusDiv); // 全局状态 let isTranslating = false; let currentTranslateButton = null; let translationPopup = null; let lastButtonClickTime = 0; // 显示状态信息 function showStatus(message, isError = false) { statusDiv.textContent = message; statusDiv.style.background = isError ? '#f44336' : '#4CAF50'; statusDiv.style.display = 'block'; setTimeout(() => { statusDiv.style.display = 'none'; }, 2000); console.log('📢 ' + message); } // 主功能初始化 function initTranslator() { console.log('🔧 初始化翻译功能'); showStatus('翻译功能已启动'); // 监听文本选择 - 使用捕获阶段,确保在其他事件之前处理 document.addEventListener('mouseup', handleTextSelection, true); console.log('✅ 翻译功能初始化完成'); } // 处理文本选择 function handleTextSelection(event) { // 防止按钮点击触发新的文本选择 if (event.target.id === 'translate-button' || event.target.parentElement?.id === 'translate-button') { return; } // 防止频繁触发 const now = Date.now(); if (now - lastButtonClickTime < 500) { return; } const selectedText = window.getSelection().toString().trim(); if (!selectedText) return; console.log('📝 选中文本:', selectedText); if (/[a-zA-Z]/.test(selectedText)) { showTranslateButton(event, selectedText); } } // 显示翻译按钮 function showTranslateButton(event, text) { removeTranslateButton(); console.log('🎯 显示翻译按钮'); const translateButton = document.createElement('div'); translateButton.id = 'translate-button'; translateButton.textContent = '翻译'; translateButton.dataset.text = text; translateButton.style.cssText = `position: fixed; left: ${event.clientX + 10}px; top: ${event.clientY + 10}px; background: #e31436; color: white; border: none; border-radius: 16px; padding: 6px 12px; font-size: 12px; font-weight: 600; cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,0.2); z-index: 10000; font-family: Arial, sans-serif; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none;`; // 使用 mousedown 而不是 click,确保在 mouseup 之前处理 translateButton.addEventListener('mousedown', function(e) { e.preventDefault(); e.stopPropagation(); console.log('🔘 翻译按钮被点击,文本:', this.dataset.text); ``` // 记录点击时间 lastButtonClickTime = Date.now(); // 立即移除按钮 this.remove(); currentTranslateButton = null; // 开始翻译 translateText(this.dataset.text); return false; ``` }); // 阻止按钮上的 mouseup 事件冒泡 translateButton.addEventListener('mouseup', function(e) { e.stopPropagation(); }); document.body.appendChild(translateButton); currentTranslateButton = translateButton; showStatus('翻译按钮已显示'); } // 移除翻译按钮 function removeTranslateButton() { if (currentTranslateButton) { currentTranslateButton.remove(); currentTranslateButton = null; } } // 翻译文本 - 使用免费的翻译 API async function translateText(text) { console.log('🌐 开始翻译:', text); showStatus('翻译中...'); try { showTranslationPopup(text, '🔄 翻译中...'); ``` // 方案1: 使用 MyMemory 翻译 API (免费,无需密钥) const response = await fetch(`https://api.mymemory.translated.net/get?q=${encodeURIComponent(text)}&langpair=en|zh`); if (!response.ok) { throw new Error(`HTTP错误: ${response.status}`); } const data = await response.json(); console.log('📦 翻译结果:', data); let translation = ''; if (data.responseData && data.responseData.translatedText) { translation = data.responseData.translatedText; } else { throw new Error('未找到翻译结果'); } showTranslationPopup(text, translation); showStatus('翻译完成'); ``` } catch (error) { console.error('❌ 翻译错误:', error); ``` // 如果 MyMemory 失败,尝试备用方案 try { console.log('🔄 尝试备用翻译方案'); // 方案2: 使用 LibreTranslate (免费开源) const backupResponse = await fetch('https://libretranslate.de/translate', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ q: text, source: 'en', target: 'zh', format: 'text' }) }); if (backupResponse.ok) { const backupData = await backupResponse.json(); translation = backupData.translatedText; showTranslationPopup(text, translation); showStatus('翻译完成'); } else { throw new Error('备用翻译也失败'); } } catch (backupError) { console.error('❌ 备用翻译错误:', backupError); showTranslationPopup(text, `❌ 翻译失败: 请稍后重试`); showStatus('翻译失败', true); } ``` } finally { isTranslating = false; } } // 显示翻译弹窗 function showTranslationPopup(original, translation) { if (translationPopup) { translationPopup.remove(); } console.log('📤 显示翻译弹窗'); translationPopup = document.createElement('div'); translationPopup.id = 'translation-popup'; translationPopup.innerHTML = ` <div style=" position: fixed; top: 50px; right: 20px; background: white; border: 2px solid #e31436; border-radius: 10px; padding: 16px; max-width: 350px; box-shadow: 0 6px 20px rgba(0,0,0,0.15); z-index: 10001; font-family: Arial, sans-serif; font-size: 14px; "> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; border-bottom: 1px solid #f0f0f0; padding-bottom: 8px;"> <h3 style="margin: 0; color: #e31436; font-size: 16px;">网页翻译</h3> <button id="close-popup" style=" background: none; border: none; font-size: 18px; cursor: pointer; color: #999; padding: 0; ">×</button> </div> ``` <div style="margin-bottom: 12px;"> <div style="font-weight: bold; margin-bottom: 4px; color: #666;">原文:</div> <div style="background: #f8f9fa; padding: 8px; border-radius: 6px; border-left: 3px solid #e31436;"> ${escapeHtml(original)} </div> </div> <div style="margin-bottom: 12px;"> <div style="font-weight: bold; margin-bottom: 4px; color: #666;">翻译:</div> <div style="background: #fff5f6; padding: 8px; border-radius: 6px; border-left: 3px solid #52c41a; color: #e31436;"> ${escapeHtml(translation)} </div> </div> <div style="display: flex; justify-content: space-between; align-items: center; margin-top: 12px; padding-top: 8px; border-top: 1px solid #f0f0f0;"> <span style="font-size: 11px; color: #999;">点击外部关闭</span> <button id="copy-translation" style=" background: #e31436; color: white; border: none; padding: 4px 8px; border-radius: 4px; font-size: 12px; cursor: pointer; ">复制译文</button> </div> </div> ``` `; document.body.appendChild(translationPopup); // 绑定关闭按钮事件 const closeButton = document.getElementById('close-popup'); closeButton.onclick = function() { console.log('❌ 关闭弹窗'); removeTranslationPopup(); }; // 绑定复制按钮事件 const copyButton = document.getElementById('copy-translation'); copyButton.onclick = function() { console.log('📋 复制译文'); const translationText = translationPopup.querySelector('div > div:nth-child(3) > div:nth-child(2)').textContent; navigator.clipboard.writeText(translationText).then(() => { copyButton.textContent = '已复制!'; copyButton.style.background = '#52c41a'; setTimeout(() => { copyButton.textContent = '复制译文'; copyButton.style.background = '#e31436'; }, 2000); }); }; // 点击外部关闭 setTimeout(() => { const outsideClickHandler = function(e) { if (translationPopup && !translationPopup.contains(e.target)) { console.log('🌐 点击外部关闭弹窗'); removeTranslationPopup(); document.removeEventListener('click', outsideClickHandler); } }; document.addEventListener('click', outsideClickHandler); translationPopup._outsideClickHandler = outsideClickHandler; }, 100); // 80秒后自动关闭 translationPopup._autoCloseTimer = setTimeout(() => { if (translationPopup && translationPopup.parentNode) { console.log('⏰ 自动关闭弹窗'); removeTranslationPopup(); } }, 80000); } // 移除翻译弹窗 function removeTranslationPopup() { if (translationPopup) { if (translationPopup._autoCloseTimer) { clearTimeout(translationPopup._autoCloseTimer); } ``` if (translationPopup._outsideClickHandler) { document.removeEventListener('click', translationPopup._outsideClickHandler); } translationPopup.remove(); translationPopup = null; ``` } } // HTML转义 function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // 页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initTranslator); } else { initTranslator(); } console.log('✅ 网页翻译扩展加载完成'); showStatus('网页翻译已就绪');
沧岚
2025年11月1日 13:01
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码