Your Chinese looks perfect here.
On a player's PC it's a row of boxes.

The translation is not the problem. tr("MENU_START") returns 开始, the table is loaded, the locale is right. What is missing is a glyph — and Godot quietly went and found one on your computer, in a font file that is not inside your export. Paste your translation CSV below and this lists every character that falls outside the set the engine actually guarantees. It runs the LocGuard scanner in your browser; nothing is uploaded.

    What the engine actually guarantees

    Godot's built-in UI font is Open Sans SemiBold, and it is a subset. Asking the engine itself — ThemeDB.fallback_font.has_char(cp) for every codepoint in the BMP, the emoji planes and CJK Extension B — gives an exact number: 1010 codepoints, in 92 ranges (G1, Y1). That enumeration is the table this page scans against; it is generated by the verification script, not typed by hand.

    scriptin the built-in font?claim
    printable ASCII 0x20–0x7Eyes, all of itG2
    Latin-1 accents — é ã ç (fr/pt/es)yesG3
    Latin Extended-A — ł š ğ (pl/cs/tr)yesG4
    Vietnamese — ạyesG5
    Cyrillic — ЖyesG6
    Greek — αyesG7
    Hebrew — אyesG8
    Arabic — بnoG9
    Chinese — 你 我noG10
    Japanese kana — あ アnoG11
    Korean — 가noG12
    Thai — กnoG13
    Devanagari — कnoG14
    emoji — 😀noG15
    arrows — ← ↑ → ↓noG16
    — … • “ ” ’ €yesG17
    ✓ ★ ♥ ♪noG18

    Two of those rows are the reason this page exists. This is not a "non-Latin languages" problem. A project with no translation at all, whose entire UI is English, ships a hex box the moment a designer writes Continue → Next or OK ✓ (G16, G18). And the em dash, the ellipsis, the curly quotes and the euro sign are in the font (G17) — so "avoid non-ASCII" is not the rule, and guessing does not work. That is why the set is measured.

    Then why does it look fine on your machine?

    Because Godot borrows. Shaping 你好 with the built-in font still produces two real glyphs (S1) — and they carry a font_rid that is not the built-in font's (S2). OS.get_system_font_path_for_text() names where they came from (S3):

    OS.get_system_font_path_for_text("Sans", "你好")
    ["/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
     "/usr/share/fonts/opentype/unifont/unifont.otf"]

    An absolute OS path, not a res:// path. Same for an emoji in a UI string (Y2). None of it travels inside your .pck. Your development machine — a full desktop with a font package installed — is the single worst place to test whether your player can read your game.

    What the player without that font sees

    FontFile.allow_system_fallback = false reproduces it, and it is the closest thing to a player's machine you can run in CI:

    The marker is not glyph index 0

    If you go looking for this in code, do not test for a zero glyph index — you will find nothing. Godot marks an undrawable codepoint by putting the codepoint itself in index and leaving font_rid invalid (S4b):

    你好 | index=20320 (U+4F60)  font_rid=RID(0)  valid=false

    That pair is the hex box on screen, and it is the only reliable way to detect this from inside the running game.

    Why nothing warns you

    The fix, and the shape of it

    var body := FontFile.new()
    body.load_dynamic_font("res://fonts/NotoSansSC-Regular.ttf")
    
    var ui := ThemeDB.fallback_font.duplicate()
    ui.allow_system_fallback = false   # fail loudly here, not on a player's PC
    ui.fallbacks = [body]

    Measured: with system fallback off, a Font in fallbacks takes the arrow's undrawable glyph to zero (S10). Measured just as carefully: the same fallback does not fix Chinese, because DejaVu Sans has no CJK either (S11). A fallback only covers what it actually owns — so "add a fallback font" is not advice until you know which codepoints you are shipping. Which is what the tool at the top answers.

    This is deliberately not a linter rule

    Every rule in LocGuard answers "is this translation table complete and consistent", and is fixed by editing the table. This one answers "can the engine draw it", and the fix is a font file. Different question, different artifact — and a check that would be wrong to fail a translator's build over. LocGuard Pro is the Godot 4 editor dock and CLI that catch the table-side failures — missing keys, empty translations, placeholder drift, unbalanced BBCode — before your players do: blobsmith.itch.io/locguard. The free CLI is locguard-lite.

    Reproducing all 35 claims

    git clone https://github.com/leobaray/locguard
    docs/verify_font_glyphs.sh /path/to/Godot_v4.7-stable_linux.x86_64 dump.json

    Every claim id on this page is printed by that script. The optional second argument re-dumps the coverage ranges as JSON — that file is the source of the table this page scans against, so a Godot upgrade is a re-run and a diff, not a rewrite. Last run: 35 passed / 0 failed against 4.7.stable.official.5b4e0cb0f. The full write-up is docs/font-glyphs-missing-in-translations.md, and the scanner this page runs is docs/glyph-scan-core.js — byte for byte the file the command line uses.

    Measured the same way