kiến thức Dùng AI để dịch mọi thứ

  • Người tạo chủ đề Người tạo chủ đề ChuSyThang21
  • Ngày bắt đầu Ngày bắt đầu
thím chia sẻ cách tìm ra giải pháp với AI được không, kiểu là cách hỏi như nào ý :D
mình dùng Qtranslate đó mà dịch máy chán quá nhiều lúc hơi khó hiểu nên p tìm giải pháp thay thế đó thím.Ngoài ra cx dựa vào cái immersion extension nữa, cái n thì add api bị lỗi nên mình ném cho AI làm cái riêng của mình luôn
 
mình dùng Qtranslate đó mà dịch máy chán quá nhiều lúc hơi khó hiểu nên p tìm giải pháp thay thế đó thím.Ngoài ra cx dựa vào cái immersion extension nữa, cái n thì add api bị lỗi nên mình ném cho AI làm cái riêng của mình luôn
ý mình là cách thím nói chuyện với AI để ra được cái tool ấy :love:
 
1739418983367.png


em cài trên chrome không được :(
 
Hôm bữa mình có lên bài tìm app dịch giống Qtranslate nhưng không thấy ổn cái nào.
Do đó mình nhờ đến AI để nó giúp tìm giải pháp.
Đầu tiên, mọi người tải Violenmonkey về vì mình sẽ tạo scripts để dùng API của AI Studio để dịch (free 100%)
Tiếp đó mọi người dùng đoạn scripts bến dưới add vào, thay API và địa chỉ API rồi sau đó sử dụng.
*Lưu ý: Mình không biết gì về code, chỉ lên ý tưởng để AI làm và đến giờ dùng thì thấy ổn nên nếu hỏi chuyên môn code thì mình ko biết TL. MN có thể thêm ý tưởng vào các AI rồi bắt nó sửa cho mình.
Mọi người có thể lấy API tại đây hoặc gõ vào gg AI Studio (CỦa google nên ko lo virus j nhé)
"Sign in - Google Accounts (https://aistudio.google.com/apikey)"
Mình tạo ra 3 nút phím tắt:
Xem tệp đính kèm 2913915 (CTRL + m : Tạo 1 bản dịch bên dưới bản tiếng anh)
Xem tệp đính kèm 2913916 (ALT + m : Cái này mụcđíchđể học tiếng anh, sẽ tạo popup dịch, xácđịnh keywords , coi nhưđể học từ mới)
Cách dùng scripts này để dịch file pdf (theo đoạn bôi đen, không dịch được cả file 1 lần)
Xem tệp đính kèm 2913919 ( ALT + t :Giống CTRL m nhưng tạo popup)
Tuy nhiên, với các file pdf như mình dùng edge sẽ không cho dùng extention nên mọi người dùng link này để mở file pdf, sẽ cho phép dùng extension.
"PDF.js viewer (https://pdf.translatewebpages.org/pdf.js/web/viewer)"
Mã:
// ==UserScript==
// @name         Gemini AI Inline Translator (Popup)
// @namespace    http://tampermonkey.net/
// @version      2.8
// @description  Dịch văn bản bôi đen bằng Google Gemini API, có phím tắt, sửa lỗi ký tự, đảm bảo chỉ dịch một lần và có nút đóng. Cải thiện chất lượng dịch. Hỗ trợ phân tích từ vựng (Alt + M) hiển thị trong popup và dịch nhanh (Alt + T).
// @author       Your Name
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// ==/UserScript==
(function () {
    'use strict';

    // API Key của bạn
    const API_KEY = 'THAY API KEY VÀO ĐÂY NH MN'; // Thay thế bằng API Key của bạn
    const API_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${API_KEY}`;

    // Biến để theo dõi trạng thái dịch
    let isTranslating = false;

     // Add CSS for the draggable popup
    GM_addStyle(`
        .draggable {
          cursor: move;
        }
    `);

    // Hàm gọi API Gemini để dịch văn bản
     function translateText(text, targetElement, isAdvanced = false, displaySimple = false) {
        if (isTranslating) return; // Ngăn chặn dịch trùng lặp
        isTranslating = true;

         // Prompt cải tiến để dịch tự nhiên hơn, không word-by-word
        let prompt = `Translate the following text to Vietnamese in a natural and fluent way, avoiding word-by-word translation. Focus on conveying the meaning and intent of the original text, rather than a literal conversion: "${text}"`;

        if (isAdvanced) {
            prompt = `Translate the following text to Vietnamese in a natural and fluent way, avoiding word-by-word translation. After that, analyze the following text and select 2-5 relevant keywords. For each keyword, provide the definition from the Oxford Dictionary, along with its part of speech, a Vietnamese translation of the definition, synonyms (separated by commas), antonyms (separated by commas). Select an example sentence for each keyword from the original text and provide a Vietnamese translation of that example sentence. Format the output as follows:  <br><b>KEYWORD</b>: Keyword<br> + Định nghĩa:<br>Definition from Oxford dictionary<br> - Bản dịch định nghĩa: vietnamese definition <br> + Loại từ: Part of speech <br> + Từ đồng nghĩa: synonym1, synonym2 <br> + Từ trái nghĩa: antonym1, antonym2 <br> + Ví dụ: example sentence from original text<br> - Bản dịch ví dụ: example sentence translation <br> Text to analyze: "${text}"`;
        }


        const requestBody = {
            contents: [
                {
                    role: "user",
                    parts: [
                        {
                            text: prompt,
                        },
                    ],
                },
            ],
           generationConfig: {
                temperature: 0.7,
           }
        };

        GM_xmlhttpRequest({
            method: 'POST',
            url: API_URL,
            headers: {
                'Content-Type': 'application/json',
            },
           data: JSON.stringify(requestBody),
           onload: function (response) {
                if (response.status >= 200 && response.status < 300) {
                    const result = JSON.parse(response.responseText);
                    if (result.candidates && result.candidates[0].content.parts[0].text) {
                         const translatedText = result.candidates[0].content.parts[0].text;
                        if(isAdvanced) {
                            displayPopup(translatedText, text); // Show in Popup for Alt+M
                       } else if (displaySimple) {
                            displaySimplePopup(text, translatedText); // Show simple Popup for Alt+T
                       }
                       else {
                           showTranslationBelow(targetElement, translatedText); // Show Inline for Ctrl+M
                        }

                   } else {
                         console.error('Lỗi dịch thuật:', result);
                        showErrorBelow(targetElement, "Lỗi dịch thuật");
                    }
                } else {
                   console.error('Lỗi API:', response.status, response.statusText);
                     showErrorBelow(targetElement, "Lỗi API: " + response.status);
                }
               isTranslating = false; // Đặt lại trạng thái dịch
            },
            onerror: function (error) {
                console.error('Lỗi kết nối API:', error);
               showErrorBelow(targetElement, "Lỗi kết nối");
                isTranslating = false; // Đặt lại trạng thái dịch
            },
       });
    }


      // Hàm hiển thị bản dịch ngay bên dưới đoạn văn bản được bôi đen
   function showTranslationBelow(targetElement, translatedText) {
       // Tìm đoạn văn cuối cùng được bôi đen
        const selection = window.getSelection();
         const lastSelectedNode = selection.focusNode;
        let lastSelectedParagraph = lastSelectedNode.parentElement;

        // Đảm bảo phần tử cuối cùng là một đoạn văn
        while (lastSelectedParagraph && lastSelectedParagraph.tagName !== 'P') {
           lastSelectedParagraph = lastSelectedParagraph.parentElement;
        }

         // Nếu không tìm thấy, sử dụng targetElement (đoạn đầu tiên)
         if (!lastSelectedParagraph) {
            lastSelectedParagraph = targetElement;
        }

        // Kiểm tra xem đã có bản dịch nào được hiển thị chưa
        if (lastSelectedParagraph.nextElementSibling && lastSelectedParagraph.nextElementSibling.classList.contains('translation-div')) {
           return; // Nếu đã có bản dịch, không hiển thị thêm
       }

        const translationDiv = document.createElement('div');
        translationDiv.classList.add('translation-div'); // Thêm class để nhận diện
        translationDiv.style.marginTop = '10px';
         translationDiv.style.padding = '10px';
        translationDiv.style.backgroundColor = '#f0f0f0';
        translationDiv.style.borderLeft = '3px solid #4CAF50';
         translationDiv.style.color = '#333';
       translationDiv.style.position = 'relative'; // Thêm thuộc tính position: relative

       // Thiết lập font chữ và cỡ chữ
        translationDiv.style.fontFamily = 'SF Pro Rounded, sans-serif';
        translationDiv.style.fontSize = '16px'; // Cỡ chữ 16px (có thể điều chỉnh từ 15-17px)

       translationDiv.textContent = `Dịch: ${translatedText}`;


        // Thêm nút đóng (nút "x")
        const closeButton = document.createElement('span');
        closeButton.textContent = 'x';
        closeButton.style.position = 'absolute';
       closeButton.style.top = '5px';
        closeButton.style.right = '5px';
       closeButton.style.cursor = 'pointer';
        closeButton.style.color = '#999';
       closeButton.style.fontSize = '14px';
        closeButton.style.fontWeight = 'bold';

        closeButton.addEventListener('click', function () {
           translationDiv.remove();
        });

        translationDiv.appendChild(closeButton);

       lastSelectedParagraph.parentNode.insertBefore(translationDiv, lastSelectedParagraph.nextSibling);
    }



      // Function to display the summary on the webpage with dynamic width and scrollable content
    function displayPopup(translatedText, originalText) {
         const summaryDiv = document.createElement('div');
        summaryDiv.classList.add('draggable');
         summaryDiv.style.position = 'fixed';
        summaryDiv.style.top = '50%';
        summaryDiv.style.left = '50%';
        summaryDiv.style.transform = 'translate(-50%, -50%)';
         summaryDiv.style.backgroundColor = '#fff';
        summaryDiv.style.border = '1px solid #ccc';
        summaryDiv.style.padding = '20px';
         summaryDiv.style.zIndex = '10000';
         summaryDiv.style.width = '700px';    // Wider width
        summaryDiv.style.maxHeight = '500px';   // Lower max height
        summaryDiv.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
        summaryDiv.style.borderRadius = '15px';
        summaryDiv.style.fontFamily = 'SF Pro Rounded, Arial, sans-serif';
        summaryDiv.style.fontSize = '16px'; // Font size 16px
        summaryDiv.style.display = 'flex';
        summaryDiv.style.flexDirection = 'column';
         summaryDiv.style.overflow = 'hidden';

         // Add summary section with scrollable content
        const summarySection = document.createElement('div');
       const cleanedSummary = translatedText.replace(/(\*\*)(.*?)\1/g, '<b>$2</b>'); // Remove ** markers
        const formattedSummary = cleanedSummary.split('<br>').map(line => {
            if (line.startsWith('<b>KEYWORD</b>:')) {
                 return `<h4 style="margin-bottom: 5px;">${line}</h4>`;
             } else if (line.startsWith('+ Định nghĩa:')) {
                const parts = line.split(':');
                if (parts.length > 1) {
                    const definition = parts.slice(1).join(':').trim();
                    const definitionParts = definition.split('<br> - Bản dịch định nghĩa:');
                    if (definitionParts.length === 2) {
                        return `<p style="margin-left: 20px; margin-bottom: 5px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;">+ Định nghĩa:<br>${definitionParts[0].trim()}</p><p style="margin-left: 20px; margin-bottom: 10px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;"> - Bản dịch định nghĩa: ${definitionParts[1].trim()}</p>`;
                   }
                }
                return `<p style="margin-left: 20px; margin-bottom: 10px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;">${line}</p>`;
             }  else if (line.startsWith('+ Ví dụ:')) {
                const parts = line.split(':');
                 if (parts.length > 1) {
                    const example = parts.slice(1).join(':').trim();
                     const exampleParts = example.split('<br> - Bản dịch ví dụ:');
                     if (exampleParts.length === 2) {
                       // Replace example with a sentence from originalText if available
                         const keywordMatch = line.match(/<b>KEYWORD<\/b>:\s*(\w+)/i);
                         let exampleFromText = null;
                      if (keywordMatch)
                      {
                           const keyword = keywordMatch[1];
                            const regex = new RegExp(`\\b${keyword}\\b`, 'i');
                           const sentences = originalText.split(/[.?!]/).filter(sentence => regex.test(sentence));
                           if (sentences.length > 0)
                             exampleFromText = sentences[0].trim() + '.';

                     }
                     const displayExample = exampleFromText ? exampleFromText : exampleParts[0].trim();
                       return `<p style="margin-left: 20px; margin-bottom: 5px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;">+ Ví dụ: ${displayExample}</p><p style="margin-left: 20px; margin-bottom: 10px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;"> - Bản dịch ví dụ: ${exampleParts[1].trim()}</p>`;
                    }
                 }

                 return `<p style="margin-left: 20px; margin-bottom: 10px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;">${line}</p>`;
             } else {
                return `<p style="margin-left: 20px; margin-bottom: 10px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;">${line}</p>`;
           }
        }).join('');

        summarySection.innerHTML = `<h3 style="color: #333;">Dịch</h3><div style="overflow-y: auto; max-height: 400px; color: #555; font-size: 16px;">${formattedSummary}</div>`; // Font size 16px and lower max-height
        summaryDiv.appendChild(summarySection);


         // Add close button
        const closeButton = document.createElement('button');
       closeButton.innerText = 'Đóng';
        closeButton.style.marginTop = '10px';
       closeButton.style.padding = '8px 16px';
        closeButton.style.backgroundColor = '#ff4444';
        closeButton.style.color = '#fff';
        closeButton.style.border = 'none';
       closeButton.style.borderRadius = '4px';
        closeButton.style.cursor = 'pointer';
       closeButton.onclick = () => summaryDiv.remove();
        summaryDiv.appendChild(closeButton);

        makeDraggable(summaryDiv);
        document.body.appendChild(summaryDiv);
   }


    // Function to display the simple translation popup
    function displaySimplePopup(originalText, translatedText) {
        const simplePopupDiv = document.createElement('div');
        simplePopupDiv.classList.add('draggable');
        simplePopupDiv.style.position = 'fixed';
        simplePopupDiv.style.top = '50%';
        simplePopupDiv.style.left = '50%';
        simplePopupDiv.style.transform = 'translate(-50%, -50%)';
        simplePopupDiv.style.backgroundColor = '#fff';
        simplePopupDiv.style.border = '1px solid #ccc';
        simplePopupDiv.style.padding = '20px';
        simplePopupDiv.style.zIndex = '10000';
        simplePopupDiv.style.width = '400px'; // Wider width for simple popup
        simplePopupDiv.style.maxHeight = '400px'; // Lower max height for simple popup
        simplePopupDiv.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
        simplePopupDiv.style.borderRadius = '15px';
        simplePopupDiv.style.fontFamily = 'SF Pro Rounded, Arial, sans-serif';
        simplePopupDiv.style.fontSize = '16px'; // Font size 16px
        simplePopupDiv.style.display = 'flex';
        simplePopupDiv.style.flexDirection = 'column';
        simplePopupDiv.style.overflow = 'hidden'; // Keep overflow hidden for container, content will scroll

        // Translated Text Section (Only translation, no original text)
        const translatedTextSection = document.createElement('div');
        translatedTextSection.innerHTML = `<div style="white-space: pre-wrap; word-wrap: break-word; text-align: justify; font-size: 16px; overflow-y: auto; max-height: 350px; padding-right: 10px;">${translatedText}</div>`; // Increased font size, added scroll and padding, lower max-height
        simplePopupDiv.appendChild(translatedTextSection);

        // Close Button
        const closeButton = document.createElement('button');
        closeButton.innerText = 'Đóng';
        closeButton.style.marginTop = '10px';
        closeButton.style.padding = '8px 16px';
        closeButton.style.backgroundColor = '#ff4444';
        closeButton.style.color = '#fff';
        closeButton.style.border = 'none';
        closeButton.style.borderRadius = '4px';
        closeButton.style.cursor = 'pointer';
        closeButton.onclick = () => simplePopupDiv.remove();
        simplePopupDiv.appendChild(closeButton);

        makeDraggable(simplePopupDiv);
        document.body.appendChild(simplePopupDiv);
    }


    // Hàm hiển thị lỗi bên dưới
  function showErrorBelow(targetElement, errorMessage) {
        // Tìm đoạn văn cuối cùng được bôi đen (tương tự như trên)
        const selection = window.getSelection();
       const lastSelectedNode = selection.focusNode;
        let lastSelectedParagraph = lastSelectedNode.parentElement;

        while (lastSelectedParagraph && lastSelectedParagraph.tagName !== 'P') {
            lastSelectedParagraph = lastSelectedParagraph.parentElement;
         }

        if (!lastSelectedParagraph) {
            lastSelectedParagraph = targetElement;
        }

        if (lastSelectedParagraph.nextElementSibling && lastSelectedParagraph.nextElementSibling.classList.contains('translation-div')) {
            return;
       }

       const errorDiv = document.createElement('div');
        errorDiv.classList.add('translation-div');
        errorDiv.style.marginTop = '10px';
        errorDiv.style.padding = '10px';
       errorDiv.style.backgroundColor = '#fdd';
         errorDiv.style.borderLeft = '3px solid #faa';
        errorDiv.style.color = '#a00';
         errorDiv.style.fontFamily = 'SF Pro Rounded Medium, sans-serif';
        errorDiv.style.fontSize = '16px';
        errorDiv.style.position = 'relative'; // Thêm thuộc tính position: relative

       errorDiv.textContent = errorMessage;

        // Thêm nút đóng (nút "x")
         const closeButton = document.createElement('span');
        closeButton.textContent = 'x';
        closeButton.style.position = 'absolute';
        closeButton.style.top = '5px';
        closeButton.style.right = '5px';
        closeButton.style.cursor = 'pointer';
        closeButton.style.color = '#999';
        closeButton.style.fontSize = '14px';
         closeButton.style.fontWeight = 'bold';

        closeButton.addEventListener('click', function () {
            errorDiv.remove();
       });

       errorDiv.appendChild(closeButton);

       lastSelectedParagraph.parentNode.insertBefore(errorDiv, lastSelectedParagraph.nextSibling);
    }

    // Function to make the summary popup draggable
    function makeDraggable(element) {
         let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        element.onmousedown = dragMouseDown;

        function dragMouseDown(e) {
            e = e || window.event;
            e.preventDefault();
             // get the mouse cursor position at startup
           pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = closeDragElement;
           // call a function whenever the cursor moves
            document.onmousemove = elementDrag;
        }

       function elementDrag(e) {
           e = e || window.event;
            e.preventDefault();
            // calculate the new cursor position:
           pos1 = pos3 - e.clientX;
            pos2 = pos4 - e.clientY;
            pos3 = e.clientX;
            pos4 = e.clientY;
             // set the element's new position:
             element.style.top = (element.offsetTop - pos2) + "px";
            element.style.left = (element.offsetLeft - pos1) + "px";
       }

       function closeDragElement() {
            // stop moving when mouse button is released:
            document.onmouseup = null;
           document.onmousemove = null;
        }
    }


     // Lắng nghe sự kiện phím tắt (Ctrl + M hoặc Cmd + M, Alt + M và Alt + T)
    document.addEventListener('keydown', function (event) {
        const selection = window.getSelection();
         const selectedText = selection.toString().trim();
        if (!selectedText) return;

        const targetElement = selection.anchorNode.parentElement;

        if ((event.ctrlKey || event.metaKey) && event.key === 'm') {
             event.preventDefault(); // Ngăn chặn hành động mặc định của trình duyệt
            translateText(selectedText, targetElement);
        }
        else if (event.altKey && event.key === 'm') {
           event.preventDefault();
            translateText(selectedText, targetElement, true); // Dịch nâng cao khi ấn Alt + M
        }
        else if (event.altKey && event.key === 't') {
            event.preventDefault();
            translateText(selectedText, targetElement, false, true); // Dịch nhanh popup khi ấn Alt + T
        }
    });


})();
Thường xuyên bị Lỗi API: 429, phen có biết nguyên nhân không?
 
Xài Immersive Translate thì coi chừng, userscript đã bị xóa trên greasyfork vì code mã hóa 1 phần. Không nên tin vào bọn chin chon chạy 1 thứ có thể đọc dữ liệu mọi site như vậy
:doubt:
sài hàng của mấy fáp sư thì cũng run thật nhưng mà k có cái nào tiện như thằng này. Nó dịch song ngữ web theo nhu cầu rất tiện nên nếu sài userscript của nó thì giới hạn các website cần dịch thôi cho an toàn. Ví dụ hay vô mấy web tiếng nga hay tiếng tàu hay tiếng nhật thì giới hạn với mấy web đó thì an toàn hơn ngài nhỉ
WdRvENZ.gif
 
Hôm bữa mình có lên bài tìm app dịch giống Qtranslate nhưng không thấy ổn cái nào.
Do đó mình nhờ đến AI để nó giúp tìm giải pháp.
Đầu tiên, mọi người tải Violenmonkey về vì mình sẽ tạo scripts để dùng API của AI Studio để dịch (free 100%)
Tiếp đó mọi người dùng đoạn scripts bến dưới add vào, thay API và địa chỉ API rồi sau đó sử dụng.
*Lưu ý: Mình không biết gì về code, chỉ lên ý tưởng để AI làm và đến giờ dùng thì thấy ổn nên nếu hỏi chuyên môn code thì mình ko biết TL. MN có thể thêm ý tưởng vào các AI rồi bắt nó sửa cho mình.
Mọi người có thể lấy API tại đây hoặc gõ vào gg AI Studio (CỦa google nên ko lo virus j nhé)
"Sign in - Google Accounts (https://aistudio.google.com/apikey)"
Mình tạo ra 3 nút phím tắt:
Xem tệp đính kèm 2913915 (CTRL + m : Tạo 1 bản dịch bên dưới bản tiếng anh)
Xem tệp đính kèm 2913916 (ALT + m : Cái này mụcđíchđể học tiếng anh, sẽ tạo popup dịch, xácđịnh keywords , coi nhưđể học từ mới)
Cách dùng scripts này để dịch file pdf (theo đoạn bôi đen, không dịch được cả file 1 lần)
Xem tệp đính kèm 2913919 ( ALT + t :Giống CTRL m nhưng tạo popup)
Tuy nhiên, với các file pdf như mình dùng edge sẽ không cho dùng extention nên mọi người dùng link này để mở file pdf, sẽ cho phép dùng extension.
"PDF.js viewer (https://pdf.translatewebpages.org/pdf.js/web/viewer)"
Mã:
// ==UserScript==
// @name         Gemini AI Inline Translator (Popup)
// @namespace    http://tampermonkey.net/
// @version      2.8
// @description  Dịch văn bản bôi đen bằng Google Gemini API, có phím tắt, sửa lỗi ký tự, đảm bảo chỉ dịch một lần và có nút đóng. Cải thiện chất lượng dịch. Hỗ trợ phân tích từ vựng (Alt + M) hiển thị trong popup và dịch nhanh (Alt + T).
// @author       Your Name
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// ==/UserScript==
(function () {
    'use strict';

    // API Key của bạn
    const API_KEY = 'THAY API KEY VÀO ĐÂY NH MN'; // Thay thế bằng API Key của bạn
    const API_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${API_KEY}`;

    // Biến để theo dõi trạng thái dịch
    let isTranslating = false;

     // Add CSS for the draggable popup
    GM_addStyle(`
        .draggable {
          cursor: move;
        }
    `);

    // Hàm gọi API Gemini để dịch văn bản
     function translateText(text, targetElement, isAdvanced = false, displaySimple = false) {
        if (isTranslating) return; // Ngăn chặn dịch trùng lặp
        isTranslating = true;

         // Prompt cải tiến để dịch tự nhiên hơn, không word-by-word
        let prompt = `Translate the following text to Vietnamese in a natural and fluent way, avoiding word-by-word translation. Focus on conveying the meaning and intent of the original text, rather than a literal conversion: "${text}"`;

        if (isAdvanced) {
            prompt = `Translate the following text to Vietnamese in a natural and fluent way, avoiding word-by-word translation. After that, analyze the following text and select 2-5 relevant keywords. For each keyword, provide the definition from the Oxford Dictionary, along with its part of speech, a Vietnamese translation of the definition, synonyms (separated by commas), antonyms (separated by commas). Select an example sentence for each keyword from the original text and provide a Vietnamese translation of that example sentence. Format the output as follows:  <br><b>KEYWORD</b>: Keyword<br> + Định nghĩa:<br>Definition from Oxford dictionary<br> - Bản dịch định nghĩa: vietnamese definition <br> + Loại từ: Part of speech <br> + Từ đồng nghĩa: synonym1, synonym2 <br> + Từ trái nghĩa: antonym1, antonym2 <br> + Ví dụ: example sentence from original text<br> - Bản dịch ví dụ: example sentence translation <br> Text to analyze: "${text}"`;
        }


        const requestBody = {
            contents: [
                {
                    role: "user",
                    parts: [
                        {
                            text: prompt,
                        },
                    ],
                },
            ],
           generationConfig: {
                temperature: 0.7,
           }
        };

        GM_xmlhttpRequest({
            method: 'POST',
            url: API_URL,
            headers: {
                'Content-Type': 'application/json',
            },
           data: JSON.stringify(requestBody),
           onload: function (response) {
                if (response.status >= 200 && response.status < 300) {
                    const result = JSON.parse(response.responseText);
                    if (result.candidates && result.candidates[0].content.parts[0].text) {
                         const translatedText = result.candidates[0].content.parts[0].text;
                        if(isAdvanced) {
                            displayPopup(translatedText, text); // Show in Popup for Alt+M
                       } else if (displaySimple) {
                            displaySimplePopup(text, translatedText); // Show simple Popup for Alt+T
                       }
                       else {
                           showTranslationBelow(targetElement, translatedText); // Show Inline for Ctrl+M
                        }

                   } else {
                         console.error('Lỗi dịch thuật:', result);
                        showErrorBelow(targetElement, "Lỗi dịch thuật");
                    }
                } else {
                   console.error('Lỗi API:', response.status, response.statusText);
                     showErrorBelow(targetElement, "Lỗi API: " + response.status);
                }
               isTranslating = false; // Đặt lại trạng thái dịch
            },
            onerror: function (error) {
                console.error('Lỗi kết nối API:', error);
               showErrorBelow(targetElement, "Lỗi kết nối");
                isTranslating = false; // Đặt lại trạng thái dịch
            },
       });
    }


      // Hàm hiển thị bản dịch ngay bên dưới đoạn văn bản được bôi đen
   function showTranslationBelow(targetElement, translatedText) {
       // Tìm đoạn văn cuối cùng được bôi đen
        const selection = window.getSelection();
         const lastSelectedNode = selection.focusNode;
        let lastSelectedParagraph = lastSelectedNode.parentElement;

        // Đảm bảo phần tử cuối cùng là một đoạn văn
        while (lastSelectedParagraph && lastSelectedParagraph.tagName !== 'P') {
           lastSelectedParagraph = lastSelectedParagraph.parentElement;
        }

         // Nếu không tìm thấy, sử dụng targetElement (đoạn đầu tiên)
         if (!lastSelectedParagraph) {
            lastSelectedParagraph = targetElement;
        }

        // Kiểm tra xem đã có bản dịch nào được hiển thị chưa
        if (lastSelectedParagraph.nextElementSibling && lastSelectedParagraph.nextElementSibling.classList.contains('translation-div')) {
           return; // Nếu đã có bản dịch, không hiển thị thêm
       }

        const translationDiv = document.createElement('div');
        translationDiv.classList.add('translation-div'); // Thêm class để nhận diện
        translationDiv.style.marginTop = '10px';
         translationDiv.style.padding = '10px';
        translationDiv.style.backgroundColor = '#f0f0f0';
        translationDiv.style.borderLeft = '3px solid #4CAF50';
         translationDiv.style.color = '#333';
       translationDiv.style.position = 'relative'; // Thêm thuộc tính position: relative

       // Thiết lập font chữ và cỡ chữ
        translationDiv.style.fontFamily = 'SF Pro Rounded, sans-serif';
        translationDiv.style.fontSize = '16px'; // Cỡ chữ 16px (có thể điều chỉnh từ 15-17px)

       translationDiv.textContent = `Dịch: ${translatedText}`;


        // Thêm nút đóng (nút "x")
        const closeButton = document.createElement('span');
        closeButton.textContent = 'x';
        closeButton.style.position = 'absolute';
       closeButton.style.top = '5px';
        closeButton.style.right = '5px';
       closeButton.style.cursor = 'pointer';
        closeButton.style.color = '#999';
       closeButton.style.fontSize = '14px';
        closeButton.style.fontWeight = 'bold';

        closeButton.addEventListener('click', function () {
           translationDiv.remove();
        });

        translationDiv.appendChild(closeButton);

       lastSelectedParagraph.parentNode.insertBefore(translationDiv, lastSelectedParagraph.nextSibling);
    }



      // Function to display the summary on the webpage with dynamic width and scrollable content
    function displayPopup(translatedText, originalText) {
         const summaryDiv = document.createElement('div');
        summaryDiv.classList.add('draggable');
         summaryDiv.style.position = 'fixed';
        summaryDiv.style.top = '50%';
        summaryDiv.style.left = '50%';
        summaryDiv.style.transform = 'translate(-50%, -50%)';
         summaryDiv.style.backgroundColor = '#fff';
        summaryDiv.style.border = '1px solid #ccc';
        summaryDiv.style.padding = '20px';
         summaryDiv.style.zIndex = '10000';
         summaryDiv.style.width = '700px';    // Wider width
        summaryDiv.style.maxHeight = '500px';   // Lower max height
        summaryDiv.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
        summaryDiv.style.borderRadius = '15px';
        summaryDiv.style.fontFamily = 'SF Pro Rounded, Arial, sans-serif';
        summaryDiv.style.fontSize = '16px'; // Font size 16px
        summaryDiv.style.display = 'flex';
        summaryDiv.style.flexDirection = 'column';
         summaryDiv.style.overflow = 'hidden';

         // Add summary section with scrollable content
        const summarySection = document.createElement('div');
       const cleanedSummary = translatedText.replace(/(\*\*)(.*?)\1/g, '<b>$2</b>'); // Remove ** markers
        const formattedSummary = cleanedSummary.split('<br>').map(line => {
            if (line.startsWith('<b>KEYWORD</b>:')) {
                 return `<h4 style="margin-bottom: 5px;">${line}</h4>`;
             } else if (line.startsWith('+ Định nghĩa:')) {
                const parts = line.split(':');
                if (parts.length > 1) {
                    const definition = parts.slice(1).join(':').trim();
                    const definitionParts = definition.split('<br> - Bản dịch định nghĩa:');
                    if (definitionParts.length === 2) {
                        return `<p style="margin-left: 20px; margin-bottom: 5px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;">+ Định nghĩa:<br>${definitionParts[0].trim()}</p><p style="margin-left: 20px; margin-bottom: 10px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;"> - Bản dịch định nghĩa: ${definitionParts[1].trim()}</p>`;
                   }
                }
                return `<p style="margin-left: 20px; margin-bottom: 10px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;">${line}</p>`;
             }  else if (line.startsWith('+ Ví dụ:')) {
                const parts = line.split(':');
                 if (parts.length > 1) {
                    const example = parts.slice(1).join(':').trim();
                     const exampleParts = example.split('<br> - Bản dịch ví dụ:');
                     if (exampleParts.length === 2) {
                       // Replace example with a sentence from originalText if available
                         const keywordMatch = line.match(/<b>KEYWORD<\/b>:\s*(\w+)/i);
                         let exampleFromText = null;
                      if (keywordMatch)
                      {
                           const keyword = keywordMatch[1];
                            const regex = new RegExp(`\\b${keyword}\\b`, 'i');
                           const sentences = originalText.split(/[.?!]/).filter(sentence => regex.test(sentence));
                           if (sentences.length > 0)
                             exampleFromText = sentences[0].trim() + '.';

                     }
                     const displayExample = exampleFromText ? exampleFromText : exampleParts[0].trim();
                       return `<p style="margin-left: 20px; margin-bottom: 5px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;">+ Ví dụ: ${displayExample}</p><p style="margin-left: 20px; margin-bottom: 10px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;"> - Bản dịch ví dụ: ${exampleParts[1].trim()}</p>`;
                    }
                 }

                 return `<p style="margin-left: 20px; margin-bottom: 10px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;">${line}</p>`;
             } else {
                return `<p style="margin-left: 20px; margin-bottom: 10px; white-space: pre-wrap; word-wrap: break-word; text-align: justify;">${line}</p>`;
           }
        }).join('');

        summarySection.innerHTML = `<h3 style="color: #333;">Dịch</h3><div style="overflow-y: auto; max-height: 400px; color: #555; font-size: 16px;">${formattedSummary}</div>`; // Font size 16px and lower max-height
        summaryDiv.appendChild(summarySection);


         // Add close button
        const closeButton = document.createElement('button');
       closeButton.innerText = 'Đóng';
        closeButton.style.marginTop = '10px';
       closeButton.style.padding = '8px 16px';
        closeButton.style.backgroundColor = '#ff4444';
        closeButton.style.color = '#fff';
        closeButton.style.border = 'none';
       closeButton.style.borderRadius = '4px';
        closeButton.style.cursor = 'pointer';
       closeButton.onclick = () => summaryDiv.remove();
        summaryDiv.appendChild(closeButton);

        makeDraggable(summaryDiv);
        document.body.appendChild(summaryDiv);
   }


    // Function to display the simple translation popup
    function displaySimplePopup(originalText, translatedText) {
        const simplePopupDiv = document.createElement('div');
        simplePopupDiv.classList.add('draggable');
        simplePopupDiv.style.position = 'fixed';
        simplePopupDiv.style.top = '50%';
        simplePopupDiv.style.left = '50%';
        simplePopupDiv.style.transform = 'translate(-50%, -50%)';
        simplePopupDiv.style.backgroundColor = '#fff';
        simplePopupDiv.style.border = '1px solid #ccc';
        simplePopupDiv.style.padding = '20px';
        simplePopupDiv.style.zIndex = '10000';
        simplePopupDiv.style.width = '400px'; // Wider width for simple popup
        simplePopupDiv.style.maxHeight = '400px'; // Lower max height for simple popup
        simplePopupDiv.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
        simplePopupDiv.style.borderRadius = '15px';
        simplePopupDiv.style.fontFamily = 'SF Pro Rounded, Arial, sans-serif';
        simplePopupDiv.style.fontSize = '16px'; // Font size 16px
        simplePopupDiv.style.display = 'flex';
        simplePopupDiv.style.flexDirection = 'column';
        simplePopupDiv.style.overflow = 'hidden'; // Keep overflow hidden for container, content will scroll

        // Translated Text Section (Only translation, no original text)
        const translatedTextSection = document.createElement('div');
        translatedTextSection.innerHTML = `<div style="white-space: pre-wrap; word-wrap: break-word; text-align: justify; font-size: 16px; overflow-y: auto; max-height: 350px; padding-right: 10px;">${translatedText}</div>`; // Increased font size, added scroll and padding, lower max-height
        simplePopupDiv.appendChild(translatedTextSection);

        // Close Button
        const closeButton = document.createElement('button');
        closeButton.innerText = 'Đóng';
        closeButton.style.marginTop = '10px';
        closeButton.style.padding = '8px 16px';
        closeButton.style.backgroundColor = '#ff4444';
        closeButton.style.color = '#fff';
        closeButton.style.border = 'none';
        closeButton.style.borderRadius = '4px';
        closeButton.style.cursor = 'pointer';
        closeButton.onclick = () => simplePopupDiv.remove();
        simplePopupDiv.appendChild(closeButton);

        makeDraggable(simplePopupDiv);
        document.body.appendChild(simplePopupDiv);
    }


    // Hàm hiển thị lỗi bên dưới
  function showErrorBelow(targetElement, errorMessage) {
        // Tìm đoạn văn cuối cùng được bôi đen (tương tự như trên)
        const selection = window.getSelection();
       const lastSelectedNode = selection.focusNode;
        let lastSelectedParagraph = lastSelectedNode.parentElement;

        while (lastSelectedParagraph && lastSelectedParagraph.tagName !== 'P') {
            lastSelectedParagraph = lastSelectedParagraph.parentElement;
         }

        if (!lastSelectedParagraph) {
            lastSelectedParagraph = targetElement;
        }

        if (lastSelectedParagraph.nextElementSibling && lastSelectedParagraph.nextElementSibling.classList.contains('translation-div')) {
            return;
       }

       const errorDiv = document.createElement('div');
        errorDiv.classList.add('translation-div');
        errorDiv.style.marginTop = '10px';
        errorDiv.style.padding = '10px';
       errorDiv.style.backgroundColor = '#fdd';
         errorDiv.style.borderLeft = '3px solid #faa';
        errorDiv.style.color = '#a00';
         errorDiv.style.fontFamily = 'SF Pro Rounded Medium, sans-serif';
        errorDiv.style.fontSize = '16px';
        errorDiv.style.position = 'relative'; // Thêm thuộc tính position: relative

       errorDiv.textContent = errorMessage;

        // Thêm nút đóng (nút "x")
         const closeButton = document.createElement('span');
        closeButton.textContent = 'x';
        closeButton.style.position = 'absolute';
        closeButton.style.top = '5px';
        closeButton.style.right = '5px';
        closeButton.style.cursor = 'pointer';
        closeButton.style.color = '#999';
        closeButton.style.fontSize = '14px';
         closeButton.style.fontWeight = 'bold';

        closeButton.addEventListener('click', function () {
            errorDiv.remove();
       });

       errorDiv.appendChild(closeButton);

       lastSelectedParagraph.parentNode.insertBefore(errorDiv, lastSelectedParagraph.nextSibling);
    }

    // Function to make the summary popup draggable
    function makeDraggable(element) {
         let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        element.onmousedown = dragMouseDown;

        function dragMouseDown(e) {
            e = e || window.event;
            e.preventDefault();
             // get the mouse cursor position at startup
           pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = closeDragElement;
           // call a function whenever the cursor moves
            document.onmousemove = elementDrag;
        }

       function elementDrag(e) {
           e = e || window.event;
            e.preventDefault();
            // calculate the new cursor position:
           pos1 = pos3 - e.clientX;
            pos2 = pos4 - e.clientY;
            pos3 = e.clientX;
            pos4 = e.clientY;
             // set the element's new position:
             element.style.top = (element.offsetTop - pos2) + "px";
            element.style.left = (element.offsetLeft - pos1) + "px";
       }

       function closeDragElement() {
            // stop moving when mouse button is released:
            document.onmouseup = null;
           document.onmousemove = null;
        }
    }


     // Lắng nghe sự kiện phím tắt (Ctrl + M hoặc Cmd + M, Alt + M và Alt + T)
    document.addEventListener('keydown', function (event) {
        const selection = window.getSelection();
         const selectedText = selection.toString().trim();
        if (!selectedText) return;

        const targetElement = selection.anchorNode.parentElement;

        if ((event.ctrlKey || event.metaKey) && event.key === 'm') {
             event.preventDefault(); // Ngăn chặn hành động mặc định của trình duyệt
            translateText(selectedText, targetElement);
        }
        else if (event.altKey && event.key === 'm') {
           event.preventDefault();
            translateText(selectedText, targetElement, true); // Dịch nâng cao khi ấn Alt + M
        }
        else if (event.altKey && event.key === 't') {
            event.preventDefault();
            translateText(selectedText, targetElement, false, true); // Dịch nhanh popup khi ấn Alt + T
        }
    });


})();
Violenmonkey em cai tren chrome hok cho bac oi, chi em cai vs
 
sài hàng của mấy fáp sư thì cũng run thật nhưng mà k có cái nào tiện như thằng này. Nó dịch song ngữ web theo nhu cầu rất tiện nên nếu sài userscript của nó thì giới hạn các website cần dịch thôi cho an toàn. Ví dụ hay vô mấy web tiếng nga hay tiếng tàu hay tiếng nhật thì giới hạn với mấy web đó thì an toàn hơn ngài nhỉ
WdRvENZ.gif
xài userscript kiểu giới hạn web vậy thì ok rồi, cơ mà dùng @match ấy, dùng @include nó load theo ifame nữa thì rip :doubt:
có tool AI nào dịch file phụ đề tiếng anh sang việt ngon ngon ko fen?
cái này k biết r fen :D
 

Thống kê chủ đề

Ngày tạo
ChuSyThang21,
Người trả lời cuối
Fioren,
Trả lời
204
Lượt xem
28.442
Quay lại
Lên đầu trang