Skip to content

chore: release v0.6.0 - #18

Open
MagicalTux wants to merge 1 commit into
masterfrom
release-plz-2026-07-28T17-03-10Z
Open

chore: release v0.6.0#18
MagicalTux wants to merge 1 commit into
masterfrom
release-plz-2026-07-28T17-03-10Z

Conversation

@MagicalTux

@MagicalTux MagicalTux commented Jul 28, 2026

Copy link
Copy Markdown
Member

🤖 New release

  • intl: 0.5.2 -> 0.6.0 (⚠ API breaking changes)

intl breaking changes

--- failure constructible_struct_adds_field: externally-constructible struct adds field ---

Description:
A pub struct constructible with a struct literal has a new pub field. Existing struct literals must be updated to include the new field.
        ref: https://doc.rust-lang.org/reference/expressions/struct-expr.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/constructible_struct_adds_field.ron

Failed in:
  field NumberSpec.nan in /tmp/.tmpuGduNP/intlrs/src/cldr.rs:69
  field NumberSpec.infinity in /tmp/.tmpuGduNP/intlrs/src/cldr.rs:71

--- failure enum_variant_added: enum variant added on exhaustive enum ---

Description:
A publicly-visible enum without #[non_exhaustive] has a new variant.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#enum-variant-new
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/enum_variant_added.ron

Failed in:
  variant Unit:Acre in /tmp/.tmpuGduNP/intlrs/src/unit.rs:63
  variant Unit:Bit in /tmp/.tmpuGduNP/intlrs/src/unit.rs:64
  variant Unit:Degree in /tmp/.tmpuGduNP/intlrs/src/unit.rs:65
  variant Unit:FluidOunce in /tmp/.tmpuGduNP/intlrs/src/unit.rs:66
  variant Unit:Gallon in /tmp/.tmpuGduNP/intlrs/src/unit.rs:67
  variant Unit:Gigabit in /tmp/.tmpuGduNP/intlrs/src/unit.rs:68
  variant Unit:Hectare in /tmp/.tmpuGduNP/intlrs/src/unit.rs:69
  variant Unit:Kilobit in /tmp/.tmpuGduNP/intlrs/src/unit.rs:70
  variant Unit:Megabit in /tmp/.tmpuGduNP/intlrs/src/unit.rs:71
  variant Unit:Microsecond in /tmp/.tmpuGduNP/intlrs/src/unit.rs:72
  variant Unit:MileScandinavian in /tmp/.tmpuGduNP/intlrs/src/unit.rs:73
  variant Unit:Millisecond in /tmp/.tmpuGduNP/intlrs/src/unit.rs:74
  variant Unit:Nanosecond in /tmp/.tmpuGduNP/intlrs/src/unit.rs:75
  variant Unit:Percent in /tmp/.tmpuGduNP/intlrs/src/unit.rs:76
  variant Unit:Petabyte in /tmp/.tmpuGduNP/intlrs/src/unit.rs:77
  variant Unit:Stone in /tmp/.tmpuGduNP/intlrs/src/unit.rs:78
  variant Unit:Terabit in /tmp/.tmpuGduNP/intlrs/src/unit.rs:79
  variant Unit:Terabyte in /tmp/.tmpuGduNP/intlrs/src/unit.rs:80
  variant Unit:Yard in /tmp/.tmpuGduNP/intlrs/src/unit.rs:81
  variant UnitWidth:Narrow in /tmp/.tmpuGduNP/intlrs/src/unit.rs:221
  variant NumberPartType:ApproximatelySign in /tmp/.tmpuGduNP/intlrs/src/number.rs:60
Changelog

0.6.0 - 2026-07-29

Added

  • (datetime) localized time-zone names from CLDR metazones
  • (units) narrow width, compound units, and the full ECMA-402 set
  • (number) vendor en-IN and zh-Hant, alias region tags onto scripts

Fixed

  • (datetime) compose date+time intervals, range seconds, half-local literals
  • (datetime) synthesize a pattern for lone time fields instead of ""
  • (datetime) render the era-relative year for y, not the astronomical one
  • (number) handle non-finite input; format_scientific no longer hangs

Other

  • Merge the number-symbols/range work into the time-zone-name work
  • (data) vendor CLDR 48 time-zone names and metazone mapping
  • ignore /.claude/

Added

  • (unit) the full ECMA-402 sanctioned unit set and general compound units.
    Unit grew from 28 to 47 variants, completing the 45 sanctioned identifiers —
    acre, bit, degree, fluid-ounce, gallon, gigabit, hectare,
    kilobit, megabit, microsecond, mile-scandinavian, millisecond,
    nanosecond, percent, petabyte, stone, terabit, terabyte, yard
    alongside the two speed-… compounds CLDR ships pre-composed. Any
    <unit>-per-<unit> ratio now formats via format_unit_id /
    format_compound_unit, and through NumberFormat's unit option:
    format_unit_id("en", 5.0, "meter-per-second", UnitWidth::Long)
    "5 meters per second", ("gallon-per-mile", Short)"5 gal/mi",
    ("gallon-per-mile", Long) in German → "5 Gallonen pro Meile". Both UTS #35
    assembly paths are implemented: the denominator's perUnitPattern when it has
    one (18 of the 45 units do) and the locale's per compoundUnitPattern
    otherwise. Unit::from_ecma_id / Unit::ecma_id expose the identifier
    mapping. Reported in #17.
  • (unit) UnitWidth::Narrow — ECMA-402 unitDisplay: "narrow" is now a real
    third width instead of an alias for short: format_unit("en", 5.0, Unit::Kilometer, UnitWidth::Narrow)"5km" (short gives "5 km"), "5°"
    for degrees, "3h" for hours. number::UnitDisplay::Narrow resolves to it.
    The narrow patterns are a third of the unit table, so they sit behind the new
    units-narrow cargo feature (in default); without it the width falls back to
    short, which is UTS #35's own narrow → short fallback.
  • (number) en-IN and zh-Hant number data, vendored from CLDR 48. en-IN
    carries Indian digit grouping (format_decimal("en-IN", 12345678.0)
    "1,23,45,678", was "12,345,678") and crore/lakh compact forms; zh-Hant
    carries the Traditional Chinese compact forms (format_compact("zh-Hant", 123456789.0)"1.2億", was "1.2亿"). Upstream ships no region files under
    zh-Hant, so codegen derives zh-TW, zh-HK and zh-MO from it through
    CLDR's own likelySubtags — the runtime lookup truncates a tag at each - and
    does no script inference, so those would otherwise reach Simplified zh.
    zh-CN/zh-SG still resolve to zh, as they should. Reported in
    #17.
  • (datetime) DateTimeFormatError::UnsupportedOptions, returned when the
    requested options resolve to a pattern with no fields left in it. Previously
    that case produced Ok(""), which a caller cannot tell apart from a real
    result.
  • (datetime) localized time-zone names (UTS #35 §4.8). time_zone_name now
    resolves real names instead of always rendering a GMT offset:
    America/Los_Angeles in July is "Pacific Daylight Time" / "PDT" /
    "Pacific Time" / "PT" for long / short / longGeneric /
    shortGeneric in en, and "heure d’été du Pacifique nord-américain" /
    "heure du Pacifique nord-américain" in fr; UTC is "Coordinated Universal Time". All 101 CLDR locales, 447 zones and 191 metazones, with the
    metazone ranges applied historically (Europe/London is British before
    1971-10-31 and GMT after) and tzdb links canonicalized (US/Pacific,
    Asia/Calcutta). The full fallback chain is implemented — the zone's own
    name, then its metazone's, then the generic location format (the locale's
    regionFormat over the country name for a single-zone country, else the
    exemplar city: "heure : Los Angeles"), then the localized GMT offset. Values
    were checked against V8/ICU. Chooses the standard or daylight name from the
    zone's DST state at the instant, which needs iana-tz; without it the zone is
    reported on standard time. Reported in
    #17.
  • (datetime) one cargo feature per tzdb area — tz-names-africa,
    tz-names-america, tz-names-antarctica, tz-names-arctic, tz-names-asia,
    tz-names-atlantic, tz-names-australia, tz-names-etc, tz-names-europe,
    tz-names-indian, tz-names-pacific — plus the tz-names umbrella, which is
    in default. The names are large (~3.6 MB of generated source, +4.4 MB
    compiled for all eleven areas; America +1.29 MB, Asia +1.28 MB, Europe
    +397 KB, Etc +22 KB), so a build can carry only the areas it uses; an area
    that is not compiled in falls back to the localized GMT offset, which is UTS
    #35's own last resort. The umbrella is in default on the same reasoning as
    units-narrow: answering a spec-mandated timeZoneName: "long" with an
    offset is a silently degraded result, which is worse than the size.
  • (number) format_range and format_range_to_parts — ECMA-402 v3
    Intl.NumberFormat.prototype.formatRange/formatRangeToParts, driven by the
    CLDR miscPatterns the tables previously did not carry.
    format_range("en", 2.9, 3.1, …) with style: currency gives
    "$2.90–$3.10"; zh separates with an ASCII hyphen, ja with U+FF1E. Per
    PartitionNumberRangePattern step 5, ends that format identically collapse
    to the approximately form rather than a degenerate range: "~3" in en,
    "≈3" in de and fr, "約 3" in ja — and that is the miscPatterns
    approximately string, which is independent of the approximatelySign symbol
    (fr has ≈{0} against ). format_range_to_parts returns
    NumberRangeParts carrying the spec's source field
    (NumberRangeSource::{StartRange, EndRange, Shared}) and tags the collapse
    marker NumberPartType::ApproximatelySign. Behind the new number-range
    cargo feature (in default; ~16 KB of code + data). Reported in
    #17.
  • (number) -u-nu-<system> support and native_numbering_system /
    default_numbering_system. Every number entry point now reads the tag's
    UTS #35 nu keyword — format_decimal("hi-u-nu-deva", …),
    format_decimal("ar-u-nu-native", …) — and NumberFormatOptions:: numbering_system accepts the same values, including the "native" alias,
    outranking the tag as ECMA-402 ResolveLocale requires. CLDR's
    otherNumberingSystems.native is now stored, which is what makes "native"
    resolvable: it is not the same as defaultNumberingSystem (ar defaults to
    latn but is natively arab, hi to latn but natively deva, zh to
    latn but natively hanidec). number does not depend on the locale
    feature, so the -u- scan is a small self-contained one in number rather
    than a new Locale accessor. Reported in
    #17.
  • (number) NumberSpec::nan and NumberSpec::infinity, the CLDR
    symbols/nan and symbols/infinity strings.

Changed

  • (unit) the CLDR unit table moved from the src/cldr/units.bin blob to
    generated Rust (src/cldr/generated/units.rs, const fn + match), matching
    how the Unicode property tables are shipped. #[cfg] sits on individual width
    dispatch arms, so units without units-narrow never compiles the narrow
    patterns. The table also gained the perUnitPattern and compoundUnitPattern
    strings and 19 more units, so the compiled footprint is ~905 KB for long+short
    and ~315 KB more for narrow, against 175 KB for the old (long+short only,
    28-unit) blob.
  • (number) format_to_parts with style: "unit" now tags the whole unit
    phrase as one unit part, as ICU does, instead of splitting it on interior
    whitespace. "5 kilometers per hour" yields integer("5") literal(" ") unit("kilometers per hour"), not six parts. Single-word units are unchanged.
  • (datetime) the localized GMT offset formats moved off the hand-curated
    26-locale data/cldr/48/timezone.json (and its src/cldr/timezone.bin blob,
    both now deleted) onto CLDR's own timeZoneNames for all 101 locales, in
    src/cldr/generated/tz_names.rs. All 26 curated locales matched CLDR 48
    byte-for-byte, so no locale changed; the other 75 stop falling back to
    English. The same table carries regionFormat and fallbackFormat, which the
    new name resolution needs.
  • (datetime) TimeZoneNameStyle::Short no longer returns the tz database's
    abbreviation. It resolves CLDR's short metazone name, so America/New_York
    still gives "EST"/"EDT", but Asia/Tokyo — for which CLDR has no short
    name — gives "GMT+9" rather than "JST", and a non-English locale gets its
    own name or offset rather than the English abbreviation. This is what
    ECMA-402 specifies and what V8/ICU produce.

Fixed

  • (datetime) TimeZoneNameStyle::ShortOffset panicked for every locale whose
    hourFormat uses U+2212 MINUS SIGN (et, fa, fr, ht, lt, sv).
    Trimming the hour's
    leading zero split the string one byte past the sign, inside the multi-byte
    character. The short offset is now built from the hourFormat subpattern
    itself, which also fixes its shape: GMT-7, not GMT-7:00 — UTS #35's short
    localized GMT drops the minute field when it is zero, as ICU does.
  • (datetime) format_gmt_offset rendered the letter H literally for the two
    locales whose hourFormat uses a single H rather than HH:
    format_gmt_offset("cs", 330) gave "GMT+H:30" and now gives "GMT+5:30"
    (likewise fi). Only HH was ever substituted.
  • (number) the CLDR number table moved from the src/cldr/numbers.bin and
    src/cldr/numsys_default.bin blobs to generated Rust
    (src/cldr/generated/numbers.rs, match lookups), following units. It is
    now keyed by (locale, numbering system) rather than by locale alone, which is
    what a blob could not gate: the non-latn blocks sit on #[cfg]-ed match arms
    behind the new number-numsys feature (in default; ~4 KB). Every record the
    blobs held was checked field-for-field against the generated table before the
    blobs were dropped — all 121 numbers.bin keys (103 locales plus the derived
    lang-REGION aliases) and all 103 numsys_default.bin keys are byte-identical.
    The base number footprint grows ~10 KB, the price of &'static str pointer
    pairs over a packed blob.
  • (number) the numbering_system option, and a -u-nu- tag, now select the
    numbering system's separators and patterns too, not just its digits. CLDR
    keys symbols-numberSystem-<ns> and decimalFormats-numberSystem-<ns> per
    system and they genuinely differ: format("ar", …, numbering_system: "arab")
    gives "١٬٢٣٤٫٥" (U+066C group, U+066B decimal), not "١,٢٣٤.٥"; te groups
    Indian-style in latn but not in telu. Requests for a system the locale
    ships no block for keep its latn symbols, which is ICU's NumberElements
    fallback — format("en", …, numbering_system: "arab") is unchanged.
  • (number) non-finite values use the locale's CLDR strings.
    format("ar", f64::NAN, …) is "ليس رقمًا" and format("fa", …) "ناعدد",
    where all four call sites previously hardcoded "NaN"/"∞". ( happens to
    be right for every vendored locale, but was not being read.)

Deprecated

  • (number) format_decimal_native is renamed to
    format_decimal_default_numbering; the old name is kept as a deprecated
    forwarder. It never read otherNumberingSystems.native — it reads
    defaultNumberingSystem, and that is the ECMA-402 behaviour worth having
    (Intl.NumberFormat('ar') also formats 1.5 with Latin digits, because ar
    defaults to latn in CLDR 48). The native system is now reachable through
    format_decimal("<lang>-u-nu-native", …) or native_numbering_system.

Fixed

  • (number) format_decimal_default_numbering (ex format_decimal_native) uses
    the default numbering system's separators, not just its digits. Persian gave
    "۱,۲۳۴.۵"arabext digits glued to latn separators, a combination no
    locale uses; Intl.NumberFormat('fa') gives "۱٬۲۳۴٫۵", which is now the
    output.

  • (datetime) a lone time field no longer formats as the empty string.
    day_period, minute, second and fractional_second_digits, each on their
    own, resolved through CLDR availableFormats — which tabulates only the
    combinations it expects to be asked for, and has no m, s, B or S entry
    in any locale. The lookup fell through to the locale's medium date pattern,
    whose fields the keep-pass then stripped in full, leaving "". Pure-time
    skeletons with no tabulated entry are now synthesized from their own fields
    (joined with the locale's time separator), the way ICU's
    DateTimePatternGenerator does. minute alone now gives "30", day_period
    alone "in the morning" (morgens, du matin, ), and
    fractional_second_digits: 3 alone "123". Date skeletons keep falling back
    to the locale's medium date pattern, whose field order a naive synthesis
    would get wrong. Reported in
    #17.

  • (datetime) y renders the era-relative year, not the astronomical one. UTS
    #35 counts the BCE side back from 1, so year 0 now formats as 1 BC and
    -1 as 2 BC; previously they rendered 0 BC and -1 BC, and a negative
    number beside a BC era is never right. This applies whether or not an era
    is requested, since that is what the y field means. The astronomical year is
    reachable through the u field, which is now rendered rather than dropped.
    Non-Gregorian calendars get the same treatment (the Islamic/Persian BH/BP
    side); the Japanese year-within-era and the Chinese cyclic year were already
    era-relative and are unchanged. Reported in
    #17.

  • (number) format_scientific no longer hangs on an infinite input. The
    mantissa normalization looped on m /= 10.0 until m < 10.0, but inf / 10.0
    is inf, so the loop never terminated: a release build spun forever and a
    debug build panicked with "attempt to add with overflow" on the exponent
    counter. Non-finite input now returns early. Reported in
    #17.

  • (number) non-finite values format as ECMA-402's / NaN on every path,
    not Rust's inf. format_decimal, format_percent, format_compact,
    format_currency and unit::format_unit all reach format_with, which spelled
    the value with {:.*} and produced "inf", "inf%", "$inf",
    "inf meters" — disagreeing with format/format_to_parts, which already
    emitted "∞". The pattern's affixes are kept ("∞%", "$∞"), the locale minus
    sign is used for negative infinity, and NaN is unsigned per ECMA-402.

  • (datetime) format_range composes a date+time interval instead of repeating
    the date. CLDR keys intervalFormats by date-only or time-only skeletons and
    never by a mixed one, so a combined request ({year, month, day, hour, minute}) always missed the lookup and fell back to formatting the whole
    pattern twice — "6/15/2024, 9:00 AM – 6/15/2024, 5:00 PM" for two times on
    one day. When the greatest differing field is a time field, UTS #35 §2.6.2
    composition now applies: the date is formatted once and the time range is
    glued into it with the locale's dateTimeFormat, giving "6/15/2024, 9:00 AM – 5:00 PM" ("2024/6/15 9時00分~17時00分" in ja). A date-field difference
    still carries the whole pattern on both ends, as ICU does. Reported in
    #17.

  • (datetime) format_range no longer drops the end of a seconds-only
    interval. The greatest-difference scan stopped at the minute, so
    {hour, minute, second} over 9:00:109:00:45 reported no difference at all
    and formatted a single time, "9:00:10 AM", silently losing the end point. It
    now gives "9:00:10 AM – 9:00:45 AM". Sub-second differences count too when
    fractional_second_digits puts them on screen (ECMA-402 groups s/S/A as
    one range field); a millisecond difference the pattern does not show still
    collapses to a single value.

  • (datetime) format_range_to_parts attributes the literals inside a fallback
    half to that half. When the two ends are formatted separately and joined by
    intervalFormatFallback, every literal was tagged Shared, including the
    ", " and ":" within each date. ECMA-402 substitutes each side into the
    {0}/{1} slot wholesale, so those are StartRange/EndRange like the
    fields they punctuate; only the fallback's own separator is Shared.
    Reported in #17.


This PR was generated with release-plz.

@MagicalTux
MagicalTux force-pushed the release-plz-2026-07-28T17-03-10Z branch 3 times, most recently from 93703c8 to ccb5dd1 Compare July 29, 2026 00:37
@MagicalTux MagicalTux changed the title chore: release v0.5.3 chore: release v0.6.0 Jul 29, 2026
@MagicalTux
MagicalTux force-pushed the release-plz-2026-07-28T17-03-10Z branch from ccb5dd1 to e99af78 Compare July 29, 2026 01:06
@MagicalTux
MagicalTux force-pushed the release-plz-2026-07-28T17-03-10Z branch from e99af78 to d59f949 Compare July 29, 2026 01:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant