Lightweight Internationalization: Replace Libraries with the Intl API

Your JavaScript bundle includes Moment.js? That’s 280KB for date formatting. The native JavaScript Intl API? Zero kilobytes. This stark difference represents thousands of dollars in bandwidth costs and seconds of load time that directly impact your conversion rates.
Modern web applications don’t need heavy internationalization libraries. The JavaScript Intl API provides date formatting, number formatting, currency formatting, pluralization, and string sorting—all built into the browser. This article shows you how to replace Moment.js, date-fns, numeral.js, and similar libraries with native solutions that improve performance and reduce complexity.
Key Takeaways
- The Intl API adds zero kilobytes to your bundle while libraries like Moment.js add 280KB
- Native browser support covers over 99.5% of users—no polyfills needed
- Replace date formatting, number formatting, and pluralization with built-in APIs
- Cache formatter instances for optimal performance in production
Why Replace Heavy Libraries with the JavaScript Intl API
The Bundle Size Problem
Popular internationalization libraries add significant weight to your application:
- Moment.js: 280KB (67KB gzipped)
- date-fns: 75KB (17KB gzipped) for common functions
- numeral.js: 72KB (18KB gzipped)
These numbers compound when you include locale data. The JavaScript Intl API requires zero additional bytes—it’s already in the browser.
Native Browser Support in 2025
Browser compatibility is no longer a concern. The Intl API has universal support across all modern browsers. Only Internet Explorer and Opera Mini lack support—browsers that represent less than 0.5% of global usage. Your users already have these APIs.
Date and Time Formatting with Intl.DateTimeFormat
Basic Date Formatting
Replace Moment.js date formatting:
// Before: Moment.js
moment().format('MMMM DD, YYYY'); // "October 3, 2025"
// After: Native Intl
new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(new Date()); // "October 3, 2025"
Advanced Options
The native API handles time zones and complex formatting:
new Intl.DateTimeFormat('en-GB', {
dateStyle: 'full',
timeStyle: 'short',
timeZone: 'Europe/London'
}).format(new Date()); // "Friday, 3 October 2025 at 15:30"
Relative Time Formatting Without Libraries
Replace moment.fromNow()
with native relative time:
// Before: Moment.js
moment().subtract(2, 'hours').fromNow(); // "2 hours ago"
// After: Native Intl
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
rtf.format(-2, 'hour'); // "2 hours ago"
rtf.format(1, 'day'); // "tomorrow"
The API automatically handles pluralization and localization across languages.
Discover how at OpenReplay.com.
Number and Currency Formatting Made Simple
Number Formatting
Replace numeral.js with native number formatting:
// Before: numeral.js
numeral(1234567.89).format('0,0.00'); // "1,234,567.89"
// After: Native Intl
new Intl.NumberFormat('en-US').format(1234567.89); // "1,234,567.89"
new Intl.NumberFormat('de-DE').format(1234567.89); // "1.234.567,89"
Currency Formatting
Native currency formatting eliminates external dependencies:
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
formatter.format(1234.5); // "$1,234.50"
// Japanese Yen (no decimal places)
new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY'
}).format(1234); // "¥1,234"
Smart Pluralization with Intl.PluralRules
Replace complex conditional logic with native pluralization:
const pr = new Intl.PluralRules('en-US', { type: 'ordinal' });
const suffixes = { one: 'st', two: 'nd', few: 'rd', other: 'th' };
function ordinal(n) {
const rule = pr.select(n);
return `${n}${suffixes[rule]}`;
}
ordinal(1); // "1st"
ordinal(22); // "22nd"
ordinal(103); // "103rd"
Locale-Aware String Sorting with Intl.Collator
Replace custom sorting with native locale-aware collation:
// Numeric-aware sorting
const collator = new Intl.Collator('en', { numeric: true });
['item2', 'item10', 'item1'].sort(collator.compare);
// ["item1", "item2", "item10"]
// German sorting (ä comes after a)
const germanCollator = new Intl.Collator('de');
['Müller', 'Mueller', 'Maler'].sort(germanCollator.compare);
// ["Maler", "Mueller", "Müller"]
Best Practices for Production
Formatter Caching
Create formatters once and reuse them:
// Cache formatters for performance
const formatters = new Map();
function getCurrencyFormatter(locale, currency) {
const key = `${locale}-${currency}`;
if (!formatters.has(key)) {
formatters.set(key, new Intl.NumberFormat(locale, {
style: 'currency',
currency
}));
}
return formatters.get(key);
}
Error Handling
Implement fallbacks for invalid inputs:
function safeFormat(date, locale = 'en-US', options = {}) {
try {
return new Intl.DateTimeFormat(locale, options).format(date);
} catch (error) {
console.warn(`Formatting failed for locale ${locale}`, error);
return new Intl.DateTimeFormat('en-US', options).format(date);
}
}
Limitations and Future Considerations
The Intl API excels at formatting but doesn’t handle date arithmetic. For calculations like adding days or finding differences between dates, you’ll need the upcoming Temporal API or a lightweight calculation library.
Consider keeping libraries only when you need:
- Complex date arithmetic
- Parsing arbitrary date strings
- Legacy browser support below IE11
Conclusion
The JavaScript Intl API transforms internationalization from a bundle-size burden into a zero-cost feature. By replacing Moment.js, date-fns, and numeral.js with native APIs, you eliminate dependencies, improve performance, and simplify maintenance.
Start your migration today: identify formatting-only uses of these libraries and replace them with Intl. Your users will experience faster load times, and your application will be more maintainable. The best code is the code you don’t have to ship.
FAQs
The Intl API handles formatting but not date arithmetic like adding days or calculating differences. For these operations, use native Date methods or wait for the Temporal API. Most applications only use libraries for formatting, making Intl a perfect replacement.
You'll save 280KB from removing Moment.js alone, reducing load time by 1-3 seconds on slower connections. Runtime performance improves too since native APIs are optimized at the browser level, often running 2-3x faster than JavaScript libraries.
All modern browsers support Intl APIs. Only Internet Explorer and Opera Mini lack support, representing less than 0.5% of users. If you must support these browsers, use a polyfill only for those users rather than shipping heavy libraries to everyone.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.