Missing Glyph Checker

Compare localisation text or a .txt/.json/.csv/.po file against a font's glyph list and find every missing character.

Boxes (□) or blank gaps where Korean or Japanese letters should be mean that the font has no glyph for those code points. A bitmap font contains only the characters baked into it, one char id= line per glyph in its .fnt. The checker pulls the translated text out of your .po (the msgstr values), .json, .csv/.tsv or .txt, compares every distinct character with the .fnt (or the font built in the UI Lab's Font stage), and lists each missing character with its Unicode code point, how often it is used and the first lines it appears on. It cannot read a TTF's character map yet.

Drop image files hereProcess many files at once
No upload · processed on this device

Why letters turn into boxes

Every character is a Unicode code point, and a BMFont stores it in decimal: 시 is U+C2DC, which the .fnt writes as char id=49884. The check is plain set membership: the distinct characters of the text minus the char id values of the font. Scripts are large, which is why game fonts for Korean or Japanese are built from the strings the game actually uses: the precomposed Hangul syllables U+AC00–U+D7A3 are 11,172 code points, and the CJK Unified Ideographs block U+4E00–U+9FFF spans 20,992.

The usual causes are a translation updated after the font was baked; a font built from the source-language text; look-alike characters with different code points (full-width ! U+FF01 against ! U+0021); and decomposed Hangul, where 가 arrives as the jamo U+1100 U+1161 instead of the single syllable U+AC00. The checker compares code points exactly, so it reports all of these.

What is read from each file matters. From a .po only msgstr (and msgstr[n]) values are taken, never the msgid source keys, but the header entry's msgstr (Language:, Content-Type:) counts as text too. JSON contributes every string value, CSV and TSV every cell including the key and source columns. Whitespace, including the no-break space U+00A0 and the ideographic space U+3000, is skipped because it is not drawn as a glyph.

Example: a Korean .po against a 4-glyph .fnt

The font was baked from 시, 작, 끝 and 내. The report below is what the checker returns for this file:

ko.po (9 lines)                         font.fnt (4 glyphs)
msgid ""                                char id=49884   시 U+C2DC
msgstr ""                               char id=51089   작 U+C791
"Language: ko\n"                        char id=45149   끝 U+B05D
msgid "Start"  →  msgstr "시작"         char id=45236   내 U+B0B4
msgid "Quit"   →  msgstr "끝내기"

text checked   "Language: ko" / "시작" / "끝내기"   (msgid values are not read)
missing        기 U+AE30 ×1   (text line 5)
               a ×2, g ×2, :, L, e, k, n, o, u   (header entry, text line 2)
to add         기 = 0xAE30 = 44592 → the rebuilt font needs "char id=44592"

The Latin letters come from the header entry, not from a translation. Either add ASCII to the font (most games need digits and Latin letters anyway) or ignore those rows; the real gap here is 기.

Where the checked text comes from

FileWhat is readWhat is ignored
.pomsgstr and msgstr[n] values with their continuation lines (the header entry included)msgid, msgctxt, comments
.jsonEvery string value at any depthObject keys, numbers, booleans
.csv / .tsvEvery cell of every row, header row and key column includedSeparators and quotes
.txt or pasted textEverythingLine breaks and other whitespace
.fnt (glyph source)The id of every char lineKerning, pages, metrics

Check the result

  • After adding the characters and rebuilding the font, run the check again: it should say that nothing is missing and name how many distinct characters were checked.
  • Open missing-glyphs.json: every entry has char, codepoint as U+XXXX, count and lines; missing-glyphs.txt is the same characters on one line, ready to paste into a font tool's character field.
  • In the game, show one test string that contains every character of the language file: no box and no blank should remain.

Troubleshooting

SymptomLikely causeHow to checkFix
Latin letters (L, a, n, g…) are reported for a Korean or Japanese .poThe header entry's msgstr (Language:, Content-Type:) is read as textThe listed lines point at the first lines of the extracted textAdd ASCII to the font, or ignore those rows
The English source column of a CSV is reportedEvery CSV/TSV cell is read, including key and source columnsMost missing characters are Latin and appear on every lineExport only the target-language column, or paste its text instead
A character that looks present is reportedA look-alike with another code point (full-width !, ~, a different dash)Compare the U+ code in the report with the .fnt idsAdd that exact code point to the font, or normalise the text before export
Hangul syllables are reported although the font has themThe text is decomposed: jamo U+1100–U+11FF instead of syllablesThe report lists U+11xx codesNormalise the strings to NFC in your localisation pipeline
Nothing is missing but the game still shows boxesThe game draws with another font or weight than the checked .fnt, or the UI Lab font was built in font-file mode, where a character missing from the TTF is rendered by the browser's fallback font and baked inCheck the .fnt the build actually ships; look at the glyph sheet for letters in a different styleCheck against the shipped .fnt; in Godot a BMFont can list fallback fonts in its importer
The line numbers do not match the fileLines are counted in the extracted text, not in the original fileLine 2 of a .po report is the header textSearch the file for the character itself
A TTF or OTF cannot be chosen as the glyph sourceThe font's cmap table is not parsed in this release—Build a .fnt from the font first, then check against it

Versions and sources

Measured in Chromium for docs/UI-LAB.md: a .po checked against a 4-glyph .fnt reported exactly a 시 작 끝 내 기 with the right counts and line numbers, and the present 가 was not reported. The worked example above was recomputed with the same functions; its header-entry rows are how the current parser behaves. The .fnt field meanings follow the AngelCode BMFont documentation, the .po structure the GNU gettext manual.

Official documentation used

Missing Glyph Checker

Compare localisation text or a .txt/.json/.csv/.po file against a font's glyph list and find every missing character.

How it works

  1. Add images
  2. Adjust settings and review the result
  3. Download a new file

Supported formats

PNG / JPG / WebP / AVIF / HEIC → PNG + JSON (ZIP) — Input decoding depends on browser support and optional engines.

What this tool does

Compare localisation text or a .txt/.json/.csv/.po file against a font's glyph list and find every missing character.

Implementation and verified quality

advanced · BMFont .fnt parser / per-character occurrence counts. Quality qualification is in progress. Pro/Flagship quality has not been established.

Before you export

Compares against a BMFont .fnt file or a font built in this Lab. It does not read the cmap table of a TTF or OTF.

Frequently asked questions

What are this tool’s limitations?

Compares against a BMFont .fnt file or a font built in this Lab. It does not read the cmap table of a TTF or OTF.

Are my files uploaded?

This tool processes the files you open on your device without uploading them. Images you explicitly attach to community posts are uploaded separately. Optional engines and models are downloaded from third parties; those requests expose connection information such as your IP address.

Will my work be saved automatically?

No. Images and editing state stay in this tab; media output can use local temporary storage. Changing language preserves your work; reloading, closing the tab, or following a link to another page can clear it.