diff --git a/application/lib/ebook_summarizer/html_summarizer.py b/application/lib/ebook_summarizer/html_summarizer.py index 8d71d1b6..e2312751 100644 --- a/application/lib/ebook_summarizer/html_summarizer.py +++ b/application/lib/ebook_summarizer/html_summarizer.py @@ -4,6 +4,7 @@ #Author: cdhigh import re, time import simple_ai_provider +from application.utils import loc_exc_pos def get_summarizer_engines(): return simple_ai_provider._PROV_AI_LIST @@ -32,22 +33,22 @@ def summarize_text(self, text): if chunkSize < 2000: chunkSize = 2000 - summarySize = self.params.get('summary_size', 200) + words = self.params.get('summary_words', 200) summary = '' errMsg = '' lang = self.params.get('summary_lang', '') if lang: summaryTips = (f"Summarize the following text in {lang}. The summary should accurately represent the content " - f"and be no more than {summarySize} words:\n\n") + f"and be no more than {words} words:\n\n") else: summaryTips = (f"Summarize the following text in the same language as the original text. The summary should accurately represent the content " - f"and be no more than {summarySize} words:\n\n") + f"and be no more than {words} words:\n\n") text = re.sub(r'<[^>]+>', '', text)[:chunkSize] - #try: - summary = self.aiAgent.chat(f"{summaryTips}{text}") - #except Exception as e: - #errMsg = str(e) + try: + summary = self.aiAgent.chat(f"{summaryTips}{text}") + except Exception as e: + errMsg = str(e) return {'error': errMsg, 'summary': summary} @@ -71,40 +72,37 @@ def summarize_soup(self, soup, chunkSize=None, maxIterations=5): #将文本分块,这个分块比较粗糙,可能按照段落分块会更好,但是考虑到AI的适应能力比较强, #并且仅用于生成摘要,所以这个简单方案还是可以接受的 chunks = [text[i:i + chunkSize] for i in range(0, len(text), chunkSize)] - summarySize = self.params.get('summary_size', 200) + words = self.params.get('summary_words', 0) or 200 interval = self.engineProperty.get('request_interval', 0) - summary = None - + summaryTips = self.params.get('custom_prompt', '') lang = self.params.get('summary_lang', '') - if lang: - summaryTips = f"Please refine or update the summary based on the following text block, ensuring the summary is in the language: {lang}, and make it more accurately reflect the article content:\n\n" + if summaryTips: #使用自定义prompt + summaryTips = summaryTips.replace('{lang}', lang).replace('{words}', str(words)) + elif lang: + summaryTips = f"Please improve and update the existing summary of the following text block(s), ensuring the summary is written in the language of {lang}. The updated summary should accurately reflect the content while distilling key points, arguments, and conclusions, and should not exceed {words} words:" else: - summaryTips = f"Please refine or update the summary based on the following text block, ensuring the summary is in the same language as the article/preset summary, and make it more accurately reflect the article content:\n\n" - errMsg = '' + summaryTips = f"Please improve and update the existing summary of the following text block(s), ensuring it is in the same language as the article and preset summary, while accurately reflecting the content and distilling key points, arguments, and conclusions. The updated summary should not exceed {words} words:" + + summary = None for i, chunk in enumerate(chunks[:maxIterations]): - prompt = ( - f"The current summary is:\n{summary}\n\n{summaryTips}" - f"Text block {i + 1}:\n{chunk}\n\n" - f"Please generate an updated summary of no more than {summarySize} words." - ) + prompt = f"Existing summary:\n{summary}\n\n{summaryTips}\n\nText block {i + 1}:\n{chunk}\n\n" + try: summary = self.aiAgent.chat(prompt) - except Exception as e: - errMsg = str(e) - break + except: + default_log.info(loc_exc_pos('Error in summary_soup')) + return + if interval > 0: time.sleep(interval) - if errMsg: - default_log.info(f'Error in summary_soup: {errMsg}') - return - #将摘要插在文章标题之后 - summaryTag = soup.new_tag('p', attrs={'class': 'ai_generated_summary'}) + summaryTag = soup.new_tag('p', attrs={'class': 'ai_generated_summary', + 'data-aiagent': str(self.aiAgent)}) style = self.params.get('summary_style', '') if style: summaryTag['style'] = style - b = soup.new_tag('b') + b = soup.new_tag('b', attrs={'class': 'ai_summary_hint'}) b.string = 'AI-Generated Summary: ' summaryTag.append(b) summaryTag.append(summary) diff --git a/application/lib/simple_ai_provider.py b/application/lib/simple_ai_provider.py index 4e8d1567..2923e15e 100644 --- a/application/lib/simple_ai_provider.py +++ b/application/lib/simple_ai_provider.py @@ -19,7 +19,7 @@ 'Openai': { 'models': ['GPT-4o mini', 'GPT-4o', 'GPT-4 Turbo', 'gpt-3.5-turbo', 'GPT-3.5 Turbo Instruct'], 'request_interval': 10, - 'context_size': 4096}, + 'context_size': 4000}, 'Anthropic': { 'models': ['claude-2', 'claude-3', 'claude-1'], 'request_interval': 6, @@ -27,7 +27,7 @@ 'Grok': { 'models': ['grok-beta'], 'request_interval': 6, - 'context_size': 4096}, + 'context_size': 4000}, 'Mistral': { 'models': ['open-mistral-7b', 'mistral-small-latest', 'open-mixtral-8x7b', 'open-mixtral-8x22b', 'mistral-small-2402', 'mistral-small-2409', 'mistral-medium', 'mistral-large-2402', 'mistral-large-2407', @@ -38,20 +38,15 @@ 'models': ['gemma2-9b-it', 'gemma-7b-it', 'llama-guard-3-8b', 'llama3-70b-8192', 'llama3-8b-8192', 'mixtral-8x7b-32768'], 'request_interval': 2, - 'context_size': 8192}, - - # 'cohere': { - # 'models': ['command-xlarge-nightly'], - # 'request_interval': 6, - # 'context_size': 2048}, - # 'alibaba': { - # 'models': ['tongyi-qianwen-base'], - # 'request_interval': 6, - # 'context_size': 4096}, - # 'baidu': { + 'context_size': 8000}, + 'Alibaba': { + 'models': ['qwen-turbo', 'qwen-plus', 'qwen-long'], + 'request_interval': 1, + 'context_size': 130000}, + # 'Baidu': { # 'models': ['ernie-bot'], # 'request_interval': 6, - # 'context_size': 4096}, + # 'context_size': 4000}, } class SimpleAiProvider: @@ -63,6 +58,9 @@ def __init__(self, name, api_key, model=None, api_host=None): self.api_host = api_host self.opener = UrlOpener() + def __repr__(self): + return f'{self.name}({self.model})' + #返回支持的AI供应商列表,返回一个python字典 def ai_list(self): return _PROV_AI_LIST @@ -84,11 +82,9 @@ def chat(self, message): return self._mistral_chat(message) elif name == 'Groq': return self._groq_chat(message) - # elif name == "cohere": - # return self._cohere_chat(message) - # elif name == "alibaba": - # return self._alibaba_chat(message) - # elif name == "baidu": + elif name == "Alibaba": + return self._alibaba_chat(message) + # elif name == "Baidu": # return self._baidu_chat(message) else: raise ValueError(f"Unsupported provider: {name}") @@ -135,19 +131,6 @@ def _gemini_chat(self, message): contents = response.json()["candidates"][0]["content"] return contents['parts'][0]['text'] - #cohere的chat接口 - def _cohere_chat(self, message): - url = self.api_host if self.api_host else 'https://api.cohere.ai/v1/generate' - headers = {"Authorization": f"Bearer {self.api_key}"} - payload = { - "model": self.model or _PROV_AI_LIST['cohere']['models'][0], - "text": message, - "max_tokens": 300 - } - response = self.opener.post(url, headers=headers, json=payload) - response.raise_for_status() - return response.json()["generations"][0]["text"] - #grok的chat接口 def _grok_chat(self, message): #直接使用openai兼容接口 @@ -163,21 +146,11 @@ def _groq_chat(self, message): #直接使用openai兼容接口 return self._openai_chat(message, defaultUrl='https://api.groq.com/openai/v1/chat/completions') + #通义千问 def _alibaba_chat(self, message): - url = self.api_host if self.api_host else 'https://api.aliyun.com/v1/ai/chat' - headers = { - "Authorization": f"Bearer {self.api_key}", - "Content-Type": "application/json" - } - payload = { - "model": self.model or _PROV_AI_LIST['alibaba']['models'][0], - "messages": [{"role": "user", "content": message}] if isinstance(message, str) else message, - "max_tokens": 300 - } - response = self.opener.post(url, headers=headers, json=payload) - response.raise_for_status() - return response.json()["choices"][0]["content"] - + #直接使用openai兼容接口 + return self._openai_chat(message, defaultUrl='https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions') + def _baidu_chat(self, message): url = self.api_host if self.api_host else 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/ernie-bot' headers = {"Content-Type": "application/json"} diff --git a/application/lib/urlopener.py b/application/lib/urlopener.py index 19e7f1ed..b7f2dbe8 100644 --- a/application/lib/urlopener.py +++ b/application/lib/urlopener.py @@ -106,8 +106,8 @@ def post(self, *args, **kwargs): def open_remote_url(self, url, data, headers, timeout, method, **kwargs): timeout = timeout if timeout else self.timeout headers = self.get_headers(url, headers) - jsonData = kwargs.get('json', None) - method = 'POST' if (data or jsonData) and (method != 'GET') else 'GET' + if not method: + method = 'POST' if (data or kwargs.get('json', None)) else 'GET' url = self.build_url(url, data, method) if method == 'GET': req_func = self.session.get #type:ignore diff --git a/application/static/base.js b/application/static/base.js index 137d4d06..e571c44c 100644 --- a/application/static/base.js +++ b/application/static/base.js @@ -108,65 +108,68 @@ function RegisterHideHambClick() { //连接服务器获取内置recipe列表,并按照语言建立一个字典all_builtin_recipes,字典键为语言,值为信息字典列表 function FetchBuiltinRecipesXml() { - var hasUserLangRss = false; - var hasEnRss = false; + //添加上传的recipe的语言代码 + var langPick = $("#language_pick"); + my_uploaded_recipes.forEach(item => { + var lang = item['language']; + if (lang && !all_builtin_recipes[lang]) { + all_builtin_recipes[lang] = []; + langPick.append($('{1}'.format(lang, LanguageName(lang)))); + } + }); + //这个是静态文件,flask和浏览器会通过etag来自动使用本地缓存 $.get('/recipes/builtin_recipes.xml', function(xml) { + //这里面的代码是异步执行的 + var hasUserLangRss = false; + var hasEnRss = false; var userLang = BrowserLanguage(); + var langPick = $("#language_pick"); $(xml).find("recipe").each(function() { - var title=$(this).attr("title"); - var language=$(this).attr("language").toLowerCase(); - var subs=$(this).attr("needs_subscription"); + var title = $(this).attr("title"); + var lang = $(this).attr("language").toLowerCase(); + var subs = $(this).attr("needs_subscription"); subs = ((subs == 'yes') || (subs == 'optional')) ? true : false; - var description=$(this).attr("description").substring(0, 200); - var id=$(this).attr("id"); + var description = $(this).attr("description").substring(0, 200); + var id = $(this).attr("id"); //忽略各国语言方言,仅取'_'前的部分 - language = language.replace('-', '_'); - var dashIndex = language.indexOf('_'); + lang = lang.replace('-', '_'); + var dashIndex = lang.indexOf('_'); if (dashIndex != -1) { - language = language.substring(0, dashIndex); + lang = lang.substring(0, dashIndex); } - if (language == userLang) { + if (lang == userLang) { hasUserLangRss = true; } - if (language == 'en') { + if (lang == 'en') { hasEnRss = true; } - if (!all_builtin_recipes[language]) { - all_builtin_recipes[language] = []; - var $newLangOpt = $('{1}'.format(language, LanguageName(language))); - $("#language_pick").append($newLangOpt); + if (!all_builtin_recipes[lang]) { + all_builtin_recipes[lang] = []; + langPick.append($('{1}'.format(lang, LanguageName(lang)))); } - all_builtin_recipes[language].push({title: title, description: description, needs_subscription: subs, id: id}); + all_builtin_recipes[lang].push({title: title, description: description, needs_subscription: subs, id: id}); }); + //自动触发和用户浏览器同样语种的选项 + var langItem; if (hasUserLangRss) { - $("#language_pick").find("option[value='{0}']".format(userLang)).attr("selected", true); - $("#language_pick").val(userLang).trigger('change'); + langItem = langPick.find("option[value='{0}']".format(userLang)); } else if (hasEnRss) { //如果有英语则选择英语源 - $("#language_pick").find("option[value='en']").attr("selected", true); - $("#language_pick").val('en').trigger('change'); + langItem = langPick.find("option[value='en']"); } else { //最后只能选择第一个语言 - var firstChild = $("#language_pick").children().first(); - firstChild.attr("selected", true); - firstChild.trigger('change'); + langItem = $("#language_pick").children().first(); + } + if (langItem) { + langItem.attr("selected", true); + langItem.trigger('change'); } }).fail(function(jqXHR, textStatus, errorThrown) { console.log("Failed to fetch '/recipes/builtin_recipes.xml': " + errorThrown); }); - //添加上传的recipe中存在,但是内置库不存在的语言代码 - my_uploaded_recipes.forEach(item => { - var language = item['language']; - if (language && !all_builtin_recipes[language]) { - all_builtin_recipes[language] = []; - var $newLangOpt = $('{1}'.format(language, LanguageName(language))); - $("#language_pick").append($newLangOpt); - } - }); - PopulateLibrary(''); } @@ -229,13 +232,14 @@ function AppendRecipeToLibrary(div, id) { hamb_arg = []; var fTpl = "{0}('{1}','{2}')"; if (id.startsWith("upload:")) { //增加汉堡按钮弹出菜单代码 - hamb_arg.push({klass: 'btn-A', title: i18n.delete, icon: 'icon-delete', act: fTpl.format('DeleteUploadRecipe', id, title)}); hamb_arg.push({klass: 'btn-E', title: i18n.share, icon: 'icon-share', act: fTpl.format('StartShareRss', id, title)}); } hamb_arg.push({klass: 'btn-B', title: i18n.viewSrc, icon: 'icon-source', act: "/viewsrc/" + id.replace(':', '__')}); hamb_arg.push({klass: 'btn-C', title: i18n.subscriSep, icon: 'icon-push', act: fTpl.format('SubscribeRecipe', id, '1')}); hamb_arg.push({klass: 'btn-D', title: i18n.subscribe, icon: 'icon-subscribe', act: fTpl.format('SubscribeRecipe', id, '0')}); - + if (id.startsWith("upload:")) { //增加汉堡按钮弹出菜单代码 + hamb_arg.push({klass: 'btn-A', title: i18n.delete, icon: 'icon-delete', act: fTpl.format('DeleteUploadRecipe', id, title)}); + } row_str.push(AddHamburgerButton(hamb_arg)); row_str.push(''); var new_item = $(row_str.join('')); diff --git a/application/templates/book_audiolator.html b/application/templates/book_audiolator.html index 2fb7d01b..45274d81 100644 --- a/application/templates/book_audiolator.html +++ b/application/templates/book_audiolator.html @@ -39,7 +39,7 @@ {{_("Api Host")}} - + diff --git a/application/templates/book_summarizer.html b/application/templates/book_summarizer.html index e0b06238..ed968cec 100644 --- a/application/templates/book_summarizer.html +++ b/application/templates/book_summarizer.html @@ -2,8 +2,8 @@ {% block titleTag -%} {{_("AI Summarizer")}} - KindleEar {% endblock -%} -{% set lang = params.get('summary_lang', '') %} -{% set summarySize = params.get('summary_size', 200) %} +{% set lang = params.get('summary_lang', '') -%} +{% set words = params.get('summary_words', 200) -%} {% block content -%} @@ -33,7 +33,7 @@ {{_("Api Host")}} - + {{_("Api Key")}} @@ -53,22 +53,26 @@ - {{_("Summary size")}} - - 100 - 200 - 300 - 400 - 500 - 600 - 700 - 800 - 900 + {{_("Summary words")}} + + 100 + 200 + 300 + 400 + 500 + 600 + 700 + 800 + 900 {{_("Summary style")}} - + + + + {{_("Custom prompt")}} + {{params.get('custom_prompt', '')}} diff --git a/application/templates/book_translator.html b/application/templates/book_translator.html index f3824fa3..9647ae17 100644 --- a/application/templates/book_translator.html +++ b/application/templates/book_translator.html @@ -64,7 +64,7 @@ {{_("Translated text style")}} - + diff --git a/application/translations/messages.pot b/application/translations/messages.pot index a0aac5fa..fc5d8c26 100644 --- a/application/translations/messages.pot +++ b/application/translations/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-11-17 17:57-0300\n" +"POT-Creation-Date: 2024-11-18 13:20-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -224,7 +224,7 @@ msgstr "" #: application/templates/adv_dict.html:79 #: application/templates/adv_inboundmail.html:34 #: application/templates/book_audiolator.html:113 -#: application/templates/book_summarizer.html:84 +#: application/templates/book_summarizer.html:88 #: application/templates/book_translator.html:80 #: application/templates/settings.html:258 msgid "Save settings" @@ -1012,7 +1012,8 @@ msgstr "" #: application/templates/book_audiolator.html:42 #: application/templates/book_summarizer.html:36 -msgid "Empty to use default endpoint" +#: application/templates/book_summarizer.html:75 +msgid "Leave empty to use default" msgstr "" #: application/templates/book_audiolator.html:46 @@ -1096,13 +1097,13 @@ msgid "Extra loud" msgstr "" #: application/templates/book_audiolator.html:105 -#: application/templates/book_summarizer.html:76 +#: application/templates/book_summarizer.html:80 #: application/templates/book_translator.html:72 msgid "Apply to all subscribed recipes" msgstr "" #: application/templates/book_audiolator.html:110 -#: application/templates/book_summarizer.html:81 +#: application/templates/book_summarizer.html:85 #: application/templates/book_translator.html:77 msgid "" "Note: Enabling this feature will significantly increase consumed CPU " @@ -1110,13 +1111,13 @@ msgid "" msgstr "" #: application/templates/book_audiolator.html:119 -#: application/templates/book_summarizer.html:90 +#: application/templates/book_summarizer.html:94 #: application/templates/book_translator.html:86 msgid "Test (Please save settings firstly)" msgstr "" #: application/templates/book_audiolator.html:121 -#: application/templates/book_summarizer.html:92 +#: application/templates/book_summarizer.html:96 #: application/templates/book_translator.html:88 msgid "Text" msgstr "" @@ -1126,7 +1127,7 @@ msgid "Your browser does not support the audio element." msgstr "" #: application/templates/book_audiolator.html:132 -#: application/templates/book_summarizer.html:101 +#: application/templates/book_summarizer.html:105 #: application/templates/book_translator.html:97 msgid "Test" msgstr "" @@ -1145,14 +1146,22 @@ msgid "Auto" msgstr "" #: application/templates/book_summarizer.html:56 -msgid "Summary size" +msgid "Summary words" msgstr "" #: application/templates/book_summarizer.html:70 msgid "Summary style" msgstr "" -#: application/templates/book_summarizer.html:96 +#: application/templates/book_summarizer.html:74 +msgid "Placeholders available:" +msgstr "" + +#: application/templates/book_summarizer.html:74 +msgid "Custom prompt" +msgstr "" + +#: application/templates/book_summarizer.html:100 msgid "Summary" msgstr "" @@ -1662,8 +1671,8 @@ msgid "Word" msgstr "" #: application/view/admin.py:48 application/view/adv.py:441 -#: application/view/settings.py:66 application/view/translator.py:85 -#: application/view/translator.py:169 application/view/translator.py:250 +#: application/view/settings.py:66 application/view/translator.py:87 +#: application/view/translator.py:171 application/view/translator.py:253 msgid "Settings Saved!" msgstr "" @@ -1907,8 +1916,8 @@ msgstr "" msgid "The article is missing?" msgstr "" -#: application/view/reader.py:190 application/view/translator.py:118 -#: application/view/translator.py:202 application/view/translator.py:283 +#: application/view/reader.py:190 application/view/translator.py:120 +#: application/view/translator.py:204 application/view/translator.py:286 msgid "The text is empty." msgstr "" @@ -2162,10 +2171,10 @@ msgid "The recipe have been subscribed, please unsubscribe it before delete." msgstr "" #: application/view/subscribe.py:304 application/view/translator.py:51 -#: application/view/translator.py:101 application/view/translator.py:114 -#: application/view/translator.py:137 application/view/translator.py:185 -#: application/view/translator.py:198 application/view/translator.py:227 -#: application/view/translator.py:266 application/view/translator.py:279 +#: application/view/translator.py:103 application/view/translator.py:116 +#: application/view/translator.py:139 application/view/translator.py:187 +#: application/view/translator.py:200 application/view/translator.py:229 +#: application/view/translator.py:269 application/view/translator.py:282 msgid "This recipe has not been subscribed to yet." msgstr "" @@ -2195,7 +2204,7 @@ msgstr "" msgid "The login information for this recipe has been saved." msgstr "" -#: application/view/translator.py:79 application/view/translator.py:162 +#: application/view/translator.py:81 application/view/translator.py:164 msgid "The api key is required." msgstr "" diff --git a/application/translations/tr_TR/LC_MESSAGES/messages.mo b/application/translations/tr_TR/LC_MESSAGES/messages.mo index a0e1cfd9..65a87c6e 100644 Binary files a/application/translations/tr_TR/LC_MESSAGES/messages.mo and b/application/translations/tr_TR/LC_MESSAGES/messages.mo differ diff --git a/application/translations/tr_TR/LC_MESSAGES/messages.po b/application/translations/tr_TR/LC_MESSAGES/messages.po index 1ced3c0c..49a57f7f 100644 --- a/application/translations/tr_TR/LC_MESSAGES/messages.po +++ b/application/translations/tr_TR/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-11-17 17:57-0300\n" +"POT-Creation-Date: 2024-11-18 13:20-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language: tr_TR\n" @@ -225,7 +225,7 @@ msgstr "Ana bilgisayar" #: application/templates/adv_dict.html:79 #: application/templates/adv_inboundmail.html:34 #: application/templates/book_audiolator.html:113 -#: application/templates/book_summarizer.html:84 +#: application/templates/book_summarizer.html:88 #: application/templates/book_translator.html:80 #: application/templates/settings.html:258 msgid "Save settings" @@ -1028,8 +1028,9 @@ msgstr "Api Host" #: application/templates/book_audiolator.html:42 #: application/templates/book_summarizer.html:36 -msgid "Empty to use default endpoint" -msgstr "Varsayılan uç noktayı kullanmak için boş bırakın" +#: application/templates/book_summarizer.html:75 +msgid "Leave empty to use default" +msgstr "Boş bırakın, varsayılan değeri kullanın" #: application/templates/book_audiolator.html:46 msgid "Region" @@ -1112,13 +1113,13 @@ msgid "Extra loud" msgstr "Ekstra yüksek sesli" #: application/templates/book_audiolator.html:105 -#: application/templates/book_summarizer.html:76 +#: application/templates/book_summarizer.html:80 #: application/templates/book_translator.html:72 msgid "Apply to all subscribed recipes" msgstr "Tüm abone olunan tarifelere uygula" #: application/templates/book_audiolator.html:110 -#: application/templates/book_summarizer.html:81 +#: application/templates/book_summarizer.html:85 #: application/templates/book_translator.html:77 msgid "" "Note: Enabling this feature will significantly increase consumed CPU " @@ -1128,13 +1129,13 @@ msgstr "" "ölçüde artırır." #: application/templates/book_audiolator.html:119 -#: application/templates/book_summarizer.html:90 +#: application/templates/book_summarizer.html:94 #: application/templates/book_translator.html:86 msgid "Test (Please save settings firstly)" msgstr "Test (Lütfen önce ayarları kaydedin)" #: application/templates/book_audiolator.html:121 -#: application/templates/book_summarizer.html:92 +#: application/templates/book_summarizer.html:96 #: application/templates/book_translator.html:88 msgid "Text" msgstr "Metin" @@ -1144,7 +1145,7 @@ msgid "Your browser does not support the audio element." msgstr "Tarayıcınız ses öğesini desteklemiyor." #: application/templates/book_audiolator.html:132 -#: application/templates/book_summarizer.html:101 +#: application/templates/book_summarizer.html:105 #: application/templates/book_translator.html:97 msgid "Test" msgstr "Test" @@ -1163,14 +1164,22 @@ msgid "Auto" msgstr "Otomatik" #: application/templates/book_summarizer.html:56 -msgid "Summary size" -msgstr "Özet Boyutu" +msgid "Summary words" +msgstr "Özet kelimeleri" #: application/templates/book_summarizer.html:70 msgid "Summary style" msgstr "Özet Tarzı" -#: application/templates/book_summarizer.html:96 +#: application/templates/book_summarizer.html:74 +msgid "Placeholders available:" +msgstr "Mevcut yer tutucular:" + +#: application/templates/book_summarizer.html:74 +msgid "Custom prompt" +msgstr "Özel prompt" + +#: application/templates/book_summarizer.html:100 msgid "Summary" msgstr "Özet" @@ -1696,8 +1705,8 @@ msgid "Word" msgstr "Kelime" #: application/view/admin.py:48 application/view/adv.py:441 -#: application/view/settings.py:66 application/view/translator.py:85 -#: application/view/translator.py:169 application/view/translator.py:250 +#: application/view/settings.py:66 application/view/translator.py:87 +#: application/view/translator.py:171 application/view/translator.py:253 msgid "Settings Saved!" msgstr "Ayarlar Kaydedildi!" @@ -1951,8 +1960,8 @@ msgstr "" msgid "The article is missing?" msgstr "Makale eksik mi?" -#: application/view/reader.py:190 application/view/translator.py:118 -#: application/view/translator.py:202 application/view/translator.py:283 +#: application/view/reader.py:190 application/view/translator.py:120 +#: application/view/translator.py:204 application/view/translator.py:286 msgid "The text is empty." msgstr "Metin boş." @@ -2208,10 +2217,10 @@ msgid "The recipe have been subscribed, please unsubscribe it before delete." msgstr "Tarif abone olunmuş, silmeden önce aboneliği iptal edin." #: application/view/subscribe.py:304 application/view/translator.py:51 -#: application/view/translator.py:101 application/view/translator.py:114 -#: application/view/translator.py:137 application/view/translator.py:185 -#: application/view/translator.py:198 application/view/translator.py:227 -#: application/view/translator.py:266 application/view/translator.py:279 +#: application/view/translator.py:103 application/view/translator.py:116 +#: application/view/translator.py:139 application/view/translator.py:187 +#: application/view/translator.py:200 application/view/translator.py:229 +#: application/view/translator.py:269 application/view/translator.py:282 msgid "This recipe has not been subscribed to yet." msgstr "Bu tarife henüz abone olunmadı." @@ -2243,7 +2252,7 @@ msgstr "Bu tarifin giriş bilgileri temizlendi." msgid "The login information for this recipe has been saved." msgstr "Bu tarifin giriş bilgileri kaydedildi." -#: application/view/translator.py:79 application/view/translator.py:162 +#: application/view/translator.py:81 application/view/translator.py:164 msgid "The api key is required." msgstr "API anahtarı gereklidir." diff --git a/application/translations/zh/LC_MESSAGES/messages.mo b/application/translations/zh/LC_MESSAGES/messages.mo index 93a36ac0..f586b3f1 100644 Binary files a/application/translations/zh/LC_MESSAGES/messages.mo and b/application/translations/zh/LC_MESSAGES/messages.mo differ diff --git a/application/translations/zh/LC_MESSAGES/messages.po b/application/translations/zh/LC_MESSAGES/messages.po index b717466c..9f0f0946 100644 --- a/application/translations/zh/LC_MESSAGES/messages.po +++ b/application/translations/zh/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: KindleEar v3.0.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-11-17 17:57-0300\n" +"POT-Creation-Date: 2024-11-18 13:20-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language: zh\n" @@ -225,7 +225,7 @@ msgstr "主机" #: application/templates/adv_dict.html:79 #: application/templates/adv_inboundmail.html:34 #: application/templates/book_audiolator.html:113 -#: application/templates/book_summarizer.html:84 +#: application/templates/book_summarizer.html:88 #: application/templates/book_translator.html:80 #: application/templates/settings.html:258 msgid "Save settings" @@ -1013,8 +1013,9 @@ msgstr "主机" #: application/templates/book_audiolator.html:42 #: application/templates/book_summarizer.html:36 -msgid "Empty to use default endpoint" -msgstr "留空为使用默认端点" +#: application/templates/book_summarizer.html:75 +msgid "Leave empty to use default" +msgstr "不填则使用默认值" #: application/templates/book_audiolator.html:46 msgid "Region" @@ -1097,13 +1098,13 @@ msgid "Extra loud" msgstr "超级高" #: application/templates/book_audiolator.html:105 -#: application/templates/book_summarizer.html:76 +#: application/templates/book_summarizer.html:80 #: application/templates/book_translator.html:72 msgid "Apply to all subscribed recipes" msgstr "应用到当前所有已订阅Recipe" #: application/templates/book_audiolator.html:110 -#: application/templates/book_summarizer.html:81 +#: application/templates/book_summarizer.html:85 #: application/templates/book_translator.html:77 msgid "" "Note: Enabling this feature will significantly increase consumed CPU " @@ -1111,13 +1112,13 @@ msgid "" msgstr "注意:启用此特性会显著增加CPU实例小时数的消耗。" #: application/templates/book_audiolator.html:119 -#: application/templates/book_summarizer.html:90 +#: application/templates/book_summarizer.html:94 #: application/templates/book_translator.html:86 msgid "Test (Please save settings firstly)" msgstr "测试 (请先保存设置)" #: application/templates/book_audiolator.html:121 -#: application/templates/book_summarizer.html:92 +#: application/templates/book_summarizer.html:96 #: application/templates/book_translator.html:88 msgid "Text" msgstr "原文" @@ -1127,7 +1128,7 @@ msgid "Your browser does not support the audio element." msgstr "您的浏览器不支持audio标签。" #: application/templates/book_audiolator.html:132 -#: application/templates/book_summarizer.html:101 +#: application/templates/book_summarizer.html:105 #: application/templates/book_translator.html:97 msgid "Test" msgstr "测试" @@ -1146,14 +1147,22 @@ msgid "Auto" msgstr "自动" #: application/templates/book_summarizer.html:56 -msgid "Summary size" -msgstr "摘要大小" +msgid "Summary words" +msgstr "摘要字数" #: application/templates/book_summarizer.html:70 msgid "Summary style" msgstr "摘要样式" -#: application/templates/book_summarizer.html:96 +#: application/templates/book_summarizer.html:74 +msgid "Placeholders available:" +msgstr "可用的占位符:" + +#: application/templates/book_summarizer.html:74 +msgid "Custom prompt" +msgstr "自定义prompt" + +#: application/templates/book_summarizer.html:100 msgid "Summary" msgstr "摘要" @@ -1665,8 +1674,8 @@ msgid "Word" msgstr "单词" #: application/view/admin.py:48 application/view/adv.py:441 -#: application/view/settings.py:66 application/view/translator.py:85 -#: application/view/translator.py:169 application/view/translator.py:250 +#: application/view/settings.py:66 application/view/translator.py:87 +#: application/view/translator.py:171 application/view/translator.py:253 msgid "Settings Saved!" msgstr "设置已保存!" @@ -1910,8 +1919,8 @@ msgstr "你可以点击下面的链接来重置你的KindleEar密码。" msgid "The article is missing?" msgstr "文章丢失了?" -#: application/view/reader.py:190 application/view/translator.py:118 -#: application/view/translator.py:202 application/view/translator.py:283 +#: application/view/reader.py:190 application/view/translator.py:120 +#: application/view/translator.py:204 application/view/translator.py:286 msgid "The text is empty." msgstr "文本为空。" @@ -2165,10 +2174,10 @@ msgid "The recipe have been subscribed, please unsubscribe it before delete." msgstr "此Recipe已经被订阅,请先取消订阅然后再删除。" #: application/view/subscribe.py:304 application/view/translator.py:51 -#: application/view/translator.py:101 application/view/translator.py:114 -#: application/view/translator.py:137 application/view/translator.py:185 -#: application/view/translator.py:198 application/view/translator.py:227 -#: application/view/translator.py:266 application/view/translator.py:279 +#: application/view/translator.py:103 application/view/translator.py:116 +#: application/view/translator.py:139 application/view/translator.py:187 +#: application/view/translator.py:200 application/view/translator.py:229 +#: application/view/translator.py:269 application/view/translator.py:282 msgid "This recipe has not been subscribed to yet." msgstr "此Recipe尚未被订阅。" @@ -2198,8 +2207,7 @@ msgstr "此Recipe的网站登录信息已经被删除。" msgid "The login information for this recipe has been saved." msgstr "此Recipe的网站登录信息已经保存。" -#: application/view/translator.py:79 application/view/translator.py:162 +#: application/view/translator.py:81 application/view/translator.py:164 msgid "The api key is required." msgstr "需要填写api key." - diff --git a/application/view/translator.py b/application/view/translator.py index f1480458..78b755a0 100644 --- a/application/view/translator.py +++ b/application/view/translator.py @@ -67,10 +67,12 @@ def BookTranslatorPost(recipeType, recipe, user, recipeId): apiHost = f'https://{apiHost}' if apiHost and not apiHost.startswith('http') else apiHost apiKeys = form.get('api_keys', '') apiKeys = apiKeys.split('\n') if apiKeys else [] + origStyle = form.get('orig_style', '').replace('{', '').replace('}', '').replace('\n', '') + transStyle = form.get('trans_style', '').replace('{', '').replace('}', '').replace('\n', '') params = {'enable': str_to_bool(form.get('enable', '')), 'engine': engineName, 'api_host': apiHost, 'api_keys': apiKeys, 'src_lang': form.get('src_lang', ''), 'dst_lang': form.get('dst_lang', 'en'), 'position': form.get('position', 'below'), - 'orig_style': form.get('orig_style', ''), 'trans_style': form.get('trans_style', '')} + 'orig_style': origStyle, 'trans_style': transStyle} engines = get_trans_engines() engine = engines.get(engineName, None) @@ -242,10 +244,11 @@ def BookSummarizerPost(recipeType, recipe, user, recipeId): engineName = form.get('engine', '') apiHost = form.get('api_host', '') apiHost = f'https://{apiHost}' if apiHost and not apiHost.startswith('http') else apiHost + style = form.get('summary_style', '').replace('{', '').replace('}', '').replace('\n', '') params = {'enable': str_to_bool(form.get('enable', '')), 'engine': engineName, 'model': form.get('model', ''), 'api_host': apiHost, 'api_key': form.get('api_key', ''), - 'summary_lang': form.get('summary_lang', ''), - 'summary_size': str_to_int(form.get('summary_size', ''), 200), 'summary_style': form.get('summary_style', ''),} + 'summary_lang': form.get('summary_lang', ''), 'custom_prompt': form.get('custom_prompt', '').strip(), + 'summary_words': str_to_int(form.get('summary_words', ''), 200), 'summary_style': style,} tips = _("Settings Saved!") apply_all = str_to_bool(form.get('apply_all', ''))