Importer and Exporter

Both APIs live in the module CliffLocalizationSuiteEditor (Type: Editor, export macro CLIFFLOCALIZATIONSUITEEDITOR_API) and are available in editor targets only.

IMPORTANT

These two entry points operate on the manifest / archive / .locres directly. For day-to-day use go through the official GatherText pipeline (the Dashboard buttons or CliffLocalizationSuite.Import/Export), which handles config generation, the subprocess, reports and live refresh automatically. Calling them directly suits toolchain integration and automated tests.

FCliffImporter

Settings struct

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;                             // 数值越小优先级越高
};

Stats struct

struct CLIFFLOCALIZATIONSUITEEDITOR_API FCliffImportStats
{
    int32 SourceCount = 0;
    int32 TranslationCount = 0;
    int32 WarningCount = 0;
    FString CompiledCulture;
    FString LocResFilePath;
    FString LocMetaFilePath;
};

Methods

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);
};

Example

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

Behaviour notes

BehaviourDescription
Validation failureReturns false, OutIssues holds every issue, and OutError is The CLIFF document is invalid; see the validation issues.
status: initialWrites the manifest only, no archive translation
Empty translation / self-translationWrite-back is refused (nothing is written when target is empty and the source is not in the target language); legacy empty translation entries are restored to the source text in place
Duplicate identityNo duplicate manifest context is added; the metadata is attached in place
Source-language importThe “effective source” of foreign archive entries is synchronised to the native translation automatically (the translation itself is untouched)
CompilationWith bCompileResources = true it generates .locmeta + the .locres for that culture and calls FTextLocalizationManager::UpdateFromLocalizationResource

FCliffExporter

Settings struct

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;
};

Output structs

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;
};

Methods

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);
};

Example

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

Behaviour notes

BehaviourDescription
Document splitOne document per culture; the header clan is the manifest stem kebab-cased (Game.manifestcliff-game)
File path<OutputDirectory>/<Culture>/<Clan>.cliff
Data sourceThe manifest plus each culture’s archive; ExportFromLocResFile reads a .locres directly (source text is filled in from the manifest)
Source language cultureNo target is written and status is set to initial (so that mixed-language source text is not mistaken for a translation)
Self-checkThe serialized result immediately goes through ParseAndValidate; HasErrors → returns false
Sidecar<manifest stem>.cliffmap.json is written when bWriteSidecar && !OutputDirectory.IsEmpty()
WarningsA missing type rule / missing clan mapping both increment WarningCount and log a line