基于 UAssetAPI 的 UE LocRes(本地化资源)读取 / 回写库。
解析逻辑参考 CUE4Parse 的 FTextLocalizationResource,读写全部使用
UAssetAPI 的 UE 类型(UnrealBinaryReader / UnrealBinaryWriter / FString)。
- 支持全部 LocRes 版本:
Legacy(v0)/Compact(v1)/Optimized_CRC32(v2)/Optimized_CityHash64_UTF16(v3) - 读取后保留原 hash / LUT 引用计数,未修改的内容写回与原文件逐字节一致
- 提供便捷索引器
file[namespace, key]读取与修改翻译 - 基于 UAssetAPI 的 UE 类型做二进制读写,无其它运行时依赖
已用 KARDS
Game.locres(zh-Hans,v3,60 命名空间 / 13471 条目)实测: 读取 → 回写 → 再读取,全部条目一致,且回写文件与原文件 1 909 867 字节逐字节相同。
# 库
cd ULocres && dotnet build
# Demo(读取 → 回写 → 读回校验)
cd ULocres.Demo
dotnet run -- "Game.locres" ["输出.locres"] [--dump]using ULocres;
// 读取
var file = LocResFile.Load(@"Content\Localization\Game\zh-Hans\Game.locres");
Console.WriteLine($"version={file.Version} namespaces={file.Namespaces.Count} entries={file.TotalEntries}");
// 查询(不存在返回 null)
string? text = file["Card", "oc_3_title"];
// 修改已有翻译(key 不变 → 原 hash 保留,写回仍兼容 v3)
file["Card", "oc_3_title"] = "新翻译";
// 新增条目
file["NewNamespace", "new_key"] = "hello";
file.Save("Game.patched.locres"); // 沿用读入版本 v3
file.Save("Game_v2.locres", ELocResVersion.Optimized_CRC32); // 或指定版本var file = new LocResFile { Version = ELocResVersion.Optimized_CRC32 };
file["Achievements", "first_win"] = "首胜!";
file.Save("out.locres");LocRes v2/v3 会对 namespace 与 key 做预哈希以加速查找。库完全对齐 UE 实现:
- 保留原 key:写回沿用读入时的 hash,逐字节一致。
- 新增 / 改名 key(v2 或 v3 均支持):
- v3(
Optimized_CityHash64_UTF16):内置CityHash.HashStringUtf16—— 逐行移植 UECityHash.cpp(v1.1 后端,含 bswap 版HashLen33to64), 结果按 UETextKeyUtil::HashString折叠(u32)low + (u32)high * 23。空串按 UE 行为返回 0。 - v2(
Optimized_CRC32):LocResFile.StrCrc32(对齐 UEFCrc::StrCrc32逐 UTF-16 字符低 8 位)。
- v3(
已用 KARDS
Game.locres的 13 471 组 (namespace, key, 读入 hash) 全量实测验证: 每个 hash 均与CityHash.HashStringUtf16一致;新增条目写回后再读回也全部一致(61/61 namespace、13 474/13 474 key)。
LocResFile
├─ Version ELocResVersion(读写版本,新建默认 v2)
├─ Namespaces List<LocResNamespace>
│ ├─ Name / NameHash / NameHashKnown
│ └─ Entries List<LocResEntry>
│ ├─ Key / KeyHash / KeyHashKnown
│ ├─ SourceStringHash 源字符串哈希(原样回写)
│ └─ LocalizedString 本地化文本
FString 即 UAssetAPI.UnrealTypes.FString;TotalEntries 为条目总数。
[FGuid magic 16B + u8 version] (Legacy 无此头)
[Compact+: i64 LUT offset → u32 count + (FString text [+ i32 refCount])]
[v2+: u32 entriesTotal](读端跳过)
u32 namespaceCount
每 namespace: [v2+: u32 nsHash] FString name, u32 keyCount
每 key: [v2+: u32 keyHash] FString key, u32 sourceHash,
Compact+: i32 lutIndex | Legacy: FString 内联
- .NET 10
- UAssetAPI 1.1.0(NuGet)