Runtime 模块概述
CliffLocalizationSuite(Type: Runtime,LoadingPhase: Default)是纯数据与算法模块:CLIFF 1.0 的解析、校验、序列化、语义映射与插件设置都住在这里。它不依赖 UnrealEd / AssetTools / Slate,可以在 Game 目标、命令行工具甚至单元测试中直接使用。
依赖
PublicDependencyModuleNames: Core, CoreUObject, Engine, DeveloperSettings
PrivateDependencyModuleNames: (空)
提供什么
| 类型 | 文件 | 职责 |
|---|---|---|
FCliffDocument | Public/Cliff/CliffDocument.h | 解析入口与文档根对象 |
FCliffHeader / FCliffGroup / FCliffEntry | 同上 | CLIFF 数据模型(header / 分组 / 条目) |
FCliffValidationIssue / ECliffValidationCategory | 同上 | 校验问题与 7 类分类 |
FCliffSemanticMapping | Public/Cliff/CliffSemanticMapping.h | clan ↔ UE Namespace、type / emotion 规则 |
FCliffSerializer | Public/Cliff/CliffSerializer.h | 规范化 CLIFF 1.0 序列化 |
UCliffLocalizationSuiteSettings | Public/Settings/CliffLocalizationSuiteSettings.h | Project Settings 与生效映射 |
ECliffDeepSeekThinkingLevel | 同上 | 思考强度枚举(配置用) |
典型用法
解析并校验
#include "Cliff/CliffDocument.h"
const FString Text = FFileHelper::LoadFileToString(CliffFilePath);
FCliffDocument Document;
TArray<FCliffValidationIssue> Issues;
// 传路径可额外做「文件名/目录 ↔ header」布局一致性检查
const bool bOk = FCliffDocument::ParseAndValidate(Text, CliffFilePath, Document, Issues, /*bCheckWidth=*/false);
if (!bOk)
{
for (const FCliffValidationIssue& Issue : Issues)
{
if (Issue.IsError())
{
UE_LOG(LogTemp, Error, TEXT("line %d [%d] %s"), Issue.Line, static_cast<int32>(Issue.Category), *Issue.Message);
}
}
return;
}
遍历条目并生成规范 ID
for (const FCliffGroup& Group : Document.Groups)
{
for (const FCliffEntry& Entry : Group.Entries)
{
const FString CanonicalId = Document.GetCanonicalId(Group, Entry); // namespace.clan.group.entry
const FString Source = Entry.Source.Get(TEXT(""));
const FString Type = Entry.Type.IsSet() ? Entry.Type.GetValue() : Group.Type.GetValue();
const FString Status = Entry.Status.Get(TEXT("initial"));
// …
}
}
语义映射
#include "Settings/CliffLocalizationSuiteSettings.h"
const UCliffLocalizationSuiteSettings* Settings = GetDefault<UCliffLocalizationSuiteSettings>();
const FCliffSemanticMapping Mapping = Settings->GetSemanticMapping();
bool bExplicit = false;
const FString UENamespace = Mapping.ResolveNamespace(TEXT("category"), &bExplicit); // UObjectCategory
const FString Clan = Mapping.ResolveClanFromNamespace(TEXT("UObjectToolTips"), &bExplicit); // tooltip
const FString Type = Mapping.ResolveTypeForNamespace(TEXT("Dialogue")); // dialogue
const FString Emotion = Mapping.ResolveEmotionForNamespace(TEXT("Dialogue"));// neutral
序列化
#include "Cliff/CliffSerializer.h"
const FString CanonicalText = FCliffSerializer::Serialize(Document); // UTF-8 无 BOM、LF 由调用方写盘时决定
FFileHelper::SaveStringToFile(CanonicalText, *OutPath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM);
从零构造文档并导出
FCliffDocument Document;
Document.Header.Namespace = TEXT("my-game");
Document.Header.Clan = TEXT("ui");
Document.Header.SourceLanguage = TEXT("en-US");
Document.Header.TargetLanguage = TEXT("zh-Hans");
FCliffGroup& Group = Document.Groups.AddDefaulted_GetRef();
Group.Path = TEXT("options");
FCliffEntry& Entry = Group.Entries.AddDefaulted_GetRef();
Entry.Id = TEXT("resolution");
Entry.Source = TEXT("Resolution");
Entry.Target = TEXT("分辨率");
Entry.Type = TEXT("noun");
Entry.Status = TEXT("final");
NOTE
模型层不做词表校验——构造出非法字段后调用
Document.Validate()才会报出vocabulary类问题。写盘前建议总是跑一次ParseAndValidate。
注意事项
| 事项 | 说明 |
|---|---|
| 线程 | 所有类型都是纯值类型/无状态工具,可在任意线程构造与解析;但 UCliffLocalizationSuiteSettings::Get() 属于 UObject,只能在游戏线程访问 |
| 大文件 | 解析是整个文本一次性处理(无流式 API);超大文件请自行分片 |
| 注释保留 | 解析器不在数据模型中保留注释(与 CLIFF 规范一致),只有导出器主动写入的文件头注释会在序列化时带出 |
| 编码 | 输入允许 BOM(会被剥离)、CRLF(视为 LF);裸 CR 视为语法错误;序列化输出应使用 ForceUTF8WithoutBOM |
x- 扩展 | 保留在 Extensions 映射中,校验时归为 extension 类,不计失败 |
下一步
- Runtime 类参考 —— 全部字段与方法签名
- 导入器与导出器 —— Editor 模块 API