npm.io
2.3.9 • Published 2h ago

@formatjs/intl-supportedvaluesof

Licence
MIT
Version
2.3.9
Deps
1
Size
220 kB
Vulns
0
Weekly
0

@formatjs/intl-supportedvaluesof

Polyfill for Intl.supportedValuesOf()

npm Version

ECMA-402 Spec Compliance

This package implements the ECMA-402 Intl.supportedValuesOf() specification:

  • Spec Section: 8.3.2 Intl.supportedValuesOf(key)
  • Returns: Supported values for internationalization keys
  • Fully spec-compliant: No optional parameters, matches native browser behavior

Installation

npm install @formatjs/intl-supportedvaluesof

Usage

As Polyfill

Import the polyfill to make Intl.supportedValuesOf available globally:

import '@formatjs/intl-supportedvaluesof/polyfill'

// Now available on the global Intl object
const calendars = Intl.supportedValuesOf('calendar')
// ['buddhist', 'chinese', 'coptic', 'dangi', 'ethioaa', 'ethiopic', 'gregory', ...]

const currencies = Intl.supportedValuesOf('currency')
// ['AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', ...]

const timeZones = Intl.supportedValuesOf('timeZone')
// ['Africa/Abidjan', 'Africa/Accra', ..., 'Pacific/Wallis']
Direct Import

Import the function directly without modifying the global namespace:

import {supportedValuesOf} from '@formatjs/intl-supportedvaluesof'

const numberingSystems = supportedValuesOf('numberingSystem')
// ['adlm', 'ahom', 'arab', 'arabext', 'bali', 'beng', 'bhks', ...]

const units = supportedValuesOf('unit')
// ['acre', 'bit', 'byte', 'celsius', 'centimeter', 'day', 'degree', ...]

Supported Keys

The function accepts one of six string keys and returns an array of supported values:

Key Returns Example Values
'calendar' Supported calendar systems 'gregory', 'islamic', 'buddhist', 'chinese'
'collation' Supported collation algorithms 'emoji', 'eor', 'phonebk', 'search'
'currency' Supported ISO 4217 currency codes 'USD', 'EUR', 'JPY', 'GBP'
'numberingSystem' Supported numbering systems 'arab', 'latn', 'hanidec', 'thai'
'timeZone' Supported IANA time zones 'America/New_York', 'Europe/London', 'Asia/Tokyo'
'unit' Supported measurement units 'meter', 'celsius', 'liter', 'acre'

API

supportedValuesOf(key: string): string[]

Returns an array of supported values for the given key.

Parameters:

  • key - One of: 'calendar', 'collation', 'currency', 'numberingSystem', 'timeZone', 'unit'

Returns:

  • A sorted array of unique string values

Throws:

  • RangeError - If the key is not one of the supported values

Example:

import {supportedValuesOf} from '@formatjs/intl-supportedvaluesof'

// Valid usage
const calendars = supportedValuesOf('calendar')
console.log(calendars) // ['buddhist', 'chinese', 'coptic', ...]

// Invalid key throws RangeError
try {
  supportedValuesOf('invalid')
} catch (e) {
  console.error(e) // RangeError: Invalid key: invalid
}

Implementation Details

This polyfill dynamically validates candidate values against the actual Intl implementation rather than maintaining static lists. This approach ensures:

  • Accuracy: Results match what your JavaScript runtime actually supports
  • Runtime-specific: Different engines (V8, JavaScriptCore, SpiderMonkey) may support different values
  • Up-to-date: No need to manually update lists when new values are added to engines
How It Works

For each category, the implementation:

  1. Loads candidate values from CLDR (Unicode Common Locale Data Repository)
  2. Tests each value by attempting to create an appropriate Intl formatter with that value
  3. Validates acceptance by checking if the formatter actually uses the requested value
  4. Returns filtered list of only the values that passed validation
Example: Calendar Validation
// Implementation tests if a calendar is supported:
function isSupportedCalendar(calendar) {
  try {
    // Attempt to create DateTimeFormat with this calendar
    const formatter = new Intl.DateTimeFormat(`en-u-ca-${calendar}`)
    // Verify the calendar was actually accepted
    const resolvedOptions = formatter.resolvedOptions()
    return resolvedOptions.calendar === calendar
  } catch {
    return false
  }
}

This ensures that only calendars actually supported by your runtime are returned, not just a static list.

TypeScript Support

This package includes TypeScript type definitions. When using as a polyfill, the global Intl namespace is automatically augmented:

import '@formatjs/intl-supportedvaluesof/polyfill'

// TypeScript knows about Intl.supportedValuesOf
const calendars: string[] = Intl.supportedValuesOf('calendar')

// TypeScript will error on invalid keys
Intl.supportedValuesOf('invalid') // Error: Argument of type '"invalid"' is not assignable...

Browser Support

This polyfill is only needed for older browsers that don't have native support for Intl.supportedValuesOf(). Native support is available in:

  • Chrome 99+
  • Edge 99+
  • Firefox 93+
  • Safari 15.4+

The polyfill requires the following Intl APIs to be available:

  • Intl.DateTimeFormat (for calendar, timeZone, numberingSystem)
  • Intl.NumberFormat (for currency, unit, numberingSystem)
  • Intl.Collator (for collation)

Breaking Changes in v3.0

Removed: Non-standard locale parameter

v2.x and earlier had a non-standard optional locale parameter that filtered results by locale. This has been removed to match the ECMA-402 specification.

// ❌ v2.x (non-standard, no longer works)
const calendars = supportedValuesOf('calendar', 'en-US')

// ✅ v3.0 (spec-compliant)
const calendars = supportedValuesOf('calendar')

The function now always returns ALL supported values, matching native browser behavior.

Migration Guide

If you need locale-specific filtering in v3.0+, implement it yourself:

import {supportedValuesOf} from '@formatjs/intl-supportedvaluesof'

// Get all supported calendars
const allCalendars = supportedValuesOf('calendar')

// Filter by what a specific locale actually uses/accepts
const enUSCalendars = allCalendars.filter(calendar => {
  try {
    const formatter = new Intl.DateTimeFormat('en-US', {calendar})
    return formatter.resolvedOptions().calendar === calendar
  } catch {
    return false
  }
})

However, note that most use cases don't need locale-specific filtering, as the spec's design returns all values that any locale could use.

Examples

Check if a calendar is supported
import {supportedValuesOf} from '@formatjs/intl-supportedvaluesof'

const calendars = supportedValuesOf('calendar')

if (calendars.includes('islamic')) {
  console.log('Islamic calendar is supported')
  const formatter = new Intl.DateTimeFormat('en-US', {calendar: 'islamic'})
  console.log(formatter.format(new Date()))
}
Display all supported currencies
import {supportedValuesOf} from '@formatjs/intl-supportedvaluesof'

const currencies = supportedValuesOf('currency')

console.log(`This runtime supports ${currencies.length} currencies:`)
currencies.forEach(currency => {
  const formatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency,
  })
  console.log(`${currency}: ${formatter.format(100)}`)
})
Validate user input
import {supportedValuesOf} from '@formatjs/intl-supportedvaluesof'

function isValidTimeZone(timeZone) {
  const supportedTimeZones = supportedValuesOf('timeZone')
  return supportedTimeZones.includes(timeZone)
}

console.log(isValidTimeZone('America/New_York')) // true
console.log(isValidTimeZone('Invalid/TimeZone')) // false

License

MIT

Resources

Keywords