@formatjs/intl-pluralrules 6.3.1 → 6.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,31 +0,0 @@
1
- import { CanonicalizeLocaleList, CoerceOptionsToObject, GetOption, SetNumberFormatDigitOptions } from "@formatjs/ecma402-abstract";
2
- import { ResolveLocale } from "@formatjs/intl-localematcher";
3
- export function InitializePluralRules(pl, locales, options, { availableLocales, relevantExtensionKeys, localeData, getDefaultLocale, getInternalSlots }) {
4
- const requestedLocales = CanonicalizeLocaleList(locales);
5
- const opt = Object.create(null);
6
- const opts = CoerceOptionsToObject(options);
7
- const internalSlots = getInternalSlots(pl);
8
- internalSlots.initializedPluralRules = true;
9
- const matcher = GetOption(opts, "localeMatcher", "string", ["best fit", "lookup"], "best fit");
10
- opt.localeMatcher = matcher;
11
- const r = ResolveLocale(availableLocales, requestedLocales, opt, relevantExtensionKeys, localeData, getDefaultLocale);
12
- internalSlots.locale = r.locale;
13
- // ECMA-402 Spec: type option ('cardinal' or 'ordinal')
14
- internalSlots.type = GetOption(opts, "type", "string", ["cardinal", "ordinal"], "cardinal");
15
- // Extension: notation options for compact notation support
16
- // Not in ECMA-402 spec, but mirrors Intl.NumberFormat notation option
17
- // Enables proper plural selection for compact numbers (e.g., "1.2M")
18
- const notation = GetOption(opts, "notation", "string", ["standard", "compact"], "standard");
19
- internalSlots.notation = notation;
20
- if (notation === "compact") {
21
- // Extension: compactDisplay option (mirrors Intl.NumberFormat)
22
- internalSlots.compactDisplay = GetOption(opts, "compactDisplay", "string", ["short", "long"], "short");
23
- // Implementation: Load NumberFormat locale data if available (soft dependency)
24
- // This is needed to calculate compact exponents using ComputeExponentForMagnitude
25
- if (typeof Intl !== "undefined" && Intl.NumberFormat && Intl.NumberFormat.localeData) {
26
- internalSlots.dataLocaleData = Intl.NumberFormat.localeData[r.locale];
27
- }
28
- }
29
- SetNumberFormatDigitOptions(internalSlots, opts, 0, 3, "standard");
30
- return pl;
31
- }
@@ -1,43 +0,0 @@
1
- import { type LDMLPluralRule, type PluralRulesInternal } from "@formatjs/ecma402-abstract";
2
- import Decimal from "@formatjs/bigdecimal";
3
- import { type OperandsRecord } from "./GetOperands.js";
4
- /**
5
- * Result of ResolvePluralInternal containing both the formatted string and plural category.
6
- * This corresponds to a Record with [[FormattedString]] and [[PluralCategory]] fields
7
- * as described in the ECMA-402 spec for ResolvePluralRange.
8
- */
9
- export interface ResolvePluralResult {
10
- /** The formatted representation of the number */
11
- formattedString: string;
12
- /** The LDML plural category (zero, one, two, few, many, or other) */
13
- pluralCategory: LDMLPluralRule;
14
- }
15
- /**
16
- * ResolvePluralInternal ( pluralRules, n )
17
- *
18
- * Internal version of ResolvePlural that returns both the formatted string and plural category.
19
- * This is needed for selectRange, which must compare formatted strings to determine if the
20
- * start and end values are identical.
21
- *
22
- * The formatted string is obtained by applying the number formatting options (digit options)
23
- * from the PluralRules object to the input number. This ensures that formatting-sensitive
24
- * plural rules work correctly (e.g., rules that depend on visible fraction digits).
25
- *
26
- * @param pl - An initialized PluralRules object
27
- * @param n - Mathematical value to resolve
28
- * @returns Record containing the formatted string and plural category
29
- */
30
- export declare function ResolvePluralInternal(pl: Intl.PluralRules, n: Decimal, { getInternalSlots, PluralRuleSelect }: {
31
- getInternalSlots(pl: Intl.PluralRules): PluralRulesInternal;
32
- PluralRuleSelect: (locale: string, type: "cardinal" | "ordinal", n: Decimal, operands: OperandsRecord) => LDMLPluralRule;
33
- }): ResolvePluralResult;
34
- /**
35
- * http://ecma-international.org/ecma-402/7.0/index.html#sec-resolveplural
36
- * @param pl
37
- * @param n
38
- * @param PluralRuleSelect Has to pass in bc it's implementation-specific
39
- */
40
- export declare function ResolvePlural(pl: Intl.PluralRules, n: Decimal, { getInternalSlots, PluralRuleSelect }: {
41
- getInternalSlots(pl: Intl.PluralRules): PluralRulesInternal;
42
- PluralRuleSelect: (locale: string, type: "cardinal" | "ordinal", n: Decimal, operands: OperandsRecord) => LDMLPluralRule;
43
- }): LDMLPluralRule;
@@ -1,75 +0,0 @@
1
- import { ComputeExponentForMagnitude, FormatNumericToString, invariant, Type } from "@formatjs/ecma402-abstract";
2
- import Decimal from "@formatjs/bigdecimal";
3
- import { GetOperands } from "./GetOperands.js";
4
- /**
5
- * ResolvePluralInternal ( pluralRules, n )
6
- *
7
- * Internal version of ResolvePlural that returns both the formatted string and plural category.
8
- * This is needed for selectRange, which must compare formatted strings to determine if the
9
- * start and end values are identical.
10
- *
11
- * The formatted string is obtained by applying the number formatting options (digit options)
12
- * from the PluralRules object to the input number. This ensures that formatting-sensitive
13
- * plural rules work correctly (e.g., rules that depend on visible fraction digits).
14
- *
15
- * @param pl - An initialized PluralRules object
16
- * @param n - Mathematical value to resolve
17
- * @returns Record containing the formatted string and plural category
18
- */
19
- export function ResolvePluralInternal(pl, n, { getInternalSlots, PluralRuleSelect }) {
20
- const internalSlots = getInternalSlots(pl);
21
- invariant(Type(internalSlots) === "Object", "pl has to be an object");
22
- invariant("initializedPluralRules" in internalSlots, "pluralrules must be initialized");
23
- // Handle non-finite values (Infinity, -Infinity, NaN)
24
- if (!n.isFinite()) {
25
- return {
26
- formattedString: String(n),
27
- pluralCategory: "other"
28
- };
29
- }
30
- const { locale, type, notation } = internalSlots;
31
- // ECMA-402 Spec: Format the number according to digit options
32
- const res = FormatNumericToString(internalSlots, n);
33
- const s = res.formattedString;
34
- // Extension: Calculate compact exponent if using compact notation
35
- // This enables CLDR c/e operands for proper plural selection with compact numbers
36
- let exponent = 0;
37
- if (notation === "compact" && !n.isZero()) {
38
- // Implementation: Only calculate exponent if NumberFormat locale data is available (soft dependency)
39
- if (internalSlots.dataLocaleData?.numbers) {
40
- try {
41
- // Calculate magnitude (floor of log10 of absolute value)
42
- const magnitudeNum = Math.floor(Math.log10(Math.abs(n.toNumber())));
43
- const magnitude = new Decimal(magnitudeNum);
44
- // Use ComputeExponentForMagnitude from ecma402-abstract
45
- // This determines which compact notation pattern to use (K, M, B, etc.)
46
- // Cast to any since it expects NumberFormatInternal
47
- exponent = ComputeExponentForMagnitude(internalSlots, magnitude);
48
- } catch {
49
- // Gracefully fall back to 0 if exponent calculation fails
50
- exponent = 0;
51
- }
52
- }
53
- }
54
- // ECMA-402 Spec: Extract CLDR operands from the formatted string
55
- // Extension: Pass exponent for c/e operands
56
- const operands = GetOperands(s, exponent);
57
- // ECMA-402 Spec: Select the appropriate plural category using the locale's plural rules
58
- const pluralCategory = PluralRuleSelect(locale, type, n, operands);
59
- return {
60
- formattedString: s,
61
- pluralCategory
62
- };
63
- }
64
- /**
65
- * http://ecma-international.org/ecma-402/7.0/index.html#sec-resolveplural
66
- * @param pl
67
- * @param n
68
- * @param PluralRuleSelect Has to pass in bc it's implementation-specific
69
- */
70
- export function ResolvePlural(pl, n, { getInternalSlots, PluralRuleSelect }) {
71
- return ResolvePluralInternal(pl, n, {
72
- getInternalSlots,
73
- PluralRuleSelect
74
- }).pluralCategory;
75
- }
@@ -1,23 +0,0 @@
1
- import { type LDMLPluralRule, type PluralRulesInternal } from "@formatjs/ecma402-abstract";
2
- import type Decimal from "@formatjs/bigdecimal";
3
- import { type OperandsRecord } from "./GetOperands.js";
4
- /**
5
- * ResolvePluralRange ( pluralRules, x, y )
6
- *
7
- * The ResolvePluralRange abstract operation is called with arguments pluralRules (which must be
8
- * an object initialized as a PluralRules), x (a mathematical value), and y (a mathematical value).
9
- * It resolves the appropriate plural form for a range by determining the plural forms of both the
10
- * start and end values, then consulting locale-specific range data.
11
- *
12
- * Specification: https://tc39.es/ecma402/#sec-resolvepluralrange
13
- *
14
- * @param pluralRules - An initialized PluralRules object
15
- * @param x - Mathematical value for the range start
16
- * @param y - Mathematical value for the range end
17
- * @returns The plural category for the range (zero, one, two, few, many, or other)
18
- */
19
- export declare function ResolvePluralRange(pluralRules: Intl.PluralRules, x: Decimal, y: Decimal, { getInternalSlots, PluralRuleSelect, PluralRuleSelectRange }: {
20
- getInternalSlots(pl: Intl.PluralRules): PluralRulesInternal;
21
- PluralRuleSelect: (locale: string, type: "cardinal" | "ordinal", n: Decimal, operands: OperandsRecord) => LDMLPluralRule;
22
- PluralRuleSelectRange: (locale: string, type: "cardinal" | "ordinal", xp: LDMLPluralRule, yp: LDMLPluralRule) => LDMLPluralRule;
23
- }): LDMLPluralRule;
@@ -1,59 +0,0 @@
1
- import { invariant, Type } from "@formatjs/ecma402-abstract";
2
- import "./GetOperands.js";
3
- import { ResolvePluralInternal } from "./ResolvePlural.js";
4
- /**
5
- * ResolvePluralRange ( pluralRules, x, y )
6
- *
7
- * The ResolvePluralRange abstract operation is called with arguments pluralRules (which must be
8
- * an object initialized as a PluralRules), x (a mathematical value), and y (a mathematical value).
9
- * It resolves the appropriate plural form for a range by determining the plural forms of both the
10
- * start and end values, then consulting locale-specific range data.
11
- *
12
- * Specification: https://tc39.es/ecma402/#sec-resolvepluralrange
13
- *
14
- * @param pluralRules - An initialized PluralRules object
15
- * @param x - Mathematical value for the range start
16
- * @param y - Mathematical value for the range end
17
- * @returns The plural category for the range (zero, one, two, few, many, or other)
18
- */
19
- export function ResolvePluralRange(pluralRules, x, y, { getInternalSlots, PluralRuleSelect, PluralRuleSelectRange }) {
20
- // 1. If x is not-a-number or y is not-a-number, throw a RangeError exception.
21
- if (!x.isFinite() || !y.isFinite()) {
22
- throw new RangeError("selectRange requires start and end values to be finite numbers");
23
- }
24
- // Validation: Assert that pluralRules has been initialized
25
- const internalSlots = getInternalSlots(pluralRules);
26
- invariant(Type(internalSlots) === "Object", "pluralRules has to be an object");
27
- invariant("initializedPluralRules" in internalSlots, "pluralrules must be initialized");
28
- // 2. Let xp be ResolvePlural(pluralRules, x).
29
- // Note: ResolvePlural returns a Record with [[FormattedString]] and [[PluralCategory]]
30
- const xp = ResolvePluralInternal(pluralRules, x, {
31
- getInternalSlots,
32
- PluralRuleSelect
33
- });
34
- // 3. Let yp be ResolvePlural(pluralRules, y).
35
- const yp = ResolvePluralInternal(pluralRules, y, {
36
- getInternalSlots,
37
- PluralRuleSelect
38
- });
39
- // 4. If xp.[[FormattedString]] is yp.[[FormattedString]], then
40
- // a. Return xp.[[PluralCategory]].
41
- // Note: When the formatted strings are identical (e.g., "1" and "1"), the values are
42
- // effectively the same, so we return the plural category of the start value.
43
- if (xp.formattedString === yp.formattedString) {
44
- return xp.pluralCategory;
45
- }
46
- // 5. Let locale be pluralRules.[[Locale]].
47
- // 6. Let type be pluralRules.[[Type]].
48
- const { locale, type } = internalSlots;
49
- // 7. Let notation be pluralRules.[[Notation]].
50
- // 8. Let compactDisplay be pluralRules.[[CompactDisplay]].
51
- // Note: notation and compactDisplay are not yet implemented for PluralRules polyfill.
52
- // When implemented, these would affect how the range is formatted and thus which
53
- // plural rules apply (see c/e operand support).
54
- // 9. Return PluralRuleSelectRange(locale, type, notation, compactDisplay, xp.[[PluralCategory]], yp.[[PluralCategory]]).
55
- // Note: PluralRuleSelectRange is implementation-defined and uses CLDR plural range data
56
- // to determine the appropriate plural category for a range based on the start and end categories.
57
- // Example: In English, "one" to "other" → "other" (e.g., "1-2 items")
58
- return PluralRuleSelectRange(locale, type, xp.pluralCategory, yp.pluralCategory);
59
- }
@@ -1,3 +0,0 @@
1
- import type { PluralRules } from "./index.js";
2
- import { type PluralRulesInternal } from "./index.js";
3
- export default function getInternalSlots(x: PluralRules): PluralRulesInternal;
@@ -1,10 +0,0 @@
1
- import "./index.js";
2
- const internalSlotMap = new WeakMap();
3
- export default function getInternalSlots(x) {
4
- let internalSlots = internalSlotMap.get(x);
5
- if (!internalSlots) {
6
- internalSlots = Object.create(null);
7
- internalSlotMap.set(x, internalSlots);
8
- }
9
- return internalSlots;
10
- }
@@ -1 +0,0 @@
1
- export declare const supportedLocales: string[];
@@ -1,217 +0,0 @@
1
- export const supportedLocales = [
2
- "af",
3
- "ak",
4
- "am",
5
- "an",
6
- "ar",
7
- "ars",
8
- "as",
9
- "asa",
10
- "ast",
11
- "az",
12
- "bal",
13
- "be",
14
- "bem",
15
- "bez",
16
- "bg",
17
- "bho",
18
- "bm",
19
- "bn",
20
- "bo",
21
- "br",
22
- "brx",
23
- "bs",
24
- "ca",
25
- "ce",
26
- "ceb",
27
- "cgg",
28
- "chr",
29
- "ckb",
30
- "cs",
31
- "cy",
32
- "da",
33
- "de",
34
- "doi",
35
- "dsb",
36
- "dv",
37
- "dz",
38
- "ee",
39
- "el",
40
- "en",
41
- "eo",
42
- "es",
43
- "et",
44
- "eu",
45
- "fa",
46
- "ff",
47
- "fi",
48
- "fil",
49
- "fo",
50
- "fr",
51
- "fur",
52
- "fy",
53
- "ga",
54
- "gd",
55
- "gl",
56
- "gsw",
57
- "gu",
58
- "guw",
59
- "gv",
60
- "ha",
61
- "haw",
62
- "he",
63
- "hi",
64
- "hnj",
65
- "hr",
66
- "hsb",
67
- "hu",
68
- "hy",
69
- "ia",
70
- "id",
71
- "ig",
72
- "ii",
73
- "io",
74
- "is",
75
- "it",
76
- "iu",
77
- "ja",
78
- "jbo",
79
- "jgo",
80
- "jmc",
81
- "jv",
82
- "jw",
83
- "ka",
84
- "kab",
85
- "kaj",
86
- "kcg",
87
- "kde",
88
- "kea",
89
- "kk",
90
- "kkj",
91
- "kl",
92
- "km",
93
- "kn",
94
- "ko",
95
- "ks",
96
- "ksb",
97
- "ksh",
98
- "ku",
99
- "kw",
100
- "ky",
101
- "lag",
102
- "lb",
103
- "lg",
104
- "lij",
105
- "lkt",
106
- "ln",
107
- "lo",
108
- "lt",
109
- "lv",
110
- "mas",
111
- "mg",
112
- "mgo",
113
- "mk",
114
- "ml",
115
- "mn",
116
- "mo",
117
- "mr",
118
- "ms",
119
- "mt",
120
- "my",
121
- "nah",
122
- "naq",
123
- "nb",
124
- "nd",
125
- "ne",
126
- "nl",
127
- "nn",
128
- "nnh",
129
- "no",
130
- "nqo",
131
- "nr",
132
- "nso",
133
- "ny",
134
- "nyn",
135
- "om",
136
- "or",
137
- "os",
138
- "osa",
139
- "pa",
140
- "pap",
141
- "pcm",
142
- "pl",
143
- "prg",
144
- "ps",
145
- "pt",
146
- "pt-PT",
147
- "rm",
148
- "ro",
149
- "rof",
150
- "ru",
151
- "rwk",
152
- "sah",
153
- "saq",
154
- "sat",
155
- "sc",
156
- "scn",
157
- "sd",
158
- "sdh",
159
- "se",
160
- "seh",
161
- "ses",
162
- "sg",
163
- "sh",
164
- "shi",
165
- "si",
166
- "sk",
167
- "sl",
168
- "sma",
169
- "smi",
170
- "smj",
171
- "smn",
172
- "sms",
173
- "sn",
174
- "so",
175
- "sq",
176
- "sr",
177
- "ss",
178
- "ssy",
179
- "st",
180
- "su",
181
- "sv",
182
- "sw",
183
- "syr",
184
- "ta",
185
- "te",
186
- "teo",
187
- "th",
188
- "ti",
189
- "tig",
190
- "tk",
191
- "tl",
192
- "tn",
193
- "to",
194
- "tpi",
195
- "tr",
196
- "ts",
197
- "tzm",
198
- "ug",
199
- "uk",
200
- "und",
201
- "ur",
202
- "uz",
203
- "ve",
204
- "vi",
205
- "vo",
206
- "vun",
207
- "wa",
208
- "wae",
209
- "wo",
210
- "xh",
211
- "xog",
212
- "yi",
213
- "yo",
214
- "yue",
215
- "zh",
216
- "zu"
217
- ];