ScreenTranslator icon indicating copy to clipboard operation
ScreenTranslator copied to clipboard

Translate with AI

Open Suki8898 opened this issue 11 months ago • 6 comments

Oh, you want to use AI for translations? Well, buddy, you’ve come to the right place! I have no idea if OpenAI’s code actually works, because I’m so broke I can’t even afford their API. But hey, Gemini API are totally free, and OpenRouter offers a variety of models ranging from free to paid—so why not give them a shot? As for my coding skills... let’s just say my code might look like it crawled out of a dumpster fire. But who cares? If it runs, it runs! I’d be incredibly grateful for any support during tough times. If you’d like to help, you can treat me to a meal here ✿ Thank you so much!

Open Translators Path and follow the instructions below

Image

OpenRouter API

//Create a file named openrouter_api.js and copy this code into it
//Replace YOUR_API_KEY_HERE with your OpenRouter API key
//Go to Setting > Translation > openrouter_api.js

const API_KEY = 'YOUR_API_KEY_HERE';
const API_URL = 'https://openrouter.ai/api/v1/chat/completions';
const MODEL = 'meta-llama/llama-3.2-3b-instruct:free'; // You can change the model here

function translate(text, from, to) {
    console.log('Start translate (OpenRouter):', text, 'from:', from, 'to:', to, 'using model:', MODEL);

    if (text.trim().length === 0) {
        proxy.setTranslated('');
        return;
    }

    const prompt = `Translate the following text from ${from} to ${to}, do not include quotation marks "", do not reply, without further explanation: "${text}"`;

    const requestBody = {
        model: MODEL,
        messages: [{
            role: "user",
            content: prompt
        }]
    };

    fetch(API_URL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${API_KEY}`,
            //'HTTP-Referer': 'https://your-app-name.com', 
            //'X-Title': 'Your App Name' // Thay thế bằng tên ứng dụng của bạn
        },
        body: JSON.stringify(requestBody),
    })
        .then(response => {
            if (!response.ok) {
                console.error('Error from OpenRouter API:', response.status, response.statusText);
                proxy.setFailed(`OpenRouter API Error: ${response.status} ${response.statusText}`);
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json();
        })
         .then(data => {
            if (data && data.choices && data.choices.length > 0 && data.choices[0].message && data.choices[0].message.content) {
                const translatedText = data.choices[0].message.content.trim();
                console.log('Translated text (OpenRouter):', translatedText);
                proxy.setTranslated(translatedText);
            } else {
                console.error('Unexpected response from OpenRouter API:', data);
                proxy.setFailed('Unexpected response from OpenRouter API');
            }
         })
        .catch(error => {
            console.error('Error fetching from OpenRouter API:', error);
            proxy.setFailed(`Error fetching from OpenRouter API: ${error.message}`);
        });
}


function init() {
    proxy.translate.connect(translate);
}

✧❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀✧

Gemini API

//Create a file named gemini_api.js and copy this code into it
//Replace YOUR_API_KEY_HERE with your Gemini API key
//Go to Setting > Translation > gemini_api.js

const API_KEY = 'YOUR_API_KEY_HERE';
const MODEL_NAME = 'gemini-2.0-flash'; // You can change to another model if desired
const TEMPERATURE = 1;
const API_URL = `https://generativelanguage.googleapis.com/v1beta/models/${MODEL_NAME}:generateContent?key=${API_KEY}`;

function translate(text, from, to) {
    console.log('Start translate (Gemini):', text, 'from:', from, 'to:', to, 'using model:', MODEL_NAME, 'temperature:', TEMPERATURE);

    if (text.trim().length === 0) {
        proxy.setTranslated('');
        return;
    }

    const prompt = `Translate the following text from ${from} to ${to}, do not include quotation marks "", do not reply, without further explanation: "${text}"`;

    const requestBody = {
        contents: [{
            parts: [{
                text: prompt
            }]
        }],
      generationConfig: {
        temperature: TEMPERATURE
      },
        safetySettings: [
            {
                category: "HARM_CATEGORY_HARASSMENT",
                threshold: "BLOCK_NONE",
            },
            {
                category: "HARM_CATEGORY_HATE_SPEECH",
                threshold: "BLOCK_NONE",
            },
            {
                category: "HARM_CATEGORY_SEXUALLY_EXPLICIT",
                threshold: "BLOCK_NONE",
            },
            {
                category: "HARM_CATEGORY_DANGEROUS_CONTENT",
                threshold: "BLOCK_NONE",
            }
        ],
    };

    fetch(API_URL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(requestBody),
    })
        .then(response => {
            if (!response.ok) {
                console.error('Error from Gemini API:', response.status, response.statusText);
                proxy.setFailed(`Gemini API Error: ${response.status} ${response.statusText}`);
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json();
        })
        .then(data => {
            if (data && data.candidates && data.candidates.length > 0 && data.candidates[0].content && data.candidates[0].content.parts && data.candidates[0].content.parts.length > 0) {
                const translatedText = data.candidates[0].content.parts[0].text.trim();
                console.log('Translated text (Gemini):', translatedText);
                proxy.setTranslated(translatedText);
            } else {
                console.error('Unexpected response from Gemini API:', data);
                proxy.setFailed('Unexpected response from Gemini API');
            }
        })
        .catch(error => {
            console.error('Error fetching from Gemini API:', error);
            proxy.setFailed(`Error fetching from Gemini API: ${error.message}`);
        });
}


function init() {
    proxy.translate.connect(translate);
}

✧❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀✧

OpenAI API

//Create a file named openai_api.js and copy this code into it
//Replace YOUR_API_KEY_HERE with your OpenAI API key
//Go to Setting > Translation > openai_api.js

const API_KEY = 'YOUR_API_KEY_HERE';
const API_URL = 'https://api.openai.com/v1/chat/completions';
const MODEL = 'gpt-3.5-turbo'; // You can change to another model if desired

function translate(text, from, to) {
  console.log('Start translate (OpenAI):', text, 'from:', from, 'to:', to);

  if (text.trim().length === 0) {
    proxy.setTranslated('');
    return;
  }

  const prompt = `Translate the following text from ${from} to ${to}, do not include quotation marks "", do not reply, without further explanation: "${text}"`;

  const requestBody = {
    model: MODEL,
    messages: [{
      role: "user",
      content: prompt
    }]
  };

  fetch(API_URL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + API_KEY
      },
      body: JSON.stringify(requestBody),
    })
    .then(response => {
      if (!response.ok) {
        console.error('Error from OpenAI API:', response.status, response.statusText);
        proxy.setFailed(`OpenAI API Error: ${response.status} ${response.statusText}`);
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      return response.json();
    })
    .then(data => {
      if (data && data.choices && data.choices.length > 0 && data.choices[0].message && data.choices[0].message.content) {
        const translatedText = data.choices[0].message.content.trim();
        console.log('Translated text (OpenAI):', translatedText);
        proxy.setTranslated(translatedText);
      } else {
        console.error('Unexpected response from OpenAI API:', data);
        proxy.setFailed('Unexpected response from OpenAI API');
      }
    })
    .catch(error => {
      console.error('Error fetching from OpenAI API:', error);
      proxy.setFailed(`Error fetching from OpenAI API: ${error.message}`);
    });
}

function init() {
    proxy.translate.connect(translate);
}

✧❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀✧

DeepSeek API

//Create a file named deepseek_api.js and copy this code into it
//Replace YOUR_API_KEY_HERE with your DeepSeek API key
//Go to Setting > Translation > deepseek_api.js

const API_KEY = 'YOUR_API_KEY_HERE';
const API_URL = 'https://api.deepseek.com/v1/chat/completions';
const MODEL = 'deepseek-chat';  // You can change to another model if desired

function translate(text, from, to) {
    console.log('Start translate (DeepSeek API):', text, 'from:', from, 'to:', to, 'using model:', MODEL);

    if (text.trim().length === 0) {
        proxy.setTranslated('');
        return;
    }

    const prompt = `Translate the following text from ${from} to ${to}, do not include quotation marks "", do not reply, without further explanation: "${text}"`;

     const requestBody = {
        model: MODEL,
        messages: [{
            role: "user",
            content: prompt
        }]
     };

    fetch(API_URL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${API_KEY}`
        },
        body: JSON.stringify(requestBody),
    })
        .then(response => {
            if (!response.ok) {
                console.error('Error from DeepSeek API:', response.status, response.statusText);
                proxy.setFailed(`DeepSeek API Error: ${response.status} ${response.statusText}`);
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json();
        })
        .then(data => {
            if (data && data.choices && data.choices.length > 0 && data.choices[0].message && data.choices[0].message.content) {
                const translatedText = data.choices[0].message.content.trim();
                console.log('Translated text (DeepSeek API):', translatedText);
                proxy.setTranslated(translatedText);
            } else {
                console.error('Unexpected response from DeepSeek API:', data);
                proxy.setFailed('Unexpected response from DeepSeek API');
            }
        })
        .catch(error => {
            console.error('Error fetching from DeepSeek API:', error);
            proxy.setFailed(`Error fetching from DeepSeek API: ${error.message}`);
        });
}

function init() {
    proxy.translate.connect(translate);
}

Suki8898 avatar Jan 22 '25 09:01 Suki8898

Image

Hello, thank you for making this. I've only tried a few AIs, but I'm stuck on deepseek where the show translator requires verification, the problem is I can't find the verification button.

For Gemini Ai, it works very well.

fadhel4112 avatar Jan 30 '25 23:01 fadhel4112

@fadhel4112 Looks like this browser isn’t great—it can’t even verify that I’m human. (Alright, fine, I’m a robot 🤖). I also tried writing for ChatGPT Web, but for some reason, the Enter button just refuses to work! Recently, DeepSeek has been hit by DDOS attacks, so they had to implement protective measures: https://status.deepseek.com/. Once the DeepSeek API is back up and running, I’ll write code to use the API instead of relying on the web.

Suki8898 avatar Jan 31 '25 03:01 Suki8898

@Suki8898 Thank you, Looking forward to the new code.

fadhel4112 avatar Jan 31 '25 14:01 fadhel4112

Man... I love you! Using gemini flash 8b, and it's working perfect for me! Thx!

dmpdev0 avatar Feb 04 '25 17:02 dmpdev0

Image Sorry to ask this, but there is a problem with translation gemini is there any tips to fix it

fadhel4112 avatar Feb 14 '25 23:02 fadhel4112

@fadhel4112 Exceeding Rate Limits: Burst Rate: Sending too many requests within a short period can trigger this error. Sustained Rate: Consistently exceeding the average rate limit over a longer period can also lead to this issue.

Quota Exhaustion: Your project might have reached its overall quota for the Gemini API or specific model usage.

You need to pay a fee to continue using the current API, create a Gemini API with a different account, or switch to using OpenRouter.

https://cloud.google.com/vertex-ai/generative-ai/docs/error-code-429

Suki8898 avatar Feb 15 '25 01:02 Suki8898

Oh dude, I love you so much! My self-edited script just stopped working several months ago, which had obsessed me for weeks. And your generous post really save my reading experience immediately! Thanks a lot!

Rapierror avatar Mar 01 '25 16:03 Rapierror

@Suki8898 Hi! I edited the initial post to be more technical and less promotional. I don't mind if you monetize your work, just don't do it in this repository. This one is for the base app and its bugs. Side features should have their own places.

I added a link to your repo in readme, so now closing this issue

OneMoreGres avatar Mar 05 '25 18:03 OneMoreGres