@formatjs/intl-pluralrules
Version:
Polyfill for Intl.PluralRules
130 lines (129 loc) • 4.23 kB
JavaScript
import { CanonicalizeLocaleList, SupportedLocales, ToNumber } from "@formatjs/ecma402-abstract";
import "./abstract/GetOperands.js";
import { InitializePluralRules } from "./abstract/InitializePluralRules.js";
import { ResolvePlural } from "./abstract/ResolvePlural.js";
import getInternalSlots from "./get_internal_slots.js";
function validateInstance(instance, method) {
if (!(instance instanceof PluralRules)) {
throw new TypeError(`Method Intl.PluralRules.prototype.${method} called on incompatible receiver ${String(instance)}`);
}
}
/**
* http://ecma-international.org/ecma-402/7.0/index.html#sec-pluralruleselect
* @param locale
* @param type
* @param _n
* @param param3
*/
function PluralRuleSelect(locale, type, _n, { IntegerDigits, NumberOfFractionDigits, FractionDigits }) {
return PluralRules.localeData[locale].fn(NumberOfFractionDigits ? `${IntegerDigits}.${FractionDigits}` : IntegerDigits, type === "ordinal");
}
export class PluralRules {
constructor(locales, options) {
// test262/test/intl402/RelativeTimeFormat/constructor/constructor/newtarget-undefined.js
// Cannot use `new.target` bc of IE11 & TS transpiles it to something else
const newTarget = this && this instanceof PluralRules ? this.constructor : void 0;
if (!newTarget) {
throw new TypeError("Intl.PluralRules must be called with 'new'");
}
return InitializePluralRules(this, locales, options, {
availableLocales: PluralRules.availableLocales,
relevantExtensionKeys: PluralRules.relevantExtensionKeys,
localeData: PluralRules.localeData,
getDefaultLocale: PluralRules.getDefaultLocale,
getInternalSlots
});
}
resolvedOptions() {
validateInstance(this, "resolvedOptions");
const opts = Object.create(null);
const internalSlots = getInternalSlots(this);
opts.locale = internalSlots.locale;
opts.type = internalSlots.type;
[
"minimumIntegerDigits",
"minimumFractionDigits",
"maximumFractionDigits",
"minimumSignificantDigits",
"maximumSignificantDigits"
].forEach((field) => {
const val = internalSlots[field];
if (val !== undefined) {
opts[field] = val;
}
});
opts.pluralCategories = [...PluralRules.localeData[opts.locale].categories[opts.type]];
return opts;
}
select(val) {
validateInstance(this, "select");
const n = ToNumber(val);
return ResolvePlural(this, n, {
getInternalSlots,
PluralRuleSelect
});
}
toString() {
return "[object Intl.PluralRules]";
}
static supportedLocalesOf(locales, options) {
return SupportedLocales(PluralRules.availableLocales, CanonicalizeLocaleList(locales), options);
}
static __addLocaleData(...data) {
for (const { data: d, locale } of data) {
PluralRules.localeData[locale] = d;
PluralRules.availableLocales.add(locale);
if (!PluralRules.__defaultLocale) {
PluralRules.__defaultLocale = locale;
}
}
}
static localeData = {};
static availableLocales = new Set();
static __defaultLocale = "";
static getDefaultLocale() {
return PluralRules.__defaultLocale;
}
static relevantExtensionKeys = [];
static polyfilled = true;
}
try {
// IE11 does not have Symbol
if (typeof Symbol !== "undefined") {
Object.defineProperty(PluralRules.prototype, Symbol.toStringTag, {
value: "Intl.PluralRules",
writable: false,
enumerable: false,
configurable: true
});
}
try {
// https://github.com/tc39/test262/blob/master/test/intl402/PluralRules/length.js
Object.defineProperty(PluralRules, "length", {
value: 0,
writable: false,
enumerable: false,
configurable: true
});
} catch {}
// https://github.com/tc39/test262/blob/master/test/intl402/RelativeTimeFormat/constructor/length.js
Object.defineProperty(PluralRules.prototype.constructor, "length", {
value: 0,
writable: false,
enumerable: false,
configurable: true
});
// https://github.com/tc39/test262/blob/master/test/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/length.js
Object.defineProperty(PluralRules.supportedLocalesOf, "length", {
value: 1,
writable: false,
enumerable: false,
configurable: true
});
Object.defineProperty(PluralRules, "name", {
value: "PluralRules",
writable: false,
enumerable: false,
configurable: true
});
} catch {}