Release Gate API

Deterministic evaluation in one call

var report = new ReleaseGateEvaluator().Evaluate(workspace, policy);

No editor window, no asset writes, no network. The evaluator reads the workspace and returns a serializable report.


Signature

public ReleaseGateReport Evaluate(
    ReleaseWorkspace workspace,
    GatePolicy policy = null)

A null policy becomes new GatePolicy() — all booleans true.

public string GenerateHtmlReport(
    ReleaseWorkspace workspace, ReleaseGateReport report)

public string GenerateJsonReport(
    ReleaseWorkspace workspace, ReleaseGateReport report)

Both return strings. Writing files is the caller’s job.


Policy

public class GatePolicy
{
    public bool RequireAllLocalesApproved = true;
    public bool BlockOnStaleTranslations = true;
    public bool BlockOnMissingTranslations = true;
    public bool BlockOnUnvisitedCaptures = true;
    public bool BlockOnVisualErrors = true;
    public bool BlockOnStaleVoiceClips = true;
    public bool BlockOnSubtitleTimingErrors = true;
    public bool BlockOnGlossaryViolations = true; // not read
}

To make a check non-blocking, set its boolean to false. Note that unapprovedCount is only consulted when RequireAllLocalesApproved is true; missing and stale have their own switches.


The four checks

Translations Approval Matrix

Iterates every SourceRevisions × TargetLocales:

  • missing approval or Missing → missing;
  • Stale → stale;
  • any other non-Approved → unapproved.

Pass:

(RequireAllLocalesApproved ? unapproved == 0 : true) &&
(BlockOnMissingTranslations ? missing == 0 : true) &&
(BlockOnStaleTranslations ? stale == 0 : true)

Visual QA Matrix & Geometry

For each CaptureTileResult:

  • coverage Unknown or Registered → unvisited;
  • unsuppressed Error or Fatal finding → error.

Pass:

(BlockOnUnvisitedCaptures ? unvisited == 0 : true) &&
(BlockOnVisualErrors ? errors == 0 : true)

Voice Coverage & Revisions

Counts voice entries with IsStale. Pass:

BlockOnStaleVoiceClips ? stale == 0 : true

Subtitle Timing & Reading Speed

For each cue:

  • invalid timing → violation;
  • else CPS > workspace.Subtitles.MaxCharactersPerSecond → violation.

Pass:

BlockOnSubtitleTimingErrors ? violations == 0 : true

Verdict

bool allPassed = approval.Passed && visual.Passed && voice.Passed && subtitle.Passed;
int defectFailures = visualErrors + staleTranslations + staleVoices + timingViolations;
int incompleteFailures = unvisitedTiles + missingTranslations;

if (allPassed) Passed;
else if (defectFailures > 0) Failed;
else if (incompleteFailures > 0 || unapprovedCount > 0) IncompleteCoverage;
else Failed;

The final else is unreachable in practice: if all checks passed the first branch wins; if not and there are no defects or incomplete counts, a check failed for another reason (for example unapproved cells with RequireAllLocalesApproved = false but a disabled blocking switch) and the report says Failed.


Report shape

public class ReleaseGateReport
{
    public string ReportId;        // GUID N
    public string ReleaseVersion;
    public GateStatus OverallStatus;
    public long TimestampTicks;    // UTC
    public List<GateCheckItem> Checks;
}

Exactly four checks are added, in this order:

  1. Translations Approval Matrix
  2. Visual QA Matrix & Geometry
  3. Voice Coverage & Revisions
  4. Subtitle Timing & Reading Speed

Each has Passed, a human-readable Details line, and a Violations list.


HTML

GenerateHtmlReport:

  • dark inline CSS;
  • release version, source locale, UTC timestamp, verdict, passed/total;
  • one card per check;
  • violation text escaped with SecurityElement.Escape;
  • no external assets or scripts.

It is safe to open offline. It is not a template system; branding is fixed.

JSON

GenerateJsonReport is JsonUtility.ToJson(report, true).

Remember:

  • enums serialize as integers;
  • computed properties (TotalChecks, PassedChecks) are absent;
  • TimestampTicks is a long, not an ISO date.

Example consumer:

var report = JsonUtility.FromJson<ReleaseGateReport>(json);
DateTime utc = new DateTime(report.TimestampTicks, DateTimeKind.Utc);

Writing files

The Release Gate window writes next to the project:

LocalizeShip_Report_v<ReleaseVersion>.html
LocalizeShip_Report_v<ReleaseVersion>.json

Your own script can choose any path:

var evaluator = new ReleaseGateEvaluator();
var report = evaluator.Evaluate(workspace);
File.WriteAllText("Build/gate.json", evaluator.GenerateJsonReport(workspace, report));
File.WriteAllText("Build/gate.html", evaluator.GenerateHtmlReport(workspace, report));

Both generators are public instance methods on the evaluator — useful for CI.


Limits

  • No text-rule, glossary, merge-state or duration-mismatch checks.
  • No per-locale policy.
  • No baseline comparison; see Release Comparison.
  • No player-build validation.
  • BlockOnGlossaryViolations is inert.


Copyright © 2026 DecNet Games. All rights reserved. LocalizeShip is a commercial Unity Asset.

This site uses Just the Docs, a documentation theme for Jekyll.