
LunaTranslator 翻译优化体系全解析从翻译前替换到自定义 Python 处理【免费下载链接】LunaTranslator视觉小说翻译器 / Visual Novel Translator项目地址: https://gitcode.com/GitHub_Trending/lu/LunaTranslatorLunaTranslator视觉小说翻译器的翻译管线并非原文进、译文出的单一过程而是围绕翻译前与翻译后两个阶段挂载了多个可插拔优化器。本文以官方文档 docs/en/transoptimi.md 为核心骨架逐项拆解翻译前替换、专有名词翻译、翻译结果修正、自定义优化、跳过纯标点句五大内置优化各自的作用机制、适用场景与配置方式并结合src/LunaTranslator/transoptimi/目录下的源码实现与myutils/utils.py中的公共工具函数说明参数在底层是如何被解析与执行的最后讲解游戏专用翻译优化与全局默认配置的层级关系。阅读本文后你将能够区分各优化项的适用边界例如何时该用翻译前替换而非专有名词翻译掌握正则、转义、整词匹配、大小写敏感等开关在配置中的真实含义了解 VNDB 元数据自动填充人名词典的规则并学会撰写自定义 Python 脚本接入翻译前后管线。一、翻译优化模块的总体架构翻译优化Translation Optimization在 LunaTranslator 中对应文本处理Text Processing下的一个独立配置区域其内置模块在源码中以LunaTranslator/transoptimi/目录下的同名 Python 文件形式存在并通过 static_data.json 中的transoptimi列表完成注册。该列表同时登记了每个模块的机器名name与界面显示名visname包括模块机器名界面显示名处理阶段vndbnamemap翻译前替换翻译前process_beforenoundict专有名词翻译翻译前 翻译后transerrorfix翻译结果修正翻译后process_aftermyprocess自定义优化翻译前 翻译后用户脚本skiponlypunctuations跳过仅包含标点的句子翻译前拦截arabic_reshaperarabic reshaper仅阿拉伯语场景languageuse: ar每个模块都以统一的Process类对外暴露两种钩子process_before(japanese)在原文送入翻译引擎前执行process_after(res, context)在翻译结果返回后执行见各模块源码。翻译是否启用某个优化由全局配置globalconfig[transoptimi][name]控制而用哪一份词典则由 postusewhich() 根据全局/游戏专用配置统一裁决返回 1 表示全局、2 表示游戏专用、3 表示两者合并、0 表示不启用。checkpostlangmatch()utils.py还支持按目标语言过滤——这正是arabic_reshaper只在阿拉伯语环境下生效的原因。二、翻译前替换vndbnamemap2.1 机制与适用场景翻译前替换会在翻译之前直接用译文把原文中命中的词条替换掉替换后的内容再进入翻译引擎。由于是先替换、后翻译被替换进去的译文会成为原文的一部分可能进一步参与翻译——因此它最适合处理不希望被翻译引擎二次处理的固定内容或在翻译前就确定好最终形态的短词条。配置界面支持两种增强模式正则Regex将原文作为正则表达式参与匹配替换可表达某字符出现 1~N 次、可选前缀/后缀等复杂模式转义Escape对配置中写下的转义序列如\n、\xNN先做解码再参与匹配便于输入源码层面的特殊字符。2.2 VNDB 元数据自动填充规则该模块与 VNDB 元数据加载联动当游戏从 VNDB 加载元数据时LunaTranslator 会查询游戏中的人物姓名将其自动填充为预设词典填充规则按用户语言分流对英文用户提取到的英文人名会作为原文对应的翻译填入即把人物名替换为英文形式对其他语言用户翻译列会被填充为与原文相同的内容从而在用户不做任何修改时替换前后文本完全一致不影响原有翻译效果。2.3 源码级实现vndbnamemap.py 的核心处理逻辑只有一层def process_before(self, s): namemap self.usewhich() s parsemayberegexreplace(namemap, s) return s, {}其真正语义由公共函数parsemayberegexreplace()utils.py承载。逐条读取词典条目后该函数按以下顺序处理每个字段key匹配原文空 key 跳过escape为 True 时先对 key/value 执行safe_escape()utils.py解码转义序列regex为 False 时将 key 用re.escape()转义为字面量value 用 lambda 包裹成常量替换保证替换文本中的\1等不会被解释为组引用whole-word为 True 时在 key 两侧追加\b词边界case-sensitive为 False 时匹配使用re.IGNORECASE最终以re.sub(key, value, line, flagsflags)执行替换。这六个字段也正是翻译前替换配置窗口中每一行条目的真实列含义理解它们即可精准控制替换行为。三、专有名词翻译noundict3.1 两种执行路径专有名词翻译是翻译优化中机制最复杂的一项它根据翻译源类型走两条完全不同的路径路径一大模型通用接口 prompt 包含DictWithPrompt对于通用 LLM 接口Universal LLM Interface若其 prompt 模板中写入了{DictWithPrompt[XXXXX]}字段则命中的专有名词词条会被直接放入模型 prompt 中引导 LLM 在翻译时按词条译名输出。该字段的使用细节见 docs/en/guochandamoxing.md文中说明若未找到匹配词条该字段会被清空以免干扰翻译内容XXXXX是可以自定义的引导提示语。这一路径的优点是词条上下文对模型完全可见专有名词能参与模型整体的语义推理。路径二其他传统翻译源或 prompt 未包含DictWithPrompt采用 VNRVisual Novel Reader的经典占位符方案翻译前扫描原文把命中词条的原文替换为形如ZX?Z的占位符ZXBZ、ZXCZ……占位符序号递增见 noundict.py 的__createfake()原文含占位符交给翻译源翻译占位符几乎不会被翻译引擎破坏翻译完成后再用case_insensitive_replace()utils.py即大小写不敏感的re.sub把占位符回替换为词条译文最终嵌入译文中。3.2 匹配细节与词条字段noundict.py 的process_before展示了词条匹配时的若干细节这些字段同样出现在配置窗口中src要匹配的原文匹配前会执行re.escape避免正则元字符误伤whole-word为 True 时追加\b词边界避免部分匹配case-sensitive为 False 时默认re.IGNORECASE忽略大小写dst词条译文不能为空——process_before1()中明确跳过dst为空的词条注释表明这是为了兼容从 VNDB 自动导入人名表且不破坏现有翻译的场景noundict.pyinfo注释列用于人工标注不影响执行。每个词条还带有配置窗口中的开关列如启用/停用dedumpcheck()noundict.py以开关状态原文译文注释作为去重键保证列表不重复。3.3 VNDB 自动填充与游戏专用词条与翻译前替换类似VNDB 元数据加载也会为专有名词翻译填充人名预设词典但分流规则略有差异对英文用户填充提取到的英文作为译文对其他语言用户则将译文留空而非填原文留空词条在process_before1中会被跳过因此不修改配置也不会影响翻译。官方文档特别建议游戏的专用词条不要添加在文本处理 → 翻译优化的全局列表中而应添加到游戏设置 → 翻译优化中对应方法的设置里。这样词条只作用于该游戏避免污染全局词典、影响其他作品的翻译界面上的建议使用/而不是两组入口即为全局与游戏专用配置的区别示意。3.4 上下文传递专有名词翻译是少数同时在翻译前后两个阶段工作的模块process_before返回(替换后的原文, context)其中 context 携带了gpt_dict命中词条全集供大模型 prompt 使用、gpt_dict_origin原始文本与占位符映射zhanweifuprocess_afternoundict.py再依据该 context 完成占位符回填。四、翻译结果修正transerrorfix翻译结果修正作用于翻译完成之后对译文结果按词典做一次替换修正且支持把整个表达式用作修正规则。典型用途包括把翻译引擎反复译错的固定词汇如某个角色名、专有名词统一纠正为正确译名用正则表达式匹配译文中的某种模式如多余的空格、错误的标点、重复词并整体替换修正格式类问题如日文全角标点与中文标点混排。其底层执行同样是parsemayberegexreplace()因此上一节列出的key、value、regex、escape、whole-word、case-sensitive六字段全部适用只是此处key对应待修正的翻译value对应修正后的替换见 transerrorfix.py 的process_after。全局词典存于transerrorfixdictconfig[dict_v2]默认空列表见 transerrorfixdictconfig.json游戏专用词条则保存在savehook_new_data[gameuid][transerrorfix]中。五、自定义优化myprocess当内置优化无法满足需求时自定义优化允许撰写一个Python 脚本在翻译前后做任意复杂度的处理。其模板见 myutils/template/myprocess.pyclass Process: def process_before(self, text: str): context {} return text, context def process_after(self, res: str, context): return res脚本需定义一个Process类并可选实现两个钩子process_before(text) - (text, context)接收原文返回处理后的文本 上下文 dict上下文可在后续process_after中读取如记录替换映射、中间状态process_after(res, context) - res接收译文与上一步的 context返回修正后的译文。myprocess.py 的调度器通过checkmd5reloadmodule()按文件 MD5 检测脚本是否变化并在变化时热重载模块module.Process ! self.__lastm时重建内部实例因此你可以在不重启翻译器的前提下反复迭代脚本逻辑。注意若脚本未定义Process或加载失败mayreinit()会令内部实例保持为空管线会直接透传原文/译文不影响翻译主流程。六、跳过仅包含标点的句子skiponlypunctuations该模块逻辑非常简洁在process_before阶段若原文中所有字符都属于标点集合标点集合来自myutils/mecab.py的punctuations则直接返回None即跳过本句的翻译skiponlypunctuations.py。典型收益是避免对……——这类无实义的句子浪费翻译 API 额度也让译文流更干净。该优化仅对纯标点句生效含任何字母/数字/文字的句子不受影响。七、游戏专用翻译优化与全局配置的层级关系所有内置优化都支持游戏级覆盖入口位于游戏设置 → 翻译优化其与全局默认的关系由两个开关决定见 utils.py 的postusewhich()裁决逻辑跟随默认Follow Default默认开启。开启时一律使用全局默认的翻译优化配置游戏级设置被忽略取消跟随默认后启用游戏专用的翻译优化设置在游戏专用模式下若再激活继承默认Inherit Default则该游戏的优化词典会在自身词条之外同时合并使用全局默认词典——对应postusewhich()返回 3 的合并分支游戏专用列表在前、全局列表在后拼接。由此形成清晰的优先级链路跟随默认(用全局) → 仅游戏专用 → 游戏专用 继承全局。游戏级配置如namemap2、noundictconfig_ex、transerrorfix均存储在按gameuid索引的savehook_new_data[gameuid]中与全局配置globalconfig/transerrorfixdictconfig相互独立、互不覆盖。八、配置实操要点小结综合官方文档与源码使用翻译优化时建议遵循以下要点选型要先替换后翻译的固定内容用翻译前替换要保专有名词不被翻译引擎改写、且能配合大模型 prompt 的用专有名词翻译要纠正已产出的译文用翻译结果修正内置能力不足时再上自定义优化脚本。词条作用域全局词条放文本处理 → 翻译优化单游戏词条放游戏设置 → 翻译优化并按需打开继承默认合并全局词典。字段语义无论哪个模块regex正则、escape转义解码、whole-word整词\b边界、case-sensitive大小写敏感四个开关语义一致均由parsemayberegexreplace()统一解释。占位符机制传统翻译源下的专有名词翻译依赖ZX?Z占位符回填词条译文为空时会被自动跳过属于设计行为而非故障。热重载自定义优化脚本保存后无需重启翻译器即可生效MD5 变化触发重载。以上机制共同构成了 LunaTranslator 面向实战的文本精修体系无论是应对 OCR/钩子提取噪声、人名地名统一还是控制翻译引擎的输出格式都能在翻译前与翻译后两个时机找到对应的挂载点而全部词典均可细粒度地收敛到单个游戏从而在全局可用性与单作品定制性之间取得平衡。【免费下载链接】LunaTranslator视觉小说翻译器 / Visual Novel Translator项目地址: https://gitcode.com/GitHub_Trending/lu/LunaTranslator创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考