When you translate a UI, the question that bites is never "is the translation right?" first. It's "does it still fit?" A button label that fits in English can overflow in German, and a card sized for French can look half-empty in Japanese.
We had a convenient way to measure this. LoveCalcs shows a daily "Love Insight" card: one short relationship tip and one general fact about love. Every item exists in 11 languages, row-aligned, so tip-037 is the same tip in each column. We published the set as an open dataset (CC BY 4.0, overview here), which made it easy to ask a simple question: on average, how long is the same idea in each language?
Counting characters properly
The first trap is JavaScript's length. It counts UTF-16 code units, not characters, so anything outside the Basic Multilingual Plane (many emoji, some rare CJK characters) counts as two. Spreading the string into an array counts code points instead:
"❤️".length // 2 (a heart plus a variation selector)
[..."❤️"].length // 2 code points, still not 1 visible symbol
[..."日本語"].length // 3
Even code points aren't "what you see": the heart above is one visible symbol made of two code points. For true user-perceived characters you'd use Intl.Segmenter with granularity: "grapheme". Our texts are plain prose with no emoji, so code points were good enough, and that's what we used:
const lengths = langs.map((lang) => ({
lang,
avgChars: Math.round(d3.mean(tips, (d) => [...d[lang]].length)),
}));
The result
Average characters per tip, across 122 tips:
| Language | Avg characters |
|---|---|
| French | 166 |
| German | 166 |
| Portuguese | 161 |
| Italian | 160 |
| Spanish | 159 |
| Russian | 147 |
| English | 142 |
| Hindi | 139 |
| Arabic | 113 |
| Japanese | 66 |
| Chinese | 48 |
The 117 facts tell the same story (French 167, English 141, Chinese 42). The Romance languages and German run about 12 to 17% longer than English, which is in line with the expansion usually budgeted for translated sentences (short labels often expand much more). Arabic is noticeably shorter in characters, and Japanese and Chinese need roughly a third to a half as many.
Why character count isn't the whole story
Fewer characters doesn't mean less space. Chinese and Japanese glyphs are typically full-width, roughly twice as wide as a Latin letter at the same font size, so a 48-character Chinese tip takes up about as much horizontal room as 90 to 100 Latin characters. Arabic is shorter but runs right to left, and its letters join, so line breaks fall differently. Hindi in Devanagari has stacked marks above and below the line, which needs extra line height or the text looks cramped.
What the numbers suggest for any card or button that holds translated text:
- Avoid fixed heights. Our insight card has none: it grows with its text, so a 166-character French tip and a 48-character Chinese one both fit without clipping.
-
Give some scripts more line height. Devanagari and Arabic usually read better with a slightly taller
line-heightthan Latin text. -
Use logical CSS properties.
margin-inline-startinstead ofmargin-leftlets a layout flip cleanly for right-to-left languages. - Test with the longest language, not English. French or German will show an overflow long before English does.
Try it yourself
There's an interactive version of the chart on Observable where you can step through each tip and read it in all 11 languages side by side. The data is also on Hugging Face and has a DOI on Zenodo if you want to cite it. The translations were made with AI assistance, so treat it as a handy layout and testing set rather than a gold-standard translation corpus.
Top comments (0)