mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:27:35 +00:00
LibJS: Implement unit number formatting
This commit is contained in:
parent
cafb717486
commit
a1d5849e67
4 changed files with 359 additions and 18 deletions
|
@ -617,8 +617,10 @@ Vector<PatternPartition> partition_number_pattern(NumberFormat& number_format, d
|
||||||
number = format_number_result.rounded_number;
|
number = format_number_result.rounded_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Unicode::NumberFormat found_pattern {};
|
||||||
|
|
||||||
// 5. Let pattern be GetNumberFormatPattern(numberFormat, x).
|
// 5. Let pattern be GetNumberFormatPattern(numberFormat, x).
|
||||||
auto pattern = get_number_format_pattern(number_format, number);
|
auto pattern = get_number_format_pattern(number_format, number, found_pattern);
|
||||||
if (!pattern.has_value())
|
if (!pattern.has_value())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
@ -672,23 +674,20 @@ Vector<PatternPartition> partition_number_pattern(NumberFormat& number_format, d
|
||||||
}
|
}
|
||||||
|
|
||||||
// g. Else if p is equal to "unitPrefix" and numberFormat.[[Style]] is "unit", then
|
// g. Else if p is equal to "unitPrefix" and numberFormat.[[Style]] is "unit", then
|
||||||
else if ((part == "unitPrefix"sv) && (number_format.style() == NumberFormat::Style::Unit)) {
|
// h. Else if p is equal to "unitSuffix" and numberFormat.[[Style]] is "unit", then
|
||||||
|
else if ((part.starts_with("unitIdentifier:"sv)) && (number_format.style() == NumberFormat::Style::Unit)) {
|
||||||
|
// Note: Our implementation combines "unitPrefix" and "unitSuffix" into one field, "unitIdentifier".
|
||||||
|
|
||||||
|
auto identifier_index = part.substring_view("unitIdentifier:"sv.length()).to_uint();
|
||||||
|
VERIFY(identifier_index.has_value());
|
||||||
|
|
||||||
// i. Let unit be numberFormat.[[Unit]].
|
// i. Let unit be numberFormat.[[Unit]].
|
||||||
// ii. Let unitDisplay be numberFormat.[[UnitDisplay]].
|
// ii. Let unitDisplay be numberFormat.[[UnitDisplay]].
|
||||||
// iii. Let mu be an ILD String value representing unit before x in unitDisplay form, which may depend on x in languages having different plural forms.
|
// iii. Let mu be an ILD String value representing unit before x in unitDisplay form, which may depend on x in languages having different plural forms.
|
||||||
|
auto unit_identifier = found_pattern.identifiers[*identifier_index];
|
||||||
|
|
||||||
// iv. Append a new Record { [[Type]]: "unit", [[Value]]: mu } as the last element of result.
|
// iv. Append a new Record { [[Type]]: "unit", [[Value]]: mu } as the last element of result.
|
||||||
|
result.append({ "unit"sv, unit_identifier });
|
||||||
// FIXME: LibUnicode will need to parse the cldr-units package.
|
|
||||||
}
|
|
||||||
|
|
||||||
// h. Else if p is equal to "unitSuffix" and numberFormat.[[Style]] is "unit", then
|
|
||||||
else if ((part == "unitSuffix"sv) && (number_format.style() == NumberFormat::Style::Unit)) {
|
|
||||||
// i. Let unit be numberFormat.[[Unit]].
|
|
||||||
// ii. Let unitDisplay be numberFormat.[[UnitDisplay]].
|
|
||||||
// iii. Let mu be an ILD String value representing unit after x in unitDisplay form, which may depend on x in languages having different plural forms.
|
|
||||||
// iv. Append a new Record { [[Type]]: "unit", [[Value]]: mu } as the last element of result.
|
|
||||||
|
|
||||||
// FIXME: LibUnicode will need to parse the cldr-units package.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// i. Else if p is equal to "currencyCode" and numberFormat.[[Style]] is "currency", then
|
// i. Else if p is equal to "currencyCode" and numberFormat.[[Style]] is "currency", then
|
||||||
|
@ -1329,7 +1328,7 @@ ThrowCompletionOr<void> set_number_format_unit_options(GlobalObject& global_obje
|
||||||
}
|
}
|
||||||
|
|
||||||
// 15.1.14 GetNumberFormatPattern ( numberFormat, x ), https://tc39.es/ecma402/#sec-getnumberformatpattern
|
// 15.1.14 GetNumberFormatPattern ( numberFormat, x ), https://tc39.es/ecma402/#sec-getnumberformatpattern
|
||||||
Optional<Variant<StringView, String>> get_number_format_pattern(NumberFormat& number_format, double number)
|
Optional<Variant<StringView, String>> get_number_format_pattern(NumberFormat& number_format, double number, Unicode::NumberFormat& found_pattern)
|
||||||
{
|
{
|
||||||
// 1. Let localeData be %NumberFormat%.[[LocaleData]].
|
// 1. Let localeData be %NumberFormat%.[[LocaleData]].
|
||||||
// 2. Let dataLocale be numberFormat.[[DataLocale]].
|
// 2. Let dataLocale be numberFormat.[[DataLocale]].
|
||||||
|
@ -1347,7 +1346,7 @@ Optional<Variant<StringView, String>> get_number_format_pattern(NumberFormat& nu
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 8. Else if style is "unit", then
|
// 8. Else if style is "unit", then
|
||||||
case NumberFormat::Style::Unit:
|
case NumberFormat::Style::Unit: {
|
||||||
// a. Let unit be numberFormat.[[Unit]].
|
// a. Let unit be numberFormat.[[Unit]].
|
||||||
// b. Let unitDisplay be numberFormat.[[UnitDisplay]].
|
// b. Let unitDisplay be numberFormat.[[UnitDisplay]].
|
||||||
// c. Let patterns be patterns.[[unit]].
|
// c. Let patterns be patterns.[[unit]].
|
||||||
|
@ -1355,9 +1354,23 @@ Optional<Variant<StringView, String>> get_number_format_pattern(NumberFormat& nu
|
||||||
// i. Let unit be "fallback".
|
// i. Let unit be "fallback".
|
||||||
// e. Let patterns be patterns.[[<unit>]].
|
// e. Let patterns be patterns.[[<unit>]].
|
||||||
// f. Let patterns be patterns.[[<unitDisplay>]].
|
// f. Let patterns be patterns.[[<unitDisplay>]].
|
||||||
|
Vector<Unicode::NumberFormat> formats;
|
||||||
|
|
||||||
// FIXME: LibUnicode will need to parse the cldr-units package.
|
switch (number_format.unit_display()) {
|
||||||
|
case NumberFormat::UnitDisplay::Long:
|
||||||
|
formats = Unicode::get_unit_formats(number_format.data_locale(), number_format.unit(), Unicode::Style::Long);
|
||||||
|
break;
|
||||||
|
case NumberFormat::UnitDisplay::Short:
|
||||||
|
formats = Unicode::get_unit_formats(number_format.data_locale(), number_format.unit(), Unicode::Style::Short);
|
||||||
|
break;
|
||||||
|
case NumberFormat::UnitDisplay::Narrow:
|
||||||
|
formats = Unicode::get_unit_formats(number_format.data_locale(), number_format.unit(), Unicode::Style::Narrow);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
patterns = Unicode::select_pattern_with_plurality(formats, number);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// 9. Else if style is "currency", then
|
// 9. Else if style is "currency", then
|
||||||
case NumberFormat::Style::Currency:
|
case NumberFormat::Style::Currency:
|
||||||
|
@ -1474,6 +1487,8 @@ Optional<Variant<StringView, String>> get_number_format_pattern(NumberFormat& nu
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
found_pattern = patterns.release_value();
|
||||||
|
|
||||||
// Handling of steps 9b/9g: Depending on the currency display and the format pattern found above,
|
// Handling of steps 9b/9g: Depending on the currency display and the format pattern found above,
|
||||||
// we might need to mutate the format pattern to inject a space between the currency display and
|
// we might need to mutate the format pattern to inject a space between the currency display and
|
||||||
// the currency number.
|
// the currency number.
|
||||||
|
|
|
@ -211,7 +211,7 @@ Array* format_numeric_to_parts(GlobalObject& global_object, NumberFormat& number
|
||||||
RawFormatResult to_raw_precision(double number, int min_precision, int max_precision);
|
RawFormatResult to_raw_precision(double number, int min_precision, int max_precision);
|
||||||
RawFormatResult to_raw_fixed(double number, int min_fraction, int max_fraction);
|
RawFormatResult to_raw_fixed(double number, int min_fraction, int max_fraction);
|
||||||
ThrowCompletionOr<void> set_number_format_unit_options(GlobalObject& global_object, NumberFormat& intl_object, Object const& options);
|
ThrowCompletionOr<void> set_number_format_unit_options(GlobalObject& global_object, NumberFormat& intl_object, Object const& options);
|
||||||
Optional<Variant<StringView, String>> get_number_format_pattern(NumberFormat& number_format, double number);
|
Optional<Variant<StringView, String>> get_number_format_pattern(NumberFormat& number_format, double number, Unicode::NumberFormat& found_pattern);
|
||||||
Optional<StringView> get_notation_sub_pattern(NumberFormat& number_format, int exponent);
|
Optional<StringView> get_notation_sub_pattern(NumberFormat& number_format, int exponent);
|
||||||
int compute_exponent(NumberFormat& number_format, double number);
|
int compute_exponent(NumberFormat& number_format, double number);
|
||||||
int compute_exponent_for_magniude(NumberFormat& number_format, int magnitude);
|
int compute_exponent_for_magniude(NumberFormat& number_format, int magnitude);
|
||||||
|
|
|
@ -889,3 +889,119 @@ describe("style=currency", () => {
|
||||||
expect(ar2.format(-1)).toBe("\u061c-\u0661\u066b\u0660\u0660\u00a0US$");
|
expect(ar2.format(-1)).toBe("\u061c-\u0661\u066b\u0660\u0660\u00a0US$");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("style=unit", () => {
|
||||||
|
test("unitDisplay=long", () => {
|
||||||
|
const en1 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "gigabit",
|
||||||
|
unitDisplay: "long",
|
||||||
|
});
|
||||||
|
expect(en1.format(1)).toBe("1 gigabit");
|
||||||
|
expect(en1.format(1.2)).toBe("1.2 gigabits");
|
||||||
|
expect(en1.format(123)).toBe("123 gigabits");
|
||||||
|
|
||||||
|
const en2 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "long",
|
||||||
|
});
|
||||||
|
expect(en2.format(1)).toBe("1 kilometer per hour");
|
||||||
|
expect(en2.format(1.2)).toBe("1.2 kilometers per hour");
|
||||||
|
expect(en2.format(123)).toBe("123 kilometers per hour");
|
||||||
|
|
||||||
|
const ar = new Intl.NumberFormat("ar", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "foot",
|
||||||
|
unitDisplay: "long",
|
||||||
|
});
|
||||||
|
expect(ar.format(1)).toBe("قدم");
|
||||||
|
expect(ar.format(1.2)).toBe("\u0661\u066b\u0662 قدم");
|
||||||
|
expect(ar.format(123)).toBe("\u0661\u0662\u0663 قدم");
|
||||||
|
|
||||||
|
const ja = new Intl.NumberFormat("ja", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "long",
|
||||||
|
});
|
||||||
|
expect(ja.format(1)).toBe("時速 1 キロメートル");
|
||||||
|
expect(ja.format(1.2)).toBe("時速 1.2 キロメートル");
|
||||||
|
expect(ja.format(123)).toBe("時速 123 キロメートル");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("unitDisplay=short", () => {
|
||||||
|
const en1 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "gigabit",
|
||||||
|
unitDisplay: "short",
|
||||||
|
});
|
||||||
|
expect(en1.format(1)).toBe("1 Gb");
|
||||||
|
expect(en1.format(1.2)).toBe("1.2 Gb");
|
||||||
|
expect(en1.format(123)).toBe("123 Gb");
|
||||||
|
|
||||||
|
const en2 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "short",
|
||||||
|
});
|
||||||
|
expect(en2.format(1)).toBe("1 km/h");
|
||||||
|
expect(en2.format(1.2)).toBe("1.2 km/h");
|
||||||
|
expect(en2.format(123)).toBe("123 km/h");
|
||||||
|
|
||||||
|
const ar = new Intl.NumberFormat("ar", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "foot",
|
||||||
|
unitDisplay: "short",
|
||||||
|
});
|
||||||
|
expect(ar.format(1)).toBe("قدم");
|
||||||
|
expect(ar.format(1.2)).toBe("\u0661\u066b\u0662 قدم");
|
||||||
|
expect(ar.format(123)).toBe("\u0661\u0662\u0663 قدم");
|
||||||
|
|
||||||
|
const ja = new Intl.NumberFormat("ja", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "short",
|
||||||
|
});
|
||||||
|
expect(ja.format(1)).toBe("1 km/h");
|
||||||
|
expect(ja.format(1.2)).toBe("1.2 km/h");
|
||||||
|
expect(ja.format(123)).toBe("123 km/h");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("unitDisplay=narrow", () => {
|
||||||
|
const en1 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "gigabit",
|
||||||
|
unitDisplay: "narrow",
|
||||||
|
});
|
||||||
|
expect(en1.format(1)).toBe("1Gb");
|
||||||
|
expect(en1.format(1.2)).toBe("1.2Gb");
|
||||||
|
expect(en1.format(123)).toBe("123Gb");
|
||||||
|
|
||||||
|
const en2 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "narrow",
|
||||||
|
});
|
||||||
|
expect(en2.format(1)).toBe("1km/h");
|
||||||
|
expect(en2.format(1.2)).toBe("1.2km/h");
|
||||||
|
expect(en2.format(123)).toBe("123km/h");
|
||||||
|
|
||||||
|
const ar = new Intl.NumberFormat("ar", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "foot",
|
||||||
|
unitDisplay: "narrow",
|
||||||
|
});
|
||||||
|
expect(ar.format(1)).toBe("قدم");
|
||||||
|
expect(ar.format(1.2)).toBe("\u0661\u066b\u0662 قدم");
|
||||||
|
expect(ar.format(123)).toBe("\u0661\u0662\u0663 قدمًا");
|
||||||
|
|
||||||
|
const ja = new Intl.NumberFormat("ja", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "narrow",
|
||||||
|
});
|
||||||
|
expect(ja.format(1)).toBe("1km/h");
|
||||||
|
expect(ja.format(1.2)).toBe("1.2km/h");
|
||||||
|
expect(ja.format(123)).toBe("123km/h");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -1100,3 +1100,213 @@ describe("style=currency", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("style=unit", () => {
|
||||||
|
test("unitDisplay=long", () => {
|
||||||
|
const en1 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "gigabit",
|
||||||
|
unitDisplay: "long",
|
||||||
|
});
|
||||||
|
expect(en1.formatToParts(1)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "gigabit" },
|
||||||
|
]);
|
||||||
|
expect(en1.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "decimal", value: "." },
|
||||||
|
{ type: "fraction", value: "2" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "gigabits" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const en2 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "long",
|
||||||
|
});
|
||||||
|
expect(en2.formatToParts(1)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "kilometer per hour" },
|
||||||
|
]);
|
||||||
|
expect(en2.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "decimal", value: "." },
|
||||||
|
{ type: "fraction", value: "2" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "kilometers per hour" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const ar = new Intl.NumberFormat("ar", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "foot",
|
||||||
|
unitDisplay: "long",
|
||||||
|
});
|
||||||
|
expect(ar.formatToParts(1)).toEqual([{ type: "unit", value: "قدم" }]);
|
||||||
|
expect(ar.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "\u0661" },
|
||||||
|
{ type: "decimal", value: "\u066b" },
|
||||||
|
{ type: "fraction", value: "\u0662" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "قدم" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const ja = new Intl.NumberFormat("ja", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "long",
|
||||||
|
});
|
||||||
|
expect(ja.formatToParts(1)).toEqual([
|
||||||
|
{ type: "unit", value: "時速" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "キロメートル" },
|
||||||
|
]);
|
||||||
|
expect(ja.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "unit", value: "時速" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "decimal", value: "." },
|
||||||
|
{ type: "fraction", value: "2" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "キロメートル" },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("unitDisplay=short", () => {
|
||||||
|
const en1 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "gigabit",
|
||||||
|
unitDisplay: "short",
|
||||||
|
});
|
||||||
|
expect(en1.formatToParts(1)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "Gb" },
|
||||||
|
]);
|
||||||
|
expect(en1.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "decimal", value: "." },
|
||||||
|
{ type: "fraction", value: "2" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "Gb" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const en2 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "short",
|
||||||
|
});
|
||||||
|
expect(en2.formatToParts(1)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "km/h" },
|
||||||
|
]);
|
||||||
|
expect(en2.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "decimal", value: "." },
|
||||||
|
{ type: "fraction", value: "2" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "km/h" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const ar = new Intl.NumberFormat("ar", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "foot",
|
||||||
|
unitDisplay: "short",
|
||||||
|
});
|
||||||
|
expect(ar.formatToParts(1)).toEqual([{ type: "unit", value: "قدم" }]);
|
||||||
|
expect(ar.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "\u0661" },
|
||||||
|
{ type: "decimal", value: "\u066b" },
|
||||||
|
{ type: "fraction", value: "\u0662" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "قدم" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const ja = new Intl.NumberFormat("ja", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "short",
|
||||||
|
});
|
||||||
|
expect(ja.formatToParts(1)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "km/h" },
|
||||||
|
]);
|
||||||
|
expect(ja.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "decimal", value: "." },
|
||||||
|
{ type: "fraction", value: "2" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "km/h" },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("unitDisplay=narrow", () => {
|
||||||
|
const en1 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "gigabit",
|
||||||
|
unitDisplay: "narrow",
|
||||||
|
});
|
||||||
|
expect(en1.formatToParts(1)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "unit", value: "Gb" },
|
||||||
|
]);
|
||||||
|
expect(en1.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "decimal", value: "." },
|
||||||
|
{ type: "fraction", value: "2" },
|
||||||
|
{ type: "unit", value: "Gb" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const en2 = new Intl.NumberFormat("en", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "narrow",
|
||||||
|
});
|
||||||
|
expect(en2.formatToParts(1)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "unit", value: "km/h" },
|
||||||
|
]);
|
||||||
|
expect(en2.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "decimal", value: "." },
|
||||||
|
{ type: "fraction", value: "2" },
|
||||||
|
{ type: "unit", value: "km/h" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const ar = new Intl.NumberFormat("ar", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "foot",
|
||||||
|
unitDisplay: "narrow",
|
||||||
|
});
|
||||||
|
expect(ar.formatToParts(1)).toEqual([{ type: "unit", value: "قدم" }]);
|
||||||
|
expect(ar.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "\u0661" },
|
||||||
|
{ type: "decimal", value: "\u066b" },
|
||||||
|
{ type: "fraction", value: "\u0662" },
|
||||||
|
{ type: "literal", value: " " },
|
||||||
|
{ type: "unit", value: "قدم" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const ja = new Intl.NumberFormat("ja", {
|
||||||
|
style: "unit",
|
||||||
|
unit: "kilometer-per-hour",
|
||||||
|
unitDisplay: "narrow",
|
||||||
|
});
|
||||||
|
expect(ja.formatToParts(1)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "unit", value: "km/h" },
|
||||||
|
]);
|
||||||
|
expect(ja.formatToParts(1.2)).toEqual([
|
||||||
|
{ type: "integer", value: "1" },
|
||||||
|
{ type: "decimal", value: "." },
|
||||||
|
{ type: "fraction", value: "2" },
|
||||||
|
{ type: "unit", value: "km/h" },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue