Intl.js Polyfill
Intl.js is a robust polyfill for the ECMA-402 ECMAScript Internationalization API, designed to provide comprehensive localization methods, including `Intl.NumberFormat` and `Intl.DateTimeFormat`, across various JavaScript environments. Currently at version 1.2.5, this library addresses the absence of native `Intl` support or incomplete locale data in legacy browsers like older Safari, as well as specific Node.js versions prior to 0.12 or lacking full CLDR data. Its release cadence is event-driven, with major/minor updates coinciding with new editions of the Ecma-402 specification (e.g., v1.2.1 for Ecma-402 2016) and significant CLDR data updates (e.g., v1.1.0 for CLDR 28.0.0). Patch releases are frequent for bug fixes and minor improvements. A key advantage of Intl.js is its ability to seamlessly integrate with public polyfill services like `cdn.polyfill.io`, ensuring that the polyfill code and corresponding locale data are only loaded by browsers that genuinely require them, thereby optimizing application performance and bandwidth usage. For server-side Node.js applications, it offers explicit mechanisms to detect and patch the runtime with the necessary `Intl` constructors and locale information. This package is crucial for developers building internationally-aware applications targeting a wide range of client and server environments.
Common errors
-
ReferenceError: Intl is not defined
cause The JavaScript runtime environment (e.g., an older browser, or specific Node.js versions) does not natively provide the ECMA-402 Intl API, and the `intl` polyfill has not been loaded or applied.fixFor browsers, include the `intl.js` polyfill via a script tag (ideally through a polyfill service like `cdn.polyfill.io`). For Node.js, ensure `require('intl')` is executed and `global.Intl` is patched before any `Intl` API usage, following the recommended conditional polyfill pattern. -
TypeError: Intl.NumberFormat is not a constructor
cause While a global `Intl` object might exist, the specific constructor (e.g., `NumberFormat` or `DateTimeFormat`) might be missing or not properly assigned, often due to an incomplete polyfill or a runtime with partial `Intl` support.fixVerify that `Intl.NumberFormat` and `Intl.DateTimeFormat` (or other required constructors) are explicitly assigned from the `intl` polyfill object (e.g., `Intl.NumberFormat = IntlPolyfill.NumberFormat;`) after `require('intl')`. -
Error: No locale data has been provided for this object.
cause An `Intl` formatting object (like `NumberFormat` or `DateTimeFormat`) was instantiated for a locale whose data was not loaded or made available to the `intl` polyfill.fixWhen using the polyfill, ensure all necessary locale data is loaded. If using `polyfill.io`, explicitly list all required locales (e.g., `features=Intl.~locale.en,Intl.~locale.fr`). If bundling locally, verify that the CLDR data for your target locales is included in your build.
Warnings
- breaking Version 0.1.3 introduced a regression where some data arrays were accidentally sorted, causing incorrect behavior. This was fixed immediately in v0.1.4.
- gotcha The behavior of `toLocaleString()` was changed in v0.1.3. It no longer overrides native ECMA-402 implementations if they already exist in the environment.
- breaking As of v1.2.5, `locale-data/json/*.json` files were removed from the npm package. This change impacts builds or setups that directly accessed these files within the `node_modules/intl` directory.
- gotcha Node.js environments have varied `Intl` support: versions prior to 0.12 and >=v3.1 lack native `Intl` APIs entirely, requiring a full polyfill. Node.js 0.12 has built-in `Intl` but often only includes English locale data, necessitating partial polyfilling for other locales.
Install
-
npm install intl -
yarn add intl -
pnpm add intl
Imports
- Intl (Polyfill Object)
import Intl from 'intl';
const IntlPolyfill = require('intl'); // ... then potentially global.Intl = IntlPolyfill; - Intl.NumberFormat, Intl.DateTimeFormat (for patching)
import { NumberFormat, DateTimeFormat } from 'intl';const IntlPolyfill = require('intl'); Intl.NumberFormat = IntlPolyfill.NumberFormat; Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat; - window.Intl (Browser via Polyfill Service)
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en,Intl.~locale.fr"></script>
Quickstart
var areIntlLocalesSupported = require('intl-locales-supported');
var localesMyAppSupports = [
'en-US',
'fr-FR',
'de-DE',
'es-ES'
];
// This example demonstrates how to conditionally polyfill the Intl API
// in Node.js environments, ensuring that the necessary locale data is available.
// It checks if global.Intl exists and if it supports the required locales.
// If not, it loads and applies the intl polyfill.
if (global.Intl) {
// Determine if the built-in `Intl` has the locale data we need.
if (!areIntlLocalesSupported(localesMyAppSupports)) {
// `Intl` exists, but it doesn't have the data we need, so load the
// polyfill and patch the constructors we need with the polyfill's.
var IntlPolyfill = require('intl');
Intl.NumberFormat = IntlPolyfill.NumberFormat;
Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat;
console.log('Patched built-in Intl with polyfill data for missing locales.');
} else {
console.log('Built-in Intl supports all required locales.');
}
} else {
// No `Intl` object globally, so use and load the polyfill entirely.
global.Intl = require('intl');
console.log('No native Intl, loaded full polyfill.');
}
// Example usage after polyfilling
const number = 123456.789;
console.log('Formatted number (en-US):', new Intl.NumberFormat('en-US').format(number));
console.log('Formatted number (fr-FR):', new Intl.NumberFormat('fr-FR').format(number));
const date = new Date();
console.log('Formatted date (en-US):', new Intl.DateTimeFormat('en-US').format(date));
console.log('Formatted date (de-DE):', new Intl.DateTimeFormat('de-DE', { dateStyle: 'full', timeStyle: 'short' }).format(date));