@formatjs/intl-pluralrules
Version:
Polyfill for Intl.PluralRules
79 lines (78 loc) • 3.25 kB
TypeScript
import { type LDMLPluralRule, type NumberFormatDigitInternalSlots, type PluralRulesData, type PluralRulesLocaleData } from "@formatjs/ecma402-abstract";
/**
* Type augmentation for Intl.PluralRules
*
* ECMA-402 Spec: selectRange method (Intl.PluralRules.prototype.selectRange)
* https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.selectrange
*
* Extension: notation and compactDisplay options (not in ECMA-402 spec)
* Mirrors Intl.NumberFormat notation option for proper plural selection with compact numbers
*/
declare global {
namespace Intl {
interface PluralRules {
selectRange(start: number | bigint, end: number | bigint): LDMLPluralRule;
}
interface PluralRulesOptions {
notation?: "standard" | "compact";
compactDisplay?: "short" | "long";
}
}
}
export interface PluralRulesInternal extends NumberFormatDigitInternalSlots {
initializedPluralRules: boolean;
locale: string;
type: "cardinal" | "ordinal";
notation: "standard" | "compact";
compactDisplay?: "short" | "long";
dataLocaleData?: any;
}
export declare class PluralRules {
constructor(locales?: string | string[], options?: Intl.PluralRulesOptions);
resolvedOptions(): Intl.ResolvedPluralRulesOptions;
select(val: number | bigint): LDMLPluralRule;
/**
* Intl.PluralRules.prototype.selectRange ( start, end )
*
* Returns a string indicating which plural rule applies to a range of numbers.
* This is useful for formatting ranges like "1-2 items" vs "2-3 items" where
* different languages have different plural rules for ranges.
*
* Specification: https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.selectrange
*
* @param start - The start value of the range (number or bigint)
* @param end - The end value of the range (number or bigint)
* @returns The plural category for the range (zero, one, two, few, many, or other)
*
* @example
* const pr = new Intl.PluralRules('en');
* pr.selectRange(1, 2); // "other" (English: "1-2 items")
* pr.selectRange(1, 1); // "one" (same value: "1 item")
*
* @example
* const prFr = new Intl.PluralRules('fr');
* prFr.selectRange(0, 1); // "one" (French: "0-1 vue")
* prFr.selectRange(1, 2); // "other" (French: "1-2 vues")
*
* @example
* // BigInt support (spec-compliant, but Chrome has a bug as of early 2025)
* pr.selectRange(BigInt(1), BigInt(2)); // "other"
*
* @throws {TypeError} If start or end is undefined
* @throws {RangeError} If start or end is not a finite number (Infinity, NaN)
*
* @note Chrome's native implementation (as of early 2025) has a bug where it throws
* "Cannot convert a BigInt value to a number" when using BigInt arguments. This is
* a browser bug - the spec requires BigInt support. This polyfill handles BigInt correctly.
*/
selectRange(start: number | bigint, end: number | bigint): LDMLPluralRule;
toString(): string;
static supportedLocalesOf(locales?: string | string[], options?: Pick<Intl.PluralRulesOptions, "localeMatcher">): string[];
static __addLocaleData(...data: PluralRulesLocaleData[]): void;
static localeData: Record<string, PluralRulesData>;
static availableLocales: Set<string>;
static __defaultLocale: string;
static getDefaultLocale(): string;
static relevantExtensionKeys: never[];
static polyfilled: boolean;
}