导入器与导出器
两个 API 位于模块 CliffLocalizationSuiteEditor(Type: Editor,导出宏 CLIFFLOCALIZATIONSUITEEDITOR_API),仅在编辑器目标可用。
IMPORTANT
这两个入口直接操作 manifest / archive /
.locres。日常请走官方 GatherText 管线(Dashboard 按钮或CliffLocalizationSuite.Import/Export),它们会自动处理配置生成、子进程、报告与热刷新。直接调用适合工具链集成与自动化测试。
FCliffImporter
设置结构
struct CLIFFLOCALIZATIONSUITEEDITOR_API FCliffImportSettings
{
FString TargetPath; // 必需:Content/Localization/<Target>
FString ManifestName = TEXT("Game.manifest");
FString ArchiveName = TEXT("Game.archive");
FString NativeCulture; // 空则用 header 的 source-language
TArray<FString> ForeignCultures; // 空则用 header 的 target-language
FCliffSemanticMapping SemanticMapping = FCliffSemanticMapping::CreateDefault();
FString SidecarPath; // 可选:.cliffmap.json 路径
bool bCompileResources = true; // 直接编译 .locmeta/.locres 并热刷新
int32 LocResPriority = 0; // 数值越小优先级越高
};
统计结构
struct CLIFFLOCALIZATIONSUITEEDITOR_API FCliffImportStats
{
int32 SourceCount = 0;
int32 TranslationCount = 0;
int32 WarningCount = 0;
FString CompiledCulture;
FString LocResFilePath;
FString LocMetaFilePath;
};
方法
class CLIFFLOCALIZATIONSUITEEDITOR_API FCliffImporter
{
public:
static bool ImportFile(const FString& InCliffFilePath, const FCliffImportSettings& InSettings,
FCliffImportStats& OutStats, TArray<FCliffValidationIssue>& OutIssues, FText& OutError);
static bool ImportText(const FString& InCliffText, const FString& InCliffSourcePath,
const FCliffImportSettings& InSettings,
FCliffImportStats& OutStats, TArray<FCliffValidationIssue>& OutIssues, FText& OutError);
};
示例
FCliffImportSettings Settings;
Settings.TargetPath = FPaths::ProjectContentDir() / TEXT("Localization/Game");
Settings.NativeCulture = TEXT("zh-Hans");
Settings.ForeignCultures = { TEXT("en"), TEXT("ja") };
Settings.SemanticMapping = GetDefault<UCliffLocalizationSuiteSettings>()->GetSemanticMapping();
Settings.SidecarPath = TEXT("G:/Translations/cliff/Game.cliffmap.json");
FCliffImportStats Stats;
TArray<FCliffValidationIssue> Issues;
FText Error;
if (!FCliffImporter::ImportFile(TEXT("G:/Translations/cliff/ja/cliff-game.cliff"), Settings, Stats, Issues, Error))
{
UE_LOG(LogTemp, Error, TEXT("import failed: %s"), *Error.ToString());
}
// Stats.SourceCount / TranslationCount / WarningCount / LocResFilePath 可直接用于报告
行为要点
| 行为 | 说明 |
|---|---|
| 校验失败 | 返回 false,OutIssues 含全部 issue,OutError 为 The CLIFF document is invalid; see the validation issues. |
status: initial | 只写 manifest,不写 archive 译文 |
| 空译文 / 自翻译 | 拒绝写回(target 为空且源文不属目标语言时不写),历史空译文条目会就地恢复为源文本 |
| 重复 identity | 不新增重复 manifest context,元数据就地挂接 |
| 源语言导入 | 自动把外语 archive 条目的「生效源」同步为原生译文(译文不动) |
| 编译 | bCompileResources = true 时生成 .locmeta + 该 culture 的 .locres 并调用 FTextLocalizationManager::UpdateFromLocalizationResource |
FCliffExporter
设置结构
struct CLIFFLOCALIZATIONSUITEEDITOR_API FCliffExportSettings
{
FString TargetPath; // 必需
FString ManifestName = TEXT("Game.manifest");
FString ArchiveName = TEXT("Game.archive");
FString NativeCulture; // 空则从 <ManifestBase>.locmeta 推导
TArray<FString> Cultures; // 必需
FString CliffNamespace; // 空则用 manifest 基础名
FString SourceLanguage; // 空则用 NativeCulture
FString Standard; // 写入 header 的 standard
FCliffSemanticMapping SemanticMapping = FCliffSemanticMapping::CreateDefault();
FString OutputDirectory; // 空 = 不写盘
bool bWriteSidecar = true;
int32 LocResPriority = 0;
};
输出结构
struct CLIFFLOCALIZATIONSUITEEDITOR_API FCliffExportDocument
{
FString Clan; // 文件级 clan(manifest 基础名 kebab 化)
FString CliffText; // 序列化后的 CLIFF 文本
FString SuggestedFilePath; // <target-language>/<clan>.cliff
FString FilePath; // 实际写出的路径(OutputDirectory 为空时为空)
TArray<FCliffValidationIssue> Issues;
};
struct CLIFFLOCALIZATIONSUITEEDITOR_API FCliffExportStats
{
int32 DocumentCount = 0; // 每个 culture 一个文档
int32 EntryCount = 0;
int32 WarningCount = 0;
FString SidecarFilePath;
};
方法
class CLIFFLOCALIZATIONSUITEEDITOR_API FCliffExporter
{
public:
static bool ExportTarget(const FCliffExportSettings& InSettings,
TArray<FCliffExportDocument>& OutDocuments,
FCliffExportStats& OutStats, FText& OutError);
static bool ExportFromLocResFile(const FString& InLocResFilePath, const FString& InCulture,
const FCliffExportSettings& InSettings,
FCliffExportDocument& OutDocument,
FCliffExportStats& OutStats,
TArray<FCliffValidationIssue>& OutIssues, FText& OutError);
};
示例
FCliffExportSettings Settings;
Settings.TargetPath = FPaths::ProjectContentDir() / TEXT("Localization/Game");
Settings.NativeCulture = TEXT("zh-Hans");
Settings.Cultures = { TEXT("zh-Hans"), TEXT("en"), TEXT("ja") };
Settings.CliffNamespace = GetDefault<UCliffLocalizationSuiteSettings>()->CliffNamespace;
Settings.SemanticMapping = GetDefault<UCliffLocalizationSuiteSettings>()->GetSemanticMapping();
Settings.Standard = GetDefault<UCliffLocalizationSuiteSettings>()->TranslationStandard;
Settings.OutputDirectory = TEXT("G:/Translations/cliff");
TArray<FCliffExportDocument> Documents;
FCliffExportStats Stats;
FText Error;
if (!FCliffExporter::ExportTarget(Settings, Documents, Stats, Error))
{
UE_LOG(LogTemp, Error, TEXT("export failed: %s"), *Error.ToString());
}
// Stats.DocumentCount(= culture 数)、EntryCount、WarningCount、SidecarFilePath
行为要点
| 行为 | 说明 |
|---|---|
| 文档划分 | 每个 culture 一个文档;header clan = manifest 基础名 kebab 化(Game.manifest → cliff-game) |
| 文件路径 | <OutputDirectory>/<Culture>/<Clan>.cliff |
| 数据来源 | manifest + 各 culture archive;ExportFromLocResFile 直接读 .locres(源文本靠 manifest 补齐) |
| 源语言 culture | 不写 target,status 置 initial(避免把混合语种源文当译文) |
| 自校验 | 序列化结果立即经 ParseAndValidate;HasErrors → 返回 false |
| 侧车 | bWriteSidecar && !OutputDirectory.IsEmpty() 时写 <Manifest 基础名>.cliffmap.json |
| 告警 | 无 type 规则 / 无 clan 映射都会累加 WarningCount 并打日志 |
相关阅读
- 导入管线 / 导出管线 —— 逐步行为说明
- 原键侧车 —— 结构细节
- AI 翻译与命令let