Engineeringこの記事を日本語で読む

Pixel fonts that have to hold Japanese and English at the same time

Pixel art games have a specific localization problem that higher-resolution games do not. Your font is not a font in the usual sense — it is art, chosen to sit at an exact size inside an exact grid, and every layout in the game was built around the number of characters it fits. Then you add Japanese, and none of those assumptions hold.

The failure is not subtle. Either the kanji are physically too small to read, or they are large enough to read and no longer fit anywhere, or you end up with two fonts on the same line that disagree about where the baseline is. None of these are bugs you can fix in the translation.

This article is about the decisions that determine whether your pixel game can carry a second script at all: the size floor for kanji, whether to mix fonts, the rendering rules that keep pixels sharp, the arithmetic of what fits, and how coverage and licensing work for this specific category of font.

Kanji have a legibility floor that Latin does not

A capital letter in a pixel font is a handful of strokes and reads clearly in a five-by-seven pixel area. That is why an eight-pixel cell has been enough for English text for as long as games have existed. A kanji character is a composition of radicals, some of which are themselves several strokes, and below a certain grid size those strokes stop being separable — not stylised, just gone.

The historical evidence is in the games themselves. Console games of the 8-bit era in Japan were frequently written entirely in kana, because an eight-by-eight tile cannot hold a kanji. That was a real constraint accepted by real teams, and it produced text that Japanese players of the time found noticeably harder to read than kanji-mixed writing, since kanji do much of the work that spaces do in English.

In practice, teams settle around three tiers. Eight-by-eight Japanese pixel fonts do exist and are impressive engineering, but they are a stylistic choice with a real legibility cost, best reserved for short strings rather than paragraphs of dialogue. Ten-by-ten to twelve-by-twelve is the common working range where most kanji stay distinguishable. Sixteen-by-sixteen is comfortable and is what a lot of Japanese games with substantial text use.

The consequence for a project designed in English first is unavoidable and worth confronting early: if your interface assumes eight-pixel text, Japanese does not fit into that design. Either you raise the base text size across the whole game — which is the cleaner outcome and also a visual redesign — or you accept a per-language font size, which means every text container must tolerate a different metric. That decision is much cheaper before the UI art is finished than after.

One font or two, and the seam between them

Japanese pixel fonts almost always include their own Latin glyphs at half the cell width, so a twelve-pixel font draws Japanese at twelve pixels wide and English at six. This matters more than it sounds, because Japanese text is full of Latin and digits: item counts, level numbers, damage values, key names, and untranslated proper nouns.

Using the Japanese font's built-in Latin glyphs gives you a single set of metrics — one baseline, one line height, one advance rule — and everything on the line agrees. The cost is that a Latin set designed as an accessory to a CJK font is rarely as characterful as a dedicated Latin pixel font, and if your game's visual identity is partly carried by its font, you will notice.

Using two fonts gives you the Latin you designed around, and hands you a seam. Two pixel fonts drawn at the same nominal size will usually disagree about baseline position, cap height, and vertical centering, because CJK glyphs are designed to fill the em square while Latin glyphs sit on a baseline with room for descenders. The symptom is text that looks like it is bouncing when scripts alternate within one line.

If you go with two, treat the alignment as data rather than something to eyeball once: a per-font vertical offset and line height stored alongside the font, applied by the drawing code. Then test on the worst case, which is a single line containing both scripts and a number — something like a HUD readout or an item name with a quantity. If that line looks settled, the rest will.

Rendering rules that keep the pixels intact

A pixel font stops being a pixel font the moment a single pixel is interpolated. These rules are unglamorous and each of them is a real shipped bug in someone's game:

  • Scale only by whole numbers. A pixel font at 1.5x has no correct answer for half its pixels, and the renderer will invent one
  • Use nearest-neighbour sampling for the font texture, never bilinear filtering, and disable mipmaps on the atlas
  • Snap text draw positions to whole pixels in your rendering resolution. Text attached to a smoothly moving camera or a tweened panel lands on fractional coordinates and shimmers as it moves
  • If the font is a pixel-styled TTF rather than a bitmap atlas, render it at exactly its design size or an integer multiple of it, with hinting and antialiasing off. These fonts are drawn to snap to a specific pixel grid and blur at any other size
  • Render the interface at a fixed low resolution and scale the whole frame up by an integer, rather than drawing text at the display resolution. This makes correctness the default instead of something each text element has to get right individually

The arithmetic of what actually fits

