导入器与导出器

两个 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 可直接用于报告

行为要点

行为说明
校验失败返回 falseOutIssues 含全部 issue,OutErrorThe 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.manifestcliff-game
文件路径<OutputDirectory>/<Culture>/<Clan>.cliff
数据来源manifest + 各 culture archive;ExportFromLocResFile 直接读 .locres(源文本靠 manifest 补齐)
源语言 culture不写 targetstatusinitial(避免把混合语种源文当译文)
自校验序列化结果立即经 ParseAndValidateHasErrors → 返回 false
侧车bWriteSidecar && !OutputDirectory.IsEmpty() 时写 <Manifest 基础名>.cliffmap.json
告警无 type 规则 / 无 clan 映射都会累加 WarningCount 并打日志

相关阅读