or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-formatjs--intl-pluralrules

Polyfill for Intl.PluralRules providing locale-sensitive plural rule selection

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@formatjs/intl-pluralrules@5.4.x

To install, run

npx @tessl/cli install tessl/npm-formatjs--intl-pluralrules@5.4.0

index.mddocs/

Intl PluralRules Polyfill

A spec-compliant polyfill for the Intl.PluralRules API that provides locale-sensitive plural rule selection for internationalization applications. This polyfill offers full ECMAScript Conformance test suite compatibility, supports dynamic locale data loading for optimal bundle size, and provides flexible integration options including conditional polyfilling based on runtime capability detection.

Package Information

  • Package Name: @formatjs/intl-pluralrules
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @formatjs/intl-pluralrules

Core Imports

import { PluralRules } from "@formatjs/intl-pluralrules";

For CommonJS:

const { PluralRules } = require("@formatjs/intl-pluralrules");

For polyfill usage:

import "@formatjs/intl-pluralrules/polyfill";
// Or to force polyfill
import "@formatjs/intl-pluralrules/polyfill-force";

Utility imports:

import { shouldPolyfill } from "@formatjs/intl-pluralrules/should-polyfill";
import { supportedLocales } from "@formatjs/intl-pluralrules/supported-locales.generated";

Basic Usage

import { PluralRules } from "@formatjs/intl-pluralrules";
import "@formatjs/intl-pluralrules/locale-data/en";

// Create PluralRules instance
const pr = new PluralRules("en");

// Get plural rule for numbers
console.log(pr.select(0)); // "other"
console.log(pr.select(1)); // "one"
console.log(pr.select(2)); // "other"

// Use with ordinal numbers
const ordinalPr = new PluralRules("en", { type: "ordinal" });
console.log(ordinalPr.select(1)); // "one" (1st)
console.log(ordinalPr.select(2)); // "two" (2nd)
console.log(ordinalPr.select(3)); // "few" (3rd)
console.log(ordinalPr.select(4)); // "other" (4th)

// Check resolved options
console.log(pr.resolvedOptions());
// {
//   locale: "en",
//   type: "cardinal",
//   minimumIntegerDigits: 1,
//   minimumFractionDigits: 0,
//   maximumFractionDigits: 3,
//   pluralCategories: ["one", "other"]
// }

Architecture

The polyfill is built around several key components:

  • PluralRules Class: Main implementation conforming to the Intl.PluralRules specification
  • Locale Data System: Modular locale data that can be loaded on-demand for optimal bundle size
  • Polyfill Detection: Runtime capability detection to only polyfill when necessary
  • Abstract Operations: Internal functions following ECMAScript specification requirements
  • Type Safety: Full TypeScript integration with proper type definitions

Capabilities

PluralRules Constructor

Creates a new PluralRules instance with locale and formatting options.

/**
 * Creates a new PluralRules instance
 * @param locales - Locale identifier(s) or array of locale identifiers
 * @param options - Configuration options for plural rules
 */
class PluralRules implements Intl.PluralRules {
  constructor(locales?: string | string[], options?: Intl.PluralRulesOptions);
}

Plural Rule Selection

Returns the plural rule category for a given number.

/**
 * Returns the plural rule for the given number
 * @param val - Number to get plural rule for
 * @returns LDML plural rule category
 */
select(val: number): LDMLPluralRule;

Options Resolution

Returns the resolved options used by the PluralRules instance.

/**
 * Returns the resolved options object
 * @returns Object containing resolved locale and formatting options
 */
resolvedOptions(): Intl.ResolvedPluralRulesOptions;

String Representation

Returns the string representation of the PluralRules instance.

/**
 * Returns string representation of the PluralRules instance
 * @returns Always returns '[object Intl.PluralRules]'
 */
toString(): string;

Locale Support Detection

Checks which locales are supported by the implementation.

/**
 * Returns an array of supported locales from the provided list
 * @param locales - Locale identifier(s) to check
 * @param options - Options for locale matching
 * @returns Array of supported locale strings
 */
static supportedLocalesOf(
  locales?: string | string[],
  options?: Pick<Intl.PluralRulesOptions, 'localeMatcher'>
): string[];

Locale Data Management

Adds locale data to the polyfill for specific locales.

/**
 * Adds locale data to the polyfill
 * @param data - Locale data objects to add
 */
static __addLocaleData(...data: PluralRulesLocaleData[]): void;

Static Properties

Additional static properties available on the PluralRules class.

