@shotlingo/localization-readiness
v0.1.0
Published
Per-locale text expansion, script family, and RTL/overflow risk for all 41 App Store Connect languages — check whether your app name still fits after translation. Zero dependencies, no network calls.
Maintainers
Readme
@shotlingo/localization-readiness
Per-locale text expansion, script family, and RTL/overflow risk for all 41 App Store Connect languages. Zero dependencies, no network calls.
npm i @shotlingo/localization-readinessThe problem
App Store metadata limits are enforced per locale. The app name field is capped at 30 characters in every language — not 30 for your English name and whatever the translation happens to need.
German runs about 35% longer than English. So a 26-character English name, comfortably inside the cap, projects to about 35 characters in German and will not be accepted as written. You find out at submission, after you have paid for the translation.
import { fitsEverywhere, overflowsIn, FIELD_LIMITS } from '@shotlingo/localization-readiness';
fitsEverywhere('Sleep Tracker & Smart Alarm', FIELD_LIMITS.title); // false
overflowsIn('Sleep Tracker & Smart Alarm', FIELD_LIMITS.title)
.map((l) => `${l.appStoreCode}: ${l.name}`);
// [ 'de-DE: German', 'pt-BR: Portuguese (Brazil)', ... ]API
| Export | What it gives you |
|---|---|
| LOCALES | All 41 locales, sorted by expansion (most-expanding first) |
| FIELD_LIMITS | title 30, subtitle 30, promotionalText 170 |
| getByCode(code) | Lookup by 'de' or 'de-DE', case-insensitive |
| getByScript(script) | 'latin' \| 'cyrillic' \| 'greek' \| 'cjk' \| 'arabic' \| 'hebrew' \| 'devanagari' \| 'thai' |
| getRtl() | The four right-to-left locales |
| projectLength(text, locale) | Projected character count after translation (rounds up) |
| overflowsIn(text, limit) | Locales where it will not fit |
| fitsEverywhere(text, limit) | true when it fits in all 41 |
Two things a length check alone gets wrong
Right-to-left is not a length problem. Hebrew expands 0%, so a length-only check calls it safe — but the layout mirrors: image placement, progress direction, and arrows all flip. All four RTL locales (ar, fa, he, ur) are marked overflowRisk: 'high' regardless of expansion, on purpose.
CJK contracts in characters but not in width. Chinese is ~50% shorter in character count, Japanese ~45%, Korean ~40% — but each character is visually wider, which is why widthPct is a separate field from expansionPct. Truncating on character count alone will cut CJK copy that was never going to overflow.
Related
- App Store localization checker — the interactive version, plus JSON and CSV downloads
@shotlingo/locale-codes— App Store / Play /.lproj/values-*code mapping@shotlingo/text-expansion— expansion ratios on their own@shotlingo/rejection-codes— App Review guideline codes and fixes
MIT © Alperen Güntekin
