How to audit multilingual font coverage with the coverage map
- Step 1Build your locale-to-block matrix first — Map each market to the blocks it needs: English → Basic Latin + Latin-1. Polish/Czech/Hungarian → Latin Extended-A. Vietnamese → Latin Extended Additional (U+1E00–U+1EFF) + U+20AB. Russian → Cyrillic. Greek → Greek + Greek Extended. Arabic → Arabic + Arabic Supplement. Hindi → Devanagari. Thai → Thai. Korean → Hangul Syllables.
- Step 2Drop the candidate font — Drag in the `.ttf`, `.otf`, `.woff`, or `.woff2`. No options to set — the tool parses the cmap and buckets every codepoint into its block.
- Step 3Match required blocks against the matrix — For each locale, find its block row. Confirm it shows 100% (or near-100% for the characters you use). A missing row means zero coverage for that script — an immediate no-go for that market.
- Step 4Drill into partial blocks — A block below 100% is the trap. Latin Extended-A at 50% may have every Polish letter and no Czech caron. Note which locales depend on a partial block and verify the specific characters before approving.
- Step 5Check the web-subsets table for your shipping plan — If you'll serve per-script subsets, the common-web-subsets table tells you whether Latin, Latin-ext, Cyrillic, and Greek are each complete enough to subset cleanly.
- Step 6Download and circulate the report — Save `<fontname>.coverage.html` and attach it to the procurement ticket. The whole i18n and design team reviews identical, reproducible evidence rather than a marketing claim.
Locale → required Unicode block (the audit checklist)
Map your markets to blocks, then confirm each block in the Coverage Map output. Ranges are from the 346-block table the tool scores against.
| Locale / language | Primary block(s) to confirm | Range | Notes |
|---|---|---|---|
| English, Western Europe | Basic Latin + Latin-1 Supplement | U+0000–U+00FF | Covers é, ñ, ü, ©, €, £ — the baseline |
| Polish, Czech, Hungarian, Romanian | Latin Extended-A | U+0100–U+017F | Partial coverage here is the classic CE-European trap |
| Vietnamese | Latin Extended Additional + ₫ | U+1E00–U+1EFF, U+20AB | Needs the stacked-diacritic letters, not just base Latin |
| Russian, Ukrainian, Serbian | Cyrillic (+ Supplement) | U+0400–U+04FF, U+0500–U+052F | Serbian italic needs localised glyph forms beyond coverage |
| Greek | Greek and Coptic + Greek Extended | U+0370–U+03FF, U+1F00–U+1FFF | Polytonic Greek lives in Greek Extended |
| Arabic | Arabic (+ Supplement, Presentation Forms) | U+0600–U+06FF, U+0750–U+077F | Coverage ≠ correct shaping — see edge cases |
| Hindi / Marathi | Devanagari | U+0900–U+097F | Conjuncts need GSUB; coverage is necessary not sufficient |
| Thai | Thai | U+0E00–U+0E7F | Tone-mark stacking needs GPOS positioning |
| Korean | Hangul Syllables | U+AC00–U+D7AF | 11,172 codepoints — Latin fonts carry none |
| Japanese / Chinese | CJK Unified Ideographs (+ Kana) | U+4E00–U+9FFF | Huge; expect large files and Pro-tier limits |
Reading partial coverage in the audit
How to interpret the percentage column for a multilingual go/no-go decision.
| What you see | What it means | Audit verdict |
|---|---|---|
| Block row absent | Zero glyphs in that block | No-go for any locale that needs it |
| Block at 100% | Every slot mapped | Go (still proof-read complex scripts visually) |
| Block at 85–99% | Common chars present, edges missing | Investigate — list the missing codepoints |
| Block at 30–84% | Selective coverage | Likely a deal-breaker for that locale |
| Latin Extended-A partial | May have Polish, lack Czech caron | Verify the exact CE-European letters you ship |
Cookbook
Locale-driven audit recipes for a global product team. The tool has no settings, so each recipe is about mapping the matrix output back to your markets.
Five-market SaaS go/no-go in one scan
ExampleMap each market to its block, then read the matrix. One missing block fails the audit for that market.
Target markets: US, France, Russia, Greece, Vietnam Coverage Map (excerpt): Basic Latin U+0000-U+007F 95 / 128 74% → EN/FR base Latin-1 Supplement U+0080-U+00FF 96 / 128 75% → é à ç ñ Cyrillic U+0400-U+04FF 255 / 256 100% → RU ok Greek and Coptic U+0370-U+03FF 135 / 144 94% → EL check Latin Extended Additional (no row) → VN FAIL Verdict: ready for US/FR/RU; Greek needs a missing-char check; Vietnamese is a no-go (no Latin Extended Additional).
Catch the Central-European Latin Extended-A trap
ExampleA font that 'supports Latin Extended' can still miss the exact letters Czech or Hungarian need. The percentage exposes it.
Latin Extended-A U+0100-U+017F 72 / 128 56% 56% is the alarm. Polish ł ą ę ż may be present while Czech ř ů and Hungarian ő ű are absent. Before approving for CE-Europe, confirm: č ď ě ň ř š ť ž ů ő ű are all mapped. Partial 'Latin Extended' is not 'Czech ready'.
Verify Vietnamese, which hides in two places
ExampleVietnamese needs the stacked-diacritic letters in Latin Extended Additional plus the đồng sign — not just base Latin.
Required for Vietnamese: Latin Extended Additional U+1E00-U+1EFF (ấ ầ ậ ệ ộ ...) Currency Symbols includes U+20AB (₫ đồng) Coverage Map: Latin Extended Additional 240 / 256 94% Currency Symbols 8 / 48 17% (check ₫) 94% on Latin Extended Additional is promising but proof the specific tone-mark combinations; confirm U+20AB for ₫.
Confirm a CJK font before committing to its file size
ExampleCJK fonts are large and may exceed the free 5 MB limit. Coverage tells you whether the breadth justifies the bytes.
Coverage Map (Pro tier, 12 MB font): CJK Unified Ideographs U+4E00-U+9FFF 20,902 / 20,992 99% Hiragana U+3040-U+309F 93 / 96 97% Katakana U+30A0-U+30FF 96 / 96 100% Basic Latin U+0000-U+007F 95 / 128 74% 99% CJK + full Kana = genuine JP/CN coverage. The Latin at 74% is fine for mixed text. File needed Pro (>5 MB free limit).
Document the audit as a procurement artefact
ExampleDownload the report per candidate so the i18n team reviews identical evidence instead of foundry marketing.
/fonts/evaluations/ BrandSans.coverage.html → 9 blocks, gaps: VN, AR BrandSans-Pro.coverage.html → 14 blocks, all target locales RivalFace.coverage.html → 6 blocks, EU-only Decision: BrandSans-Pro covers the full locale matrix. The .coverage.html files are the attached evidence.
Edge cases and what actually happens
Every row below was probed against the live API. Some documented requirements (alphabetical axis order, numerical tuple order) are not actually enforced in practice — useful to know if you've been blaming the wrong thing for a 400.
100% Arabic coverage still renders wrong
Shaping not checkedThe map reports codepoint coverage, not shaping. Arabic needs contextual GSUB substitutions (initial/medial/final/isolated forms) and GPOS positioning. A font with 100% Arabic-block coverage but no shaping rules renders disconnected, wrong-form letters. Coverage is the first gate; always proof rendered Arabic, Devanagari, and other complex scripts visually.
Latin Extended-A partial but 'supports CE Europe' on the box
VerifyFoundries often claim 'Latin Extended' while shipping only a subset. A block at 56% can have Polish and miss Czech/Hungarian carons. The percentage is your trigger to enumerate the exact letters each locale needs — don't trust marketing language over the count.
Hangul Syllables shown as one giant block
ExpectedKorean lives in Hangul Syllables (U+AC00–U+D7AF), an 11,172-codepoint block. A real Korean font covers nearly all of it; a Latin font covers none. The percentage cleanly separates the two — but a font at, say, 40% Hangul is unusable for Korean text even though the block appears.
A locale needs two blocks; only one is covered
Partial localeVietnamese needs Latin Extended Additional plus the ₫ sign; polytonic Greek needs Greek and Coptic plus Greek Extended. If only one of the pair is covered, the locale is incomplete. Always map a locale to all its blocks, not just the obvious one.
Variable font — coverage is identical across weights
SupportedA variable font shares one cmap across every axis position, so Bold and Light have the same coverage. You audit once for the whole family. No need to freeze each instance — though shaping behaviour can still differ subtly at extreme axis values, so proof complex scripts at the weights you ship.
Emoji needed but font carries none
By designIf your product renders emoji, check the emoji blocks (Emoticons U+1F600–U+1F64F, etc.). Most text fonts carry zero — and that's usually fine, because the OS supplies a colour emoji fallback. The map's absence of those rows tells you to rely on system emoji, not the brand font.
CJK candidate exceeds the free 5 MB limit
413 rejectedFull CJK fonts routinely exceed the free-tier 5 MB cap and are rejected before parsing. Auditing pan-CJK coverage typically needs Pro (50 MB) or Developer (1 GB). Subset Latin candidates fit free easily.
Serbian/Macedonian italic localisation
VerifyCyrillic at 100% confirms the codepoints, but Serbian and Macedonian italic require localised glyph variants (e.g. italic б, г, д, п, т) selected via locl features. Coverage can't see this — proof Serbian italic text visually even at 100% Cyrillic.
Block present but the specific punctuation you need is missing
VerifyGeneral Punctuation (U+2000–U+206F) at, say, 60% may lack the exact dash, quote, or non-breaking-space variant your locale's typography requires. For multilingual typography, partial punctuation coverage is worth enumerating, not just glancing at the percentage.
Frequently asked questions
Does 100% block coverage mean the font is ready for that language?
It means the codepoints exist — necessary but not sufficient. Latin and Cyrillic at 100% are usually ready. Complex scripts (Arabic, Devanagari, Thai, Khmer) also need correct GSUB/GPOS shaping; 100% coverage with broken shaping still renders wrong. Treat coverage as the first gate, then proof rendered text.
How do I know which blocks each locale needs?
Use the locale-to-block table above. Common ones: English → Basic Latin + Latin-1; CE-Europe → Latin Extended-A; Vietnamese → Latin Extended Additional + U+20AB; Russian → Cyrillic; Greek → Greek + Greek Extended; Arabic → Arabic; Hindi → Devanagari; Korean → Hangul Syllables; CJK → CJK Unified Ideographs.
What's the most common multilingual gotcha the map catches?
Partial Latin Extended-A. A font advertised as 'Latin Extended' often ships only Western/Polish accents and misses Czech (ř ů), Hungarian (ő ű), or Romanian (ș ț). The percentage column exposes it — a block below 100% is your prompt to enumerate the exact letters.
Can I audit a CJK font on the free tier?
Often not — full CJK fonts exceed the free 5 MB upload limit and are rejected before parsing. Pro raises it to 50 MB and Developer to 1 GB. Latin and pan-European candidates fit free comfortably.
Does it work on Arabic and Indic shaping?
It reports whether the Arabic or Devanagari codepoints exist, not whether the shaping rules are correct. A complete block with no GSUB still renders disconnected/incorrect glyphs. Use the map to confirm presence, then proof actual rendered strings for any complex script.
How do I document the audit for the team?
Download each candidate's .coverage.html report and store them together (e.g. /fonts/evaluations/). Everyone reviews the same reproducible matrix instead of a foundry's marketing claim. The report embeds both the block matrix and the web-subsets table inline.
Can I audit several fonts at once?
Not in one pass — the tool takes a single file. Run each candidate separately and compare the downloaded reports. For an automated batch audit across a whole font directory, see the design-system automation guide.
Why is a block I expected missing entirely?
Because the font has zero covered codepoints in it. The matrix omits empty blocks, so absence equals no coverage. If Hebrew or Thai isn't listed, the candidate simply doesn't carry those scripts.
Does the map see fallback fonts?
No — it analyses exactly the one file you upload. Real pages stack fonts (font-family: Brand, system-ui, sans-serif), and the browser falls back per glyph. The map tells you what the brand font itself must cover; anything it lacks will hit your fallback at runtime.
Is auditing a licensed foundry sample safe?
Yes. Everything runs in your browser — opentype.js parses locally and the badge reads 0 bytes uploaded. NDA'd or unreleased brand fonts never reach a server. Only an anonymous run counter is recorded for signed-in users.
What about emoji coverage for a global product?
Check the emoji blocks (Emoticons, Miscellaneous Symbols and Pictographs, Supplemental Symbols and Pictographs). Most brand text fonts carry none — and that's fine, because the OS provides colour emoji as fallback. If you need brand-consistent emoji, the absence of those rows tells you to source a dedicated emoji font.
After picking a font, how do I ship per-locale subsets?
Use the coverage data to decide which subsets to build, then run the Font Subsetter per script and wire unicode-range per @font-face so each locale loads only its bytes. The Google Fonts CSS generator and font-face generator help assemble the CSS.
Privacy first
Every JAD Font tool runs entirely in your browser using opentype.js and the wawoff2 WASM Brotli encoder. Your fonts never leave your device — verified by zero outbound network requests during processing.