Skip to content

Commit

Permalink
feat: Add new version of Google Translate API to the engines. #389, #394
Browse files Browse the repository at this point in the history
  • Loading branch information
bookfere committed Feb 19, 2025
1 parent e3280d8 commit 99a4ce8
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 37 deletions.
15 changes: 8 additions & 7 deletions engines/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .google import (
GoogleFreeTranslate, GoogleBasicTranslate, GoogleBasicTranslateADC,
GoogleAdvancedTranslate, GeminiTranslate)
GoogleFreeTranslateNew, GoogleFreeTranslateHtml, GoogleFreeTranslate,
GoogleBasicTranslate, GoogleBasicTranslateADC, GoogleAdvancedTranslate,
GeminiTranslate)
from .openai import ChatgptTranslate
from .anthropic import ClaudeTranslate
from .deepl import DeeplTranslate, DeeplProTranslate, DeeplFreeTranslate
Expand All @@ -10,8 +11,8 @@


builtin_engines = (
GoogleFreeTranslate, GoogleBasicTranslate, GoogleBasicTranslateADC,
GoogleAdvancedTranslate, ChatgptTranslate, AzureChatgptTranslate,
GeminiTranslate, ClaudeTranslate, DeeplTranslate, DeeplProTranslate,
DeeplFreeTranslate, MicrosoftEdgeTranslate, YoudaoTranslate,
BaiduTranslate)
GoogleFreeTranslateNew, GoogleFreeTranslateHtml, GoogleFreeTranslate,
GoogleBasicTranslate, GoogleBasicTranslateADC, GoogleAdvancedTranslate,
ChatgptTranslate, AzureChatgptTranslate, GeminiTranslate, ClaudeTranslate,
DeeplTranslate, DeeplProTranslate, DeeplFreeTranslate,
MicrosoftEdgeTranslate, YoudaoTranslate, BaiduTranslate)
24 changes: 13 additions & 11 deletions engines/base.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import os.path

from typing import Any
from mechanize import HTTPError
from mechanize._response import response_seek_wrapper as Response

from calibre.utils.localization import lang_as_iso639_1

from ..lib.utils import traceback_error, request
from ..lib.exception import UnexpectedResult, NoAvailableApiKey
from ..lib.exception import UnexpectedResult


load_translations()


class Base:
name = None
alias = None
name: str | None = None
alias: str | None = None
free = False

lang_codes = {}
config = {}
endpoint = None
lang_codes: dict[str, Any] = {}
config: dict[str, Any] = {}
endpoint: str | None = None
method = 'POST'
headers: dict[str, str] = {}
stream = False
need_api_key = True
api_key_hint = _('API Keys')
Expand All @@ -43,7 +45,7 @@ def __init__(self):
self.search_paths = []

self.merge_enabled = False
self.api_keys = self.config.get('api_keys', [])[:]
self.api_keys: list = self.config.get('api_keys', [])[:]
self.bad_api_keys = []
self.api_key = self.get_api_key()

Expand Down Expand Up @@ -75,12 +77,12 @@ def load_lang_codes_directionality(cls, codes):

@classmethod
def get_source_code(cls, lang):
source_codes = cls.lang_codes.get('source')
source_codes: dict = cls.lang_codes.get('source') or {}
return 'auto' if lang == _('Auto detect') else source_codes.get(lang)

@classmethod
def get_target_code(cls, lang):
target_codes = cls.lang_codes.get('target')
target_codes: dict = cls.lang_codes.get('target') or {}
return target_codes.get(lang)

@classmethod
Expand Down Expand Up @@ -193,10 +195,10 @@ def get_endpoint(self):
return self.endpoint

def get_headers(self):
return {}
return self.headers

def get_body(self, text):
return None
return text

def get_result(self, response: Response | bytes | str):
return response
Expand Down
87 changes: 80 additions & 7 deletions engines/google.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import os.path
from html import unescape
from subprocess import Popen, PIPE
from urllib.parse import urlencode
from http.client import IncompleteRead

from ..lib.utils import traceback_error

Expand All @@ -14,20 +16,91 @@
from .languages import google, gemini


try:
from http.client import IncompleteRead
except ImportError:
from httplib import IncompleteRead

