Skip to content

Localize version 0.26.0

Choose a tag to compare

@kipcole9 kipcole9 released this 06 May 11:02
· 113 commits to main since this release

[0.26.0] — May 6th, 2026

This release fixes user-reported bug #22 in time interval formatting and a number of RBNF conformance bugs arising from a more complete conformance testing process. The RBNF bugs have been around unreported and undiagnosed for many years.

Breaking Change

  • The default Localize.Interval.to_string/3 format output (which is :medium) for time-only inputs now includes seconds. Localize.Interval.to_string!(~T[12:00:00], ~T[14:00:00], locale: :ja) shifts from 午後0時00分~2時00分 to 12:00:00~14:00:00. :en's :medium shifts from 12:00 – 2:00 PM to 12:00:00 PM – 2:00:00 PM. Users who relied on no-seconds output should explicitly pass time_format: :short.

Bug Fixes

  • Fix Localize.Interval.to_string/3 collapsing the :short, :medium, :long, and :full time styles to the same :hm skeleton on Time inputs. :short keeps CLDR's interval-format dispatch (collapsed AM/PM); :medium and above route through the locale's per-style time-format pattern, restoring per-style differentiation and including seconds in the default :medium output. Thanks to @woylie for the report. Fixes #22.

  • Fix :time_format being silently ignored on Localize.Interval.to_string/3 for Time inputs. The option now takes precedence over :format, matching the precedence used on datetime intervals. Thanks to @woylie for the report. Fixes #22.

  • Fix Localize.Interval.to_string/3 crashing with FunctionClauseError when called with a binary :format (or :time_format) on Time inputs. Binary patterns are now applied to both endpoints and joined via the locale's interval-format fallback template, matching the behaviour of datetime intervals. Thanks to @woylie for the report. Fixes #22.

  • RBNF parser now distinguishes >> from >>> so CJK locales emit fractional digits without an inter-digit separator — Localize.Number.Rbnf.to_string(3.14, "spellout-numbering", locale: :zh) is 三点一四 instead of 三点一 四.

  • RBNF leading and embedded zeros in fractional digits, and very small magnitudes, are now preserved — 0.05 en is "zero point zero five", 3.04 zh is 三点〇四, and 0.000001 en is "zero point zero zero zero zero zero one".

  • RBNF 0.x special-base rule now matches when the integer part is zero and the value is non-zero, routing ko 0.5 spellout-numbering through its locale-correct sino-Korean 영점오 instead of the previous x.x-fallback 공점공오.

  • RBNF negative floats no longer double their output or silently drop the sign — ko -0.5 spellout-numbering is -영점오 instead of 공점공점오, and locales that lack a -x rule now get an ASCII - prefix.

  • RBNF integer <#,##0< quotient and float >%name> / >#,##0> / <%name< modulo and quotient no longer crash, completing case-clause coverage for every TR35 substitution-argument shape.

  • RBNF $(cardinal,…) and $(ordinal,…) plural-keyed substitutions now use the requested locale's plural rules instead of hard-coding English — fr Localize.Number.Rbnf.to_string(21, "digits-ordinal-masculine", locale: :fr) is "21e" instead of "21er".

  • RBNF fraction-with-rule numerator/denominator algorithm is now spec-correct — ky 1.5 spellout-cardinal is бир бүтүн ондон беш instead of бир бүтүн беш.

Enhancements

  • Add :minimum_significant_digits and :maximum_significant_digits options to Localize.Number.to_string/2.

  • Localize.Number.Rbnf.to_string/3 now accepts Decimal inputs in addition to native integers and floats, with whole-valued Decimals routed through the integer path with no precision loss.

  • RBNF >>> integer modulo now applies the source-preceding rule per TR35 §RBNF_Syntax, closing a latent gap; no current CLDR locale exercises this path.