From 96a7a4175985af4cf95885f7420b17bf93b36265 Mon Sep 17 00:00:00 2001 From: Gabe Date: Wed, 1 Oct 2025 13:22:22 +0800 Subject: [PATCH] feat: support placeholder selection --- src/config/api.js | 12 +++++----- src/config/i18n.js | 10 ++++++++ src/libs/translator.js | 45 ++++++++++++++++++++--------------- src/views/Options/Apis.js | 49 +++++++++++++++++++++++++++++++++++---- 4 files changed, 86 insertions(+), 30 deletions(-) diff --git a/src/config/api.js b/src/config/api.js index b8c7f58..a7df438 100644 --- a/src/config/api.js +++ b/src/config/api.js @@ -138,8 +138,8 @@ export const BUILTIN_STONES = [ "machine-like", // 机器风格 "concise", // 简明风格 ]; -export const BUILTIN_PLACEHOULDERS = ["{ }", "{{ }}", "[ ]", "[[ ]]"]; -export const BUILTIN_TAG_NAMES = ["i", "a", "span"]; +export const BUILTIN_PLACEHOLDERS = ["{ }", "{{ }}", "[ ]", "[[ ]]"]; +export const BUILTIN_PLACETAGS = ["i", "a", "x", "span"]; export const OPT_LANGS_TO = [ ["en", "English - English"], @@ -357,10 +357,10 @@ const defaultApi = { model: "", // 模型名称 systemPrompt: defaultSystemPrompt, userPrompt: "", - tone: "neutral", // 翻译风格 - placeholder: "{ }", // 占位符(todo: 备用) - tagName: "i", // 标签符 (todo: 备用) - aiTerms: false, // AI智能专业术语 (todo: 备用) + tone: BUILTIN_STONES[0], // 翻译风格 + placeholder: BUILTIN_PLACEHOLDERS[0], // 占位符 + placetag: [BUILTIN_PLACETAGS[0]], // 占位标签 + // aiTerms: false, // AI智能专业术语 (todo: 备用) customHeader: "", customBody: "", reqHook: "", // request 钩子函数 diff --git a/src/config/i18n.js b/src/config/i18n.js index cc1bf02..47bbac6 100644 --- a/src/config/i18n.js +++ b/src/config/i18n.js @@ -1493,4 +1493,14 @@ export const I18N = { en: `Mini/Regular Mode`, zh_TW: `迷你/常規模式`, }, + api_placeholder: { + zh: `占位符`, + en: `Placeholder`, + zh_TW: `佔位符`, + }, + api_placetag: { + zh: `占位标签`, + en: `Placeholder tags`, + zh_TW: `佔位標`, + }, }; diff --git a/src/libs/translator.js b/src/libs/translator.js index 19fd7a5..a87d552 100644 --- a/src/libs/translator.js +++ b/src/libs/translator.js @@ -209,13 +209,6 @@ export class Translator { /^\d{1,2}:\d{2}(:\d{2})?$/, ]; - // 占位符 - static PLACEHOLDER = { - startDelimiter: "{", - endDelimiter: "}", - tagName: "i", - }; - static DEFAULT_OPTIONS = DEFAULT_SETTING; // 默认配置 static DEFAULT_RULE = GLOBLA_RULE; // 默认规则 @@ -280,6 +273,12 @@ export class Translator { #docInfo = {}; // 网页信息 #textClass = {}; // 译文样式class #textSheet = ""; // 译文样式字典 + #apiSetting = null; + #placeholder = { + startDelimiter: "{", + endDelimiter: "}", + tagName: "i", + }; #isUserscript = false; #transboxManager = null; // 划词翻译 @@ -312,6 +311,18 @@ export class Translator { constructor(rule = {}, setting = {}, isUserscript) { this.#setting = { ...Translator.DEFAULT_OPTIONS, ...setting }; this.#rule = { ...Translator.DEFAULT_RULE, ...rule }; + this.#apiSetting = + this.#setting.transApis.find( + (api) => api.apiSlug === this.#rule.apiSlug + ) || DEFAULT_API_SETTING; + const [startDelimiter, endDelimiter] = + this.#apiSetting.placeholder.split(" "); + this.#placeholder = { + startDelimiter, + endDelimiter, + tagName: this.#apiSetting.placetag, + }; + this.#isUserscript = isUserscript; this.#eventName = genEventName(); this.#docInfo = { @@ -437,11 +448,9 @@ export class Translator { #createPlaceholderRegex() { const escapedStart = Translator.escapeRegex( - Translator.PLACEHOLDER.startDelimiter - ); - const escapedEnd = Translator.escapeRegex( - Translator.PLACEHOLDER.endDelimiter + this.#placeholder.startDelimiter ); + const escapedEnd = Translator.escapeRegex(this.#placeholder.endDelimiter); const patternString = `(${escapedStart}\\d+${escapedEnd}|<\\/?\\w+\\d+>)`; const flags = "g"; return new RegExp(patternString, flags); @@ -1031,10 +1040,11 @@ export class Translator { let replaceCounter = 0; // {{n}} let wrapCounter = 0; // const placeholderMap = new Map(); + const { startDelimiter, endDelimiter } = this.#placeholder; const pushReplace = (html) => { replaceCounter++; - const placeholder = `${Translator.PLACEHOLDER.startDelimiter}${replaceCounter}${Translator.PLACEHOLDER.endDelimiter}`; + const placeholder = `${startDelimiter}${replaceCounter}${endDelimiter}`; placeholderMap.set(placeholder, html); return placeholder; }; @@ -1095,8 +1105,8 @@ export class Translator { if (Translator.TAGS.WARP.has(node.tagName)) { wrapCounter++; - const startPlaceholder = `<${Translator.PLACEHOLDER.tagName}${wrapCounter}>`; - const endPlaceholder = ``; + const startPlaceholder = `<${this.#placeholder.tagName}${wrapCounter}>`; + const endPlaceholder = ``; placeholderMap.set(startPlaceholder, buildOpeningTag(node)); placeholderMap.set(endPlaceholder, ``); return `${startPlaceholder}${innerContent}${endPlaceholder}`; @@ -1139,16 +1149,13 @@ export class Translator { // 发起翻译请求 #translateFetch(text, deLang = "") { - const { apiSlug, fromLang, toLang } = this.#rule; - const apiSetting = - this.#setting.transApis.find((api) => api.apiSlug === apiSlug) || - DEFAULT_API_SETTING; + const { fromLang, toLang } = this.#rule; return apiTranslate({ text, fromLang: deLang || fromLang, toLang, - apiSetting, + apiSetting: this.#apiSetting, docInfo: this.#docInfo, }); } diff --git a/src/views/Options/Apis.js b/src/views/Options/Apis.js index 27de6e1..c72fe88 100644 --- a/src/views/Options/Apis.js +++ b/src/views/Options/Apis.js @@ -40,8 +40,8 @@ import { OPT_ALL_TYPES, API_SPE_TYPES, BUILTIN_STONES, - // BUILTIN_PLACEHOULDERS, - // BUILTIN_TAG_NAMES, + BUILTIN_PLACEHOLDERS, + BUILTIN_PLACETAGS, } from "../../config"; function TestButton({ apiSlug, api }) { @@ -233,8 +233,8 @@ function ApiFields({ apiSlug, isUserApi, deleteApi }) { useContext = false, contextSize = DEFAULT_CONTEXT_SIZE, tone = "neutral", - // placeholder = "{ }", - // tagName = "i", + placeholder = BUILTIN_PLACEHOLDERS[0], + placetag = BUILTIN_PLACETAGS[0], // aiTerms = false, } = formData; @@ -360,7 +360,7 @@ function ApiFields({ apiSlug, isUserApi, deleteApi }) { freeSolo size="small" fullWidth - options={BUILTIN_PLACEHOULDERS} + options={BUILTIN_PLACEHOLDERS} name="placeholder" label={i18n("placeholder")} value={placeholder} @@ -610,6 +610,45 @@ function ApiFields({ apiSlug, isUserApi, deleteApi }) { {showMore && ( <> + + + + + {BUILTIN_PLACEHOLDERS.map((item) => ( + + {item} + + ))} + + + + + {BUILTIN_PLACETAGS.map((item) => ( + + {`<${item}N>`} + + ))} + + + + +