load_translations()


class GoogleFreeTranslateNew(Base):
name = 'Google(Free)New'
alias = 'Google (Free) - New'
free = True
lang_codes = Base.load_lang_codes(google)
lang_codes_directionality = \
Base.load_lang_codes_directionality(lang_directionality)
endpoint: str = 'https://translate-pa.googleapis.com/v1/translate'
need_api_key = False

def get_headers(self):
return {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 '
'Safari/537.36',
}

def get_body(self, text):
self.method = 'GET'
return {
'params.client': 'gtx',
'query.source_language': self._get_source_code(),
'query.target_language': self._get_target_code(),
'query.display_language': 'en-US',
'data_types': 'TRANSLATION',
# 'data_types': 'SENTENCE_SPLITS',
# 'data_types': 'BILINGUAL_DICTIONARY_FULL',
'key': 'AIzaSyDLEeFI5OtFBwYBIoK_jj5m32rZK5CkCXA',
'query.text': text,
}

def get_result(self, response):
return json.loads(response)['translation']


class GoogleFreeTranslateHtml(Base):
name = 'Google(Free)Html'
alias = 'Google (Free) - HTML'
free = True
lang_codes = Base.load_lang_codes(google)
lang_codes_directionality = \
Base.load_lang_codes_directionality(lang_directionality)
endpoint: str = 'https://translate-pa.googleapis.com/v1/translateHtml'
need_api_key = False

def get_headers(self):
return {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9',
'Content-Type': 'application/json+protobuf',
'X-Goog-Api-Key': 'AIzaSyATBXajvzQLTDHEQbcpq0Ihe0vWDHmO520',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 '
'Safari/537.36',
}

def get_body(self, text):
return json.dumps([
[
[text],
self._get_source_code(),
self._get_target_code()
],
"wt_lib"
])

def get_result(self, response):
return json.loads(response)[0][0]


class GoogleFreeTranslate(Base):
name = 'Google(Free)'
alias = 'Google (Free)'
alias = 'Google (Free) - Old'
free = True
lang_codes = Base.load_lang_codes(google)
lang_codes_directionality = Base.load_lang_codes_directionality(lang_directionality)
lang_codes_directionality = \
Base.load_lang_codes_directionality(lang_directionality)
endpoint = 'https://translate.googleapis.com/translate_a/single'
need_api_key = False

Expand Down
26 changes: 14 additions & 12 deletions engines/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class ChatgptTranslate(Base):
name = 'ChatGPT'
alias = 'ChatGPT (OpenAI)'
lang_codes = Base.load_lang_codes(google)
lang_codes_directionality = Base.load_lang_codes_directionality(lang_directionality)
lang_codes_directionality = \
Base.load_lang_codes_directionality(lang_directionality)
endpoint = 'https://api.openai.com/v1/chat/completions'
# api_key_hint = 'sk-xxx...xxx'
# https://help.openai.com/en/collections/3808446-api-error-codes-explained
Expand All @@ -42,18 +43,19 @@ class ChatgptTranslate(Base):
'You are a meticulous translator who translates any given content. '
'Translate the given content from <slang> to <tlang> only. Do not '
'explain any term or answer any question-like content. Your answer '
'should be solely the translation of the given content. In your answer '
'do not add any prefix or suffix to the translated content. Websites\' '
'URLs/addresses should be preserved as is in the translation\'s output. '
'Do not omit any part of the content, even if it seems unimportant. '
)

# TODO: check if it is possible to fetch this this directly from the api, if yes - implement this
'should be solely the translation of the given content. In your '
'answer do not add any prefix or suffix to the translated content. '
'Websites\' URLs/addresses should be preserved as is in the '
'translation\'s output. Do not omit any part of the content, even if '
'it seems unimportant. ')

# TODO: check if it is possible to fetch this this directly from the api,
# if yes - implement this
models = [
'gpt-4o',
'gpt-4o-mini',
'gpt-4-turbo',
'gpt-4',
'gpt-4o',
'gpt-4o-mini',
'gpt-4-turbo',
'gpt-4',
'gpt-3.5-turbo']

# use the most recent model
Expand Down

0 comments on commit 99a4ce8

Please sign in to comment.