Steam Short Description Save Fails Over 300 Characters After Weblate CJK Export — How to Fix
Problem: Steamworks will not save your localized short description for Simplified Chinese, Japanese, or Korean. The UI shows an error at or near the 300-character limit. Your Weblate export and spreadsheet both looked under budget in English QA columns.
Who is affected now: Micro-studios in the October 2026 Next Fest CN/JP/KR capsule rush who cleared Weblate string-freeze export on gameplay strings but paste store marketing copy from TMS without a Steam-accurate counter. This is store-metadata length, not merge conflicts (TMS) and not Unity String Tables missing in player builds (engine payload).
Fastest safe fix: Count each locale with a Steam-matching script (not Excel LEN alone) → trim duplicated boilerplate and full-width punctuation → save one locale at a time in Steamworks → file store_copy_receipt_v1.json with short_description_chars per locale → run store-page QA localization checklist screenshot parity → attach receipt to BUILD_RECEIPT before fest visibility.
Direct answer
Steamworks enforces a maximum length on the short description field (documented under store page description). Weblate and Google Sheets often under-count because they treat some full-width CJK punctuation as one code unit while your paste adds hidden newlines, duplicate tag lines, or English boilerplate appended per locale. The save fails even when translators “shaved 20 characters” in a spreadsheet that was counting the wrong surface.
Why this issue spikes in July–October 2026
- Parallel locale paste week — CN/JP/KR short descriptions land the same day as capsule art, without per-locale Steam paste tests.
- Weblate 100% ≠ Steam save — gameplay PO can be green while marketing strings live in a separate component with no
max_lengthcheck. - Full-width punctuation drift —
,。:replace ASCII,.:` and consume budget faster than translators expect. - LLM polish passes — “make it punchy” drafts add demo-boundary clauses that fit in English but overflow in Japanese.
- Partner diff same afternoon — reviewers paste your short description beside
build_id; overflow blocks save hours before fest lock.
Symptoms and search phrases
- Steamworks: “exceeds maximum length” or save button disabled on short description.
- English saves; zh-Hans / ja / ko fails only.
- Spreadsheet shows ≤300; Steam rejects paste.
- Extra blank line at end of Weblate export (counts in Steam paste).
- Duplicated “Demo” / “Next Fest” clause in every locale file.
- HTML or markup accidentally pasted from long description template.
- Capsule screenshot shows localized text; short description still English (separate issue—fix both).
Root causes (check in order)
- Full-width punctuation and spaces — CJK punctuation counts as characters in Steam paste.
- Duplicate boilerplate per locale — English legal/footer copied into each translation.
- Hidden newlines / CRLF — Weblate export adds
\n\nSteam counts. - Wrong counter — Excel byte length, Twitter counters, or PO
msgstrlength ≠ Steam field. - Unescaped markup —
<br>or bullet characters from About-section templates. - Merged cells in sheet QA — Translator edited summary cell, not Steam paste target.
- Locale file concatenation — Export script joined hook + body + tags without re-count.
Beginner path (first 40 minutes)
Prerequisites: Steamworks partner access, exported short description per locale in git (store-copy/short-description.{locale}.txt), one fest demo installed for screenshot parity.
- Copy failing locale text from Weblate → paste into plain
.txtin git. - Run counter script below → note
steam_char_count. - If
> 300→ remove one full-width comma block or duplicate demo clause. - Paste trimmed text into Steamworks → Save → screenshot success toast.
- Repeat per locale → fill
store_copy_receipt_v1.json. - Capture capsule screenshot from localized player build (not English-only).
Common mistake: Using gameplay Weblate conflict_count: 0 as proof store copy is shippable.
Fastest safe fix path
Step 1 — Per-locale Steam character counter
Steam counts characters in the short description field as pasted (including newlines). Use the same normalization before every paste:
#!/usr/bin/env python3
"""store_copy_count.py — match Steam short description budget (300 default)."""
import sys
from pathlib import Path
MAX = 300
def steam_char_count(text: str) -> int:
# Normalize Windows newlines; do not strip intentional single trailing newline
t = text.replace("\r\n", "\n").replace("\r", "\n")
return len(t)
def main(path: Path) -> None:
text = path.read_text(encoding="utf-8")
n = steam_char_count(text)
status = "PASS" if n <= MAX else "FAIL"
print(f"{path.name}: steam_char_count={n} max={MAX} {status}")
if n > MAX:
print(f" trim {n - MAX} characters before Steamworks paste")
if __name__ == "__main__":
main(Path(sys.argv[1]))
python store_copy_count.py store-copy/short-description.ja.txt
python store_copy_count.py store-copy/short-description.zh-Hans.txt
python store_copy_count.py store-copy/short-description.ko.txt
| Locale file | steam_char_count |
Pass |
|---|---|---|
short-description.en.txt |
≤300 | |
short-description.ja.txt |
≤300 | |
short-description.zh-Hans.txt |
≤300 | |
short-description.ko.txt |
≤300 |
Save terminal output → release-evidence/02-store/copy/char-count-proof.txt.
Step 2 — Trim templates (glyph-safe edits)
Apply in order—stop when counter passes:
| Trim target | Example | Savings |
|---|---|---|
| Duplicate demo boundary | Second “Demo” / “体験版” clause | 10–40 |
| Full-width → half-width punctuation | ,→, 。→. (only where style allows) |
1–15 |
| Redundant platform list | “PC (Windows)” twice | 8–20 |
| Footer boilerplate | Repeated Discord/URL lines not allowed in short field | 20–80 |
| Double newlines | \n\n → \n |
1 each |
| Tag-like comma chains | Genre list beyond two words | 10–30 |
Do not delete demo-boundary language entirely—shrink with 300-character evidence checklist slot anatomy (hook + genre + demo boundary).
Step 3 — Weblate component discipline (prevention at source)
For store-copy components in Weblate:
- Add translation check or reviewer rule: max 300 characters on short-description keys (custom check or manual gate).
- Separate marketing component from gameplay UI—do not share PO with unbounded
msgstr. - Lock glossary entries that force long English trademarks into CJK lines.
- Export only after merge conflicts = 0.
Pair with 14 Free Weblate string-freeze tools and 18 Free localization tooling.
Step 4 — store_copy_receipt_v1.json
{
"schema": "store_copy_receipt_v1",
"checked_at_utc": "2026-05-24T23:15:00Z",
"build_label": "fest-demo-2026-10-rc1",
"short_description_max": 300,
"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 }
},
"fullwidth_punctuation_normalized": true,
"duplicate_boilerplate_removed": true,
"screenshot_locale_matches_player": true,
"string_freeze_receipt_ref": "string_freeze_receipt_v1.json",
"pass": true
}
Block fest promotion if any locale steam_char_count > 300 or steamworks_save_ok: false.
Step 5 — Steamworks save + screenshot parity
| Check | Pass |
|---|---|
| Each locale saves without length error | Yes |
| Supported Languages matches shipped locales | Yes |
| Capsule screenshot text matches installed demo language | Yes |
| Short description demo verbs match hour-one build | Yes |
Use 18 Free store-page QA localization checklist—distinct from gameplay string receipts.
Step 6 — BUILD_RECEIPT column
| Column | Example |
|---|---|
store_copy_receipt |
pass |
short_description_chars_ja |
298 |
string_freeze_receipt |
pass |
Align with Wednesday demo build smoke ritual metadata diff column.
Working dev path — proof table before paste
| Source | Counter | Trust for Steam? |
|---|---|---|
Excel LEN() |
Cell length | Risky (newlines) |
| Weblate UI | Varies by view | Review only |
store_copy_count.py |
steam_char_count |
Yes |
| Steamworks preview | Live | Final authority |
CI hook (optional):
# fail build if any store-copy file exceeds 300
for f in store-copy/short-description.*.txt; do
python store_copy_count.py "$f" || exit 1
done
Verification checklist
- [ ] All shipped locales:
steam_char_count ≤ 300 - [ ] Steamworks Save succeeds per locale (screenshot)
- [ ]
store_copy_receipt_v1.jsonpass: true - [ ] No duplicate demo/footer boilerplate across locales
- [ ] Gameplay
string_freeze_receiptstillconflict_count: 0 - [ ] Capsule screenshots from localized player build
- [ ] Supported Languages doc matches truth
Prevention
- Store copy lives in git, not only Steamworks—diff before paste.
- Run char-count CI on Weblate export PRs for marketing components.
- One template per locale—ban appending English footer on export.
- Pair TMS freeze with store_copy_receipt in same release ticket.
- Writers use 7-day metadata parity sprint folder structure.
Troubleshooting
| Symptom | Fix |
|---|---|
| Sheet 298, Steam fails | Hidden newline—open hex or store_copy_count.py |
| Only Japanese fails | Full-width punctuation + longer demo clause |
| Save OK, wrong language on capsule | Player build locale—Unity/Godot help + new screenshots |
| All locales fail | Pasted About-section HTML into short field |
| Intermittent fail | Trailing space on copy/paste—normalize in .txt |
FAQ
Does Steam count bytes for CJK?
Treat the limit as characters in the pasted field for troubleshooting—use the script above and Steamworks as final judge, not byte length.
Weblate is 100% translated. Why still fail?
Gameplay completion ≠ marketing string length. Use separate components and checks.
Is this the same as Weblate merge conflicts?
No—conflicts block export; this article is post-export paste to Steamworks.
Can I use the English short description for all locales temporarily?
Only if Supported Languages and capsules honestly reflect English-only—do not claim CN/JP/KR without localized copy and screenshots.
Related links
- Weblate Merge Conflicts Block October Fest String Freeze
- Unity Localization String Tables Empty After Addressables Strip
- 14 Free Weblate String Freeze PO Export Tools
- 18 Free Game Localization and Translation Tooling (2026)
- 18 Free Store Page QA Localization Checklist
- Steam Next Fest 2026 Demo Short Description 300 Character Checklist
- 7-Day Store Metadata Parity Sprint
- Wednesday Demo Build Smoke Ritual
- Your First BUILD_RECEIPT JSON and Upload Log
- Official: Steamworks — Store page description, Supported Languages, Weblate — Checks
Count in git with the same script you use before Steam paste—fest week is too late to discover full-width commas ate your last twelve characters.