支持mineruVLM模型

This commit is contained in:
xunbu committed 2025-08-20 13:36:01 +08:00
1 parent d3d74564f1
commit 0cf0aa15da
4 files changed
+42 -10

No files matched your search

+6 -3
View File
@@ -205,7 +205,7 @@ class BaseWorkflowParams(BaseModel):
concurrent: int = Field(default=default_params["concurrent"], description="并发请求数。") concurrent: int = Field(default=default_params["concurrent"], description="并发请求数。")
temperature: float = Field(default=default_params["temperature"], description="LLM温度参数。") temperature: float = Field(default=default_params["temperature"], description="LLM温度参数。")
thinking: ThinkingMode = Field(default=default_params["thinking"], description="是否启用深度思考", thinking: ThinkingMode = Field(default=default_params["thinking"], description="是否启用深度思考",
examples=["default", "enable", "disable"]), examples=["default", "enable", "disable"])
custom_prompt: Optional[str] = Field(None, description="用户自定义的翻译Prompt。", alias="custom_prompt") custom_prompt: Optional[str] = Field(None, description="用户自定义的翻译Prompt。", alias="custom_prompt")
@@ -220,6 +220,7 @@ class MarkdownWorkflowParams(BaseWorkflowParams):
mineru_token: Optional[str] = Field(None, description="当 `convert_engine` 为 'mineru' 时必填的API令牌。") mineru_token: Optional[str] = Field(None, description="当 `convert_engine` 为 'mineru' 时必填的API令牌。")
formula_ocr: bool = Field(True, description="是否对公式进行OCR识别。对 `mineru` 和 `docling` 均有效。") formula_ocr: bool = Field(True, description="是否对公式进行OCR识别。对 `mineru` 和 `docling` 均有效。")
code_ocr: bool = Field(True, description="是否对代码块进行OCR识别。仅 `docling` 引擎有效。") code_ocr: bool = Field(True, description="是否对代码块进行OCR识别。仅 `docling` 引擎有效。")
model_version: Literal["pipline", "vlm"] = Field("vlm", description="Mineru模型的版本,'vlm'是更新的版本。仅 `mineru` 引擎有效。")
@field_validator('mineru_token') @field_validator('mineru_token')
def check_mineru_token(cls, v, values): def check_mineru_token(cls, v, values):
@@ -479,7 +480,8 @@ async def _perform_translation(
converter_config = None converter_config = None
if payload.convert_engine == 'mineru': if payload.convert_engine == 'mineru':
converter_config = ConverterMineruConfig(logger=task_logger, mineru_token=payload.mineru_token, converter_config = ConverterMineruConfig(logger=task_logger, mineru_token=payload.mineru_token,
formula_ocr=payload.formula_ocr) formula_ocr=payload.formula_ocr,
model_version=payload.model_version)
elif payload.convert_engine == 'docling' and DOCLING_EXIST: elif payload.convert_engine == 'docling' and DOCLING_EXIST:
converter_config = ConverterDoclingConfig(logger=task_logger, code_ocr=payload.code_ocr, converter_config = ConverterDoclingConfig(logger=task_logger, code_ocr=payload.code_ocr,
formula_ocr=payload.formula_ocr) formula_ocr=payload.formula_ocr)
@@ -1214,6 +1216,7 @@ async def temp_translate(
temperature: float = Body(default_params["temperature"]), temperature: float = Body(default_params["temperature"]),
thinking: ThinkingMode = Body(default_params["thinking"]), thinking: ThinkingMode = Body(default_params["thinking"]),
chunk_size: int = Body(default_params["chunk_size"]), custom_prompt: Optional[str] = Body(None), chunk_size: int = Body(default_params["chunk_size"]), custom_prompt: Optional[str] = Body(None),
model_version: Literal["pipline", "vlm"] = Body("vlm"),
): ):
file_name = Path(file_name) file_name = Path(file_name)
try: try:
@@ -1222,7 +1225,7 @@ async def temp_translate(
decoded_content = file_content.encode('utf-8') decoded_content = file_content.encode('utf-8')
try: try:
workflow_config = MarkdownBasedWorkflowConfig( workflow_config = MarkdownBasedWorkflowConfig(
convert_engine="mineru", converter_config=ConverterMineruConfig(mineru_token=mineru_token), convert_engine="mineru", converter_config=ConverterMineruConfig(mineru_token=mineru_token, model_version=model_version),
translator_config=MDTranslatorConfig(base_url=base_url, api_key=api_key, model_id=model_id, translator_config=MDTranslatorConfig(base_url=base_url, api_key=api_key, model_id=model_id,
to_lang=to_lang, custom_prompt=custom_prompt, temperature=temperature, to_lang=to_lang, custom_prompt=custom_prompt, temperature=temperature,
thinking=thinking, chunk_size=chunk_size, concurrent=concurrent), thinking=thinking, chunk_size=chunk_size, concurrent=concurrent),
@@ -2,7 +2,7 @@ import asyncio
import time import time
import zipfile import zipfile
from dataclasses import dataclass from dataclasses import dataclass
from typing import Hashable from typing import Hashable, Literal
import httpx import httpx
@@ -18,9 +18,10 @@ URL = 'https://mineru.net/api/v4/file-urls/batch'
class ConverterMineruConfig(X2MarkdownConverterConfig): class ConverterMineruConfig(X2MarkdownConverterConfig):
mineru_token: str mineru_token: str
formula_ocr: bool = True formula_ocr: bool = True
model_version: Literal["pipline", "vlm"] = "vlm"
def gethash(self) -> Hashable: def gethash(self) -> Hashable:
return self.formula_ocr return (self.formula_ocr,self.model_version)
timeout = httpx.Timeout( timeout = httpx.Timeout(
@@ -44,6 +45,7 @@ class ConverterMineru(X2MarkdownConverter):
super().__init__(config=config) super().__init__(config=config)
self.mineru_token = config.mineru_token.strip() self.mineru_token = config.mineru_token.strip()
self.formula = config.formula_ocr self.formula = config.formula_ocr
self.model_version=config.model_version
def _get_header(self): def _get_header(self):
return { return {
@@ -56,6 +58,7 @@ class ConverterMineru(X2MarkdownConverter):
"enable_formula": self.formula, "enable_formula": self.formula,
"language": "auto", "language": "auto",
"enable_table": True, "enable_table": True,
"model_version":self.model_version,
"files": [ "files": [
{"name": f"{document.name}", "is_ocr": True} {"name": f"{document.name}", "is_ocr": True}
] ]
+30 -4
View File
@@ -44,6 +44,10 @@
"engineOptionDocling": "Docling (本地)", "engineOptionDocling": "Docling (本地)",
"getMineruTokenTitle": "获取Mineru Token", "getMineruTokenTitle": "获取Mineru Token",
"mineruTokenPlaceholder": "使用Mineru引擎时需要", "mineruTokenPlaceholder": "使用Mineru引擎时需要",
"modelVersionLabel": "Mineru 模型版本",
"modelVersionVlm": "VLM",
"modelVersionPipline": "Pipeline",
"modelVersionHelp": "mineru VLM是更新的内测模型。",
"formulaOcrLabel": "公式识别", "formulaOcrLabel": "公式识别",
"codeOcrLabel": "代码识别", "codeOcrLabel": "代码识别",
"aiSettingsTitleText": "翻译模型", "aiSettingsTitleText": "翻译模型",
@@ -87,6 +91,14 @@
"taskCardStartBtn": "开始翻译", "taskCardStartBtn": "开始翻译",
"downloadMdEmbedded": "Markdown(嵌图)", "downloadMdEmbedded": "Markdown(嵌图)",
"downloadMdZip": "Markdown压缩包", "downloadMdZip": "Markdown压缩包",
"downloadTxt": "TXT",
"downloadJson": "JSON",
"downloadDocx": "DOCX",
"downloadXlsx": "XLSX",
"downloadSrt": "SRT",
"downloadEpub": "EPUB",
"downloadHtml": "HTML",
"downloadPdf": "PDF",
"previewTitle": "预览", "previewTitle": "预览",
"previewBilingualBtn": "双语", "previewBilingualBtn": "双语",
"previewTranslatedOnlyBtn": "仅译文", "previewTranslatedOnlyBtn": "仅译文",
@@ -95,7 +107,7 @@
"closeBtn": "关闭", "closeBtn": "关闭",
"downloadBtn": "下载", "downloadBtn": "下载",
"tutorialModalTitle": "使用教程", "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\">首先,在配置面板顶部选择您需要的翻译流程。不同的工作流适用于不同类型的文件:<ul><li><b>转Markdown再翻译</b>: 适用于翻译PDF、markdown、图片等文件。</li><li><b>纯文本翻译</b>: 用于翻译 <code>.txt</code> 等纯文本文件。</li><li><b>JSON翻译</b>: 用于翻译 <code>.json</code> 文件中的特定字段。</li><li><b>DOCX翻译</b>: 用于翻译 <code>.docx</code> 文件。</li><li><b>XLSX翻译</b>: 用于翻译 <code>.xlsx</code> 电子表格文件。</li><li><b>SRT字幕翻译</b>: 用于翻译 <code>.srt</code> 字幕文件。</li><li><b>EPUB翻译</b>: 用于翻译 <code>.epub</code> 电子书文件。</li></ul><div class=\"alert alert-info mt-2\" role=\"alert\"><i class=\"bi bi-lightbulb-fill me-2\"></i>新增功能: \"自动选择工作流\"开关已默认开启。您只需上传文件,系统会自动为您匹配合适的工作流,简化操作。</div></p></li><li><strong><i class=\"bi bi-gear-fill me-2\"></i>配置参数</strong><p class=\"mt-2\">根据您选择的工作流,完成相应的配置。所有配置项都会自动保存在您的浏览器中。</p><ul><li class=\"mb-2\"><strong>解析配置</strong> (仅在“转Markdown再翻译”工作流下显示):<ul class=\"mt-1\"><li><strong>解析引擎</strong>: 选择一个引擎将您的文件(如PDF)转换为适合翻译的Markdown格式。如果您的文件已经是Markdown格式,则无需选择。</li><li><strong>Mineru Token</strong>: 如果您选择 <code>minerU</code> 引擎,需要在此处填入您的Token。</li></ul></li><li class=\"mb-2\"><strong>DOCX/XLSX/SRT/EPUB翻译选项</strong> (在对应工作流下显示):<ul class=\"mt-1\"><li><strong>插入模式</strong>: 定义翻译结果如何放入文档或字幕。您可以选择直接“替换”原文,或是在原文之后“附加”,或是在原文之前“前置”。</li><li><strong>分隔符</strong>: 当选择“附加”或“前置”模式时,此项用于在原文和译文之间插入分隔符。</li></ul></li><li class=\"mb-2\"><strong>JSON路径配置</strong> (仅在“JSON翻译”工作流下显示):<ul class=\"mt-1\"><li><strong>需要翻译的JSON路径</strong>: 每行输入一个 <a href=\"https://goessner.net/articles/JsonPath/\" target=\"_blank\">JSONPath</a> 表达式,指定需要翻译的字段。</li><li>例如:<code>$..description</code>翻译所有键为description的值。<code>$.items[0].name</code>翻译第一个item的name值。</li></ul></li><li class=\"mb-2\"><strong>翻译模型</strong>:<ul class=\"mt-1\"><li><strong>选择平台/API 地址/API Key/模型 ID</strong>: 配置您希望使用的AI翻译服务。</li><li>模型ID参考平台文档,建议使用非推理模型或混合推理模型(关闭思考)。</li></ul></li><li class=\"mb-2\"><strong>翻译配置</strong>:<ul class=\"mt-1\"><li><strong>目标语言/自定义Prompt</strong>: 指定翻译的目标语言和附加指令。</li><li><strong>思考模式</strong>:设置混合推理模型是否进行思考,目前支持智谱的glm4.5系列、阿里云的qwen3系列、火山引擎的seed1.6系列,建议选择禁用思考。</li></ul></li><li class=\"mb-2\"><strong>高级参数</strong>:<ul class=\"mt-1\"><li><strong>分块大小/并发数/Temperature</strong>: 发给ai的分块大小、并发请求数和温度,通常保持默认即可。</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-play-circle-fill me-2\"></i>开始翻译</strong><p class=\"mt-2\">文件选择成功后,点击任务卡片右下角的 <span class=\"badge bg-primary\">开始翻译</span> 按钮。系统将开始处理任务,您可以在日志区域查看实时进度。</p></li><li><strong><i class=\"bi bi-check-circle-fill me-2\"></i>查看与下载</strong><p class=\"mt-2\">翻译完成后,任务卡片下方会出现操作按钮:</p><ul><li><span class=\"badge bg-success\"><i class=\"bi bi-eye-fill me-1\"></i>预览</span>: 在右侧滑出的面板中进行原文和译文的对照预览(仅作参考)。</li><li><span class=\"badge bg-secondary\"><i class=\"bi bi-download me-1\"></i>下载</span>: 下载包括 PDF, DOCX, XLSX, HTML, Markdown 等多种格式的译文。</li></ul></li></ol><div class=\"alert alert-info mt-3\" role=\"alert\"><i class=\"bi bi-info-circle-fill me-2\"></i><strong>提示</strong>: 所有配置都会自动保Line 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\">首先,在配置面板顶部选择您需要的翻译流程。不同的工作流适用于不同类型的文件:<ul><li><b>转Markdown再翻译</b>: 适用于翻译PDF、markdown、图片等文件。</li><li><b>纯文本翻译</b>: 用于翻译 <code>.txt</code> 等纯文本文件。</li><li><b>JSON翻译</b>: 用于翻译 <code>.json</code> 文件中的特定字段。</li><li><b>DOCX翻译</b>: 用于翻译 <code>.docx</code> 文件。</li><li><b>XLSX翻译</b>: 用于翻译 <code>.xlsx</code> 电子表格文件。</li><li><b>SRT字幕翻译</b>: 用于翻译 <code>.srt</code> 字幕文件。</li><li><b>EPUB翻译</b>: 用于翻译 <code>.epub</code> 电子书文件。</li><li><b>HTML翻译</b>: 用于翻译 <code>.html</code> 文件。</li></ul><div class=\"alert alert-info mt-2\" role=\"alert\"><i class=\"bi bi-lightbulb-fill me-2\"></i>新增功能: \"自动选择工作流\"开关已默认开启。您只需上传文件,系统会自动为您匹配合适的工作流,简化操作。</div></p></li><li><strong><i class=\"bi bi-gear-fill me-2\"></i>配置参数</strong><p class=\"mt-2\">根据您选择的工作流,完成相应的配置。所有配置项都会自动保存在您的浏览器中。</p><ul><li class=\"mb-2\"><strong>解析配置</strong> (仅在“转Markdown再翻译”工作流下显示):<ul class=\"mt-1\"><li><strong>解析引擎</strong>: 选择一个引擎将您的文件(如PDF)转换为适合翻译的Markdown格式。如果您的文件已经是Markdown格式,则无需选择。</li><li><strong>Mineru Token</strong>: 如果您选择 <code>minerU</code> 引擎,需要在此处填入您的Token。</li></ul></li><li class=\"mb-2\"><strong>DOCX/XLSX/SRT/EPUB/HTML翻译选项</strong> (在对应工作流下显示):<ul class=\"mt-1\"><li><strong>插入模式</strong>: 定义翻译结果如何放入文档或字幕。您可以选择直接“替换”原文,或是在原文之后“附加”,或是在原文之前“前置”。</li><li><strong>分隔符</strong>: 当选择“附加”或“前置”模式时,此项用于在原文和译文之间插入分隔符。</li></ul></li><li class=\"mb-2\"><strong>JSON路径配置</strong> (仅在“JSON翻译”工作流下显示):<ul class=\"mt-1\"><li><strong>需要翻译的JSON路径</strong>: 每行输入一个 <a href=\"https://goessner.net/articles/JsonPath/\" target=\"_blank\">JSONPath</a> 表达式,指定需要翻译的字段。</li><li>例如:<code>$..description</code>翻译所有键为description的值。<code>$.items[0].name</code>翻译第一个item的name值。</li></ul></li><li class=\"mb-2\"><strong>翻译模型</strong>:<ul class=\"mt-1\"><li><strong>选择平台/API 地址/API Key/模型 ID</strong>: 配置您希望使用的AI翻译服务。</li><li>模型ID参考平台文档,建议使用非推理模型或混合推理模型(关闭思考)。</li></ul></li><li class=\"mb-2\"><strong>翻译配置</strong>:<ul class=\"mt-1\"><li><strong>目标语言/自定义Prompt</strong>: 指定翻译的目标语言和附加指令。</li><li><strong>思考模式</strong>:设置混合推理模型是否进行思考,目前支持智谱的glm4.5系列、阿里云的qwen3系列、火山引擎的seed1.6系列,建议选择禁用思考。</li></ul></li><li class=\"mb-2\"><strong>高级参数</strong>:<ul class=\"mt-1\"><li><strong>分块大小/并发数/Temperature</strong>: 发给ai的分块大小、并发请求数和温度,通常保持默认即可。</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-play-circle-fill me-2\"></i>开始翻译</strong><p class=\"mt-2\">文件选择成功后,点击任务卡片右下角的 <span class=\"badge bg-primary\">开始翻译</span> 按钮。系统将开始处理任务,您可以在日志区域查看实时进度。</p></li><li><strong><i class=\"bi bi-check-circle-fill me-2\"></i>查看与下载</strong><p class=\"mt-2\">翻译完成后,任务卡片下方会出现操作按钮:</p><ul><li><span class=\"badge bg-success\"><i class=\"bi bi-eye-fill me-1\"></i>预览</span>: 在右侧滑出的面板中进行原文和译文的对照预览(仅作参考)。</li><li><span class=\"badge bg-secondary\"><i class=\"bi bi-download me-1\"></i>下载</span>: 下载包括 PDF, DOCX, XLSX, HTML, Markdown 等多种格式的译文。</li></ul></li></ol><div class=\"alert alert-info mt-3\" role=\"alert\"><i class=\"bi bi-info-cirLine truncated
"tutorialUnderstandBtn": "我明白了", "tutorialUnderstandBtn": "我明白了",
"contributorsModalTitle": "感谢贡献", "contributorsModalTitle": "感谢贡献",
"contributorsPara1": "DocuTranslate是一个开源项目!大家的需求与使用是项目进步的动力。", "contributorsPara1": "DocuTranslate是一个开源项目!大家的需求与使用是项目进步的动力。",
@@ -128,7 +140,8 @@
"pdf_preparing": "PDF准备中,请稍后...", "pdf_preparing": "PDF准备中,请稍后...",
"pdf_print_failed": "自动打印失败,请在预览中手动打印。", "pdf_print_failed": "自动打印失败,请在预览中手动打印。",
"pdf_fetch_failed": "获取HTML内容失败,无法生成PDF。", "pdf_fetch_failed": "获取HTML内容失败,无法生成PDF。",
"init_failed_alert": "页面初始化失败,请检查后端服务是否正常并刷新页面。", "init_i18n_failed_alert": "加载界面翻译资源失败,请检查网络连接或联系管理员。",
"init_failed_alert": "初始化失败,无法连接到后端服务。请检查服务是否运行或刷新页面。",
"admin_tasklist_failed": "无法从服务器加载任务列表,请检查后台连接。", "admin_tasklist_failed": "无法从服务器加载任务列表,请检查后台连接。",
"btn_startTranslation": "开始翻译", "btn_startTranslation": "开始翻译",
"btn_initializing": "初始化...", "btn_initializing": "初始化...",
@@ -180,6 +193,10 @@
"engineOptionDocling": "Docling (Local)", "engineOptionDocling": "Docling (Local)",
"getMineruTokenTitle": "Get Mineru Token", "getMineruTokenTitle": "Get Mineru Token",
"mineruTokenPlaceholder": "Required for Mineru engine", "mineruTokenPlaceholder": "Required for Mineru engine",
"modelVersionLabel": "Mineru Model Version",
"modelVersionVlm": "VLM",
"modelVersionPipline": "Pipeline",
"modelVersionHelp": "Mineru VLM is a newer internal beta model.",
"formulaOcrLabel": "Formula Recognition", "formulaOcrLabel": "Formula Recognition",
"codeOcrLabel": "Code Recognition", "codeOcrLabel": "Code Recognition",
"aiSettingsTitleText": "Translation Model", "aiSettingsTitleText": "Translation Model",
@@ -223,6 +240,14 @@
"taskCardStartBtn": "Start Translation", "taskCardStartBtn": "Start Translation",
"downloadMdEmbedded": "Markdown (Embedded Img)", "downloadMdEmbedded": "Markdown (Embedded Img)",
"downloadMdZip": "Markdown (.zip)", "downloadMdZip": "Markdown (.zip)",
"downloadTxt": "TXT",
"downloadJson": "JSON",
"downloadDocx": "DOCX",
"downloadXlsx": "XLSX",
"downloadSrt": "SRT",
"downloadEpub": "EPUB",
"downloadHtml": "HTML",
"downloadPdf": "PDF",
"previewTitle": "Preview", "previewTitle": "Preview",
"previewBilingualBtn": "Bilingual", "previewBilingualBtn": "Bilingual",
"previewTranslatedOnlyBtn": "Translated Only", "previewTranslatedOnlyBtn": "Translated Only",
@@ -231,7 +256,7 @@
"closeBtn": "Close", "closeBtn": "Close",
"downloadBtn": "Download", "downloadBtn": "Download",
"tutorialModalTitle": "Tutorial", "tutorialModalTitle": "Tutorial",
"tutorialModalBody": "<p><i class=\"bi bi-camera-video me-2\"></i>Video tutorials can be found by searching <a href=\"https://search.bilibili.com/all?keyword=docutranslate\" target=\"_blank\">docutranslate on Bilibili</a></a>.</p><p>Welcome to DocuTranslate! Follow these steps to translate your documents:</p><ol><li><strong><i class=\"bi bi-diagram-3 me-2\"></i>Select Workflow</strong><p class=\"mt-2\">First, choose the translation process you need from the top of the settings panel. Different workflows are for different file types:<ul><li><b>Markdown-based</b>: For translating PDF, markdown, images, etc.</li><li><b>Plain Text</b>: For translating <code>.txt</code> and other plain text files.</li><li><b>JSON</b>: For translating specific fields in <code>.json</code> files.</li><li><b>DOCX</b>: For translating <code>.docx</code> files.</li><li><b>XLSX</b>: For translating <code>.xlsx</code> spreadsheet files.</li><li><b>SRT Subtitle</b>: For translating <code>.srt</code> subtitle files.</li><li><b>EPUB</b>: For translating <code>.epub</code> ebook files.</li></ul><div class=\"alert alert-info mt-2\" role=\"alert\"><i class=\"bi bi-lightbulb-fill me-2\"></i>New Feature: \"Auto-select workflow\" is on by default. Just upload your file, and the system will automatically pick the right workflow for you.</div></p></li><li><strong><i class=\"bi bi-gear-fill me-2\"></i>Configure Parameters</strong><p class=\"mt-2\">Based on your chosen workflow, complete the necessary settings. All settings are automatically saved in your browser.</p><ul><li class=\"mb-2\"><strong>Parsing Configuration</strong> (Only for \"Markdown-based\" workflow):<ul class=\"mt-1\"><li><strong>Parsing Engine</strong>: Choose an engine to convert your file (like a PDF) into a translation-friendly Markdown format. Not needed if your file is already Markdown.</li><li><strong>Mineru Token</strong>: If you select the <code>minerU</code> engine, you need to enter your token here.</li></ul></li><li class=\"mb-2\"><strong>DOCX/XLSX/SRT/EPUB Options</strong> (For their respective workflows):<ul class=\"mt-1\"><li><strong>Insert Mode</strong>: Define how the translation is placed in the document. You can \"Replace\" the original, \"Append\" after it, or \"Prepend\" before it.</li><li><strong>Separator</strong>: When using \"Append\" or \"Prepend\", this is used to separate the original and translated text.</li></ul></li><li class=\"mb-2\"><strong>JSON Path Configuration</strong> (Only for \"JSON\" workflow):<ul class=\"mt-1\"><li><strong>JSON paths to translate</strong>: Enter one <a href=\"https://goessner.net/articles/JsonPath/\" target=\"_blank\">JSONPath</a> expression per line to specify which fields to translate.</li><li>E.g., <code>$..description</code> translates all values with the key 'description'. <code>$.items[0].name</code> translates the name of the first item.</li></ul></li><li class=\"mb-2\"><strong>Translation Model</strong>:<ul class=\"mt-1\"><li><strong>Platform/API Base URL/API Key/Model ID</strong>: Configure the AI translation service you want to use.</li><li>Refer to the platform's documentation for Model IDs. It's recommended to use non-inference models or mixed-inference models (with thinking turned off).</li></ul></li><li class=\"mb-2\"><strong>Translation Configuration</strong>:<ul class=\"mt-1\"><li><strong>Target Language/Custom Prompt</strong>: Specify the target language and any additional instructions.</li><li><strong>Thinking Mode</strong>: Sets whether a mixed-inference model should 'think'. Supported for Zhipu's glm4.5 series, Alibaba's qwen3 series, VolcEngine's seed1.6 series, etc. Disabling is recommended.</li></ul></li><li class=\"mb-2\"><strong>Advanced Parameters</strong>:<ul class=\"mt-1\"><li><strong>Chunk Size/Concurrency/Temperature</strong>: The size of text chunks sent to the AI, number of concurrent requests, and creativity level. Default values usually work fine.</li></ul></li></ul></li><li><strong><i class=\"bi bi-file-earmark-arrow-up-fill me-2\"></i>Upload File</strong><p class=\"mt-2\">In the task list on the right, click or drag your document into the file drop area.</p></li><li><strong><i class=\"bi bi-play-circle-fill me-2\"></i>Start Translation</strong><p class=\"mt-2\">Once the file is selected, click the <span class=\"badge bg-primary\">Start Translation</span> button on the task card. The system will start processing, and you can see real-time progress in the log area.</p></li><li><strong><i class=\"bi bi-check-circle-fill me-2\"></i>Review & Download</strong><p class=\"mt-2\">After translation is complete, action buttons will appear on the task card:</p><ul><li><span class=\"badge bg-success\"><i class=\"bi bi-eye-fill me-1\"></i>Preview</span>: Opens a side panel for a side-by-side preview of the original and translation (for reference only).</li><li><span class=\"badge bg-secondary\"><i class=\"bi bi-download me-1\"></i>Download</span>: Download the translation in various formats, incluLine truncated "tutorialModalBody": "<p><i class=\"bi bi-camera-video me-2\"></i>Video tutorials can be found by searching <a href=\"https://search.bilibili.com/all?keyword=docutranslate\" target=\"_blank\">docutranslate</a> on Bilibili.</p><p>Welcome to DocuTranslate! Follow these steps to translate your documents:</p><ol><li><strong><i class=\"bi bi-diagram-3 me-2\"></i>Select Workflow</strong><p class=\"mt-2\">First, choose the translation process you need from the top of the settings panel. Different workflows are for different file types:<ul><li><b>Markdown-based</b>: For translating PDF, markdown, images, etc.</li><li><b>Plain Text</b>: For translating <code>.txt</code> and other plain text files.</li><li><b>JSON</b>: For translating specific fields in <code>.json</code> files.</li><li><b>DOCX</b>: For translating <code>.docx</code> files.</li><li><b>XLSX</b>: For translating <code>.xlsx</code> spreadsheet files.</li><li><b>SRT Subtitle</b>: For translating <code>.srt</code> subtitle files.</li><li><b>EPUB</b>: For translating <code>.epub</code> ebook files.</li><li><b>HTML</b>: For translating <code>.html</code> files.</li></ul><div class=\"alert alert-info mt-2\" role=\"alert\"><i class=\"bi bi-lightbulb-fill me-2\"></i>New Feature: \"Auto-select workflow\" is on by default. Just upload your file, and the system will automatically pick the right workflow for you, simplifying the process.</div></p></li><li><strong><i class=\"bi bi-gear-fill me-2\"></i>Configure Parameters</strong><p class=\"mt-2\">Based on your chosen workflow, complete the necessary settings. All settings are automatically saved in your browser.</p><ul><li class=\"mb-2\"><strong>Parsing Configuration</strong> (Only for \"Markdown-based\" workflow):<ul class=\"mt-1\"><li><strong>Parsing Engine</strong>: Choose an engine to convert your file (like a PDF) into a translation-friendly Markdown format. Not needed if your file is already Markdown.</li><li><strong>Mineru Token</strong>: If you select the <code>minerU</code> engine, you need to enter your token here.</li></ul></li><li class=\"mb-2\"><strong>DOCX/XLSX/SRT/EPUB/HTML Options</strong> (For their respective workflows):<ul class=\"mt-1\"><li><strong>Insert Mode</strong>: Define how the translation is placed in the document. You can \"Replace\" the original, \"Append\" after it, or \"Prepend\" before it.</li><li><strong>Separator</strong>: When using \"Append\" or \"Prepend\", this is used to separate the original and translated text.</li></ul></li><li class=\"mb-2\"><strong>JSON Path Configuration</strong> (Only for \"JSON\" workflow):<ul class=\"mt-1\"><li><strong>JSON paths to translate</strong>: Enter one <a href=\"https://goessner.net/articles/JsonPath/\" target=\"_blank\">JSONPath</a> expression per line to specify which fields to translate.</li><li>E.g., <code>$..description</code> translates all values with the key 'description'. <code>$.items[0].name</code> translates the name of the first item.</li></ul></li><li class=\"mb-2\"><strong>Translation Model</strong>:<ul class=\"mt-1\"><li><strong>Platform/API Base URL/API Key/Model ID</strong>: Configure the AI translation service you want to use.</li><li>Refer to the platform's documentation for Model IDs. It's recommended to use non-inference models or mixed-inference models (with thinking turned off).</li></ul></li><li class=\"mb-2\"><strong>Translation Configuration</strong>:<ul class=\"mt-1\"><li><strong>Target Language/Custom Prompt</strong>: Specify the target language and any additional instructions.</li><li><strong>Thinking Mode</strong>: Sets whether a mixed-inference model should 'think'. Supported for Zhipu's glm4.5 series, Alibaba's qwen3 series, VolcEngine's seed1.6 series, etc. Disabling is recommended.</li></ul></li><li class=\"mb-2\"><strong>Advanced Parameters</strong>:<ul class=\"mt-1\"><li><strong>Chunk Size/Concurrency/Temperature</strong>: The size of text chunks sent to the AI, number of concurrent requests, and creativity level. Default values usually work fine.</li></ul></li></ul></li><li><strong><i class=\"bi bi-file-earmark-arrow-up-fill me-2\"></i>Upload File</strong><p class=\"mt-2\">In the task list on the right, click or drag your document into the file drop area.</p></li><li><strong><i class=\"bi bi-play-circle-fill me-2\"></i>Start Translation</strong><p class=\"mt-2\">Once the file is selected, click the <span class=\"badge bg-primary\">Start Translation</span> button on the task card. The system will start processing, and you can see real-time progress in the log area.</p></li><li><strong><i class=\"bi bi-check-circle-fill me-2\"></i>Review & Download</strong><p class=\"mt-2\">After translation is complete, action buttons will appear on the task card:</p><ul><li><span class=\"badge bg-success\"><i class=\"bi bi-eye-fill me-1\"></i>Preview</span>: Opens a side panel for a side-by-side preview of the original and translation (for reference only).</li><li><span class=\"badge bg-secondary\"><i class=\"bi bLine truncated
"tutorialUnderstandBtn": "Got it", "tutorialUnderstandBtn": "Got it",
"contributorsModalTitle": "Thanks for Contributing", "contributorsModalTitle": "Thanks for Contributing",
"contributorsPara1": "DocuTranslate is an open-source project! The community's needs and usage are what drive its progress.", "contributorsPara1": "DocuTranslate is an open-source project! The community's needs and usage are what drive its progress.",
@@ -264,7 +289,8 @@
"pdf_preparing": "Preparing PDF, please wait...", "pdf_preparing": "Preparing PDF, please wait...",
"pdf_print_failed": "Automatic printing failed. Please print manually from the preview.", "pdf_print_failed": "Automatic printing failed. Please print manually from the preview.",
"pdf_fetch_failed": "Failed to fetch HTML content, cannot generate PDF.", "pdf_fetch_failed": "Failed to fetch HTML content, cannot generate PDF.",
"init_failed_alert": "Page initialization failed. Please check if the backend service is running and refresh the page.", "init_i18n_failed_alert": "Failed to load interface translations. Please check your network connection or contact an administrator.",
"init_failed_alert": "Initialization failed, could not connect to the backend service. Please ensure the service is running and refresh the page.",
"admin_tasklist_failed": "Could not load task list from server. Please check backend connection.", "admin_tasklist_failed": "Could not load task list from server. Please check backend connection.",
"btn_startTranslation": "Start Translation", "btn_startTranslation": "Start Translation",
"btn_initializing": "Initializing...", "btn_initializing": "Initializing...",
+1 -1
View File
@@ -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 data-i18n-title="pageTitle">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> body { background-color: var(--bs-body-bg); } .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; /* for scrollbar */ } .task-area { height: calc(100vh - 2rem); overflow-y: auto; } .task-card { transition: all 0.3s ease-in-out; } .task-id-placeholder { color: var(--bs-secondary-color); font-style: italic; } .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; } .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); } .file-name-display.input-error-text { color: var(--bs-danger); font-weight: bold; } #printFrame, #translatedPreviewFrame { border: none; width: 100%; } #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; /* Important for split.js */ } .preview-pane-wrapper h6 { flex-shrink: 0; padding: 0.25rem; } .preview-pane-wrapper .preview-pane { flex-grow: 1; /* Make the inner pane grow */ border: 1px solid var(--bs-border-color); border-radius: .375rem; overflow: auto; } .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, .preview-pane pre { width: 100%; height: 95%; border: none; margin: 0; padding: 0; overflow: auto; background-color: var(--bs-body-bg); } .slider-reset-btn { visibility: hidden; } .bottom-left-controls { position: fixed; bottom: 1rem; left: 1rem; z-index: 1050; display: flex; gap: 0.5rem; } @media (max-width: 991.98px) { .main-container { height: auto; padding-bottom: 6rem; } .settings-panel, .task-area { height: auto; overflow-y: visible; } .settings-panel { padding-right: 0; margin-bottom: 2rem; } } @media (max-width: 767.98px) { .task-card .col-md-7 { margin-top: 1.5rem; } Line 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 data-i18n-title="pageTitle">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> body { background-color: var(--bs-body-bg); } .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; /* for scrollbar */ } .task-area { height: calc(100vh - 2rem); overflow-y: auto; } .task-card { transition: all 0.3s ease-in-out; } .task-id-placeholder { color: var(--bs-secondary-color); font-style: italic; } .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; } .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); } .file-name-display.input-error-text { color: var(--bs-danger); font-weight: bold; } #printFrame, #translatedPreviewFrame { border: none; width: 100%; } #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; /* Important for split.js */ } .preview-pane-wrapper h6 { flex-shrink: 0; padding: 0.25rem; } .preview-pane-wrapper .preview-pane { flex-grow: 1; /* Make the inner pane grow */ border: 1px solid var(--bs-border-color); border-radius: .375rem; overflow: auto; } .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, .preview-pane pre { width: 100%; height: 95%; border: none; margin: 0; padding: 0; overflow: auto; background-color: var(--bs-body-bg); } .slider-reset-btn { visibility: hidden; } .bottom-left-controls { position: fixed; bottom: 1rem; left: 1rem; z-index: 1050; display: flex; gap: 0.5rem; } @media (max-width: 991.98px) { .main-container { height: auto; padding-bottom: 6rem; } .settings-panel, .task-area { height: auto; overflow-y: visible; } .settings-panel { padding-right: 0; margin-bottom: 2rem; } } @media (max-width: 767.98px) { .task-card .col-md-7 { margin-top: 1.5rem; } Line truncated