Pixel games have an advantage here that higher-resolution games lack: text fitting is arithmetic, not estimation. Almost all CJK glyphs in a given pixel font advance the same width, and Latin glyphs in the same font are typically exactly half that. So you can state the capacity of every text box as a number of characters, before any translation exists.

Work it out once per text container and write it down. A dialogue box on a three-hundred-and-twenty pixel wide canvas, with eight pixels of padding on each side, has three hundred and four usable pixels. At a twelve-pixel font that is twenty-five Japanese characters per line, or fifty Latin characters — which in practice is around eight or nine English words. Three lines gives you seventy-five Japanese characters or roughly a hundred and fifty Latin ones.

Those numbers are the single most useful thing you can hand a translator, and they belong in the translation file next to the string rather than in a document nobody opens. A limit expressed as characters per line for this specific box is something a translator can work to. 'Please keep it short' is not.

Do the calculation in both directions, because the direction of expansion is not consistent. Japanese usually needs fewer characters than English to say the same thing, but each one occupies double the width, so a box sized generously for English can still overflow. Going the other way, a box sized to fit Japanese comfortably can overflow in German or Russian, where words are long and the font is half-width. If you are shipping more than two languages, size the box to the worst case you will actually ship rather than to the source language.

Canvas width          320 px
Box padding            8 px each side
Usable width         304 px

Font 12 px
  Japanese (full width, 12 px)   304 / 12 = 25 chars per line
  Latin    (half width,  6 px)   304 /  6 = 50 chars per line

3-line box -> 75 Japanese characters, or ~150 Latin characters
Give the translator these numbers, not "keep it short".

Coverage, subsetting, and the licence you have to read

Glyph coverage is the question of which characters the font actually contains, and for Japanese the useful thresholds are well defined. The set of common-use kanji designated for general writing numbers a little over two thousand characters, and the first level of the older JIS standard, which is the practical target for a font aiming at general text, is close to three thousand. Below that, ordinary words start hitting characters the font does not have.

The reassuring part is that bitmap kanji at pixel-art sizes are cheap. Three thousand glyphs at twelve by twelve pixels is well under half a million pixels of atlas — comfortably inside a single one-thousand-and-twenty-four square texture. Font size only becomes a memory problem at high resolutions or with vector fonts, which is a different category of game from this one.

Subsetting — generating an atlas containing only the characters your translated text actually uses — is still worth doing for large sets, but it introduces a dependency that must be automated. Every text change can add a character that is not in the atlas, and the symptom in the shipped build is a blank box in the middle of a sentence in a language your team does not read. Make atlas generation a build step that reads your localization files, and make a character missing from the font a build failure rather than a runtime surprise.

Licensing deserves more attention for pixel fonts than for ordinary ones, because your use is unusual: you are embedding the font into a game binary, often after converting it into a texture atlas, which some licences treat as modification and redistribution. Well-known freely available Japanese pixel fonts that developers commonly evaluate include PixelMplus at ten and twelve pixels, Misaki at eight by eight, and k8x12. Terms vary between them and can change over time, so read the licence on the distribution page yourself, confirm that embedding and commercial use are permitted, note any attribution requirement, and keep a copy of the licence text in your project so the answer is still available two years from now.

If a language you want to ship falls outside your font's coverage, that is a product decision, not a technical detail. Shipping it with a non-pixel fallback font is visually inconsistent but readable; shipping it with missing glyphs is not shippable at all. Decide deliberately, and prefer dropping a language over shipping one full of blank boxes.

What to check when you add a language

Most of these are invisible in a spreadsheet and obvious in thirty seconds of looking at the game, which is why the check is worth building into your process rather than leaving to chance:

  • Render a test screen containing every character that appears in the translated text, and read it at the size the player sees — not zoomed in an editor, where everything is legible
  • Look specifically for dense characters that are present but not readable at your grid size. A font can technically cover a character and still turn it into a smudge
  • Check a line that mixes scripts and digits, since that is where a two-font setup shows its seam
  • Check line spacing per language. CJK glyphs fill the em square, so lines that look correctly spaced in Latin can touch in Japanese
  • Check wrapping on a language with no spaces, and confirm lines do not begin with a closing bracket or a full stop
  • Verify integer scaling survives every path text takes: fullscreen, windowed, resized, and any camera zoom or screen shake
  • Re-run the atlas generation and the missing-character check after every text update, including hotfixes — that is when the character nobody planned for arrives

Related articles