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
UnknownorRegistered→ unvisited; - unsuppressed
ErrororFatalfinding → 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:
Translations Approval MatrixVisual QA Matrix & GeometryVoice Coverage & RevisionsSubtitle 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; TimestampTicksis 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.
BlockOnGlossaryViolationsis inert.