"""专有名词与隐语(不应直译)处理规则。 日语字幕"日 → 中文"翻译中,两类词是 LLM 误译重灾区: 1. **片假名专有名词**(人名/品牌/角色/道具名):模型常按读音硬译 (如 ジンゴ → "芒果"),产生与原文无对应的荒谬结果。 2. **成人语境隐语/俗称**(AV/色情内容的委婉说法):模型常按字面直译 (如 マンゴー → 芒果、バナナ → 香蕉、金玉 → 金玉),实际这些词在 色情语境中是生殖器官或性行为的代称。 本模块维护三张规则表(专名、拟声/口语、成人语境隐语),并提供规则构建 函数 build_proper_noun_rule,供翻译节点在系统提示词中动态注入,让 LLM 按正确语义处理。 处理策略(详见 docs/proper_nouns.md): - 人名:音译(保留姓氏/称谓),不直译字面义; - 品牌/产品名:保留原文或使用约定译名; - 角色/道具专名:保留原文或按上下文意译,禁止按读音硬译; - 拟声/拟态词:用中文对应拟声词,不直译; - **成人语境隐语:按"实际含义"的常用中文翻译处理,禁止字面直译**。 匹配基于"原文文本是否包含专名"判断,未命中时不注入规则(避免干扰普通 翻译)。纯函数,可独立测试(tests/test_proper_nouns.py)。 """ from __future__ import annotations # 一、专名表:{日文原文: (中文处理建议, 说明)}。 # 命中即注入对应指令。 PROPER_NOUNS: dict[str, tuple[str, str]] = { # 角色/道具专名:勿按读音硬译 "ジンゴ": ("保留原英文'Jingo'或按上下文意译;禁止译作'芒果'", "实测被误译'芒果'(4500s),片假名专名"), "マンゴー": ("保留'マンゴー/Mango';仅当确指水果时译'芒果'", "与'芒果'同音易误译,见成人隐语表"), # 人名:音译,勿留日文 "カンタくん": ("音译'康太君/坎塔君',勿保留'カンタ君'", "人名(3803s)"), "松井": ("保留'松井'(姓氏汉字)", "人名,参考'松井小姐'"), "ひな子": ("音译'日奈子/雏子'", "人名,参考'松井日奈子'"), "カリン": ("音译'果林/花梨'", "人名,参考'北冈果林'"), "北岡": ("保留'北冈'(姓氏汉字)", "人名"), "権藤": ("音译'权藤/昆藤'", "人名,参考'医务室长权藤'"), "金山": ("保留'金山'(姓氏汉字)", "人名,参考'金山先生'"), } # 二、高频"伪专名"(拟声/口语):勿按字面直译 ONOMATOPOEIA: dict[str, tuple[str, str]] = { "パンパン": ("按语境译'鼓胀、饱满、涨满'", "勿译'砰砰'"), "グリグリ": ("用力碾/钻、搅动", "勿译'咕噜咕噜'"), "チンポ": ("按上下文译为俗语(肉棒/鸡巴)", "勿音译'金宝'"), "ビクビク": ("一颤一颤、哆嗦", "勿译'比库比库'"), "ヌルヌル": ("滑溜溜、黏糊糊", "勿译'奴鲁奴鲁'"), "ビンビン": ("硬邦邦、精神十足", "勿译'宾宾'"), "マット": ("垫子(日语借词)", "勿译'马特'"), "リラックス": ("放松(外来语还原含义)", "勿音译'丽拉库斯'"), } # 三、成人语境隐语/俗称:{日文原文: (实际含义, 对应中文常用翻译, 说明)}。 # 这些词在色情语境中是生殖器官/性行为的代称,LLM 若按字面直译会严重错译。 # 结构:词条 -> (实际含义, 常用中文翻译, 补充说明/约束) ADULT_EUPHEMISMS: dict[str, tuple[str, str, str]] = { # 水果谐音/形状类(画面常见比喻) "マンゴー": ("女性生殖器", "小穴、鲍鱼、妹妹;若为谐音梗可保留'芒果'", "与'マンコ'同音,直译'芒果'为常见误译"), "バナナ": ("男性生殖器", "肉棒、鸡鸡、老二;画面打码可译'香肠'", "水果形状比喻,直译'香蕉'错误"), "リンゴ": ("睾丸(阴囊)", "蛋蛋;若出自'淫梦'梗可保留'苹果'并加注释", "食物比喻,直译'苹果'错误"), # 物品比喻类 "ちんぽう": ("男性生殖器", "阳具、鸡巴(粗俗)", "与'珍宝(ちんぽう)'谐音"), "ちんちん": ("男性生殖器", "小鸡鸡(委婉)", "小朋友用语,女优常用来装可爱"), "金玉": ("睾丸", "蛋蛋、睾丸(正式)", "直译'金玉'会让人摸不着头脑"), "にくつぼ": ("女性生殖器", "肉洞、蜜穴(偏文学性);小穴(口语)", "字面'肉壶',实为色情比喻"), "おまんこ": ("女性生殖器", "小穴、阴部(正式/粗俗)", "最常用称,勿照搬"), "おそそ": ("女性生殖器", "那里、下面(委婉)", "儿童语/婉语,直译会破坏语气"), "オチンチン": ("男性生殖器", "小弟弟(常用);网络流行语可直译'欧金金'", "与'欧金金'同源网络梗"), # 状态/动作类 "ほんばん": ("真实插入的性行为", "真枪实弹、来真的、本番(音译)", "AV 术语,勿直译'本番'为'正本'"), "すまた": ("股间摩擦(不插入)", "素股(音译最常用)、腿交、磨大腿", "AV 术语"), "せいかん": ("户外/野外性行为", "野战、户外做爱", "字面'青姦',勿照搬"), "エッチ": ("性行为/色情的", "做爱、嘿咻、H(音译)", "通用隐语,勿直译'H'"), "アヘ顔": ("高潮时翻白眼吐舌的表情", "阿黑颜(音译)、高潮脸、失神脸", "网络亚文化词,直译'阿嘿脸'外行"), } def build_proper_noun_rule(terms: str | list[str]) -> str | None: """根据待翻译文本中的专名/隐语,构建翻译提示词片段。 参数 terms: 待翻译的原文行(字符串列表或整体文本)。 返回注入提示词的规则字符串;若原文未命中任何专名/隐语则返回 None (不注入,避免干扰普通翻译)。 """ if isinstance(terms, str): joined = terms else: joined = "\n".join(terms) rules: list[str] = [] for token, (advice, reason) in PROPER_NOUNS.items(): if token in joined: rules.append(f" 日文'{token}':{advice}({reason})。") for token, (advice, reason) in ONOMATOPOEIA.items(): if token in joined: rules.append(f" 日文'{token}':{advice}({reason})。") for token, (meaning, cn, note) in ADULT_EUPHEMISMS.items(): if token in joined: rules.append( f" 日文'{token}'是成人语境隐语(实际含义:{meaning})," f"请译为'{cn}',切勿按字面直译。{note}。" ) if not rules: return None return ( "注意以下专有名词/隐语按规则处理(不要按读音或字面硬译):\n" + "\n".join(rules) )