支持mineru 2.7.1
This commit is contained in:
1 parent
50255069b7
commit
3b13157670
5 files changed
+94
-56
No files matched your search
@@ -337,7 +337,7 @@ class TranslateServiceRequest(BaseModel):
|
||||
],
|
||||
)
|
||||
file_content: str = Field(
|
||||
..., description="Base64编码的文件内容。", examples=["JVBERi0xLjQK..."]
|
||||
..., description="Base64编码的文件内容。", examples=["JVBERi0xLjcKJeLjz9MKMSAwIG9iago8PC9..."]
|
||||
)
|
||||
payload: TranslatePayload = Field(
|
||||
..., description="包含工作流类型和相应参数的载荷。"
|
||||
@@ -666,7 +666,7 @@ async def _perform_translation(
|
||||
"force_json",
|
||||
"rpm",
|
||||
"tpm",
|
||||
"provider", # Added provider
|
||||
"provider",
|
||||
},
|
||||
exclude_none=True,
|
||||
)
|
||||
@@ -688,7 +688,9 @@ async def _perform_translation(
|
||||
converter_config = ConverterMineruDeployConfig(
|
||||
base_url=payload.mineru_deploy_base_url,
|
||||
backend=payload.mineru_deploy_backend,
|
||||
parse_method=payload.mineru_deploy_parse_method,
|
||||
formula_enable=payload.mineru_deploy_formula_enable,
|
||||
table_enable=payload.mineru_deploy_table_enable,
|
||||
start_page_id=payload.mineru_deploy_start_page_id,
|
||||
end_page_id=payload.mineru_deploy_end_page_id,
|
||||
lang_list=payload.mineru_deploy_lang_list,
|
||||
@@ -2214,8 +2216,10 @@ async def service_flat_translate(
|
||||
formula_ocr: bool = Form(True, description="[PDF] 是否启用公式识别"),
|
||||
code_ocr: bool = Form(True, description="[Docling] 是否启用代码块识别"),
|
||||
mineru_deploy_base_url: str = Form("http://127.0.0.1:8000", description="[MinerU Local] 服务地址"),
|
||||
mineru_deploy_backend: str = Form("VLM", description="[MinerU Local] 后端类型"),
|
||||
mineru_deploy_backend: str = Form("hybrid-auto-engine", description="[MinerU Local] 后端类型: hybrid-auto-engine, pipeline 等"),
|
||||
mineru_deploy_parse_method: str = Form("auto", description="[MinerU Local] 解析方法: auto, txt, ocr"),
|
||||
mineru_deploy_formula_enable: bool = Form(True, description="[MinerU Local] 是否启用公式"),
|
||||
mineru_deploy_table_enable: bool = Form(True, description="[MinerU Local] 是否启用表格"),
|
||||
mineru_deploy_start_page_id: int = Form(0, description="[MinerU Local] 起始页码"),
|
||||
mineru_deploy_end_page_id: int = Form(99999, description="[MinerU Local] 结束页码"),
|
||||
mineru_deploy_lang_list: Optional[List[str]] = Form(None, description="[MinerU Local] 语言列表"),
|
||||
@@ -2317,7 +2321,9 @@ async def service_flat_translate(
|
||||
# --- MinerU 本地部署参数 ---
|
||||
"mineru_deploy_base_url": mineru_deploy_base_url,
|
||||
"mineru_deploy_backend": mineru_deploy_backend,
|
||||
"mineru_deploy_parse_method": mineru_deploy_parse_method,
|
||||
"mineru_deploy_formula_enable": mineru_deploy_formula_enable,
|
||||
"mineru_deploy_table_enable": mineru_deploy_table_enable,
|
||||
"mineru_deploy_start_page_id": mineru_deploy_start_page_id,
|
||||
"mineru_deploy_end_page_id": mineru_deploy_end_page_id,
|
||||
"mineru_deploy_lang_list": mineru_deploy_lang_list,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
import asyncio
|
||||
from dataclasses import dataclass
|
||||
from typing import Literal, Hashable
|
||||
from typing import Literal, Hashable, List
|
||||
|
||||
import httpx
|
||||
|
||||
@@ -16,24 +16,42 @@ from docutranslate.utils.markdown_utils import embed_inline_image_from_zip
|
||||
@dataclass(kw_only=True)
|
||||
class ConverterMineruDeployConfig(X2MarkdownConverterConfig):
|
||||
base_url: str = "http://127.0.0.1:8000"
|
||||
output_dir: str = "./output" # 覆盖默认值 ./output
|
||||
lang_list: list[Literal["ch", "ch_server", "ch_lite", "en", "korean", "japan", "chinese_cht", "ta", "te", "ka", "th", "el", "latin", "arabic", "east_slavic", "cyrillic", "devanagari"]] | None = None
|
||||
backend: Literal["pipeline", "vlm-transformers", "vlm-mlx-engine", "vlm-vllm-async-engine", "vlm-lmdeploy-engine","vlm-http-client"] = "pipeline"
|
||||
# parse_method: str = "auto"
|
||||
output_dir: str = "./output"
|
||||
# 支持的语言列表 (来自 MinerU API)
|
||||
lang_list: List[str] | None = None # 默认值在 API 侧处理,这里 None 即可
|
||||
|
||||
# 后端引擎选项 (更新适配最新的 MinerU API)
|
||||
backend: Literal[
|
||||
"pipeline",
|
||||
"vlm-auto-engine",
|
||||
"vlm-http-client",
|
||||
"hybrid-auto-engine",
|
||||
"hybrid-http-client"
|
||||
] = "hybrid-auto-engine"
|
||||
|
||||
parse_method: Literal["auto", "txt", "ocr"] = "auto"
|
||||
formula_enable: bool = True
|
||||
# table_enable: bool = True
|
||||
server_url: str | None = None #(Adapted only for vlm-http-client backend)openai compatible server url, e.g., http://127.0.0.1:30000
|
||||
# return_md: bool = True
|
||||
# return_middle_json: bool = True
|
||||
# return_model_output: bool = False
|
||||
# return_content_list: bool = False
|
||||
# return_images: bool = True
|
||||
# response_format_zip: bool = True
|
||||
table_enable: bool = True
|
||||
|
||||
# 用于 vlm-http-client 或 hybrid-http-client 后端
|
||||
server_url: str | None = None
|
||||
|
||||
# 返回选项
|
||||
return_md: bool = True
|
||||
return_middle_json: bool = False
|
||||
return_model_output: bool = False
|
||||
return_content_list: bool = False
|
||||
return_images: bool = True
|
||||
response_format_zip: bool = True
|
||||
|
||||
# 页面范围
|
||||
start_page_id: int = 0
|
||||
end_page_id: int = 99999
|
||||
|
||||
def gethash(self) ->Hashable:
|
||||
return (self.backend,self.formula_enable,self.start_page_id,self.end_page_id)
|
||||
def gethash(self) -> Hashable:
|
||||
return (self.backend, self.formula_enable, self.table_enable,
|
||||
self.parse_method, self.start_page_id, self.end_page_id)
|
||||
|
||||
|
||||
# 配置HTTP客户端
|
||||
timeout = httpx.Timeout(
|
||||
@@ -57,27 +75,37 @@ class ConverterMineruDeploy(X2MarkdownConverter):
|
||||
|
||||
self._api_url = f"{self.base_url}/file_parse"
|
||||
|
||||
def _build_form_data(self)->dict:
|
||||
def _build_form_data(self) -> dict:
|
||||
# httpx 在处理 data 参数时,如果值为 list,会自动展开为多个同名 key (例如 lang_list=ch&lang_list=en)
|
||||
# 这符合 FastAPI/Starlette 对 List 字段的解析要求
|
||||
data = {
|
||||
"output_dir": self.config.output_dir,
|
||||
"backend": self.config.backend,
|
||||
"parse_method": "auto",
|
||||
"formula_enable": self.config.formula_enable,
|
||||
"table_enable": True,
|
||||
"server_url": None,
|
||||
"return_md": True,
|
||||
"return_middle_json": True,
|
||||
"return_model_output": False,
|
||||
"return_content_list": False,
|
||||
"return_images": True,
|
||||
"response_format_zip": True,
|
||||
"parse_method": self.config.parse_method,
|
||||
# bool 类型在 multipart/form-data 中通常需要转为字符串 'true'/'false',但 httpx 会处理 python bool
|
||||
"formula_enable": str(self.config.formula_enable).lower(),
|
||||
"table_enable": str(self.config.table_enable).lower(),
|
||||
"return_md": str(self.config.return_md).lower(),
|
||||
"return_middle_json": str(self.config.return_middle_json).lower(),
|
||||
"return_model_output": str(self.config.return_model_output).lower(),
|
||||
"return_content_list": str(self.config.return_content_list).lower(),
|
||||
"return_images": str(self.config.return_images).lower(),
|
||||
"response_format_zip": str(self.config.response_format_zip).lower(),
|
||||
"start_page_id": self.config.start_page_id,
|
||||
"end_page_id": self.config.end_page_id
|
||||
}
|
||||
|
||||
if self.config.lang_list:
|
||||
data["lang_list"] = self.config.lang_list
|
||||
else:
|
||||
data["lang_list"] = ["ch"] # 默认值
|
||||
|
||||
if self.config.server_url:
|
||||
data["server_url"] = self.config.server_url
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def convert(self,d:Document)->MarkdownDocument:
|
||||
def convert(self, d: Document) -> MarkdownDocument:
|
||||
self.logger.info("开始解析文件")
|
||||
files = [("files", (d.name, d.content, "application/octet-stream"))]
|
||||
response = client.post(
|
||||
@@ -88,15 +116,15 @@ class ConverterMineruDeploy(X2MarkdownConverter):
|
||||
)
|
||||
|
||||
response.raise_for_status() # 检查是否有错误
|
||||
md=embed_inline_image_from_zip(response.content,None)
|
||||
# Mineru API 返回 zip 时包含图片和 md
|
||||
md = embed_inline_image_from_zip(response.content, None)
|
||||
self.logger.info("已转化为markdown")
|
||||
return MarkdownDocument.from_bytes(md.encode(),suffix=".md",stem=d.stem)
|
||||
|
||||
return MarkdownDocument.from_bytes(md.encode(), suffix=".md", stem=d.stem)
|
||||
|
||||
async def convert_async(self, d: Document) -> MarkdownDocument:
|
||||
self.logger.info("开始解析文件")
|
||||
files = [("files", (d.name, d.content, "application/octet-stream"))]
|
||||
response =await client_async.post(
|
||||
response = await client_async.post(
|
||||
self._api_url,
|
||||
files=files,
|
||||
data=self._build_form_data(),
|
||||
@@ -104,15 +132,9 @@ class ConverterMineruDeploy(X2MarkdownConverter):
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
md = await asyncio.to_thread(embed_inline_image_from_zip,response.content, None)
|
||||
md = await asyncio.to_thread(embed_inline_image_from_zip, response.content, None)
|
||||
self.logger.info("已转化为markdown")
|
||||
return MarkdownDocument.from_bytes(md.encode(), suffix=".md", stem=d.stem)
|
||||
|
||||
def support_format(self) -> list[str]:
|
||||
return [".pdf", ".doc", ".docx", ".ppt", ".pptx", ".png", ".jpg", ".jpeg"]
|
||||
|
||||
if __name__ == '__main__':
|
||||
d = Document.from_path(r"C:\Users\jxgm\Desktop\testfiles\table.pdf")
|
||||
config=ConverterMineruDeployConfig()
|
||||
converter = ConverterMineruDeploy(config=config)
|
||||
converter.convert(d)
|
||||
@@ -252,17 +252,27 @@ class MarkdownWorkflowParams(BaseWorkflowParams):
|
||||
"http://127.0.0.1:8000",
|
||||
description="[仅当 convert_engine='mineru_deploy'] 本地部署的 MinerU 服务地址。",
|
||||
)
|
||||
# --- UPDATED BACKEND LIST ---
|
||||
mineru_deploy_backend: Literal[
|
||||
"pipeline",
|
||||
"vlm-transformers",
|
||||
"vlm-mlx-engine",
|
||||
"vlm-vllm-async-engine",
|
||||
"vlm-lmdeploy-engine",
|
||||
"vlm-auto-engine",
|
||||
"vlm-http-client",
|
||||
"hybrid-auto-engine",
|
||||
"hybrid-http-client"
|
||||
] = Field(
|
||||
"pipeline",
|
||||
"hybrid-auto-engine",
|
||||
description="[仅当 convert_engine='mineru_deploy'] 本地部署的 MinerU 服务使用的后端。",
|
||||
)
|
||||
# --- NEW PARAMETERS START ---
|
||||
mineru_deploy_parse_method: Literal["auto", "txt", "ocr"] = Field(
|
||||
"auto",
|
||||
description="[仅当 convert_engine='mineru_deploy'] 解析方法: auto, txt, ocr"
|
||||
)
|
||||
mineru_deploy_table_enable: bool = Field(
|
||||
True,
|
||||
description="[仅当 convert_engine='mineru_deploy'] 本地部署的服务是否启用表格解析。",
|
||||
)
|
||||
# --- NEW PARAMETERS END ---
|
||||
mineru_deploy_formula_enable: bool = Field(
|
||||
True,
|
||||
description="[仅当 convert_engine='mineru_deploy'] 本地部署的服务是否启用公式解析。",
|
||||
@@ -275,13 +285,13 @@ class MarkdownWorkflowParams(BaseWorkflowParams):
|
||||
)
|
||||
mineru_deploy_lang_list: Optional[List[str]] = Field(
|
||||
None,
|
||||
description="[仅当 convert_engine='mineru_deploy' 且 backend='pipeline'] 语言列表。",
|
||||
examples=[None],
|
||||
description="[仅当 convert_engine='mineru_deploy'] 语言列表, 默认 ['ch']。",
|
||||
examples=[["ch", "en"]],
|
||||
)
|
||||
# 修改: 默认值改为 ""
|
||||
mineru_deploy_server_url: Optional[str] = Field(
|
||||
default="",
|
||||
description="[仅当 convert_engine='mineru_deploy' 且 backend='vlm-http-client'] Server URL.",
|
||||
description="[仅当 convert_engine='mineru_deploy' 且 backend为http-client相关时] Server URL.",
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
@@ -312,10 +322,6 @@ class TextWorkflowParams(BaseWorkflowParams):
|
||||
"\n",
|
||||
description="当 insert_mode 为 'append' 或 'prepend' 时,用于分隔原文和译文的分隔符。",
|
||||
)
|
||||
segment_mode: Literal["line", "paragraph", "none"] = Field(
|
||||
"line",
|
||||
description="分段模式。'line':按行分段(每行独立翻译),'paragraph':按段落分段(连续非空行合并为段落),'none':不分段(全文视为一个段落)。",
|
||||
)
|
||||
|
||||
|
||||
class JsonWorkflowParams(BaseWorkflowParams):
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"mineruDeployLangListLabel": "语言列表 (Pipeline模式)",
|
||||
"mineruDeployServerUrlLabel": "Server URL",
|
||||
"mineruDeployServerUrlPlaceholder": "例如: http://127.0.0.1:30000",
|
||||
"mineruDeployParseMethodLabel": "解析方法 (Parse Method)",
|
||||
"mineruDeployTableEnableLabel": "表格识别 (Table Recognition)",
|
||||
"mineruDeployStartPageLabel": "起始页码",
|
||||
"mineruDeployEndPageLabel": "结束页码",
|
||||
"mineruDeployFormulaEnableLabel": "启用公式解析",
|
||||
@@ -137,7 +139,7 @@
|
||||
"previewTranslated": "译文",
|
||||
"closeBtn": "关闭",
|
||||
"tutorialModalTitle": "使用教程",
|
||||
"tutorialModalBody": "<p><i class=\"bi bi-camera-video me-2\"></i>视频教程可以在B站搜索 <a href=\"https://search.bilibili.com/all?keyword=docutranslate\" target=\"_blank\">docutranslate</a> 获取。</p><p>欢迎使用 DocuTranslate!请按照以下步骤完成文档翻译:</p><ol><li><strong><i class=\"bi bi-diagram-3 me-2\"></i>第一步:选择工作流</strong><p class=\"mt-2\">在左侧配置面板的顶部,首先选择最适合您文件类型的处理流程。</p><div class=\"alert alert-info mt-2\" role=\"alert\"><i class=\"bi bi-lightbulb-fill me-2\"></i>提示: 默认已开启“自动选择工作流”。您只需上传文件,系统会自动为您匹配合适的工作流,简化操作。</div><ul><li><b>转Markdown再翻译</b>: 适用于翻译PDF、markdown、图片等文件。这是最通用和强大的模式。</li><li><b>纯文本翻译</b>: 用于翻译 <code>.txt</code> 纯文本文件。</li><li><b>EPUB翻译</b>: 用于翻译 <code>.epub</code> 电子书文件。</li><li><b>DOCX翻译</b>: 用于翻译 <code>.docx</code> Word文档。</li><li><b>XLSX翻译</b>: 用于翻译 <code>.xlsx</code> 或 <code>.csv</code> 电子表格文件。</li><li><b>PPTX翻译</b>: 用于翻译 <code>.pptx</code> 幻灯片文件。</li><li><b>SRT字幕翻译</b>: 用于翻译 <code>.srt</code> 字幕文件。</li><li><b>ASS字幕翻译</b>: 用于翻译 <code>.ass</code> 特效字幕文件。</li><li><b>JSON翻译</b>: 用于翻译 <code>.json</code> 文件中的特定字段。</li><li><b>HTML翻译</b>: 用于翻译 <code>.html</code> 网页文件。</li></ul></li><li><strong><i class=\"bi bi-gear-fill me-2\"></i>第二步:配置参数</strong><p class=\"mt-2\">选择工作流后,下方会显示相关的配置选项。请依次完成设置(所有配置都会自动保存在您的浏览器中):</p><p class=\"mb-2\"><strong>A. 工作流特定选项</strong> (根据您第一步的选择出现):</p><ul class=\"ms-4\"><li><u>如果选择“转Markdown再翻译”</u>,请配置 <strong>解析配置</strong>:<ul><li><strong>解析引擎</strong>: 选择一个引擎将您的文件(如PDF)转换为适合翻译的Markdown格式。如果您的文件已经是Markdown格式,则无需选择。</li><li><strong>Mineru Token</strong>: 如果您选择 <code>minerU</code> 引擎,需要在此处填入您的Token。</li></ul></li><li><u>如果选择“纯文本/DOCX/XLSX/PPTX/SRT/ASS/EPUB/HTML”</u>,请配置其 <strong>翻译选项</strong>:<ul><li><strong>插入模式</strong>: 定义翻译结果如何放入文档。您可以选择直接“替换”原文,或是在原文之后“附加”,或是在原文之前“前置”。</li><li><strong>分隔符</strong>: 当选择“附加”或“前置”模式时,此项用于在原文和译文之间插入分隔符(例如ASS格式常用 <code>\\N</code>,EPUB格式常用 <code><br /></code> 作为换行分隔符)。</li></ul></li><li><u>如果选择“JSON翻译”</u>,请配置 <strong>JSON路径</strong>:<ul><li><strong>需要翻译的JSON路径</strong>: 每行输入一个 <a href=\"https://goessner.net/articles/JsonPath/\" target=\"_blank\">JSONPath</a> 表达式,将翻译所有与路径匹配的对象中的字符串。例如:<code>$.*</code>(翻译全部字符串),<code>$..description</code>(翻译所有键为<code>description</code>的值)。</li></ul></li></ul><p class=\"mb-2 mt-3\"><strong>B. 通用选项</strong> (适用于所有工作流):</p><ul class=\"ms-4\"><li><strong>翻译模型</strong>:<ul><li><strong>选择平台/API 地址/API Key/模型ID</strong>: 配置您希望使用的AI翻译服务。模型能力指令遵循越强,<strong>出错</strong>、<strong>漏翻</strong>的概率越低。</li><li><strong>跳过翻译</strong>: 勾选此项后,将只执行文档解析和格式转换,不调用AI进行翻译。</li></ul></li><li><strong>翻译配置</strong>:<ul><li><strong>目标语言</strong>: 指定翻译的目标语言。</li><li><strong>自定义Prompt</strong>: 可选,添加额外指令,如“人名保持原文不翻译”。</li><li><strong>思考模式</strong>: 针对部分支持混合推理的模型进行设置,建议选择“禁用(推荐)”。</li><li><strong>分块大小/并发数等</strong>: 高级参数,用于调整性能和API请求行为,通常保持默认即可。</li></ul></li><li><strong>术语表</strong>:<ul><li><strong>上传术语表 (可选)</strong>: 上传CSV文件(需包含'src'和'dst'列)来保证特定术语翻译的统一性和准确性。</li><li><strong>自动生成术语表</strong>: 启用后,程序会先从原文中提取术语并生成一个术语表,然后再进行翻译。</li></ul></li></ul></li><li><strong><i class=\"bi bi-file-earmark-arrow-up-fill me-2\"></i>第三步:上传文件</strong><p class=\"mt-2\">在右侧的任务列表中,点击或拖拽您的文档到文件上传区域。</p></li><li><strong><i class=\"bi bi-pLine truncated
|
||||
"tutorialModalBody": "<p><i class=\"bi bi-camera-video me-2\"></i>视频教程可以在B站搜索 <a href=\"https://search.bilibili.com/all?keyword=docutranslate\" target=\"_blank\">docutranslate</a> 获取。</p><p>欢迎使用 DocuTranslate!请按照以下步骤完成文档翻译:</p><ol><li><strong><i class=\"bi bi-diagram-3 me-2\"></i>第一步:选择工作流</strong><p class=\"mt-2\">在左侧配置面板的顶部,首先选择最适合您文件类型的处理流程。</p><div class=\"alert alert-info mt-2\" role=\"alert\"><i class=\"bi bi-lightbulb-fill me-2\"></i>提示: 默认已开启“自动选择工作流”。您只需上传文件,系统会自动为您匹配合适的工作流,简化操作。</div><ul><li><b>转Markdown再翻译</b>: 适用于翻译PDF、markdown、图片等文件。这是最通用和强大的模式。</li><li><b>纯文本翻译</b>: 用于翻译 <code>.txt</code> 纯文本文件。</li><li><b>EPUB翻译</b>: 用于翻译 <code>.epub</code> 电子书文件。</li><li><b>DOCX翻译</b>: 用于翻译 <code>.docx</code> Word文档。</li><li><b>XLSX翻译</b>: 用于翻译 <code>.xlsx</code> 或 <code>.csv</code> 电子表格文件。</li><li><b>PPTX翻译</b>: 用于翻译 <code>.pptx</code> 幻灯片文件。</li><li><b>SRT字幕翻译</b>: 用于翻译 <code>.srt</code> 字幕文件。</li><li><b>ASS字幕翻译</b>: 用于翻译 <code>.ass</code> 特效字幕文件。</li><li><b>JSON翻译</b>: 用于翻译 <code>.json</code> 文件中的特定字段。</li><li><b>HTML翻译</b>: 用于翻译 <code>.html</code> 网页文件。</li></ul></li><li><strong><i class=\"bi bi-gear-fill me-2\"></i>第二步:配置参数</strong><p class=\"mt-2\">选择工作流后,下方会显示相关的配置选项。请依次完成设置(所有配置都会自动保存在您的浏览器中):</p><p class=\"mb-2\"><strong>A. 工作流特定选项</strong> (根据您第一步的选择出现):</p><ul class=\"ms-4\"><li><u>如果选择“转Markdown再翻译”</u>,请配置 <strong>解析配置</strong>:<ul><li><strong>解析引擎</strong>: 选择一个引擎将您的文件(如PDF)转换为适合翻译的Markdown格式。如果您的文件已经是Markdown格式,则无需选择。</li><li><strong>Mineru Token</strong>: 如果您选择 <code>minerU</code> 引擎,需要在此处填入您的Token。</li></ul></li><li><u>如果选择“纯文本/DOCX/XLSX/PPTX/SRT/ASS/EPUB/HTML”</u>,请配置其 <strong>翻译选项</strong>:<ul><li><strong>插入模式</strong>: 定义翻译结果如何放入文档。您可以选择直接“替换”原文,或是在原文之后“附加”,或是在原文之前“前置”。</li><li><strong>分隔符</strong>: 当选择“附加”或“前置”模式时,此项用于在原文和译文之间插入分隔符(例如ASS格式常用 <code>\\N</code>,EPUB格式常用 <code><br /></code> 作为换行分隔符)。</li></ul></li><li><u>如果选择“JSON翻译”</u>,请配置 <strong>JSON路径</strong>:<ul><li><strong>需要翻译的JSON路径</strong>: 每行输入一个 <a href=\"https://goessner.net/articles/JsonPath/\" target=\"_blank\">JSONPath</a> 表达式,将翻译所有与路径匹配的对象中的字符串。例如:<code>$.*</code>(翻译全部字符串),<code>$..description</code>(翻译所有键为<code>description</code>的值)。</li></ul></li></ul><p class=\"mb-2 mt-3\"><strong>B. 通用选项</strong> (适用于所有工作流):</p><ul class=\"ms-4\"><li><strong>翻译模型</strong>:<ul><li><strong>选择平台/API 地址/API Key/Model ID</strong>: 配置您希望使用的AI翻译服务。模型能力指令遵循越强,<strong>出错</strong>、<strong>漏翻</strong>的概率越低。</li><li><strong>跳过翻译</strong>: 勾选此项后,将只执行文档解析和格式转换,不调用AI进行翻译。</li></ul></li><li><strong>翻译配置</strong>:<ul><li><strong>目标语言</strong>: 指定翻译的目标语言。</li><li><strong>自定义Prompt</strong>: 可选,添加额外指令,如“人名保持原文不翻译”。</li><li><strong>思考模式</strong>: 针对部分支持混合推理的模型进行设置,建议选择“禁用(推荐)”。</li><li><strong>分块大小/并发数等</strong>: 高级参数,用于调整性能和API请求行为,通常保持默认即可。</li></ul></li><li><strong>术语表</strong>:<ul><li><strong>上传术语表 (可选)</strong>: 上传CSV文件(需包含'src'和'dst'列)来保证特定术语翻译的统一性和准确性。</li><li><strong>自动生成术语表</strong>: 启用后,程序会先从原文中提取术语并生成一个术语表,然后再进行翻译。</li></ul></li></ul></li><li><strong><i class=\"bi bi-file-earmark-arrow-up-fill me-2\"></i>第三步:上传文件</strong><p class=\"mt-2\">在右侧的任务列表中,点击或拖拽您的文档到文件上传区域。</p></li><li><strong><i class=\"bi bi-pLine truncated
|
||||
"tutorialUnderstandBtn": "我明白了",
|
||||
"contributorsModalTitle": "感谢贡献",
|
||||
"contributorsPara1": "DocuTranslate是一个开源项目!大家的需求与使用是项目进步的动力。",
|
||||
@@ -236,6 +238,8 @@
|
||||
"mineruDeployLangListLabel": "Language List (Pipeline Mode)",
|
||||
"mineruDeployServerUrlLabel": "Server URL",
|
||||
"mineruDeployServerUrlPlaceholder": "e.g., http://127.0.0.1:30000",
|
||||
"mineruDeployParseMethodLabel": "Parse Method",
|
||||
"mineruDeployTableEnableLabel": "Table Recognition",
|
||||
"mineruDeployStartPageLabel": "Start Page",
|
||||
"mineruDeployEndPageLabel": "End Page",
|
||||
"mineruDeployFormulaEnableLabel": "Enable Formula Parsing",
|
||||
|
||||
@@ -1 +1 @@
|
||||
<!DOCTYPE html>
<html lang="zh-CN" data-bs-theme="auto">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DocuTranslate - 交互式文档翻译</title>
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
<!-- Bootstrap CSS -->
<link href="/static/bootstrap.css" rel="stylesheet" crossorigin="anonymous">
<!-- Bootstrap Icons -->
<link rel="stylesheet" href="/static/bootstrap-icons.css">
<style>
/* 复用原版 CSS */
body {
background-color: var(--bs-body-bg);
}
button:focus {
outline: none !important;
box-shadow: none !important;
}
.main-container {
display: flex;
flex-direction: column;
height: 100vh;
padding-top: 1rem;
padding-bottom: 1rem;
}
.settings-panel {
height: calc(100vh - 2rem);
overflow-y: auto;
padding-right: 15px;
}
.task-area {
height: calc(100vh - 2rem);
overflow-y: auto;
}
.task-card {
transition: all 0.3s ease-in-out;
}
.log-area {
height: 150px;
background-color: var(--bs-tertiary-bg);
border: 1px solid var(--bs-border-color);
border-radius: .375rem;
font-family: monospace;
font-size: 0.8rem;
padding: 10px;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-all;
}
.log-area-wrapper {
position: relative;
}
.copy-log-btn {
position: absolute;
bottom: 5px;
right: 5px;
z-index: 10;
opacity: 0.5;
transition: all 0.2s ease-in-out;
padding: 0.1rem 0.4rem;
line-height: 1;
}
.copy-log-btn:hover {
opacity: 1;
}
.file-drop-area {
border: 2px dashed var(--bs-secondary-bg);
border-radius: .375rem;
padding: 2rem;
text-align: center;
cursor: pointer;
transition: all 0.2s ease-in-out;
background-color: var(--bs-body-bg);
}
.file-drop-area.drag-over {
border-color: var(--bs-primary);
background-color: var(--bs-secondary-bg);
}
.file-drop-area.file-selected {
border-style: solid;
border-color: var(--bs-success);
background-color: var(--bs-success-bg-subtle);
}
.file-drop-area.input-error {
border-color: var(--bs-danger);
}
#previewOffcanvas {
--bs-offcanvas-width: 95vw;
max-width: 1600px;
}
.preview-split-container {
display: flex;
flex-direction: row;
height: 90%;
}
.preview-pane-wrapper {
display: flex;
flex-direction: column;
overflow: hidden;
width: 100%;
height: 100%;
}
.preview-pane-wrapper .preview-pane {
flex-grow: 1;
border: 1px solid var(--bs-border-color);
border-radius: .375rem;
overflow: auto;
position: relative;
}
.gutter {
background-color: var(--bs-tertiary-bg);
background-repeat: no-repeat;
background-position: 50%;
}
.gutter.gutter-horizontal {
cursor: col-resize;
border-left: 1px solid var(--bs-border-color);
border-right: 1px solid var(--bs-border-color);
}
.gutter.gutter-vertical {
cursor: row-resize;
border-top: 1px solid var(--bs-border-color);
border-bottom: 1px solid var(--bs-border-color);
}
.preview-pane iframe {
width: 100%;
height: 100%;
border: none;
}
.preview-pane pre {
margin: 0;
padding: 1rem;
background-color: var(--bs-body-bg);
white-space: pre;
}
.bottom-left-controls {
position: fixed;
bottom: 1rem;
left: 1rem;
z-index: 1050;
display: flex;
gap: 0.5rem;
}
.step-number {
margin-right: 0.25rem;
}
#translatedPreviewContainer .preview-pane {
overflow: hidden;
}
#translatedPreviewContainer .preview-pane iframe {
display: block;
width: 100%;
height: 100%;
}
.lang-list-container {
max-height: 200px;
overflow-y: auto;
border: 1px solid var(--bs-border-color);
border-radius: 0.375rem;
paddinLine truncated
|
||||
<!DOCTYPE html>
<html lang="zh-CN" data-bs-theme="auto">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DocuTranslate - 交互式文档翻译</title>
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
<!-- Bootstrap CSS -->
<link href="/static/bootstrap.css" rel="stylesheet" crossorigin="anonymous">
<!-- Bootstrap Icons -->
<link rel="stylesheet" href="/static/bootstrap-icons.css">
<style>
/* 复用原版 CSS */
body {
background-color: var(--bs-body-bg);
}
button:focus {
outline: none !important;
box-shadow: none !important;
}
.main-container {
display: flex;
flex-direction: column;
height: 100vh;
padding-top: 1rem;
padding-bottom: 1rem;
}
.settings-panel {
height: calc(100vh - 2rem);
overflow-y: auto;
padding-right: 15px;
}
.task-area {
height: calc(100vh - 2rem);
overflow-y: auto;
}
.task-card {
transition: all 0.3s ease-in-out;
}
.log-area {
height: 150px;
background-color: var(--bs-tertiary-bg);
border: 1px solid var(--bs-border-color);
border-radius: .375rem;
font-family: monospace;
font-size: 0.8rem;
padding: 10px;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-all;
}
.log-area-wrapper {
position: relative;
}
.copy-log-btn {
position: absolute;
bottom: 5px;
right: 5px;
z-index: 10;
opacity: 0.5;
transition: all 0.2s ease-in-out;
padding: 0.1rem 0.4rem;
line-height: 1;
}
.copy-log-btn:hover {
opacity: 1;
}
.file-drop-area {
border: 2px dashed var(--bs-secondary-bg);
border-radius: .375rem;
padding: 2rem;
text-align: center;
cursor: pointer;
transition: all 0.2s ease-in-out;
background-color: var(--bs-body-bg);
}
.file-drop-area.drag-over {
border-color: var(--bs-primary);
background-color: var(--bs-secondary-bg);
}
.file-drop-area.file-selected {
border-style: solid;
border-color: var(--bs-success);
background-color: var(--bs-success-bg-subtle);
}
.file-drop-area.input-error {
border-color: var(--bs-danger);
}
#previewOffcanvas {
--bs-offcanvas-width: 95vw;
max-width: 1600px;
}
.preview-split-container {
display: flex;
flex-direction: row;
height: 90%;
}
.preview-pane-wrapper {
display: flex;
flex-direction: column;
overflow: hidden;
width: 100%;
height: 100%;
}
.preview-pane-wrapper .preview-pane {
flex-grow: 1;
border: 1px solid var(--bs-border-color);
border-radius: .375rem;
overflow: auto;
position: relative;
}
.gutter {
background-color: var(--bs-tertiary-bg);
background-repeat: no-repeat;
background-position: 50%;
}
.gutter.gutter-horizontal {
cursor: col-resize;
border-left: 1px solid var(--bs-border-color);
border-right: 1px solid var(--bs-border-color);
}
.gutter.gutter-vertical {
cursor: row-resize;
border-top: 1px solid var(--bs-border-color);
border-bottom: 1px solid var(--bs-border-color);
}
.preview-pane iframe {
width: 100%;
height: 100%;
border: none;
}
.preview-pane pre {
margin: 0;
padding: 1rem;
background-color: var(--bs-body-bg);
white-space: pre;
}
.bottom-left-controls {
position: fixed;
bottom: 1rem;
left: 1rem;
z-index: 1050;
display: flex;
gap: 0.5rem;
}
.step-number {
margin-right: 0.25rem;
}
#translatedPreviewContainer .preview-pane {
overflow: hidden;
}
#translatedPreviewContainer .preview-pane iframe {
display: block;
width: 100%;
height: 100%;
}
.lang-list-container {
max-height: 200px;
overflow-y: auto;
border: 1px solid var(--bs-border-color);
border-radius: 0.375rem;
paddinLine truncated
|
||||
Reference in new issue
Block a user