Rxova
Skip to content

Introduction

A React currency <input> that’s correct in every language. Bulgarian spaces, Japanese yen, Hindi lakhs, Arabic digits, Swiss apostrophes — all right by default. Zero dependencies, no cursor jumps, no config. Pass a locale and a currency; Intl does the rest.

One amount formatted in Bulgarian, German, French, Japanese, Egyptian and Kuwaiti Arabic, Hindi and Swiss German

Every other library hardcodes “a comma every three digits” and breaks the moment it meets Bulgarian or Hindi. This one asks Intl.NumberFormat for the answer — so 5000 stays 5000 but 50000 becomes 50 000, ¥ shows no decimals, and ₹ groups in lakhs. Automatically.

Terminal window
pnpm add @rxova/react-intl-currency-input
react and react-dom (>= 18) are the only peers. No stylesheet to import.

There is no <input type="currency">. A currency field has to, per locale:

  • pick the right group separator, (en-US), . (de-DE), and a non-breaking space in bg-BG / fr-FR (U+00A0 or U+202F, not an ASCII space);
  • pick the right decimal separator. or ,;
  • place the symbol correctly — leading $5, trailing 5 € — where the symbol may be multiple characters and contain letters (лв., CHF, , kr);
  • use the right number of fraction digits — JPY 0, most currencies 2, KWD/BHD 3;
  • honor the minimum-grouping quirk — Bulgarian shows no group separator below 10000 (50005000, but 5000050 000);
  • optionally render native digits — ar-EG ٠١٢٣, fa-IR, bn-IN;

…and do all of that without the caret jumping as separators shift while typing.

Every one of those bullets except the caret is already solved by Intl.NumberFormat — if you let it own the formatting and never reconstruct grouping yourself.

The most-downloaded React currency inputs are buggy precisely because they re-implement grouping with a hardcoded separator and a hardcoded “every three digits” rule. That is what mis-formats Bulgarian and inserts a separator where there should be none.

This library delegates 100% of formatting to Intl and derives every separator from formatToParts. Bulgarian, right-to-left symbol placement, and three-digit currencies then come out correct by construction — they are not special cases in the code.

Rather than fight caret math, the field simply shows a formatted value when idle and a plain number while focused. No separators move while you type, so there is nothing to reposition. It is a small, arguably-correct UX trade for a field you only read formatted once you are done.

LibraryApproachThe gap
@rxova/react-intl-currency-inputDelegates all formatting to Intl
react-currency-input-fieldHardcoded separator + “every 3 digits”Mis-formats bg-BG; groups below 10000 where it should not
react-number-formatIts own parser/formatter, separators by handCorrect only if you know every locale rule — the work this library removes
react-text-maskA mask is a hardcoded-locale assumptionNo Intl awareness at all

Not “another masked money input” — the locale-correct one.