/**
 * Set of available locales supported by the polyfill
 */
static availableLocales: Set<string>;

/**
 * Default locale used when none is specified
 */
static getDefaultLocale(): string;

/**
 * Flag indicating this is a polyfilled implementation
 */
static polyfilled: boolean;

/**
 * Array of relevant Unicode extension keys (empty for PluralRules)
 */
static relevantExtensionKeys: never[];

/**
 * Internal locale data storage
 */
static localeData: Record<string, PluralRulesData>;

Polyfill Detection

Determines if the polyfill is needed for the current environment.

/**
 * Determines if polyfill is needed for the given locale
 * @param locale - Locale to check (defaults to 'en')
 * @returns Locale string if polyfill needed, undefined if native support exists
 */
function shouldPolyfill(locale?: string): string | undefined;

Supported Locales List

Array of all locale codes supported by the polyfill.

/**
 * Array of supported locale codes
 */
const supportedLocales: string[];

Types

/**
 * LDML plural rule categories
 */
type LDMLPluralRule = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';

/**
 * Internal slots interface for PluralRules instances
 * Note: NumberFormatDigitInternalSlots is from @formatjs/ecma402-abstract
 */
interface PluralRulesInternal extends NumberFormatDigitInternalSlots {
  initializedPluralRules: boolean;
  locale: string;
  type: 'cardinal' | 'ordinal';
}

/**
 * Structure for locale-specific plural rules data
 */
interface PluralRulesLocaleData {
  data: PluralRulesData;
  locale: string;
}

/**
 * Plural rules data containing categories and evaluation function
 */
interface PluralRulesData {
  categories: {
    cardinal: LDMLPluralRule[];
    ordinal: LDMLPluralRule[];
  };
  fn: (n: string, ord?: boolean) => LDMLPluralRule;
}

/**
 * Operands record for plural rule calculations
 * Note: Decimal is from the decimal.js package
 */
interface OperandsRecord {
  Number: Decimal;
  IntegerDigits: number;
  NumberOfFractionDigits: number;
  NumberOfFractionDigitsWithoutTrailing: number;
  FractionDigits: number;
  FractionDigitsWithoutTrailing: number;
}

Polyfill Usage

Conditional Polyfill

// Only polyfills if native support is missing or insufficient
import "@formatjs/intl-pluralrules/polyfill";

// Now Intl.PluralRules is available globally
const pr = new Intl.PluralRules("en");

Force Polyfill

// Always uses the polyfill implementation
import "@formatjs/intl-pluralrules/polyfill-force";

// Intl.PluralRules is replaced with polyfill
const pr = new Intl.PluralRules("en");

Manual Detection

import { shouldPolyfill } from "@formatjs/intl-pluralrules/should-polyfill";

if (shouldPolyfill()) {
  // Load and apply polyfill
  import("@formatjs/intl-pluralrules/polyfill");
}

Error Handling

The polyfill throws appropriate errors following the ECMAScript specification:

  • TypeError: When constructor is called without new
  • TypeError: When methods are called on incompatible receivers
  • RangeError: When invalid options are provided (handled by underlying abstract operations)

Example error handling:

try {
  // This will throw TypeError
  const pr = PluralRules("en"); // Missing 'new'
} catch (error) {
  console.error(error.message); // "Intl.PluralRules must be called with 'new'"
}

try {
  const pr = new PluralRules("en");
  // This will throw TypeError
  pr.select.call({}, 1);
} catch (error) {
  console.error(error.message); // Method called on incompatible receiver
}

Advanced Usage

Custom Locale Data

import { PluralRules } from "@formatjs/intl-pluralrules";

// Define custom locale data
const customLocaleData = {
  data: {
    categories: {
      cardinal: ["one", "other"],
      ordinal: ["other"]
    },
    fn: (n: string, ord?: boolean) => {
      return parseInt(n) === 1 && !ord ? "one" : "other";
    }
  },
  locale: "custom-locale"
};

// Add the custom locale data
PluralRules.__addLocaleData(customLocaleData);

const pr = new PluralRules("custom-locale");
console.log(pr.select(1)); // "one"
console.log(pr.select(2)); // "other"

Fraction Digit Handling

const pr = new PluralRules("en", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

// Fraction digits affect plural rule calculation
console.log(pr.select(1.00)); // Considers formatting options

Locale Fallback

// The polyfill handles locale fallback automatically
const pr = new PluralRules("en-US-variant-something");
console.log(pr.resolvedOptions().locale); // Will fallback to "en" if full locale not available