Lesson 232: Steam Short Description CJK 300-Char Receipt on BUILD_RECEIPT (2026)
Direct answer: Before spring fest store visibility, file store_copy_cjk_receipt_v1.json proving every shipped locale has steam_char_count ≤ 300, Steamworks Save succeeded, and capsule screenshots match the localized player build—then promote BUILD_RECEIPT store_copy_cjk. Distinct from Lesson 219 string tables (in-game UI) and help store_copy_receipt_v1 (symptom fix without Photoshop export crosswalk).

Why this matters now (May 2027 CJK capsule paste week)
May 2027 teams finish FMOD bank strip and paste CN/JP/KR short descriptions from Photoshop text layers or Weblate exports—English saves, Japanese fails at 302 characters because full-width , and duplicate 体験版 clauses were counted in a spreadsheet, not Steam. Marketing blames translators; the fix is git-tracked .txt files, one counter script, and a receipt before BUILD_RECEIPT promotion.
The Steam 300-char CJK help documents fastest recovery; Photoshop/GIMP export proof preflight is the ninety-second art-pipeline gate—this lesson is the BUILD_RECEIPT milestone with CI hook verify_store_copy_cjk_v1.
Beginner path (per-locale save proof)
| Step | Action | Success check |
|---|---|---|
| 1 | Export each locale to store-copy/short-description.{locale}.txt |
UTF-8, no HTML |
| 2 | Run store_copy_count.py per file |
steam_char_count ≤ 300 |
| 3 | Trim duplicate demo boilerplate | Counter passes |
| 4 | Paste into Steamworks → Save | No length error |
| 5 | Screenshot save toast per locale | Archive PNG |
| 6 | File store_copy_cjk_receipt_v1.json |
cjk_copy_pass: true |
| 7 | BUILD_RECEIPT row | store_copy_cjk GREEN |
Time: ~68 minutes first CJK paste week; ~15 minutes when templates are pinned.
Developer path (gates J1–J6)
| Gate | Check | Fail when |
|---|---|---|
| J1 | Source files in git | Paste-only in Steamworks |
| J2 | steam_char_count per locale |
Any locale > 300 |
| J3 | Photoshop/GIMP export audit | Hidden newlines from art handoff |
| J4 | Steamworks save proof | Spreadsheet green, Steam red |
| J5 | Screenshot locale parity | CN capsule, English player |
| J6 | store_copy_cjk_receipt_v1 + BUILD_RECEIPT |
Fest promotion without receipt |
J1 — Git layout (store-copy/)
store-copy/
short-description.en.txt
short-description.ja.txt
short-description.zh-Hans.txt
short-description.ko.txt
char-count-proof.txt # CI output
STORE_COPY_CJK_RECEIPT.json # promoted copy
Rule: never edit Steamworks only—diff must be reviewable in PR.
J2 — Counter script (Steam-matching)
#!/usr/bin/env python3
"""store_copy_count.py — BUILD_RECEIPT gate for short description budget."""
import sys
from pathlib import Path
MAX = 300
def steam_char_count(text: str) -> int:
t = text.replace("\r\n", "\n").replace("\r", "\n")
return len(t)
def main(path: Path) -> None:
n = steam_char_count(path.read_text(encoding="utf-8"))
status = "PASS" if n <= MAX else "FAIL"
print(f"{path.name}: steam_char_count={n} max={MAX} {status}")
sys.exit(0 if n <= MAX else 1)
if __name__ == "__main__":
main(Path(sys.argv[1]))
for f in store-copy/short-description.*.txt; do python store_copy_count.py "$f"; done
Archive output → release-evidence/02-store/copy/char-count-proof.txt.
J3 — Photoshop/GIMP export crosswalk
| Export mistake | Steam symptom | Fix |
|---|---|---|
| Paragraph returns from text box | +2 hidden newlines |
Single \n max at EOF |
Full-width punctuation , 。 |
Over budget vs ASCII | Trim or half-width where style allows |
| English footer duplicated per locale | +40–80 chars | One template per locale |
| Smart quotes from design paste | Odd counts | Normalize to ASCII quotes in .txt |
Pair with guide #12 when authored for layer → plain text discipline.
store_copy_cjk_receipt_v1.json
{
"schema": "store_copy_cjk_receipt_v1",
"build_label": "spring-fest-2027-rc1",
"short_description_max": 300,
"export_source": {
"photoshop_doc": "store-copy/psd/short-description-masters.psd",
"weblate_component": "store-marketing-short",
"git_paths": [
"store-copy/short-description.ja.txt",
"store-copy/short-description.zh-Hans.txt",
"store-copy/short-description.ko.txt"
]
},
"locales": {
"english": { "steam_char_count": 287, "steamworks_save_ok": true },
"japanese": { "steam_char_count": 298, "steamworks_save_ok": true },
"schinese": { "steam_char_count": 295, "steamworks_save_ok": true },
"koreana": { "steam_char_count": 291, "steamworks_save_ok": true }
},
"paired_receipts": {
"string_tables_fest": "release-evidence/localization/ADDRESSABLES_FEST_STRING_TABLE_RECEIPT.json",
"string_freeze": "release-evidence/localization/STRING_FREEZE_RECEIPT.json"
},
"gates": {
"J1_git_sources": "pass",
"J2_char_count": "pass",
"J3_export_crosswalk": "pass",
"J4_steamworks_save": "pass",
"J5_screenshot_parity": "pass",
"J6_build_receipt": "pass"
},
"cjk_copy_pass": true,
"fest_promotion_allowed": true
}
Pin under release-evidence/02-store/copy/STORE_COPY_CJK_RECEIPT.json.
BUILD_RECEIPT row (J6)
| Column | Pass when |
|---|---|
store_copy_cjk |
Receipt path + cjk_copy_pass: true |
string_table_receipt |
Lesson 219 independent |
short_description_chars_ja |
Integer ≤ 300 from receipt |
ALTER TABLE release_publish_gate ADD COLUMN IF NOT EXISTS
store_copy_cjk_blocked BOOLEAN NOT NULL DEFAULT false;
Relationship to help vs guide
| Artifact | Role |
|---|---|
| Steam 300-char CJK help | Symptom + store_copy_receipt_v1 cousin |
| Photoshop/GIMP export preflight | C1–C6 export preflight |
| This lesson | BUILD_RECEIPT store_copy_cjk + Photoshop/Weblate crosswalk |
Key takeaways
- Weblate 100% ≠ Steam save for marketing strings.
- Count in git with the same script before every paste.
- Full-width punctuation eats budget faster than translators expect.
- Lesson 219 fixes in-game UI; 232 fixes store short description.
- Run store-page QA checklist after receipt.
- Pair Weblate freeze tools on gameplay PO only.
- 300-character evidence checklist defines slot anatomy—do not delete demo boundary entirely.
- Q2 capstone 235 wires 232 with 230–234.
Common mistakes
- Using Excel
LEN()as authority. - Pasting About section HTML into short description.
- Localized capsule with English-only installed build.
- Merging help
store_copy_receiptwithoutexport_sourceblock. - Skipping ko because “we only market JP/CN this week.”
Troubleshooting
| Symptom | Lane |
|---|---|
| Sheet 298, Steam fails | J3 hidden newline |
| Only Japanese fails | Full-width punctuation + demo clause |
| Save OK, wrong capsule language | J5 player locale + new screenshots |
| Gameplay localized, store English | Separate receipts—219 vs 232 |
| All locales fail | HTML in short field |
Mini exercise (65 minutes)
- Add
\n\ntoshort-description.ja.txt—confirm J2 fails. - Trim to ≤300; pass Steamworks save; screenshot J4.
- File receipt with
export_sourcepaths. - Link 219 receipt in
paired_receipts. - Set BUILD_RECEIPT
store_copy_cjkGREEN.
Continuity — Q2 2027 spring fest shipping (230–235)
| Lesson | Receipt focus |
|---|---|
| 230 | Fab 8K throttle |
| 231 | FMOD bank strip |
| 232 (this) | CJK short description |
| 233 | Spline fest landing LCP |
| 234 | Micro-trailer stereo embed |
| 235 | Q2 capstone |
Previous: Lesson 231 — Unity FMOD bank-strip boot probe
Capstone: Lesson 235 — Q2 spring fest shipping — arc 230–235 closed.
FAQ
Same as Steam 300-char help?
Help fixes paste failure; 232 adds BUILD_RECEIPT + Photoshop/Weblate export crosswalk.
Same as Lesson 219?
219 = String Tables in player build; 232 = Steamworks short description field.
Use store_copy_receipt_v1 or store_copy_cjk_receipt_v1?
Help cousin for triage; promote store_copy_cjk on BUILD_RECEIPT for this course arc.
CJK short descriptions fail in Steamworks when counters lie—git sources, one script, save proof per locale, then store_copy_cjk_receipt.