@formatjs/ecma402-abstract
Version:
A collection of implementation for ECMAScript abstract operations
86 lines (85 loc) • 3.35 kB
JavaScript
import { ResolveLocale } from "@formatjs/intl-localematcher";
import { CanonicalizeLocaleList } from "../CanonicalizeLocaleList.js";
import { CoerceOptionsToObject } from "../CoerceOptionsToObject.js";
import { GetOption } from "../GetOption.js";
import { GetStringOrBooleanOption } from "../GetStringOrBooleanOption.js";
import "../types/number.js";
import { invariant } from "../utils.js";
import { CurrencyDigits } from "./CurrencyDigits.js";
import { SetNumberFormatDigitOptions } from "./SetNumberFormatDigitOptions.js";
import { SetNumberFormatUnitOptions } from "./SetNumberFormatUnitOptions.js";
/**
* https://tc39.es/ecma402/#sec-initializenumberformat
*/
export function InitializeNumberFormat(nf, locales, opts, { getInternalSlots, localeData, availableLocales, numberingSystemNames, getDefaultLocale, currencyDigitsData }) {
const requestedLocales = CanonicalizeLocaleList(locales);
const options = CoerceOptionsToObject(opts);
const opt = Object.create(null);
const matcher = GetOption(options, "localeMatcher", "string", ["lookup", "best fit"], "best fit");
opt.localeMatcher = matcher;
const numberingSystem = GetOption(options, "numberingSystem", "string", undefined, undefined);
if (numberingSystem !== undefined && numberingSystemNames.indexOf(numberingSystem) < 0) {
// 8.a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal,
// throw a RangeError exception.
throw RangeError(`Invalid numberingSystems: ${numberingSystem}`);
}
opt.nu = numberingSystem;
const r = ResolveLocale(
Array.from(availableLocales),
requestedLocales,
opt,
// [[RelevantExtensionKeys]] slot, which is a constant
["nu"],
localeData,
getDefaultLocale
);
const dataLocaleData = localeData[r.dataLocale];
invariant(!!dataLocaleData, `Missing locale data for ${r.dataLocale}`);
const internalSlots = getInternalSlots(nf);
internalSlots.locale = r.locale;
internalSlots.dataLocale = r.dataLocale;
internalSlots.numberingSystem = r.nu;
internalSlots.dataLocaleData = dataLocaleData;
SetNumberFormatUnitOptions(internalSlots, options);
const style = internalSlots.style;
const notation = GetOption(options, "notation", "string", [
"standard",
"scientific",
"engineering",
"compact"
], "standard");
internalSlots.notation = notation;
let mnfdDefault;
let mxfdDefault;
if (style === "currency" && notation === "standard") {
const currency = internalSlots.currency;
const cDigits = CurrencyDigits(currency, { currencyDigitsData });
mnfdDefault = cDigits;
mxfdDefault = cDigits;
} else {
mnfdDefault = 0;
mxfdDefault = style === "percent" ? 0 : 3;
}
SetNumberFormatDigitOptions(internalSlots, options, mnfdDefault, mxfdDefault, notation);
const compactDisplay = GetOption(options, "compactDisplay", "string", ["short", "long"], "short");
let defaultUseGrouping = "auto";
if (notation === "compact") {
internalSlots.compactDisplay = compactDisplay;
defaultUseGrouping = "min2";
}
let useGrouping = GetStringOrBooleanOption(options, "useGrouping", [
"min2",
"auto",
"always"
], "always", false, defaultUseGrouping);
internalSlots.useGrouping = useGrouping;
let signDisplay = GetOption(options, "signDisplay", "string", [
"auto",
"never",
"always",
"exceptZero",
"negative"
], "auto");
internalSlots.signDisplay = signDisplay;
return nf;
}