星露谷物语英中 / 德英 / 日中 / 韩中 / 英日 / 西英 / 法英 / 俄英 / 葡英 / 土英 / 匈英 / 意英等 12 种语言对双语同屏显示 Mod。 基于 Content Patcher 实现,无需修改游戏代码,支持实时切换显示模式。
所有界面文本、对话、事件、物品描述、信件、日历节日等均可显示为 语言A / 语言B,方便对照学习。
- 多语言对支持 — 通过 GMCM 或
config.json在以下 12 种语言对之间实时切换:en-zh:英中双语(默认)de-en:德英双语ja-zh:日中双语(含合并字体支持,假名 + 繁体汉字均能显示)ko-zh:韩中双语(含合并字体支持,韩文谚文 + 汉字均能显示)en-ja:英日双语(需将游戏语言设为 日本語 以正确显示日文字形)es-en:西英双语fr-en:法英双语ru-en:俄英双语(需将游戏语言设为 Русский 以显示西里尔字形)pt-en:葡英双语tr-en:土英双语hu-en:匈英双语it-en:意英双语- 其他自定义对只需导出对应语言数据并重建包即可
- 关闭 —
BilingualMode=off时跟随游戏原生语言设置,不进行任何干预 - 多个语言对并列 — 一次构建可同时包含多种语言对,玩家按需切换
⚠ 游戏内必须将 Language 设置为下表中对应的语言,否则中文/日文等 CJK 字符会显示为 * 或乱码。
| BilingualMode | 对应双语 | 游戏语言应设为 |
|---|---|---|
en-zh |
英 + 中 | 中文 |
de-en |
德 + 英 | Deutsch 或 English 均可(两者都用拉丁字母) |
ja-zh |
日 + 中 | 中文 或 日本語 均可 |
ko-zh |
韩 + 中 | 中文 或 한국어 均可 |
en-ja |
英 + 日 | 日本語 |
es-en |
西 + 英 | Español 或 English 均可 |
fr-en |
法 + 英 | Français 或 English 均可 |
ru-en |
俄 + 英 | Русский(西里尔字形依赖俄文字体) |
pt-en |
葡 + 英 | Português 或 English 均可 |
tr-en |
土 + 英 | Türkçe 或 English 均可 |
hu-en |
匈 + 英 | Magyar 或 English 均可 |
it-en |
意 + 英 | Italiano 或 English 均可 |
off |
关闭双语 | 任意(跟随游戏原生设置) |
原因:含 CJK(中日韩)字符的双语对依赖合并字体。目前合并字体只能在 CJK 游戏语言环境下正确加载,English 环境下会出现纵向马赛克乱码。这是 FNA 渲染路径的已知限制,详见"已知限制"章节。
- 配置格式变更 —
BilingualMode取值从 v1 的true/false改为语言对代码(如en-zh、ja-zh)或off。旧版本的"true"在 v2 中会触发 CP 验证警告,请手动修改config.json为合法值。 - 日中字体合并 — 新增
fonts/字体合并流程,解决日中双语下的假名/繁体汉字缺失问题(详见下文"字体合并"章节)。
支持切换的场景:
- Strings/* 界面文本(菜单、按钮、提示等)
- Characters/Dialogue/* 所有 NPC 对话(含 $d/$p 条件语句、$y 快速问答、$q/$r Q&A、#$1 条件分支)
- Data/Events/* 所有剧情事件(含 $q/$r 问答、$y 快速问答、#$b# 分段)
- Data/Objects, Data/Tools, Data/Weapons 等物品的名称和描述
- Data/Bundles, Data/Monsters, Data/hats, Data/Boots 等管道分隔型数据
- Data/NPCGiftTastes 所有 NPC 送礼反应(爱/喜欢/普通/讨厌/厌恶五档)
- Data/mail 信件(正文+标题)
- Data/Festivals/* 日历节日名称 + 节日 NPC 对话 + 节日事件
- Data/SecretNotes, Data/Achievements 秘密纸条和成就
- Data/ExtraDialogue, Strings/MovieReactions, Strings/SpecialOrderStrings 对话文本
- Strings/schedules/* NPC 日程文本
通过 Generic Mod Config Menu (GMCM) 在游戏中实时切换,无需重启立即生效。
| 对话 | 背包物品 |
|---|---|
![]() |
![]() |
| 开场动画 | 任务日志 |
|---|---|
![]() |
![]() |
本 Mod 是一个 Content Patcher 内容包(content pack),本身不含游戏修改逻辑。运行时需要以下组件:
| 组件 | 下载地址 | 说明 |
|---|---|---|
| Stardew Valley 1.6+ | Steam / GOG | 游戏本体,必须为 1.6 或更高版本(已包含官方中文语言包) |
| SMAPI 4.0+ | smapi.io | 模组加载器。将 Modding API 注入游戏,是运行所有 Mod 的基础 |
| Content Patcher 2.0+ | Nexus Mods | 数据包框架。本 Mod 通过它替换游戏文本,不修改任何游戏文件 |
| GMCM 1.16+(可选) | Nexus Mods | 游戏内配置菜单。推荐安装以便在游戏中切换语言模式 |
安装顺序: SMAPI → Content Patcher → GMCM(可选)→ 本 Mod
从 Releases 页面下载最新版本的 BilingualMod-v*.zip。
-
确保已安装上述所有前置依赖(SMAPI、Content Patcher)
-
下载
BilingualMod-v*.zip(从本页面顶部 Releases 获取) -
解压 zip 文件,将
BilingualMod文件夹整体放入Stardew Valley/Mods/目录下- 最终路径应为:
Stardew Valley/Mods/BilingualMod/content.json - 如果放错了(例如多了一层文件夹),Mod 不会被识别
- 最终路径应为:
-
通过
StardewModdingAPI.exe启动游戏(不要用原版 Stardew Valley.exe) -
在标题画面将 Language 设为 中文
- ⚠ 这一步必须做,否则中文字体无法渲染,双语文字会显示为方框
-
配置语言模式(二选一):
方法一:在标题画面配置(推荐)
- 在主菜单(标题画面),点击左下角的 ⚙ 齿轮图标(Mods 按钮)
- 选择
Stardew Valley Bilingual Text - 找到
BilingualMode下拉列表(默认en-zh) - 选择需要的语言对(
en-zh、de-en、ja-zh、ko-zh、en-ja、es-en、fr-en、ru-en、pt-en、tr-en、hu-en、it-en)或off关闭 - 点击 保存并退出,然后加载存档
方法二:进入游戏后配置
- 加载存档后,按
ESC打开背包/暂停界面 - 点击菜单栏右侧的 🎮 游戏手柄图标(Mods 按钮)
- 向下滚动到底部,选择
Stardew Valley Bilingual Text - 修改
BilingualMode下拉列表到所需语言对或off - 每次更改后点击 保存并退出
默认模式为 en-zh 英中双语(安装后即可看到双语效果)。也可以直接编辑
Mods/BilingualMod/config.json文件,例如"BilingualMode": "ja-zh"或"off"。
- 下载最新
BilingualMod-v*.zip - 删除旧版
Stardew Valley/Mods/BilingualMod/整个文件夹 - 解压新的 zip 到
Stardew Valley/Mods/,步骤与首次安装相同 - 启动游戏即可
⚠ 不要直接覆盖旧文件,有时旧版的文件结构会和新版冲突。
| 类别 | 资产数 |
|---|---|
| Strings/* 界面文本 | 30 |
| 字幕 (Strings/credits, List) | 1 |
| 对话 (Characters/Dialogue/* + ExtraDialogue + MovieReactions + SpecialOrderStrings + StringsFromCSFiles + 1_6_Strings + StringsFromMaps + SimpleNonVillagerDialogues) | 48 |
| 日程文本 (Strings/schedules/*) | 30 |
| Data 文本 (mail, TV/*, FestivalDates) | 4 |
| 事件对话 (Data/Events/*) | 43 |
| 类别 | 方法 | 条目数 |
|---|---|---|
| 一般物品 (Data/Objects) | Fields DisplayName+Description |
807 |
| 工具 (Data/Tools) | Fields | 37 |
| 武器 (Data/Weapons) | Fields | 67 |
| 大件可制造 (Data/BigCraftables) | Fields | 182 |
| 上衣 (Data/Shirts) | Fields | 303 |
| 裤子 (Data/Pants) | Fields | 18 |
| 帽子 (Data/hats) | Fields (数值索引 5,1) | 122 |
| 靴子 (Data/Boots) | Fields (数值索引 6,1) | 18 |
| 特殊能力 (Data/Powers) | Fields | 36 |
| 饰品 (Data/Trinkets) | Fields | 8 |
| 任务 (Data/Quests) | Fields (数值索引 1,2) | 66 |
| 订婚对话 (Data/EngagementDialogue) | Fields (数值索引 0,1) | 26 |
| Bundle (Data/Bundles) | Fields (数值索引 6) | 31 |
| 怪物 (Data/Monsters) | Fields (数值索引 14) | 51 |
| 送礼反应 (Data/NPCGiftTastes) | Fields (多字段 pipe_multi 索引 0,2,4,6,8) | 39 |
| 类别 | 条目数 |
|---|---|
| 成就 (Data/Achievements) | 39 |
| 秘密纸条 (Data/SecretNotes) | 38 |
| 模式 | 活跃补丁数 |
|---|---|
| BilingualMode = off(关闭) | 0(所有补丁通过 When 条件跳过,游戏原生文本) |
| BilingualMode = en-zh | ~186(含 2 个字体重定向 + 1 credits) |
| BilingualMode = de-en | ~186(无需字体重定向,两种语言均使用拉丁字体) |
| BilingualMode = ja-zh | ~190(含 4 个字体重定向:2 SpriteFont + 2 BmFont) |
| BilingualMode = ko-zh | ~190(含 4 个字体重定向:2 SpriteFont + 2 BmFont) |
| BilingualMode = en-ja | ~186(无字体重定向,需将游戏语言设为 日本語) |
| BilingualMode = es-en | ~186(无字体重定向,两种语言均使用拉丁字体) |
| BilingualMode = fr-en | ~186(无字体重定向,两种语言均使用拉丁字体) |
| BilingualMode = ru-en | ~186(无字体重定向,需将游戏语言设为 Русский) |
| BilingualMode = pt-en | ~186(无字体重定向,两种语言均使用拉丁字体) |
| BilingualMode = tr-en | ~186(无字体重定向,两种语言均使用拉丁字体) |
| BilingualMode = hu-en | ~186(无字体重定向,两种语言均使用拉丁字体) |
| BilingualMode = it-en | ~186(无字体重定向,两种语言均使用拉丁字体) |
仅列出计数参考;每个实际构建的补丁数因缺失资产的跳过情况略有不同。
| 节日 | 资产 | 条目数 |
|---|---|---|
| 复活节 (Egg Festival) | Data/Festivals/spring13 |
78 条(NPC 对话 + 事件 + 名称) |
| 花舞节 (Flower Dance) | Data/Festivals/spring24 |
80 条 |
| 卢奥节 (Luau) | Data/Festivals/summer11 |
100 条 |
| 月光水母之舞 (Dance of the Moonlight Jellies) | Data/Festivals/summer28 |
82 条 |
| 星露谷展览会 (Stardew Valley Fair) | Data/Festivals/fall16 |
91 条 |
| 万灵节 (Spirit's Eve) | Data/Festivals/fall27 |
88 条 |
| 冰雪节 (Festival of Ice) | Data/Festivals/winter8 |
93 条 |
| 冬日星盛宴 (Feast of the Winter Star) | Data/Festivals/winter25 |
88 条 |
普通用户不需要执行此流程。直接下载 Releases 中的 zip 即可。
以下流程仅适用于开发者需要修改或更新本 Mod 时。
前置要求:Python 3.10+(仓库根
.python-version固定 3.11,CI 使用 3.11)。
cd AssetExporter
dotnet build构建后 Mod 自动部署到 Stardew Valley/Mods/AssetExporter。复制 assets-list.txt 和 config.json 到该目录,启动游戏一次,会在游戏目录生成 Export_TextAssets/{en,zh,de,ja,ko,es,fr,ru,pt,tr,hu,it}/。
cd BilingualModBuilder
# 全部 12 个默认语言对(en:zh de:en ja:zh ko:zh en:ja es:en fr:en ru:en pt:en tr:en hu:en it:en)
python build_bilingual_pack.py
# 自定义子集(如仅英中)
python build_bilingual_pack.py --pairs en:zh
# 交换语言顺序(中文在前英文在后)
python build_bilingual_pack.py --pairs zh:en生成的 Content Patcher 包位于 BilingualModBuilder/BilingualMod/,复制到 Stardew Valley/Mods/ 即可使用。
如需导出其他语言的游戏数据,修改
AssetExporter/config.json的Languages字段(仓库默认 12 种语言),运行 AssetExporter mod 后即可获得对应语言的 JSON 文件。导出的游戏版本与时间记录在_export/manifest.json。
零版本构建可跳过此步。若打包 ja:zh、ko:zh 等跨 CJK 对,需另外执行以下两条命令生成合并字体 XNB,否则日文假名/繁体汉字/韩文谚文在游戏中显示为 *。
SpriteFont(XNA 位图字体):
cd BilingualModBuilder
# 1. 用 xnbcli(Node.js)解包原 zh-CN 和 ja-JP 版 SpriteFont1 + SmallFont
# 解包后数据位于 _tmp/font-zh/ 和 _tmp/font-ja/
# 若需韩语支持,还需解包 ko-KR 版到 _tmp/font-ko/
# 2. 双向合并日文字形到中文字体;韩文字形则合并到已合并的中文字体上
# (产生 _tmp/font-merged-zh/ 等)
python merge_font.py SpriteFont1
python merge_font.py SmallFont
# 3. 用 Python XNB 打包器直接生成 .xnb(避免 xnbcli 的 UTF-8 与 FNA 格式不兼容问题)
python pack_xnb.py SpriteFont1
python pack_xnb.py SmallFontBmFont(文本系统位图字体,用于加载文字/TV/信件):
# 1. 用 xnbcli 解包 Content/Fonts/Chinese.xnb 和 Japanese.xnb(会导出 XML)
# 若需韩语支持,还需解包 Korean.xnb 到 _tmp/font-ko-bmf/
# 2. 把日文字符合并到中文 BmFont 的 XML 中(反之亦然);韩文字形则合并到已合并的中文 BmFont 上
python merge_bmfont.py
# 3. 用 xnbcli 重新打包为 .xnb
# 输出位于 BilingualMod/assets/Chinese.xnb 和 Japanese.xnb三个字体脚本均支持
--tmp-dir/--out-dir参数指定输入输出目录(默认<仓库根>/_tmp与<仓库根>/BilingualMod/assets),不再依赖本机绝对路径。完整的字体合并流程也可通过.\build.ps1 -Fonts一键执行。
build_bilingual_pack.py 会根据 --pairs 自动为 ja:zh 等对添加对应的 CP Load 补丁,指向 assets/ 下生成的合并字体文件。
⚠ 日中/日韩/韩中等跨 CJK 语言对的字体支持
星露谷为每种 CJK 语言编译了独立的位图字体(SpriteFont + BmFont)。在 v2 之前,跨 CJK 对(如ja:zh)会出现假名/繁体汉字显示为*的问题。v2 起内置两种字体系统的合并支持,韩语谚文亦从合并字体中获得完整字形覆盖:
字体系统 用途 合并工具 输出资产 SpriteFont (SpriteFont1, SmallFont) 对话、道具悬浮、HUD 元素 merge_font.py+pack_xnb.pyassets/{font}.zh-CN.xnbBmFont (Chinese, Japanese) 加载文字、TV 字幕、信件正文、部分 UI merge_bmfont.py+ xnbcliassets/{Chinese,Japanese}.xnb两个流程都做了多向合并:
SpriteFont1.zh-CN.xnb= 中文 base + 日文缺失字符(~1184 个:假名 + 繁体汉字 + 少量符号);若解包了韩文字体,还会追加韩文谚文(U+AC00–D7AF)等缺失字形BmFont Chinese.xnb= 中文 base + 日文缺失字符的 XML,扩展纹理页指向Japanese_0/1.xnb;若解包了Korean.xnb,韩文字形会以同样的方式追加到Chinese.xml中BmFont Japanese.xnb= 日文 base + 中文缺失字符的 XML,扩展纹理页指向Chinese_0..3.xnb构建命令:见下方"从源码构建"小节中的"字体合并流程"。韩语字体合并为可选步骤,未解包
_tmp/font-ko/与_tmp/font-ko-bmf/时脚本会自动跳过,仅影响ko:zh下的谚文显示。已知限制:
ja:zh、ko:zh下共享 CJK 汉字(如"日"、"本")保留中文字形(笔画为简化体形态),而非对应语言特定的字形变体。CP 的Load一个Target只能指向一个文件,无法在游戏运行时按Language令牌动态切换两份字体。接受此视觉细节即可获得完整功能覆盖。
python verify.py --pack # 检查 content.json(mail 格式、节日、对话安全)
python verify.py --data # Token 完整性和分隔符检查
python verify.py --dialogue # 对话分段安全分析
python verify.py --parser # 检查 build script 的 parser 分配是否正确,捕捉 ^ 性别分支 / #\$b# 分段遗漏
python verify.py --log=SMAPI-latest.txt # SMAPI 日志分析.\build.ps1 # 完整构建(编译导出器 + 构建双语包 + 验证 + 部署)
.\build.ps1 -Quick # 仅构建双语包(跳过编译和导出)
.\build.ps1 -Deploy # 仅部署到 Mods 目录
.\build.ps1 -Fonts # 执行字体合并全流程(解包→合并→打包→同步 XNB)
.\build.ps1 -Export # 提示启动游戏重新导出文本资产
.\build.ps1 -Test # 构建后运行 pytest 与 verify.py 全量验证
.\build.ps1 -Release # 构建后打包发布 zip(与 CI release.yml 逻辑一致)
build.ps1支持-ModTarget(部署目标,默认自动探测 Steam/GOG 安装目录)、-GameDir(游戏目录)、-TmpDir(字体临时目录)参数。
stardew-bilin/
├── AssetExporter/ # C# SMAPI Mod,用于导出游戏文本资产
│ ├── AssetExporter.csproj
│ ├── manifest.json
│ ├── config.json # 配置导出语言列表(12 种官方语言)
│ ├── ModEntry.cs # 遍历资产列表,按类型导出 JSON
│ └── assets-list.txt # 需要导出的资产路径列表
├── BilingualModBuilder/ # Python 构建脚本
│ ├── build_bilingual_pack.py # 主入口:参数解析 + DEFAULT_PAIRS 语言对配置 + 分派
│ ├── asset_builders.py # 按 asset 类型的构建器(string/data/festival/font)
│ ├── config_builder.py # content.json 组装 + manifest/config 同步
│ ├── parsers.py # 文本解析器(对话/邮件/事件/Q&A/条件 + 模板常量)
│ ├── merge_font.py # SpriteFont 双向合并(JA/ZH 互补)
│ ├── merge_bmfont.py # BmFont XML 双向合并
│ ├── pack_xnb.py # 纯 Python XNB 打包器(UTF-8 char + format=0 BGRA32)
│ ├── check_export_freshness.py # 导出数据新鲜度检查(CI 告警,不阻断)
│ ├── assets-list.txt # 资产路径列表(与导出时一致)
│ ├── BilingualMod/ # 构建输出(由 .gitignore 忽略)
│ │ ├── content.json # 自动生成的 Content Patcher 补丁
│ │ ├── manifest.json
│ │ ├── config.json
│ │ └── assets/ # 合并后的字体 XNB 文件(按需生成)
│ └── tests/ # pytest 单元测试
│ ├── test_parsers_d1.py # #$1 条件对话
│ ├── test_parsers_qr.py # $q/$r 内联问答
│ ├── test_parsers_y.py # $y 快速问答 + 烹饪频道
│ └── test_multipair.py # 多语言对支持 + 字体补丁
├── BilingualMod/ # Content Patcher 内容包(游戏使用的版本)
│ ├── manifest.json
│ ├── config.json # 默认 "BilingualMode": "en-zh"
│ ├── content.json # 由 build_bilingual_pack.py 自动生成
│ └── assets/ # 合并后的字体 XNB(含 .zh-CN 与合并 BmFont)
├── _export/ # 导出的游戏文本资产(按语言分目录)
│ ├── manifest.json # 导出时的游戏版本/SMAPI/时间记录
│ ├── en/ # 英文原文 JSON
│ ├── zh/ # 中文翻译 JSON
│ ├── de/ # 德文 JSON
│ ├── ja/ # 日文 JSON
│ ├── ko/ # 韩文 JSON
│ ├── es/ # 西班牙文 JSON
│ ├── fr/ # 法文 JSON
│ ├── ru/ # 俄文 JSON
│ ├── pt/ # 葡萄牙文 JSON
│ ├── tr/ # 土耳其文 JSON
│ ├── hu/ # 匈牙利文 JSON
│ └── it/ # 意大利文 JSON
├── xnbcli/ # xnbcli Node.js 工具(用于解包 XNB)
├── docs/
│ ├── tech-doc.md # 原始技术方案文档(v1 架构,仅供参考)
│ └── roadmap.md # 开发路线图(需求/技术债/优先级)
├── images/ # 效果截图
├── verify.py # 统一验证系统
├── build.ps1 # 一键构建脚本
├── .gitignore
└── README.md
graph TB
subgraph "构建流水线"
EX[AssetExporter] -->|"语言切换+缓存失效"| EN_RAW[Export_TextAssets/en/]
EX -->|"游戏当前 locale"| ZH_RAW[Export_TextAssets/zh/]
PY[build_bilingual_pack.py] -->|"读取中英文 JSON"| EN_RAW
PY -->|"读取中英文 JSON"| ZH_RAW
PY -->|"字符串: EditData+Entries"| BP[content.json]
PY -->|"模型型: EditData+Fields"| BP
PY -->|"^分隔型: EditData+Entries"| BP
PY -->|"对话: 分段双语"| BP
PY -->|"信件: [#]去重"| BP
PY -->|"事件: 脚本解析"| BP
end
subgraph "运行时"
SMAPI[SMAPI] --> CP[Content Patcher]
CP -->|"读取 content.json"| BP
CP -->|"根据 LanguageMode 选择"| WHEN{"When 条件"}
WHEN -->|"中文: 0 补丁"| NATIVE[游戏原生 .zh-CN 覆盖层]
WHEN -->|"English/Bilingual"| PATCH[EditData 补丁]
PATCH -->|"在 .zh-CN 覆盖层之后生效"| FINAL[最终文本]
end
sequenceDiagram
participant User as 玩家
participant SMAPI as SMAPI
participant CP as Content Patcher
participant Mod as BilingualMod
participant Game as 游戏引擎
User->>SMAPI: 启动游戏 (StardewModdingAPI.exe)
SMAPI->>CP: 加载 Content Patcher
CP->>Mod: 读取 content.json
CP->>Mod: 读取 config.json (LanguageMode=Bilingual)
Mod-->>CP: 返回资产替换规则
CP->>CP: 解析 {{LanguageMode}} 令牌
Game->>CP: 请求资产 Strings/UI
CP->>Mod: 根据令牌值选择 English/Bilingual 补丁
Mod-->>CP: 返回 { "key": "cooking / 烹饪", ... }
CP-->>Game: 返回替换后的字典
Game->>Game: 渲染文本 "cooking / 烹饪"
| 组件 | 技术 | 说明 |
|---|---|---|
| 英文导出 | LocalizedContentManager 切换为 en + SMAPI 缓存失效 |
强制加载纯英文 XNB(绕过当前中文 locale) |
| 中文导出 | Helper.GameContent 直接加载 |
获取合并后的中文数据(base + .zh-CN 覆盖层) |
| Token 解析 | 多源正则 \[LocalizedText (source):(key)\] |
提取 source 路径加载正确的 Strings 资产;支持 format 参数(如 TrashCan_Description 15 → 15%) |
| 对话双语 | 按 #$e#/#$b# 分段 + ^ 性别配对 |
每段独立做双语,避免中文被结束标记丢弃;支持 $d COND#T|F 条件分支;^ 性别配对输出 "EN男 / ZH男 ^ EN女 / ZH女",跳过 ${...^...}$ CP 令牌;$q/$r Q&A 和 #$1 条件对话:保留 EN 命令结构,仅双语化文本部分 |
| 信件双语 | [#] 去重 + 命令 %% 终结 |
只保留 EN 的 [#] 标记和命令,ZH 取纯文本;%command 在 / 前终结 |
| 事件双语 | 引号感知脚本分割器 | 按 / 分割事件脚本(尊重引号),对 speak/message/$q/$r/$p 等做双语 |
^ 分隔资产 |
EditData + Entries 全值替换 |
读取 _raw 字段,按 ^ 分割后逐字段双语再拼接 |
| 普通双语 | bilingualize_pair() 统一处理 |
^ 性别分支配对输出 "EN男 / ZH男 ^ EN女 / ZH女"(跳过 ${...^...}$ CP 令牌);自动识别 $y 'Q_Opt1_Resp1' 格式,按 _ 分割后逐段双语化,所有 parser 共享此函数 |
| 日历节日 | EditData + Entries |
替换 name + 全部 NPC 对话(dialogue parser)+ 事件脚本(event parser),不影响 conditions/mainEvent 等 |
| 多字段管道型 | pipe_multi 类型 |
支持多个对话字段(如 NPCGiftTastes 的 0/2/4/6/8 五档送礼对话),读取 _raw 全值后按字段拆分双语;使用 ` |
| Content Patcher | 全部用 EditData + Load 字体 |
所有补丁加 When: "BilingualMode": "<pair_code>",关闭(off)时 0 补丁;跨 CJK 对额外加 4 个 Load 字体重定向(2 SpriteFont + 2 BmFont) |
| 多语言对 | --pairs en:zh de:en ja:zh |
一次构建生成多个并列补丁集,各自 When 条件不同,玩家通过 BilingualMode 选择当前生效的语言对 |
| 字体合并(SpriteFont) | merge_font.py + pack_xnb.py |
双向合并中日 SpriteFont 字形(6988→8172 字形),纯 Python XNB 打包器写 format=0 BGRA32 未压缩 + UTF-8 char 编码,避开 xnbcli 的 DXT 压缩 stub 和 7-bit int char 误解 |
| 字体合并(BmFont) | merge_bmfont.py + xnbcli |
双向合并 BmFont XML,扩展纹理页指向对方语言的原生 .xnb 纹理,保留各 base 的字形 metrics |
| 验证 | verify.py 九合一 |
Token 完整性、^ 分隔、对话安全、SMAPI 日志、mail 格式、节日名称、parser 分配、CookingChannel 配方名去重、#$1 重复前缀 |
-
Special Orders/Crop 任务
{Crop:Text}token —Strings/SpecialOrderStrings中的{Crop:Text}、{FishType:Text}、{Monster:LocalizedName}等是游戏运行时 token,Content Patcher 无法控制其解析行为。双语格式中 EN/ZH 两侧的 token 会解析为同一值(当前语言对应的作物/物品名),导致句内混用(如 "Harvest 100 芋头 / 收获 100 份芋头")。 -
海盗的任务动态文本 —
ItemDeliveryQuest的任务目标由 C# 代码("Looking for " + npcName + "'s " + itemName)在运行时拼接,不会经过 Content Patcher 的数据流。修复需要 Harmony C# 补丁。
- 动态格式字符串的双语重复 — 841 个 key 含
{0}{1}等string.Format占位符。当占位符对应的参数本身也是双语文本(如季节名Summer / 夏季、物品名Parsnip / 防风草),string.Format将双语参数同时代入模板的 EN 半段和 ZH 半段,产生嵌套双语。这是 Content Patcher 架构的固有局限 — 无法控制运行时string.Format的参数代入。影响轻微(文字冗余但不丢失信息),需 C# Harmony 补丁彻底修复。 - 字幕 (Strings/credits)(v2.4.0 已修复) — 历史版本数据格式为
List<string>,导出器仅支持字典格式,故字幕未覆盖。v2.4.0 起 AssetExporter 增加List<string>导出分支,builder 用 CPEditData以字符串为 key 编辑列表:标题行双语,人名/URL/图片行保持原样。 - Tent 剧情事件 — 游戏官方数据
Data/Events/Tent与Data/Events/IslandFarmHouse均为空字典(1.6.15),该位置无剧情事件,非导出缺陷,无法补全。 - 节日 NPC 缺失少量对话 key —
Dwarf_y2、Sandy_y2、Event.cs.1862在部分节日中无官方中文翻译(数据源限制)。安装贴吧汉化修正后重新导出即可补全。 - 日中字体中共享汉字的字形风格(v2 现状) — CP
Load一个Target只能指向一个FromFile,故ja:zh共享 CJK 汉字固定使用中文字形(简化笔画形态),不区分游戏语言。若需日文字形,需 C# Mod 按 SMAPI 令牌切换字体实例。 - 电视烹饪频道菜名前缀重复(v1.1 已修复) — 历史版本
Data/TV/CookingChannel的RecipeName/Dialogue格式导致菜名在双语两侧重复出现。 $y快速问答仅显示英文(v1.1 已修复) — 历史版本bilingualize_pair将$y 'EN'和$y 'ZH'简单拼接,游戏只处理第一个$y块。现改为按_分割后逐段双语配对,修复全部 14 处$y文本。$q/$r问答仅显示英文(v1.2 已修复) — 历史版本Data/ExtraDialogue中 5 条 Morris 对话含$q/$rQ&A 结构,EN/ZH 两侧各有一套命令。bilingualize_pair简单拼接后产生两套$q命令,游戏只处理第一个(英文)。现改为保留 EN 命令结构,仅双语化文本部分。#$1条件对话中文丢失(v1.2 已修复) — 14 条对话中#$1条件块使用#$e#而非$k/$0作为终结符(Abigail 周四、Caroline 多段对话等)。_bilingualize_d1_segment因找不到$k/$0返回 None,降级后产生两套#$1前缀,游戏只处理第一个。现改为无条件型$k/$0时以#$e#/#$b#/段尾为终止位置。- 对话分段模板误用导致部分页面仅显示单语(v1.3 已修复) —
StringsFromCSFiles、Strings/1_6_Strings、StringsFromMaps中含有#$b#/#$e#分段标记的文本(113 条)被误分配到 plain template parser(bilingualize_pair),导致 EN/ZH 两侧的#$b#段在游戏内交错穿插,部分对话页仅显示英文。现改为资产级is_dialogue分类 + 逐条目#$b#/#$e#自动检测双层防护,每条#$b#段独立双语化,每页都显示EN / ZH。 - 事件脚本值被对话解析器破坏(v2.2.1 已修复) —
Data/ExtraDialogue(SkullCavern_100_event、SummitEvent_Dialogue3_*)、Strings/Locations(Birdie 岛事件IslandSecret_Event_BirdieIntro/alreadyGotNuts等)、Strings/1_6_Strings(ForestPylonEvent)等对话型资产中存放了完整事件脚本(clubloop/.../speak MrQi "..."),被make_dialogue_bilingual/bilingualize_pair当作普通文本分段双语,EN/ZH 两侧脚本用/拼接导致引号失衡、speak文本中泄露clubloop/pause等原始命令,游戏事件解析失败后把残余命令当对话文本显示。现增加looks_like_event_script()检测(含/+ 事件命令 hint ≥2),命中条目改用make_event_bilingual保留命令结构、仅双语化speak/message引号内文本,共修复 17 条(9 ExtraDialogue + 7 Locations + 1 1_6_Strings)。 - 日中字体渲染缺失假名/繁体汉字(v2.0 已修复) — 历史版本未合并字体,游戏内只加载原字体的字形。v2 引入
merge_font.py(SpriteFont 双向合并)+merge_bmfont.py(BmFont 双向合并)+pack_xnb.py(Python XNB 打包,UTF-8 char + format=0 BGRA32),覆盖 Loading 文字、TV 字幕、信件、NPC 对话、技能悬浮框等所有字体路径。 - 选档界面保持单语显示(v2.5.0 已修复) — 历史版本把存档选择界面(
LoadGameMenu)的农场名/金钱/日期/季节名全部双语化,槽位高度由游戏代码固定,文本翻倍导致拥挤;日期模板中英语序不同(英Day X of Season, Year Y/ 中第 Y 年 Season X 日),双语化后占位符重组语义错乱。现这些键(LoadGameMenu.cs.10992-11023、Utility.cs.5678、Utility.cs.5680-5683)保持游戏当前语言单语显示。 - 对话框打字机效果(v2.5.0 起文档化,不可修复) — SDV 对话有逐字符打字机效果,双语文本长度翻倍导致第二语言(英文)逐字显示较慢。打字机速度由游戏代码控制,Content Patcher 无法修改(游戏内也无相关设置,仅"打字音效"开关)。缓解方式:点击对话框即可跳过打字机效果,直接显示全文。
字体合并经历了多次修复迭代:
| 问题 | 表现 | 根因 | 修复 |
|---|---|---|---|
SpriteFont 加载错乱 |
ArgumentOutOfRangeException |
xnbcli stub 的 dxt-js 把 raw BGRA 当 DXT3 压缩数据 | pack_xnb.py 写 format=0 未压缩 BGRA32 |
Character map must be in ascending order(初次) |
SpriteFont 构造越界 | merge_font.py 漏合并 kerning 列表 |
补齐 kerning 数据 |
Character map must be in ascending order(二次) |
仍越界 | 假名追加在 CJK 汉字之后,违反升序 | 合并后按 code point 排序所有四表 |
Character map must be in ascending order(三次) |
仍越界 | xnbcli 写 char 为 UTF-8,FNA 读为 7-bit 编码整数,CJK 字节被错误合并 | 用 pack_xnb.py 替代 xnbcli,保持原始 UTF-8 char 写法(与原版 XNB 一致) |
Loading / TV / 信件 仍显示 * |
仅 SpriteFont 部分修好 | 漏掉 BmFont 系统的合并 | 新增 merge_bmfont.py,双向合并 XML + 扩展纹理页 |
开发方向、玩家需求分析、技术债与优先级见 docs/roadmap.md。
当前阶段(v2.2.0 工程加固)已完成的重点:
- CI 接入自动化验证 — push/PR 自动运行 pytest 与 verify.py 全部检查,tag 发布前强制通过
- 字体脚本路径参数化 —
merge_font.py/merge_bmfont.py/pack_xnb.py支持--tmp-dir/--out-dir,不再硬编码本机路径 - build.ps1 重写 — UTF-8(BOM) 编码、路径参数化(
-ModTarget/-GameDir)、新增-Fonts(字体合并)/-Export(重新导出)/-Test(全量测试)开关 - 导出数据版本追踪 —
_export/manifest.json记录游戏版本与导出时间,游戏更新后便于发现数据过时
MIT



