# 火山 Stage6 / ExpressSystem 本地化方案 ## 当前决策 ExpressSystem 的玩家可见玩法文字统一通过 `l10n.*` 引用,并以 Unity Localization 的 `Params` String Table Collection 作为唯一数据源。 - `l10n.xxx` 查询 `Params/xxx`。 - 查询使用 `DontUseFallback`,不回退中文或其他 Locale。 - 中文表保存源数据;其他 Locale 表保留同一套 Key,未翻译值留空。 - Key 不存在时返回 `⟦key⟧` 并记录包含 Table、Key、Locale 的错误。 - Express 必填值解析为空或缺失标记时安全终止命令,不启动粒子或释放演出。 - `StreamingAssets/Config/params.csv` 已退出运行链路。 - 固定 UI 继续使用 `UIText`;普通 Yarn 对白、Task、教学和角色名不迁入 `Params`。 ## 轮次配置 三轮正式内容由 `ExpressionContentCatalog` 管理,场景中的 `ExpressionManager` 持有 Catalog 引用: | Round ID | Target | Tokens | 非目标粒子数 | |---|---|---|---:| | `log1` | `l10n.hs.exp.log1.target` | `l10n.hs.exp.log1.tokens` | 16 | | `log2` | `l10n.hs.exp.log2.target` | `l10n.hs.exp.log2.tokens` | 28 | | `log3` | `l10n.hs.exp.log3.target` | `l10n.hs.exp.log3.tokens` | 38 | Round ID 大小写敏感;重复 ID、未知 ID、空引用、非 `l10n.*` 引用或解析 后的空值均视为数据错误。 正式 Yarn 使用: ```yarn <> ``` 旧 `start_expression` 继续兼容原始字符串,也允许将前两个参数写为 `l10n.*`。`completionNode`、`memoryKey`、`preset`、颜色、Timeline 名称及 数值参数均为结构参数,不做本地化解析。 ## Locale 生命周期 启动轮次时捕获当前 Locale,目标句、token 和 `l10n.hs.exp.pool` 并行解析; 校验通过后才初始化粒子系统。该 Locale 快照会保留到下一轮开始或 ExpressSystem 关闭,当前轮 后续释放演出都使用同一快照。没有活动轮次时,演出命令使用命令调用时的 当前 Locale。 这可避免切换语言时旧异步请求覆盖新一轮内容。`PunchTapeItem` 也通过请求 版本号避免旧名称刷新覆盖新 Locale。 ## Key 约定 Express 使用短前缀 `hs.exp.*`: - 三轮目标和 token:`hs.exp.log{1..3}.target`、`.tokens` - LOG3 攻击词:`hs.exp.atk.*` - 最终稳定文字:`hs.exp.final.win` - 全局随机字符池:`hs.exp.pool` 重复演出复用同一 Key,但 Yarn 中仍保留原有调用次数、等待、数值、顺序和 `#line:` 标签。 ## token 与粒子单位 干扰 token 只接受半角 `|`: - 按 `|` 拆分; - Trim 并删除空项; - 全空时中止轮次; - 全角 `|` 是数据错误。 `ExpressionParticleLanguageProfile` 决定当前 Locale 的粒子单位: - `zh-Hans`、`ja-JP` 使用 `Grapheme`,通过 `StringInfo` 按 Unicode 文本元素 切分;空白不生成粒子,但最终排列保留间距; - `en`、`es`、`ru`、`pt-BR` 使用 `Word`,按 Unicode 空白切分并折叠连续 空白;撇号、连字符和标点留在词内; - Locale 先完整匹配,再按语言前缀匹配;未知 Locale 警告一次并回退 `Grapheme`。 目标句、token、`hs.exp.pool` 在 Yarn 命令入口一次性解析为 `ExpressionRoundTextSnapshot`。目标粒子数量、最终排列、攻击词长度校验、 truth leak 和老虎机覆盖池都使用同一份快照或同一 Unit Mode,不会在 Manager 内再次按字母拆分。切换全局 Locale 不会改变进行中的轮次快照。 `hs.exp.pool` 仍禁止 `|` 和全角 `|`。Grapheme 模式使用连续文本,Word 模式 使用空白分隔单词;两种模式都保留重复项作为随机权重。目标粒子从该池取单位, 非目标和背景浮动粒子从本轮 token 展开的干扰池取单位;临时老虎机池结束后按 粒子角色恢复。 Word Profile 还会缩小三类字号、降低非目标粒子数量,并启用宽度感知排版、 字形边缘连接、Bounds 分离、屏幕边界和鼠标命中。全屏 Actor 故障/老虎机演出 仍保持原来的字符级视觉。 ## 内容校验 编辑器校验覆盖: - Stage6 正式 Express 文字参数不得残留中文硬编码; - Yarn 和 Catalog 中引用的 `l10n.*` Key 必须存在于 `Params` Shared Data; - Profile Locale Code 必须唯一,所有支持 Locale 必须可解析; - 中文值必须非空; - 未翻译 Locale 的空值只报告待翻译,不导致校验失败; - 每个非空 Locale 的目标文字和 `.tokens` 必须按该 Locale 模式得到有效单位, `.tokens` 不能使用全角 `|`; - `hs.exp.pool` 必须存在于所有 Params Locale 表;中文非空,非空译文不得 包含 `|`、`|` 或只有空白,并按 Locale 模式验证; - completion node、preset、memory key、颜色、Timeline 等结构参数不误报。 EditMode 与 PlayMode 测试覆盖原始字符串、空值不回退、缺 Key 占位、显式 Locale、轮次配置、Locale/Profile 解析、Word/Grapheme 切分、快照、粒子 数量倍率,以及真实粒子组件的 Bounds 命中和字形边缘连接行为。