Currency Formatting Differences by Locale
How the same amount is formatted differently across locales. Covers symbol placement, decimal and thousands separators, narrow symbols, and right-to-left currency formatting.
Detailed Explanation
Locale-Specific Currency Formatting
The same monetary amount can look dramatically different depending on the user's locale. Understanding these differences is essential for building truly international applications.
Symbol Position
| Locale | Format | Example |
|---|---|---|
| en-US | Symbol before, no space | $1,234.56 |
| de-DE | Symbol after, with space | 1.234,56 € |
| fr-FR | Symbol after, narrow space | 1 234,56 € |
| ja-JP | Symbol before, no space | ¥1,234 |
| ar-SA | Symbol after | ١٬٢٣٤٫٥٦ ر.س. |
Decimal and Thousands Separators
| Locale | Decimal | Thousands | Example |
|---|---|---|---|
| en-US | . (period) | , (comma) | 1,234.56 |
| de-DE | , (comma) | . (period) | 1.234,56 |
| fr-FR | , (comma) | (thin space) | 1 234,56 |
| sv-SE | , (comma) | (space) | 1 234,56 |
| hi-IN | . (period) | , (Indian) | 1,23,456.78 |
Indian Numbering System
India uses a unique grouping system (lakhs and crores):
new Intl.NumberFormat("en-IN", {
style: "currency",
currency: "INR",
}).format(1234567.89);
// => "₹12,34,567.89" (not ₹1,234,567.89)
Negative Amount Formats
How negative amounts are displayed varies:
const amount = -1234.56;
// en-US: -$1,234.56
// de-DE: -1.234,56 €
// ja-JP: -¥1,234.56
// Accounting (en-US): ($1,234.56)
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
currencySign: "accounting",
}).format(-1234.56);
// => "($1,234.56)"
Right-to-Left (RTL) Currencies
Arabic and Hebrew locales present unique challenges:
- Text direction is RTL, but numbers are still LTR
- Currency symbols may appear on either side
- Use CSS
direction: rtlwithunicode-bidi: embedfor proper rendering - Always test with RTL locales
Best Practice
Never build locale formatting manually. Use Intl.NumberFormat and let the browser's ICU data handle the complexity:
function formatMoney(amount, currency, locale) {
return new Intl.NumberFormat(locale, {
style: "currency",
currency: currency,
}).format(amount);
}
Use Case
Frontend developers building international applications need to understand how currency formatting varies by locale. Using Intl.NumberFormat correctly is the simplest approach, but knowing the underlying rules helps when debugging formatting issues, building PDF generators that don't support Intl, or validating user input that may use different separator conventions.