diff --git a/yadt/document_il/translator/translator.py b/yadt/document_il/translator/translator.py index 944aa29..cbc7ac8 100644 --- a/yadt/document_il/translator/translator.py +++ b/yadt/document_il/translator/translator.py @@ -85,7 +85,8 @@ def __init__(self, lang_in, lang_out, ignore_cache): def __del__(self): print(f"{self.name} translate call count: {self.translate_call_count}") print( - f"{self.name} translate cache call count: {self.translate_cache_call_count}" + f"{self.name} translate cache call count: { + self.translate_cache_call_count}" ) def add_cache_impact_parameters(self, k: str, v): @@ -168,6 +169,49 @@ def do_translate(self, text): return remove_control_characters(result) +class BingTranslator(BaseTranslator): + # https://github.com/immersive-translate/old-immersive-translate/blob/6df13da22664bea2f51efe5db64c63aca59c4e79/src/background/translationService.js + name = "bing" + lang_map = {"zh": "zh-Hans"} + + def __init__(self, lang_in, lang_out, ignore_cache=False): + super().__init__(lang_in, lang_out, ignore_cache) + self.session = requests.Session() + self.endpoint = "https://www.bing.com/translator" + self.headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0", # noqa: E501 + } + + def find_sid(self): + response = self.session.get(self.endpoint) + response.raise_for_status() + url = response.url[:-10] + ig = re.findall(r"\"ig\":\"(.*?)\"", response.text)[0] + iid = re.findall(r"data-iid=\"(.*?)\"", response.text)[-1] + key, token = re.findall( + r"params_AbusePreventionHelper\s=\s\[(.*?),\"(.*?)\",", + response.text + )[0] + return url, ig, iid, key, token + + def do_translate(self, text): + text = text[:1000] # bing translate max length + url, ig, iid, key, token = self.find_sid() + response = self.session.post( + f"{url}ttranslatev3?IG={ig}&IID={iid}", + data={ + "fromLang": self.lang_in, + "to": self.lang_out, + "text": text, + "token": token, + "key": key, + }, + headers=self.headers, + ) + response.raise_for_status() + return response.json()[0]["translations"][0]["text"] + + class OpenAITranslator(BaseTranslator): # https://github.com/openai/openai-python name = "openai" diff --git a/yadt/main.py b/yadt/main.py index e00e256..e1e6d00 100644 --- a/yadt/main.py +++ b/yadt/main.py @@ -5,7 +5,7 @@ import logging import argparse import httpx -from yadt.document_il.translator.translator import OpenAITranslator, GoogleTranslator +from yadt.document_il.translator.translator import OpenAITranslator, GoogleTranslator, BingTranslator from yadt.document_il.translator.translator import set_translate_rate_limiter from yadt.translation_config import TranslationConfig # noqa: E402 @@ -105,18 +105,22 @@ def create_parser(): service_params = translation_params.add_mutually_exclusive_group() service_params.add_argument( "--openai", - "-oai", default=False, action="store_true", help="Use OpenAI translator.", ) service_params.add_argument( "--google", - "-g", default=False, action="store_true", help="Use Google translator.", ) + service_params.add_argument( + "--bing", + default=False, + action="store_true", + help="Use Bing translator.", + ) openai_params = parser.add_argument_group( "Translation - OpenAI Options", description="OpenAI specific options" ) @@ -188,8 +192,8 @@ def main(): create_cache_folder() # 验证翻译服务选择 - if not (args.openai or args.google): - parser.error("必须选择一个翻译服务:--openai 或 --google") + if not (args.openai or args.google or args.bing): + parser.error("必须选择一个翻译服务:--openai、--google 或 --bing") # 验证 OpenAI 参数 if args.openai and not args.openai_api_key: @@ -205,6 +209,12 @@ def main(): api_key=args.openai_api_key, ignore_cache=args.ignore_cache, ) + elif args.bing: + translator = BingTranslator( + lang_in=args.lang_in, + lang_out=args.lang_out, + ignore_cache=args.ignore_cache, + ) else: translator = GoogleTranslator( lang_in=args.lang_in,