UE5 插件开发:C++ Tooltip 本地化失效的避坑指南

UE5 插件开发:C++ Tooltip 本地化失效的避坑指南

在进行 UE 插件开发时,我们通常会为 UPROPERTY 编写注释,期望这些注释能作为 Tooltip 在编辑器中显示,并支持多语言本地化。但在实际操作中,经常会遇到翻译失效的问题。

问题现象

当你完成了以下步骤:

  1. 代码注释: 编写了 /** My Tooltip with \n Newline */
  2. 文本收集: 成功 Gather 到了对应的 SourceString。
  3. 完成翻译: 在 PO 文件中填好了对应的中文并编译为 LocRes。

却发现编辑器里悬停显示的依然是旧的英文,甚至当你删除了代码中的注释,编辑器里依然顽固地显示着之前的旧文本。

这种情况通常不是缓存的问题,而是掉进了 UE 本地化中最隐蔽的陷阱:UHT 元数据持久化 (Metadata Persistence)


原因分析

UE 的 Tooltip 并非在运行时直接读取代码注释,其真实流程如下:

  1. 编译期 (UHT): Unreal Header Tool 解析 .h 文件。它读取注释并将其转换为一个字符串常量,作为 MetaData 烧录进生成的 .gen.cpp 文件中,最终编译进二进制。
  2. 运行期 (Editor): 编辑器通过反射系统 (FProperty::GetToolTipText) 获取这个硬编码在二进制里的 SourceString
  3. 查字典: 编辑器拿着这个 SourceString 去 LocRes 里寻找匹配的翻译。

核心症结:SourceString 的不确定性

UHT 在处理注释时非常不透明:

  • 它可能会将 /** A \n B */ 解析为 "A\nB",也可能解析为 "A B"
  • 解析结果受操作系统换行符(CRLF/LF)和缩进的影响。

导致失效的典型场景:

  1. 最初写的注释生成的 Key A 被烧录进了二进制。
  2. 你发现翻译不对,修改了注释,UHT 生成了 Key B。
  3. 由于增量编译或构建缓存的原因,二进制文件没有彻底更新,或者 UHT 认为该 .h 无需重新处理。
  4. 结果是:LocRes 里存的是 Key B 的翻译,但二进制里残留的依然是 Key A。 由于 SourceString 不匹配,翻译永远无法生效。

解决方案:显式元数据 (Explicit Meta)

与其去猜测 UHT 会如何解析注释,不如直接接管这个过程。

最佳实践:对于必须本地化的编辑器属性,不要依赖注释,直接使用显式元数据。

修改方式

1
2
3
4
5
6
7
8
9
10
11
// ❌ 依赖注释(不推荐)
/**
* The Enhanced Input Action.
* Triggers the attack.
*/
UPROPERTY(EditAnywhere)
UInputAction* InputAction;

// ✅ 显式覆盖(推荐)
UPROPERTY(EditAnywhere, meta=(ToolTip="The Enhanced Input Action. Triggers the attack."))
UInputAction* InputAction;

为什么这样做有效?

  1. 跳过不确定解析: meta=(ToolTip="...") 是直接赋值。UHT 不会对其进行任何“智能化”处理,你写什么,二进制里就是什么。
  2. 跨平台一致性: 无论什么操作系统或 IDE,这个字符串在二进制层面上是绝对一致的。
  3. 强制 UHT 更新: 修改 meta 会明确告知 UHT 文件已变更,从而确保重新编译并刷新二进制中的元数据。

结语

如果你遇到了“代码改了、翻译更新了,但编辑器死活不认”的本地化难题,请尝试以下操作:

  1. 放弃依赖注释: 在对应的 UPROPERTY 中添加 meta=(ToolTip="你的文本")
  2. 手动强制更新: 如果可能,清理并重新编译项目,确保二进制中的 SourceString 被刷新。
  3. 重新收集文本: 运行一次新的 Gather Text 流程。

这通常是解决 UE Tooltip 本地化顽疾最稳妥、最高效的方法。