Lesson 225: Ren'Py PO-Hash Language Receipt on BUILD_RECEIPT (2026)

Direct answer: When Weblate shows 100% but the Ren'Py selector stays English, file po_hash_language_receipt_v1.json proving export PO sha256 matches game/tl/ on the installed build, then set BUILD_RECEIPT column po_hash_language to verified—after Lesson 209 matrix wiring and the PO-hash preflight (H-gates). Distinct from language_receipt_v1 (L-gates UI) and .rpyc rebuild receipt (bytecode lane).

Lesson hero for Ren'Py PO-hash language receipt on BUILD_RECEIPT

Why this matters now (January 2027 storefront truth)

January 2027 Q1 recovery continues after Lesson 224 VOD rows. Visual-novel SKUs promote CN/JP/KR store capsules from Weblate freeze tooling while the fest build still boots English—producers blame translators when the installer packaged last week’s PO tree. Lesson 202 covers Unity; language_receipt covers selector UI; this lesson owns hash parity on BUILD_RECEIPT. Planned help #8 (selector stuck English) pairs copy-paste fixes.

Beginner path (hash audit evening)

Step Action Success check
1 Confirm language_map_v1.json Weblate preflight done
2 Build po_hash_manifest_v1.json sha256 per PO under game/tl/
3 Diff vs Weblate export manifest hash_mismatch_count: 0
4 Installed exe boot smoke One non-English line
5 File po_hash_language_receipt_v1.json selector_stuck_resolved: true
6 Update BUILD_RECEIPT + matrix po_hash_language GREEN

Time: ~25 min audit + 20 min rebuild if mismatch—65 minutes first fest SKU.

Developer path (gates H1–H6)

Gate Check Fail when
H1 language_map_v1.json linked Weblate preflight skipped
H2 po_hash_manifest_v1.json Missing sha256 for shipped locale
H3 Export ↔ installed parity Any hash_mismatch
H4 Preferences selector Missing mapped locale button
H5 Boot smoke (installed) English-only on CN-primary store
H6 BUILD_RECEIPT po_hash_language Column empty while store claims 3+ langs

Extend localization_receipt_matrix_v1.json

Add optional extension on the Ren'Py engine row (do not merge into Unity JSON):

{
  "renpy_vn_demo": {
    "receipt_schema": "language_receipt_v1",
    "receipt_path": "release-evidence/localization/renpy/LANGUAGE_RECEIPT.json",
    "extensions": {
      "po_hash_language_receipt": "release-evidence/localization/PO_HASH_LANGUAGE_RECEIPT.json"
    },
    "pass": true
  }
}

po_hash_language_receipt_v1.json

{
  "schema": "po_hash_language_receipt_v1",
  "build_label": "vn-fest-2027-01-12-rc1",
  "language_map_path": "release-evidence/localization/language_map_v1.json",
  "po_hash_manifest_path": "release-evidence/localization/po_hash_manifest_v1.json",
  "locales_shipped": ["english", "chinese", "japanese", "korean"],
  "hash_mismatch_count": 0,
  "selector_stuck_resolved": true,
  "paired_receipts": {
    "language_receipt": "release-evidence/localization/renpy/LANGUAGE_RECEIPT.json",
    "localization_matrix": "release-evidence/localization/LOCALIZATION_RECEIPT_MATRIX.json"
  },
  "gates": {
    "H1_language_map": "pass",
    "H2_po_manifest": "pass",
    "H3_hash_parity": "pass",
    "H4_preferences": "pass",
    "H5_boot_smoke": "pass",
    "H6_build_receipt": "pass"
  },
  "fest_promotion_allowed": true
}

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

BUILD_RECEIPT row (H6)

Column Pass when
language_receipt L-gates GREEN (Weblate preflight)
po_hash_language This receipt fest_promotion_allowed: true
localization_matrix Lesson 209 matrix path
fest_locales Matches store capsule languages
ALTER TABLE release_publish_gate ADD COLUMN IF NOT EXISTS
  po_hash_language_blocked BOOLEAN NOT NULL DEFAULT false;

CI verify_po_hash_language_receipt_v1 fails when:

  • hash_mismatch_count > 0 and fest_promotion_allowed: true
  • selector_stuck_resolved: false while po_hash_language is verified
  • locales_shipped omits a locale advertised on the store page

Hash mismatch recovery order

  1. Re-copy PO into game/tl/ from Weblate export artifact.
  2. Rerun PO-hash preflight H2–H3.
  3. If hashes match but boot still English → R-gates .rpyc rebuild.
  4. Refresh matrix + BUILD_RECEIPT; Thursday review.

Proof table (Thursday review)

Locale Export sha256 Build sha256 Selector Boot
chinese yes non-EN
japanese yes
korean yes

Key takeaways

  1. Weblate 100% ≠ shipped PO—hash before debate.
  2. po_hash_language is optional until store claims multi-locale—then it is mandatory.
  3. Keep language_receipt and po_hash_language_receipt as separate files.
  4. Unity SKUs use string_table_receipt—never merge schemas.
  5. Evening beginner pipeline is onboarding; this lesson is BUILD_RECEIPT promotion.
  6. Q1 capstone 229 will wire 225 with 224, 226–228.
  7. Help #8 should link here for hash_mismatch rows.
  8. 18-free store localization QA catches capsule lies; this catches installer lies.

Common mistakes

  • Verifying PO in git but shipping old archive.rpa.
  • Setting po_hash_language: verified with hash_mismatch_count: 1.
  • Skipping H5 on “English primary” SKUs that still show JP screenshots on Steam.
  • Pasting hash gates into Unity string_table_receipt JSON.
  • Running only editor F5 smoke—depot build still English.

Troubleshooting

Symptom Lane
hash_mismatch Re-import PO; rebuild distribution
Hash match, English boot R-gates rebuild
Missing buttons L-gates Weblate preflight
Unity + Ren'Py portfolio Lesson 209 matrix
Fest language wrong after playtest branch Ren'Py save/language isolation preflight — separate from PO hash

Mini exercise (65 minutes)

  1. Export PO from Weblate; record export sha256 manifest.
  2. Copy into game/tl/; build H2 manifest; fail H3 deliberately (wrong file).
  3. Fix copy; pass H3–H5 on installed exe.
  4. File po_hash_language_receipt_v1.json; extend Lesson 209 matrix row.
  5. Set BUILD_RECEIPT po_hash_language GREEN on Thursday template.

Continuity — Q1 2027 post-fest recovery (224–229)

Lesson Receipt focus
224 MKV gap reencode
225 (this) Ren'Py PO-hash language
226 Wwise DSP packaged Windows
227–229 Review keys, FMOD WebGL, Q1 capstone (queued)

Previous: Lesson 224 — OBS MKV gap reencode
Next: Lesson 226 — Wwise DSP packaged Windows receipt.

FAQ

Same as Lesson 209?
209 wires matrix + columns; 225 files the po_hash_language proof for Ren'Py SKUs.

Same as the PO-hash guide chapter?
Guide = H-gates preflight; lesson = BUILD_RECEIPT + CI + matrix extension.

Required for English-only VN?
Set po_hash_language: n/a when store and fest_locales are EN-only—do not fake hashes.


Localized store copy with English-only installed PO is a packaging bugpo_hash_language_receipt makes it visible before fest traffic.