Lesson 209: Cross-Engine Localization Receipt Columns on BUILD_RECEIPT (2026)

Direct answer: Studios shipping Unity RPG and Ren'Py VN SKUs from one Weblate project need two receipt schemas on one BUILD_RECEIPT row—not merged JSON. This lesson ships localization_receipt_matrix_v1.json with M1–M6 gates so Lesson 202 string_table_receipt and language_receipt_v1 stay separate but Thursday row review treats them as one promotion decision.

Lesson hero for cross-engine localization receipt matrix on BUILD_RECEIPT

Why this matters now (October 2026 mixed portfolios)

October 2026 fest teams run CN/JP store capsules from Weblate while the Unity demo shows raw UI_* keys and the Ren'Py build menus stay English-only—different engines, same producer panic. Lesson 202 owns Unity string_table_receipt; after Addressables strip PRs add Lesson 219 addressables_fest_string_table_receipt; the Ren'Py evening pipeline owns language_receipt—this lesson is the portfolio milestone wiring both columns on BUILD_RECEIPT.

Beginner path (45-minute matrix pass)

Step Action Success check
1 List SKUs in fest scope Unity exe + Ren'Py build IDs
2 Pass engine-specific smokes 202 GREEN + language_receipt GREEN
3 Verify store locale list matches both builds Same fest_locales[]
4 Write localization_receipt_matrix_v1.json Both engines pass: true
5 Patch BUILD_RECEIPT template Two columns, one row
6 Run Thursday row review Matrix + store parity

Time: ~45 minutes when both receipts exist; 72 minutes first mixed portfolio setup.

Developer path (gates M1–M6)

Gate Check Fail when
M1 string_freeze_receipt conflict-free Weblate merge blocked
M2 Unity string_table_receipt_v1 pass Raw keys in installed player
M3 Ren'Py language_receipt_v1 pass Selector missing fest locales
M4 fest_locales aligned across SKUs Store lists CN, Unity build EN-only
M5 Matrix references correct receipt paths Wrong schema mixed into one file
M6 BUILD_RECEIPT row + Thursday review Any M1–M5 red

Receipt schema separation (do not merge)

Engine Receipt file BUILD_RECEIPT column
Unity string_table_receipt_v1.json string_table_receipt
Ren'Py language_receipt_v1.json language_receipt
Ren'Py (hash audit) po_hash_language_receipt_v1.json po_hash_language (optional; see PO-hash preflight)
Portfolio localization_receipt_matrix_v1.json localization_matrix

Anti-pattern: Pasting Ren'Py gates.L3_selector_ui into Unity JSON—breaks CI validators.

localization_receipt_matrix_v1.json

{
  "schema": "localization_receipt_matrix_v1",
  "build_label": "fest-portfolio-2026-10-rc2",
  "fest_locales": ["en", "ja", "zh-Hans"],
  "engines": {
    "unity_rpg_demo": {
      "receipt_schema": "string_table_receipt_v1",
      "receipt_path": "release-evidence/localization/unity/STRING_TABLE_RECEIPT.json",
      "pass": true,
      "boot_locale_smoke": "ja"
    },
    "renpy_vn_demo": {
      "receipt_schema": "language_receipt_v1",
      "receipt_path": "release-evidence/localization/renpy/LANGUAGE_RECEIPT.json",
      "pass": true,
      "store_parity": true
    }
  },
  "gates": {
    "M1_string_freeze": "pass",
    "M2_unity_string_table": "pass",
    "M3_renpy_language": "pass",
    "M4_locale_alignment": "pass",
    "M5_schema_separation": "pass",
    "M6_matrix_committed": "pass"
  },
  "promotion_allowed": true
}

Pin under release-evidence/localization/LOCALIZATION_RECEIPT_MATRIX.json.

BUILD_RECEIPT row template (one upload, two proofs)

Column Unity RPG demo Ren'Py VN demo
string_table_receipt path or verified n/a
language_receipt n/a path or verified
localization_matrix matrix path matrix path
fest_locales ja,zh-Hans same array
store_capsule_locales must match fest_locales must match

Thursday row review adds one line: matrix promotion_allowed before fest branch merge.

Publish gate

ALTER TABLE release_publish_gate ADD COLUMN IF NOT EXISTS
  localization_matrix_blocked BOOLEAN NOT NULL DEFAULT false;

CI verify_localization_receipt_matrix_v1 requires:

  • engines.*.pass === true for every SKU in fest_scope
  • fest_locales identical across engine entries
  • Referenced receipt files exist and validate against schema

Prerequisites

Common mistakes

  • One Weblate export, zero Ren'Py renpy.compile_all() — PO green, game English.
  • Unity Editor screenshots while Ren'Py installed build is wrong locale.
  • Merging receipts into a single JSON blob—breaks per-engine CI.
  • Promoting Unity when only VN language_receipt passed.

Troubleshooting

Symptom Lane
Unity keys, VN OK Lesson 202 L3–L5
VN English, Unity OK Ren'Py preflight
Store CN, both builds EN M4 store parity — regen screenshots from installed builds
Matrix pass, promotion blocked Check string_freeze_receipt M1

Mini exercise (60 minutes)

  1. Pass Lesson 202 smoke on Unity SKU.
  2. File language_receipt_v1.json on Ren'Py SKU from blog pipeline.
  3. Intentionally mismatch fest_locales — confirm M4 fails.
  4. Write matrix JSON with both paths.
  5. Add BUILD_RECEIPT row; run Thursday checklist.

Continuity

FAQ

Single-engine studio?
Skip matrix—use Lesson 202 or Ren'Py blog only. Matrix is for two receipts, one producer gate.

Same Weblate project, different components?
Map weblate_export_manifest per component; matrix rows reference each receipt path.

HTML5 Construct demo localized?
Out of scope—this lesson is Unity + Ren'Py receipt columns; itch HTML5 uses separate store copy checks.


Weblate proves PO once—your matrix proves each engine's player build before October promotion.