• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License")
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16const fakeLocale = "er-or"
17
18function main() throws {
19    testSelect()
20    testResolvedOptions()
21    testSelectWithOptions()
22    testSupportedLocalesOf()
23}
24
25function runSelectTest(locale: string, value: number, expected: string, options?: Intl.PluralRulesOptions) {
26    const rules = new Intl.PluralRules(locale, options)
27    const result = rules.select(value)
28    assertEQ(result, expected)
29}
30
31function testSelect() {
32    runSelectTest("en", 1, "one")
33    runSelectTest("en", 2, "other")
34    runSelectTest("en", 0, "other")
35
36    runSelectTest("ru", 1, "one")
37    runSelectTest("ru", 2, "few")
38    runSelectTest("ru", 5, "many")
39    runSelectTest("ru", 21, "one")
40    runSelectTest("ru", 102, "few")
41    runSelectTest("ru", 1005, "many")
42
43    runSelectTest("fr", 1, "one")
44    runSelectTest("fr", 2, "other")
45    runSelectTest("fr", 0, "one")
46
47    runSelectTest("zh", 1, "other")
48    runSelectTest("zh", 100, "other")
49    runSelectTest("zh", 0, "other")
50
51    runSelectTest("ja", 1, "other")
52    runSelectTest("ja", 5, "other")
53
54    runSelectTest(fakeLocale, 1, "one")
55    runSelectTest(fakeLocale, 2, "other")
56}
57
58function testResolvedOptions() {
59    {
60        const rules = new Intl.PluralRules("en")
61        const result = rules.resolvedOptions()
62        assertEQ(result.minimumIntegerDigits, 1)
63        assertEQ(result.minimumFractionDigits, 0)
64        assertEQ(result.maximumFractionDigits, 3)
65        assertEQ(result.minimumSignificantDigits, undefined)
66        assertEQ(result.maximumSignificantDigits, undefined)
67        assertEQ(result.type, "cardinal")
68    }
69    {
70        const rules = new Intl.PluralRules("en", { type: "ordinal" } as Intl.PluralRulesOptions)
71        const result = rules.resolvedOptions()
72        assertEQ(result.type, "ordinal")
73    }
74    {
75        const rules = new Intl.PluralRules("en", { minimumFractionDigits: 2 } as Intl.PluralRulesOptions)
76        const result = rules.resolvedOptions()
77        assertEQ(result.minimumFractionDigits, 2)
78    }
79    {
80        const rules = new Intl.PluralRules("en", { maximumFractionDigits: 4 } as Intl.PluralRulesOptions)
81        const result = rules.resolvedOptions()
82        assertEQ(result.maximumFractionDigits, 4)
83    }
84    {
85        const rules = new Intl.PluralRules("en", { minimumSignificantDigits: 3 } as Intl.PluralRulesOptions)
86        const result = rules.resolvedOptions()
87        assertEQ(result.minimumSignificantDigits, 3)
88    }
89}
90
91function runTestWithOptions(locale: string, value: number, options: Intl.PluralRulesOptions, expected: string) {
92    const rules = new Intl.PluralRules(locale, options)
93    const result = rules.select(value)
94    assertEQ(result, expected)
95}
96
97function testSelectWithOptions() {
98    runTestWithOptions("en", 1, { type: "cardinal" }, "one")
99    runTestWithOptions("en", 2, { type: "cardinal" }, "other")
100    runTestWithOptions("en", 1, { type: "ordinal" }, "one")
101    runTestWithOptions("en", 2, { type: "ordinal" }, "two")
102    runTestWithOptions("en", 3, { type: "ordinal" }, "few")
103    runTestWithOptions("en", 4, { type: "ordinal" }, "other")
104
105    runTestWithOptions("fr", 1, { localeMatcher: "lookup" }, "one")
106    runTestWithOptions("fr", 1, { localeMatcher: "best fit" }, "one")
107
108    runTestWithOptions("fr", 0, { minimumFractionDigits: 2 }, "one")
109    runTestWithOptions("fr", 0.5, { maximumFractionDigits: 1 }, "one")
110    runTestWithOptions("fr", 1.5, { minimumFractionDigits: 2, maximumFractionDigits: 2 }, "one")
111    runTestWithOptions("en", 1.99, { minimumFractionDigits: 1, maximumFractionDigits: 2 }, "other")
112    runTestWithOptions("en", 2.5, { minimumFractionDigits: 1 }, "other")
113
114    runTestWithOptions("de", 1, { minimumIntegerDigits: 2 }, "one")
115    runTestWithOptions("de", 9, { minimumIntegerDigits: 3 }, "other")
116
117    runTestWithOptions("ru", 1, { minimumSignificantDigits: 2 }, "other")
118    runTestWithOptions("ru", 12, { minimumSignificantDigits: 2, maximumSignificantDigits: 3 }, "many")
119    runTestWithOptions("ru", 1234, { minimumSignificantDigits: 3, maximumSignificantDigits: 5 }, "few")
120    runTestWithOptions("ru", 0.0005, { minimumSignificantDigits: 1, maximumSignificantDigits: 2 }, "other")
121
122    runTestWithOptions("ja", 0, {}, "other")
123    runTestWithOptions("zh", 2, {}, "other")
124    runTestWithOptions("ar", 0, {}, "zero")
125    runTestWithOptions("ar", 1, {}, "one")
126    runTestWithOptions("ar", 2, {}, "two")
127    runTestWithOptions("ar", 3, {}, "few")
128    runTestWithOptions("ar", 11, {}, "many")
129    runTestWithOptions("ar", 100, {}, "other")
130
131    runTestWithOptions(
132        "fr",
133        1234.567,
134        {
135            localeMatcher: "best fit",
136            type: "cardinal",
137            minimumIntegerDigits: 3,
138            minimumFractionDigits: 2,
139            maximumFractionDigits: 4,
140            minimumSignificantDigits: 3,
141            maximumSignificantDigits: 5
142        },
143        "other"
144    )
145    runTestWithOptions(
146        "fr",
147        1.0,
148        {
149            localeMatcher: "lookup",
150            type: "cardinal",
151            minimumIntegerDigits: 1,
152            minimumFractionDigits: 0,
153            maximumFractionDigits: 2,
154            minimumSignificantDigits: 1,
155            maximumSignificantDigits: 3
156        },
157        "one"
158    )
159    runTestWithOptions(
160        "ar",
161        2,
162        {
163            localeMatcher: "best fit",
164            type: "cardinal",
165            minimumIntegerDigits: 1,
166            minimumFractionDigits: 0,
167            maximumFractionDigits: 3,
168            minimumSignificantDigits: 1,
169            maximumSignificantDigits: 5
170        },
171        "two"
172    )
173    runTestWithOptions(
174        "en",
175        3,
176        {
177            localeMatcher: "lookup",
178            type: "ordinal",
179            minimumIntegerDigits: 1,
180            minimumFractionDigits: 0,
181            maximumFractionDigits: 2,
182            minimumSignificantDigits: 1,
183            maximumSignificantDigits: 3
184        },
185        "few"
186    )
187}
188
189function runSupportedLocalesTest(
190    locales: string | FixedArray<string>,
191    options: Intl.SupportedLocalesOfOptions | undefined,
192    expected: string[])
193{
194    const result = Intl.PluralRules.supportedLocalesOf(locales, options)
195    assertEQ(result.length, expected.length)
196    for (let i = 0; i < result.length; i++) {
197        assertEQ(result[i], expected[i])
198    }
199}
200
201function testSupportedLocalesOf() {
202    runSupportedLocalesTest(
203        "en",
204        undefined,
205        intlBestFitLocales("en")
206    )
207    runSupportedLocalesTest(
208        fakeLocale,
209        undefined,
210        intlBestFitLocales(fakeLocale)
211    )
212    runSupportedLocalesTest(
213        ["fr", fakeLocale, "ru"],
214        undefined,
215        intlBestFitLocales(["fr", fakeLocale, "ru"])
216    )
217    runSupportedLocalesTest(
218        ["ru-RU", "zh-CN", "en-US"],
219        undefined,
220        intlBestFitLocales(["ru-RU", "zh-CN", "en-US"])
221    )
222    runSupportedLocalesTest(
223        ["ru-RU", "zh-CN", "en-US"],
224        { localeMatcher: "best fit" } as Intl.SupportedLocalesOfOptions,
225        intlBestFitLocales(["ru-RU", "zh-CN", "en-US"])
226    )
227
228    runSupportedLocalesTest(
229        "en",
230        { localeMatcher: "lookup" } as Intl.SupportedLocalesOfOptions,
231        intlLookUpLocales("en")
232    )
233    runSupportedLocalesTest(
234        fakeLocale,
235        { localeMatcher: "lookup" } as Intl.SupportedLocalesOfOptions,
236        intlLookUpLocales(fakeLocale)
237    )
238
239    runSupportedLocalesTest(
240        ["ru-RU", "zh-CN", fakeLocale, "en-US"],
241        { localeMatcher: "lookup" } as Intl.SupportedLocalesOfOptions,
242        intlLookUpLocales(["ru-RU", "zh-CN", fakeLocale, "en-US"])
243    )
244}
245