RORK LABJP
RORKMAX — Rork Max generates pure Swift instead of React Native, enabling true native apps across iPhone, iPad, Watch, TV, Vision Pro, and iMessageAPPLE — Rork's 2026 direction has a clear theme of native empowerment across the Apple ecosystemEXPO — Standard builds run on React Native and Expo, so you're left with a real project structure and code you can keep working onFUNDING — Rork recently raised $15M and now sees over 743,000 monthly visits with 85% growthPRICING — Rork is free to start, with paid plans from $25/month and Rork Max at $200/monthCROSS — Rork builds iOS, Android, and web from a single prompt, finished off with a bit of follow-up tweakingRORKMAX — Rork Max generates pure Swift instead of React Native, enabling true native apps across iPhone, iPad, Watch, TV, Vision Pro, and iMessageAPPLE — Rork's 2026 direction has a clear theme of native empowerment across the Apple ecosystemEXPO — Standard builds run on React Native and Expo, so you're left with a real project structure and code you can keep working onFUNDING — Rork recently raised $15M and now sees over 743,000 monthly visits with 85% growthPRICING — Rork is free to start, with paid plans from $25/month and Rork Max at $200/monthCROSS — Rork builds iOS, Android, and web from a single prompt, finished off with a bit of follow-up tweaking
Articles/Dev Tools
Dev Tools/2026-07-13Advanced

When "{n} items" Breaks Across Languages — Designing Quantity Strings with CLDR Plural Categories and Intl.PluralRules

The assumption that one is singular and everything else is plural falls apart in Russian and Arabic. Here is how to hold the CLDR plural categories as a map and render quantities correctly with Intl.PluralRules and i18next, drawn from localizing an indie wallpaper app into sixteen languages.

Rork505Localization8PluralsIntl.PluralRulesi18next

Premium Article

A few days after shipping a wallpaper app in sixteen languages, I got a short note from a Russian-speaking user: the favorites count "looked off somehow." On my own iPhone, in Japanese and in English, nothing was wrong.

It took me a while to trace it. I had written the count as n === 1 ? "1 item" : n + " items". If you only ever look at English and Japanese, that branch looks permanently correct. But in Russian the word form changes between two and five, and then twenty-one snaps back to the same form as one. The very premise of the ternary simply did not exist in that language.

This article reframes how quantity strings branch per language through the map of CLDR plural categories, then walks through selecting the right form with Intl.PluralRules and i18next. When you send a Rork or Expo app out into the world, this is the quiet trap I want to close before release.

Where "one is singular, everything else is plural" stops holding

The singular-versus-plural split we carry around unconsciously is really just a convenience of one language: English. Look across the world's languages and quantity forms are far more varied.

Japanese has no grammatical plural at all. "1 item" and "3 items" share the same form; you just drop n in. English is special only at one, then flat. If that were the whole world, a ternary would be enough.

The trouble starts beyond that. Russian and Ukrainian pick among three forms based on the trailing digits. Polish is similarly intricate, and Arabic carries six forms: zero, one, two, few, many, and other. A single "everything else is plural" branch cannot render any of those languages correctly.

So quantity bugs surface only in the languages a developer can't read. They never reproduce on your own device, so review never catches them. That is exactly why the per-language rules should live in a standardized map, not in your head.

Hold the CLDR plural categories as a map

That map is the CLDR (Unicode Common Locale Data Repository) plural categories. CLDR defines each language's quantity rules as a mapping onto one of six categories.

CategoryMeaningRepresentative languages
oneSingular-likeEnglish, German, Spanish (at 1)
otherDefault / everything elseJapanese, Chinese, Korean (only this)
fewSmall countsRussian, Polish, Czech
manyLarge countsRussian, Polish, Arabic
twoDualArabic, Slovenian, Welsh
zeroZeroArabic, Latvian

The point is that these are not numbers but a language's own partitioning of word forms. Russian classifying 21 as one is counterintuitive, yet you never have to memorize the rules. Let CLDR hold the map; you only supply one string per category name.

In a language like Japanese that has only other, the translator writes a single string. Whether more categories exist is the language's business, and the calling code should absorb that difference behind one identical call.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Why a ternary plural breaks in Russian, Arabic, and Polish, explained through CLDR categories
A reusable helper that selects the right form with Intl.PluralRules, plus a Hermes fallback
How to keep cardinals and ordinals apart, and how to test the languages that actually break
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Dev Tools2026-07-14
Designing Seams That Survive AI Regeneration in Rork
Every follow-up prompt to Rork can quietly wipe out logic you wrote by hand. Protecting it with prompts is a patch, not a fix. Here is how to separate generated code from code you own, and draw a boundary that regeneration cannot reach, with working Zustand and service-layer examples.
Dev Tools2026-07-14
Adding a Single Zod Validation Boundary to Rork's Generated Fetch Code
The network code Rork generates implicitly trusts the shape of the response. When the API shifts, the screen quietly goes blank. Here is how to slip a single Zod parse layer between the generated UI and the network to make failures predictable, with numbers from real operation.
Dev Tools2026-07-13
postMessage Is Fire-and-Forget — Designing a Correlated Request/Response Bridge Between a WebView and React Native
postMessage between a WebView and React Native is one-way, so you never learn whether the work you asked for actually succeeded. Here is a typed request/response bridge, with correlation IDs and timeouts, built in working TypeScript.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →