Unity Localization String Tables Empty in Player Build After Addressables Strip — How to Fix
Problem: Unity Localization looks correct in the Editor—Play Mode shows Japanese or Simplified Chinese on menus. Your fest player build (or Development Build) shows raw keys like UI_START_BUTTON or English fallbacks on the first screen.
Who is affected now: Teams in the October 2026 localization rush who passed Weblate string-freeze export on PO files but stripped Addressables groups to shrink the demo depot. Store capsules can be localized while the installed build still ships without String Table assets—distinct from Weblate merge conflicts (TMS export) and from FMOD banks missing after strip (audio payload).
Fastest safe fix: Open Build Report → confirm String Table assets and Shared Table Data appear in player data → move tables to Localization_Local Addressables group (Include in Build, never stripped) → verify LocalizationSettings selected locale on boot → run installed build smoke per target locale → file string_table_receipt_v1.json with table hashes → attach to BUILD_RECEIPT before Steam upload.
Direct answer
Unity Localization resolves UI through String Table assets (and optional Asset Tables). If those assets lived only in Addressables groups you marked remote, strip, or fest-cut, the player executable never contains the translated tables—LocalizedString has nothing to load, so you see keys or default locale strings. Editor Play Mode reads assets directly from the project, hiding the gap until a real build.
Why this issue spikes in October 2026 prep
- CN/JP/KR capsule week — Marketing localizes store copy while gameplay build still strips
Localizationgroups. - Addressables size discipline — Same PR that removed audio banks or gameplay labels also removed Shared Table Data.
- Weblate ≠ engine import — Clean PO export does not prove String Tables shipped in player data.
- Smart Strings / collections — Unity 6.x teams bundle tables into Addressables without a non-stripped lane.
- Wednesday smoke — Demo smoke ritual expects receipt rows beside
menu_fps_capandstring_freeze.
Symptoms and search phrases
- Editor: localized buttons; player: *`UI_` keys** visible.
LocalizationSettings.SelectedLocalecorrect in Editor; wrong or null in build.- Build Report: zero
*StringTable*/*SharedTableData*entries after strip PR. Addressables.BuildLayoutGenerationshows tables only in stripped group.- Recent change: “move all UI to Addressables” or “remote fest content only.”
- Pseudo-localization worked in Editor; fest build shows English only.
- Steam review: “Chinese on store page, English in demo.”
Root causes (check in order)
- String Table collection in stripped Addressables group — tables not in player build.
Shared Table Dataasset excluded — collection references missing shared data.LocalizationSettingsprefab not in Resources / not loaded on boot — init order issue.- Wrong active locale — code forces
enin player; Editor usedja. - Asset Tables for fonts/sprites stripped — text renders but shows tofu/keys (related).
- LocalizedString references broken keys — table entry renamed; Editor cached old IDs.
- Fest vs playtest depot — playtest had tables; fest promotion reused stripped artifact.
Beginner path (first 45 minutes)
Prerequisites: Unity Localization package installed, one fest target locale (e.g. ja), installed player or Steam build.
- Window → Asset Management → Addressables → Groups — find groups tagged fest strip.
- Note which group holds UI_Strings / StringTable assets.
- Build player → Build Report → search
StringTable,SharedTableData. - If zero hits → deployment strip (this article).
- Install build → first menu → switch locale if your game supports it → screenshot.
- If keys visible → continue fix path; if English only → locale selector + table inclusion.
Common mistake: Passing Weblate export while never importing into String Tables referenced by UI.
Fastest safe fix path
Step 1 — Enumerate localization assets in Build Report
| Check | Pass |
|---|---|
*Shared Table Data*.asset listed |
Yes |
Per-locale *String Table*.asset listed |
Yes |
| Tables under included Addressables group or non-Addressables | Yes |
| Total localization asset size > 0 | Yes |
| No tables only in Remote.BuildPath stripped group | Yes |
Screenshot → release-evidence/01-build/l10n/build-report-string-tables.png.
Step 2 — Create non-stripped Localization_Local group
Rule: Localization payload for fest demos should not share groups you cut for optional gameplay content.
| Asset | Recommended home |
|---|---|
Localization Settings |
Resources or dedicated Local Addressables group |
| String Table collections | Localization_Local — Build Path Local, Include in Build Yes |
| Shared Table Data | Same group as collections |
| Optional fonts (Asset Table) | Localization_Local or Resources |
Steps:
- Addressables Groups → Create
Localization_Local. - Move all String Table + Shared Table Data assets from strip groups.
- Remove Addressables labels from tables that gameplay strip scripts target.
- Build → New Build → Default Build Script → verify layout includes
Localization_Local.
Step 3 — Import Weblate PO into tables (if TMS is source)
After Weblate freeze:
- Export clean PO per locale.
- Unity Localization Tables window → Import extensions PO into correct collection.
- Apply → run Analyze rule sets for missing keys.
- Commit table assets + shared data together—do not import PO only to
StreamingAssetsloose files without table linkage.
Pair with 14 Free Weblate string-freeze tools and 18 Free localization tooling.
Step 4 — Boot locale smoke (installed build)
// BootLocaleProbe.cs — attach to bootstrap; adjust API to your package version
using UnityEngine;
using UnityEngine.Localization.Settings;
public class BootLocaleProbe : MonoBehaviour {
async void Start() {
await LocalizationSettings.InitializationOperation.Task;
var locale = LocalizationSettings.SelectedLocale;
Debug.Log($"Active locale: {locale?.Identifier}");
if (locale == null)
Debug.LogError("LocalizationSettings.SelectedLocale is null in player build");
}
}
| Locale | Pass |
|---|---|
ja (example) |
First screen shows translated text, not keys |
zh-Hans |
Store-declared locale matches pixels |
en fallback |
Only if SKU intentionally English-only |
Test on installed build—not Editor only.
Step 5 — string_table_receipt_v1.json
{
"schema": "string_table_receipt_v1",
"checked_at_utc": "2026-05-24T22:00:00Z",
"build_label": "fest-demo-2026-10-rc1",
"addressables_group": "Localization_Local",
"locales_in_build": ["en", "ja", "zh-Hans"],
"shared_table_data_sha256": "sha256:abc123...",
"string_table_manifest_sha256": "sha256:def456...",
"boot_locale": "ja",
"first_screen_translated_ok": true,
"raw_keys_visible": false,
"string_freeze_receipt_ref": "string_freeze_receipt_v1.json",
"pass": true
}
Hash sorted table asset paths from built player data or Addressables layout report.
Step 6 — BUILD_RECEIPT + store parity
| Column | Example |
|---|---|
string_table_receipt |
pass |
string_freeze_receipt |
pass |
first_screen_translated_ok |
true |
Run 18 Free store-page QA localization checklist—screenshot text must match installed locale, not only PO files.
Block fest visibility if raw_keys_visible: true.
Working dev path — Addressables layout diff
When a PR touches Addressables:
# After build, search player layout / build report
StringTable
SharedTableData
Localization Settings
| Diff signal | Action |
|---|---|
| Tables moved to remote group | Revert strip on Localization_Local |
| Keys in Editor, tables in report | Locale selector / LocalizedString reference |
| Tables present, wrong language | Import PO + SelectedLocale |
| Playtest OK, fest fail | Separate CI lanes per build_label help |
Verification checklist
- [ ] Build Report lists Shared Table Data + String Tables
- [ ] Tables live in non-stripped
Localization_Localgroup - [ ] Installed build: no raw keys on first screen for shipped locales
- [ ]
string_table_receipt_v1.jsonpass: true - [ ]
string_freeze_receiptreferenced andconflict_count: 0 - [ ] Store screenshots captured from localized player build
- [ ] Steam Supported Languages matches build capability
Prevention
- Never strip
Localization_Localwithout L10n QA sign-off. - Add string table enumeration CI step on fest upload workflow.
- Pair engine import with Weblate export in same release ticket.
- Document fest vs playtest localization groups in
playtest_scope_map_v1.json. - Run pseudo-localization in Editor, then player smoke per locale.
Troubleshooting
| Symptom | Fix |
|---|---|
| Keys everywhere | Tables not in build—Step 1–2 |
| English only, no keys | Wrong SelectedLocale—Step 4 |
| Missing glyphs | Asset Table fonts stripped—add CJK font to Localization_Local |
[Addressables] InvalidKeyException |
Invalid key runtime loading |
| Store CN, game EN | This article + screenshot regen from player |
FAQ
Weblate says 100% translated. Why keys in build?
Weblate proves PO quality, not player payload. Import PO into String Tables and verify Build Report.
Should String Tables use Addressables at all?
Yes for large games—but fest demos need a local, non-stripped group. Remote-only tables are fine for optional DLC, not core UI.
Is this the same as stripping FMOD banks?
Same Addressables strip failure mode, different asset type. Fix both receipts on BUILD_RECEIPT.
Do I need the Localization package for IMGUI/UI Toolkit?
UI Toolkit uses String Table bindings; uGUI uses Localize String Event—both need tables in the build.
Related links
- Steam Short Description Over 300 Characters After CJK Export
- Weblate Merge Conflicts Block October Fest String Freeze
- FMOD Banks Missing After Addressables Strip
- Unity Addressables Invalid Key at Runtime
- 14 Free Weblate String Freeze PO Export Tools
- 18 Free Game Localization and Translation Tooling (2026)
- 18 Free Store Page QA Localization Checklist
- 7-Day Store Metadata Parity Sprint
- Wednesday Demo Build Smoke Ritual
- Your First BUILD_RECEIPT JSON and Upload Log
- Official: Unity Localization Package, Addressables — Build layout
Prove String Tables in the Build Report before you prove Weblate export green—fest players run your exe, not your PO folder.