diff --git a/engines/__init__.py b/engines/__init__.py index e28126dc..71338047 100644 --- a/engines/__init__.py +++ b/engines/__init__.py @@ -10,10 +10,11 @@ from .baidu import BaiduTranslate from .microsoft import MicrosoftEdgeTranslate, AzureChatgptTranslate from .deepseek import DeepseekTranslate +from .laratranslate import LaraTranslate builtin_engines: tuple[type[Base], ...] = ( GoogleFreeTranslateNew, GoogleFreeTranslateHtml, GoogleFreeTranslate, GoogleBasicTranslate, GoogleBasicTranslateADC, GoogleAdvancedTranslate, ChatgptTranslate, AzureChatgptTranslate, GeminiTranslate, ClaudeTranslate, DeepseekTranslate, DeeplTranslate, DeeplProTranslate, DeeplFreeTranslate, - MicrosoftEdgeTranslate, YoudaoTranslate, BaiduTranslate) + MicrosoftEdgeTranslate, YoudaoTranslate, BaiduTranslate, LaraTranslate) diff --git a/engines/genai.py b/engines/genai.py index cf281246..506d1c05 100644 --- a/engines/genai.py +++ b/engines/genai.py @@ -14,6 +14,7 @@ class GenAI(Base, ABC): temperature: float top_p: float top_k: int + not_need_tlang: bool = False @abstractmethod def get_models(self) -> list[str]: diff --git a/engines/laratranslate.py b/engines/laratranslate.py new file mode 100644 index 00000000..76af7c7a --- /dev/null +++ b/engines/laratranslate.py @@ -0,0 +1,71 @@ +import json +from .languages import google +from .genai import GenAI + + +class LaraTranslate(GenAI): + name = 'LaraTranslate(Free)' + alias = 'Lara Translate (Free)' + free = True + lang_codes = GenAI.load_lang_codes(google) + need_api_key = False + + samplings = ['top_p'] + sampling = 'top_p' + + endpoint = 'https://webapi.laratranslate.com/translate/segmented' + api_key_errors: list[str] = ['401'] + + concurrency_limit = 1 + request_interval: float = 1.0 + request_timeout: float = 30.0 + + temperature = 1.0 + top_p = 1.0 + top_k = 1 + stream = False + not_need_tlang = True + + prompt = ( + '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. ' + ) + + models: list[str] = [] + model: str | None = None + + def __init__(self): + super().__init__() + self.prompt = self.config.get('prompt', self.prompt) + + def _prompt(self, _text): + return self.prompt + + def get_models(self): + return [] + + def get_headers(self): + return {'Content-Type': 'application/json'} + + def get_body(self, text): + source = self._get_source_code() + if source == 'auto': + source = '' + return json.dumps( + { + 'adapt_to': [], + 'content_type': 'text/plain', + 'glossaries': [], + 'instructions': [self.prompt], + 'q': text, + 'source': source, + 'style': 'faithful', + 'target': self._get_target_code() + } + ) + + def get_result(self, response): + return json.loads(response)['content']['translations'][0]['translation'] diff --git a/setting.py b/setting.py index 632080d4..24efb70c 100644 --- a/setting.py +++ b/setting.py @@ -1324,7 +1324,7 @@ def update_prompt(self, widget, config): if not issubclass(self.current_engine, GenAI): return prompt = widget.toPlainText().strip() - if prompt and '' not in prompt: + if prompt and not self.current_engine.not_need_tlang and '' not in prompt: self.alert.pop( _('the prompt must include {}.').format(''), 'warning')