icu4x 0.9.0 → 0.10.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c0cb2adcc5d5af24a00272def5a66e3b03a928b0cb522a0d7c5ee6b50eacdb5
4
- data.tar.gz: 2f44d6cddb74e64fc922c6269d32b060ed8b03e751969d7bd0e1c87d584f0a59
3
+ metadata.gz: e325a3954b6ced7e74233f9932c136e417028cda9f87770fe3f6d46daadd6e93
4
+ data.tar.gz: 61fdc9da91abc2e3f1146e1398be2ac7248dd8e37f8158f5c4f9acd71a065b05
5
5
  SHA512:
6
- metadata.gz: 15b7967a5eecc044bbd3d3c1f3dfc36c08fd655cf9e83164c418239aa24a6cad7b622ac25d923cbc1d8f453cb8996be8ce5a1e38e3114f511a5f4ef1ebae2950
7
- data.tar.gz: 68e9db100a5255557d6bf1c298f990dae44f8743ce0829ecc050a56491dd9ba27ac9d42aff3df583f1111b919c9af8395cca75f1c3eccc98ce6789502e826f56
6
+ metadata.gz: 50ffdd36e7e8aaff6cb04136616314b295c7bec0909357d770d2cb8307a892d54820298cebf35221afc99587d4fcbbb55a4ac68bdfa125b3de46af93c59c2d5a
7
+ data.tar.gz: 0b632c37b59bb2abbada6686dd3a51b32b59d7619f41893f2da1b070cef59a53e896dc6aa15b564c9c7a41ca23f6cda39e8009e6aff50314b27e8f1944d0ca83
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.10.0] - 2026-05-08
4
+
5
+ ### Added
6
+
7
+ - `era:` option for `ICU4X::DateTimeFormat` to control era display (`:auto`, `:full`, `:with_era`, `:never`) (#144)
8
+ - Locale variant APIs: `ICU4X::Locale#variants`, `#add_variant!`, `#add_variant`, `#remove_variant!`, `#remove_variant` (#143)
9
+
10
+ ### Fixed
11
+
12
+ - `hour12: true/false` now maps to `Clock12`/`Clock24` for locale-aware hour cycle preference, not fixed `H12`/`H23` (#145)
13
+ - Declare `bigdecimal` as an explicit runtime dependency (#149)
14
+ - Remove deprecated `AnyCalendarKind::JapaneseExtended` (#141)
15
+
16
+ ### Changed
17
+
18
+ - Update ICU4X crates from 2.1 to 2.2 (CLDR 48.2, TZDB 2026a) (#138)
19
+
3
20
  ## [0.9.0] - 2026-02-01
4
21
 
5
22
  ### Added
data/Cargo.lock CHANGED
@@ -26,12 +26,6 @@ dependencies = [
26
26
  "derive_arbitrary",
27
27
  ]
28
28
 
29
- [[package]]
30
- name = "arrayvec"
31
- version = "0.7.6"
32
- source = "registry+https://github.com/rust-lang/crates.io-index"
33
- checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
34
-
35
29
  [[package]]
36
30
  name = "autocfg"
37
31
  version = "1.5.0"
@@ -93,9 +87,9 @@ checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
93
87
 
94
88
  [[package]]
95
89
  name = "calendrical_calculations"
96
- version = "0.2.3"
90
+ version = "0.2.4"
97
91
  source = "registry+https://github.com/rust-lang/crates.io-index"
98
- checksum = "3a0b39595c6ee54a8d0900204ba4c401d0ab4eb45adaf07178e8d017541529e7"
92
+ checksum = "5abbd6eeda6885048d357edc66748eea6e0268e3dd11f326fff5bd248d779c26"
99
93
  dependencies = [
100
94
  "core_maths",
101
95
  "displaydoc",
@@ -240,12 +234,6 @@ dependencies = [
240
234
  "syn",
241
235
  ]
242
236
 
243
- [[package]]
244
- name = "downcast-rs"
245
- version = "1.2.1"
246
- source = "registry+https://github.com/rust-lang/crates.io-index"
247
- checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
248
-
249
237
  [[package]]
250
238
  name = "either"
251
239
  version = "1.15.0"
@@ -310,9 +298,9 @@ checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
310
298
 
311
299
  [[package]]
312
300
  name = "fixed_decimal"
313
- version = "0.7.1"
301
+ version = "0.7.2"
314
302
  source = "registry+https://github.com/rust-lang/crates.io-index"
315
- checksum = "35eabf480f94d69182677e37571d3be065822acfafd12f2f085db44fbbcc8e57"
303
+ checksum = "79c3c892f121fff406e5dd6b28c1b30096b95111c30701a899d4f2b18da6d1bd"
316
304
  dependencies = [
317
305
  "displaydoc",
318
306
  "smallvec",
@@ -391,9 +379,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
391
379
 
392
380
  [[package]]
393
381
  name = "icu"
394
- version = "2.1.1"
382
+ version = "2.2.0"
395
383
  source = "registry+https://github.com/rust-lang/crates.io-index"
396
- checksum = "67ab713dd86fa032cb5487f9ac3a85d47b5dcf4c7b8c7dd00210b3cadd6a6551"
384
+ checksum = "00380f83691e089bcfa4aeb03a2d96a910b1c9ea406d6f822fc19dfb8b58d1ec"
397
385
  dependencies = [
398
386
  "icu_calendar",
399
387
  "icu_casemap",
@@ -417,7 +405,7 @@ dependencies = [
417
405
 
418
406
  [[package]]
419
407
  name = "icu4x"
420
- version = "0.9.0"
408
+ version = "0.10.0"
421
409
  dependencies = [
422
410
  "fixed_decimal",
423
411
  "icu",
@@ -437,7 +425,7 @@ dependencies = [
437
425
 
438
426
  [[package]]
439
427
  name = "icu4x_macros"
440
- version = "0.9.0"
428
+ version = "0.10.0"
441
429
  dependencies = [
442
430
  "proc-macro2",
443
431
  "quote",
@@ -446,9 +434,9 @@ dependencies = [
446
434
 
447
435
  [[package]]
448
436
  name = "icu_calendar"
449
- version = "2.1.1"
437
+ version = "2.2.1"
450
438
  source = "registry+https://github.com/rust-lang/crates.io-index"
451
- checksum = "d6f0e52e009b6b16ba9c0693578796f2dd4aaa59a7f8f920423706714a89ac4e"
439
+ checksum = "a2b2acc6263f494f1df50685b53ff8e57869e47d5c6fe39c23d518ae9a4f3e45"
452
440
  dependencies = [
453
441
  "calendrical_calculations",
454
442
  "databake",
@@ -465,15 +453,15 @@ dependencies = [
465
453
 
466
454
  [[package]]
467
455
  name = "icu_calendar_data"
468
- version = "2.1.1"
456
+ version = "2.2.0"
469
457
  source = "registry+https://github.com/rust-lang/crates.io-index"
470
- checksum = "527f04223b17edfe0bd43baf14a0cb1b017830db65f3950dc00224860a9a446d"
458
+ checksum = "118577bcf3a0fa7c6ac0a7d6e951814da84ee56b9b1f68fb4d8d10b08cefaf4d"
471
459
 
472
460
  [[package]]
473
461
  name = "icu_casemap"
474
- version = "2.1.1"
462
+ version = "2.2.0"
475
463
  source = "registry+https://github.com/rust-lang/crates.io-index"
476
- checksum = "d4ca9983e8bf51223c2f89014fa4eaa9e9b336c47f3af0d000538f86f841fba1"
464
+ checksum = "070f98b5b82798fcb93654bf96ed9f40064fc44c86f51a09ea711092cd5cc5be"
477
465
  dependencies = [
478
466
  "databake",
479
467
  "icu_casemap_data",
@@ -489,15 +477,15 @@ dependencies = [
489
477
 
490
478
  [[package]]
491
479
  name = "icu_casemap_data"
492
- version = "2.1.1"
480
+ version = "2.2.0"
493
481
  source = "registry+https://github.com/rust-lang/crates.io-index"
494
- checksum = "98d4663d0f99b301033a19e0acf94e9d2fa4b107638580165e5a6ccc49ad1450"
482
+ checksum = "846b0857ca091204be3c874bc93daaf89d4777e8d2d20b0d3ffe8f671d98014b"
495
483
 
496
484
  [[package]]
497
485
  name = "icu_codepointtrie_builder"
498
- version = "0.5.1"
486
+ version = "0.6.0"
499
487
  source = "registry+https://github.com/rust-lang/crates.io-index"
500
- checksum = "e22f92e06fd322f6e89264f637df4646e374abecdbc4ed7a9f73897e354ec1ef"
488
+ checksum = "2dd18415f0eee16ca74696b2c702bc36056de17fbc4e1aaffc09578921e9357a"
501
489
  dependencies = [
502
490
  "icu_collections",
503
491
  "wasmi",
@@ -507,9 +495,9 @@ dependencies = [
507
495
 
508
496
  [[package]]
509
497
  name = "icu_collator"
510
- version = "2.1.1"
498
+ version = "2.2.0"
511
499
  source = "registry+https://github.com/rust-lang/crates.io-index"
512
- checksum = "32eed11a5572f1088b63fa21dc2e70d4a865e5739fc2d10abc05be93bae97019"
500
+ checksum = "b521b92a2666061ddda902769d8a4cf730b5c9529a845cc1b69770b12a6c9a71"
513
501
  dependencies = [
514
502
  "databake",
515
503
  "icu_collator_data",
@@ -528,20 +516,21 @@ dependencies = [
528
516
 
529
517
  [[package]]
530
518
  name = "icu_collator_data"
531
- version = "2.1.1"
519
+ version = "2.2.0"
532
520
  source = "registry+https://github.com/rust-lang/crates.io-index"
533
- checksum = "5ab06f0e83a613efddba3e4913e00e43ed4001fae651cb7d40fc7e66b83b6fb9"
521
+ checksum = "038ed8e5817f2059c2f3efb0945ba78d060d3d25e8f1a1bea5139f821a21a2f0"
534
522
 
535
523
  [[package]]
536
524
  name = "icu_collections"
537
- version = "2.1.1"
525
+ version = "2.2.0"
538
526
  source = "registry+https://github.com/rust-lang/crates.io-index"
539
- checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
527
+ checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c"
540
528
  dependencies = [
541
529
  "databake",
542
530
  "displaydoc",
543
531
  "potential_utf",
544
532
  "serde",
533
+ "utf8_iter",
545
534
  "yoke",
546
535
  "zerofrom",
547
536
  "zerovec",
@@ -549,13 +538,12 @@ dependencies = [
549
538
 
550
539
  [[package]]
551
540
  name = "icu_datetime"
552
- version = "2.1.1"
541
+ version = "2.2.0"
553
542
  source = "registry+https://github.com/rust-lang/crates.io-index"
554
- checksum = "1b9d49f41ded8e63761b6b4c3120dfdc289415a1ed10107db6198eb311057ca5"
543
+ checksum = "989d56ea5bbc43ae2b4e0388874b002884eaf4ed3a76c84a6c8c5ad575e04d72"
555
544
  dependencies = [
556
545
  "databake",
557
546
  "displaydoc",
558
- "either",
559
547
  "fixed_decimal",
560
548
  "icu_calendar",
561
549
  "icu_datetime_data",
@@ -566,7 +554,6 @@ dependencies = [
566
554
  "icu_plurals",
567
555
  "icu_provider",
568
556
  "icu_time",
569
- "litemap",
570
557
  "potential_utf",
571
558
  "serde",
572
559
  "smallvec",
@@ -578,21 +565,24 @@ dependencies = [
578
565
 
579
566
  [[package]]
580
567
  name = "icu_datetime_data"
581
- version = "2.1.1"
568
+ version = "2.2.0"
582
569
  source = "registry+https://github.com/rust-lang/crates.io-index"
583
- checksum = "0bf2a384725c67fcd32d27737bc7ba9dc5fe21311dfe3ba530f4b4d53e72bacc"
570
+ checksum = "40d3cc1b690d9703202bc319692ac8a1f3a6390686f0930ff40542450fa34f0b"
584
571
 
585
572
  [[package]]
586
573
  name = "icu_decimal"
587
- version = "2.1.1"
574
+ version = "2.2.0"
588
575
  source = "registry+https://github.com/rust-lang/crates.io-index"
589
- checksum = "a38c52231bc348f9b982c1868a2af3195199623007ba2c7650f432038f5b3e8e"
576
+ checksum = "288247df2e32aa776ac54fdd64de552149ac43cb840f2761811f0e8d09719dd4"
590
577
  dependencies = [
591
578
  "databake",
579
+ "displaydoc",
592
580
  "fixed_decimal",
593
581
  "icu_decimal_data",
594
582
  "icu_locale",
595
583
  "icu_locale_core",
584
+ "icu_pattern",
585
+ "icu_plurals",
596
586
  "icu_provider",
597
587
  "serde",
598
588
  "writeable",
@@ -601,15 +591,15 @@ dependencies = [
601
591
 
602
592
  [[package]]
603
593
  name = "icu_decimal_data"
604
- version = "2.1.1"
594
+ version = "2.2.0"
605
595
  source = "registry+https://github.com/rust-lang/crates.io-index"
606
- checksum = "2905b4044eab2dd848fe84199f9195567b63ab3a93094711501363f63546fef7"
596
+ checksum = "6f14a5ca9e8af29eef62064f269078424283d90dbaffeac5225addf62aaabc22"
607
597
 
608
598
  [[package]]
609
599
  name = "icu_experimental"
610
- version = "0.4.0"
600
+ version = "0.5.0"
611
601
  source = "registry+https://github.com/rust-lang/crates.io-index"
612
- checksum = "f4ffa4d60b9cb8b024082afaf9e94d853184e483ec69322c74dc437bf8a882a5"
602
+ checksum = "0a881116e620fd635f564fd9cb9bc36c256b9da2221df8b3f55643d8ef32140f"
613
603
  dependencies = [
614
604
  "databake",
615
605
  "displaydoc",
@@ -643,15 +633,15 @@ dependencies = [
643
633
 
644
634
  [[package]]
645
635
  name = "icu_experimental_data"
646
- version = "0.4.0"
636
+ version = "0.5.0"
647
637
  source = "registry+https://github.com/rust-lang/crates.io-index"
648
- checksum = "2578ea93f0373bb28800f7d1100e7e771c4d248d0d3759250fed08fa27694139"
638
+ checksum = "f72090d4f08a2bc94565cb02de6d5b87939424e462d9927d73a34f6f8e5d1232"
649
639
 
650
640
  [[package]]
651
641
  name = "icu_list"
652
- version = "2.1.1"
642
+ version = "2.2.0"
653
643
  source = "registry+https://github.com/rust-lang/crates.io-index"
654
- checksum = "d3a0b7b126e2fc42777d3c348611553d540bd3683caa39b387c5dd1036bb21a8"
644
+ checksum = "aeeaf517689324395bed4767f7c65504f5455942ed4c14ee54c2087ca00b816e"
655
645
  dependencies = [
656
646
  "databake",
657
647
  "icu_list_data",
@@ -665,15 +655,15 @@ dependencies = [
665
655
 
666
656
  [[package]]
667
657
  name = "icu_list_data"
668
- version = "2.1.1"
658
+ version = "2.2.0"
669
659
  source = "registry+https://github.com/rust-lang/crates.io-index"
670
- checksum = "51044c242fe2a882cc0a464314bbdb9f441556a1cb238fb527fc47355ec2827b"
660
+ checksum = "ed62dbf114db9a4163481ed071509c4cd52cbcef9cb85979eba08a95549d73f3"
671
661
 
672
662
  [[package]]
673
663
  name = "icu_locale"
674
- version = "2.1.1"
664
+ version = "2.2.0"
675
665
  source = "registry+https://github.com/rust-lang/crates.io-index"
676
- checksum = "532b11722e350ab6bf916ba6eb0efe3ee54b932666afec989465f9243fe6dd60"
666
+ checksum = "d5a396343c7208121dc86e35623d3dfe19814a7613cfd14964994cdc9c9a2e26"
677
667
  dependencies = [
678
668
  "databake",
679
669
  "icu_collections",
@@ -688,9 +678,9 @@ dependencies = [
688
678
 
689
679
  [[package]]
690
680
  name = "icu_locale_core"
691
- version = "2.1.1"
681
+ version = "2.2.0"
692
682
  source = "registry+https://github.com/rust-lang/crates.io-index"
693
- checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
683
+ checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29"
694
684
  dependencies = [
695
685
  "databake",
696
686
  "displaydoc",
@@ -703,15 +693,15 @@ dependencies = [
703
693
 
704
694
  [[package]]
705
695
  name = "icu_locale_data"
706
- version = "2.1.1"
696
+ version = "2.2.0"
707
697
  source = "registry+https://github.com/rust-lang/crates.io-index"
708
- checksum = "f03e2fcaefecdf05619f3d6f91740e79ab969b4dd54f77cbf546b1d0d28e3147"
698
+ checksum = "d5fdcc9ac77c6d74ff5cf6e65ef3181d6af32003b16fce3a77fb451d2f695993"
709
699
 
710
700
  [[package]]
711
701
  name = "icu_normalizer"
712
- version = "2.1.1"
702
+ version = "2.2.0"
713
703
  source = "registry+https://github.com/rust-lang/crates.io-index"
714
- checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
704
+ checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4"
715
705
  dependencies = [
716
706
  "databake",
717
707
  "icu_collections",
@@ -728,15 +718,15 @@ dependencies = [
728
718
 
729
719
  [[package]]
730
720
  name = "icu_normalizer_data"
731
- version = "2.1.1"
721
+ version = "2.2.0"
732
722
  source = "registry+https://github.com/rust-lang/crates.io-index"
733
- checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
723
+ checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38"
734
724
 
735
725
  [[package]]
736
726
  name = "icu_pattern"
737
- version = "0.4.1"
727
+ version = "0.4.2"
738
728
  source = "registry+https://github.com/rust-lang/crates.io-index"
739
- checksum = "7a7ff8c0ff6f61cdce299dcb54f557b0a251adbc78f6f0c35a21332c452b4a1b"
729
+ checksum = "1c4c568054ffe735398a9f4c55aec37ad7c768844553cc0978f09cc9b933a1fb"
740
730
  dependencies = [
741
731
  "databake",
742
732
  "displaydoc",
@@ -749,9 +739,9 @@ dependencies = [
749
739
 
750
740
  [[package]]
751
741
  name = "icu_plurals"
752
- version = "2.1.1"
742
+ version = "2.2.0"
753
743
  source = "registry+https://github.com/rust-lang/crates.io-index"
754
- checksum = "4f9cfe49f5b1d1163cc58db451562339916a9ca5cbcaae83924d41a0bf839474"
744
+ checksum = "2a50023f1d49ad5c4333380328a0d4a19e4b9d6d842ec06639affd5ba47c8103"
755
745
  dependencies = [
756
746
  "databake",
757
747
  "displaydoc",
@@ -765,15 +755,15 @@ dependencies = [
765
755
 
766
756
  [[package]]
767
757
  name = "icu_plurals_data"
768
- version = "2.1.1"
758
+ version = "2.2.0"
769
759
  source = "registry+https://github.com/rust-lang/crates.io-index"
770
- checksum = "f018a98dccf7f0eb02ba06ac0ff67d102d8ded80734724305e924de304e12ff0"
760
+ checksum = "8485497155dc865f901decb93ecc20d3e467df67bfeceb91e3ba34e2b11e8e1d"
771
761
 
772
762
  [[package]]
773
763
  name = "icu_properties"
774
- version = "2.1.2"
764
+ version = "2.2.0"
775
765
  source = "registry+https://github.com/rust-lang/crates.io-index"
776
- checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
766
+ checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de"
777
767
  dependencies = [
778
768
  "databake",
779
769
  "icu_collections",
@@ -787,15 +777,15 @@ dependencies = [
787
777
 
788
778
  [[package]]
789
779
  name = "icu_properties_data"
790
- version = "2.1.2"
780
+ version = "2.2.0"
791
781
  source = "registry+https://github.com/rust-lang/crates.io-index"
792
- checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
782
+ checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14"
793
783
 
794
784
  [[package]]
795
785
  name = "icu_provider"
796
- version = "2.1.1"
786
+ version = "2.2.0"
797
787
  source = "registry+https://github.com/rust-lang/crates.io-index"
798
- checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
788
+ checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421"
799
789
  dependencies = [
800
790
  "bincode",
801
791
  "databake",
@@ -816,9 +806,9 @@ dependencies = [
816
806
 
817
807
  [[package]]
818
808
  name = "icu_provider_adapters"
819
- version = "2.1.1"
809
+ version = "2.2.0"
820
810
  source = "registry+https://github.com/rust-lang/crates.io-index"
821
- checksum = "37dafa75fcb2ca73939cf7e7f4967d30be122b5e1d10f2b344e0addca8fa9446"
811
+ checksum = "e4824c9432b167eb1f742b6557e31fb646179a02b4c7c62dc40e55601d07c0e4"
822
812
  dependencies = [
823
813
  "icu_locale",
824
814
  "icu_provider",
@@ -826,9 +816,9 @@ dependencies = [
826
816
 
827
817
  [[package]]
828
818
  name = "icu_provider_baked"
829
- version = "2.1.1"
819
+ version = "2.2.0"
830
820
  source = "registry+https://github.com/rust-lang/crates.io-index"
831
- checksum = "612def768d023c68ce31e9e649e20140b447b2519340845e3f279c82e6cdf7ec"
821
+ checksum = "78281a8e833ce359621537b1b7c5c6d405d156df618059b71da6d2f9e20072fe"
832
822
  dependencies = [
833
823
  "crlify",
834
824
  "databake",
@@ -841,9 +831,9 @@ dependencies = [
841
831
 
842
832
  [[package]]
843
833
  name = "icu_provider_blob"
844
- version = "2.1.1"
834
+ version = "2.2.0"
845
835
  source = "registry+https://github.com/rust-lang/crates.io-index"
846
- checksum = "bcd377d80121ab5d320c90f914cf7145a6881556d886c2aa2c6f89cdae5f7a30"
836
+ checksum = "af99a43c4436b6c9a37c27a822ff05238bbad134bcdf6176732208acfae46a3f"
847
837
  dependencies = [
848
838
  "icu_provider",
849
839
  "log",
@@ -856,9 +846,9 @@ dependencies = [
856
846
 
857
847
  [[package]]
858
848
  name = "icu_provider_export"
859
- version = "2.1.1"
849
+ version = "2.2.0"
860
850
  source = "registry+https://github.com/rust-lang/crates.io-index"
861
- checksum = "088df9d306e2c713acf6ac13eaa58f41b48b070a14501232ed7a0fb911837df0"
851
+ checksum = "547184e72c2ef149fee3218a18d88a6dfae166b1b8fe3ee0cc364c5dd2c4653e"
862
852
  dependencies = [
863
853
  "displaydoc",
864
854
  "icu_locale",
@@ -873,9 +863,9 @@ dependencies = [
873
863
 
874
864
  [[package]]
875
865
  name = "icu_provider_fs"
876
- version = "2.1.1"
866
+ version = "2.2.0"
877
867
  source = "registry+https://github.com/rust-lang/crates.io-index"
878
- checksum = "2ebc3256f30a1d5b69489713eca389a18ace8e35b437ef7efad628994497285e"
868
+ checksum = "4f2fbaf4b4e6a7feea3968de8fd31972d83bfa1859ee3393a54d682b85af5303"
879
869
  dependencies = [
880
870
  "bincode",
881
871
  "crlify",
@@ -888,18 +878,16 @@ dependencies = [
888
878
 
889
879
  [[package]]
890
880
  name = "icu_provider_registry"
891
- version = "2.1.1"
881
+ version = "2.2.0"
892
882
  source = "registry+https://github.com/rust-lang/crates.io-index"
893
- checksum = "d3af68b82555117bc91a46a8ed8774157aadcb7904edcda0281c0a3df4ed12a0"
883
+ checksum = "9b9bcbe57266350ac59340174baedca7dbb2ad020fa62664e12f5437ce3c8f43"
894
884
 
895
885
  [[package]]
896
886
  name = "icu_provider_source"
897
- version = "2.1.1"
887
+ version = "2.2.0"
898
888
  source = "registry+https://github.com/rust-lang/crates.io-index"
899
- checksum = "d7bb8935cff3b53b70c26d8a1d727c99ab6ddbfb92c09a009debaa0b4c0b0e46"
889
+ checksum = "70e229a41d4f32b0323afdaccbb7ab3ad761c0572625fef35be10530c044a1d0"
900
890
  dependencies = [
901
- "calendrical_calculations",
902
- "displaydoc",
903
891
  "elsa",
904
892
  "flate2",
905
893
  "icu",
@@ -931,9 +919,9 @@ dependencies = [
931
919
 
932
920
  [[package]]
933
921
  name = "icu_segmenter"
934
- version = "2.1.2"
922
+ version = "2.2.0"
935
923
  source = "registry+https://github.com/rust-lang/crates.io-index"
936
- checksum = "a807a7488f3f758629ae86d99d9d30dce24da2fb2945d74c80a4f4a62c71db73"
924
+ checksum = "5c0794db0b1a86193ac9c48768d0e6c52c54448e0870ad87907d456ee0dac964"
937
925
  dependencies = [
938
926
  "core_maths",
939
927
  "databake",
@@ -949,15 +937,15 @@ dependencies = [
949
937
 
950
938
  [[package]]
951
939
  name = "icu_segmenter_data"
952
- version = "2.1.1"
940
+ version = "2.2.0"
953
941
  source = "registry+https://github.com/rust-lang/crates.io-index"
954
- checksum = "6ebbb7321d9e21d25f5660366cb6c08201d0175898a3a6f7a41ee9685af21c80"
942
+ checksum = "e4a2c462a4d927d512f5f882a033ddd62f33a05bb9f230d98f736ac3dc85938f"
955
943
 
956
944
  [[package]]
957
945
  name = "icu_time"
958
- version = "2.1.1"
946
+ version = "2.2.0"
959
947
  source = "registry+https://github.com/rust-lang/crates.io-index"
960
- checksum = "8242b00da3b3b6678f731437a11c8833a43c821ae081eca60ba1b7579d45b6d8"
948
+ checksum = "ec3af0c141da0a61d4f6970cd1d5f4b388b17ea22f8124f8f6049d3d5147586a"
961
949
  dependencies = [
962
950
  "calendrical_calculations",
963
951
  "databake",
@@ -974,9 +962,9 @@ dependencies = [
974
962
 
975
963
  [[package]]
976
964
  name = "icu_time_data"
977
- version = "2.1.1"
965
+ version = "2.2.0"
978
966
  source = "registry+https://github.com/rust-lang/crates.io-index"
979
- checksum = "3e10b0e5e87a2c84bd5fa407705732052edebe69291d347d0c3033785470edbf"
967
+ checksum = "6f2f8aeca682d874a5247084aa4fb7d1cef9ba45d889c21209a8818dcaaa0ec9"
980
968
 
981
969
  [[package]]
982
970
  name = "indexmap"
@@ -1014,9 +1002,9 @@ checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
1014
1002
 
1015
1003
  [[package]]
1016
1004
  name = "ixdtf"
1017
- version = "0.6.4"
1005
+ version = "0.6.5"
1018
1006
  source = "registry+https://github.com/rust-lang/crates.io-index"
1019
- checksum = "84de9d95a6d2547d9b77ee3f25fa0ee32e3c3a6484d47a55adebc0439c077992"
1007
+ checksum = "2ceaf4c6c48465bead8cb6a0b7c4ee0c86ecbb31239032b9c66ab9a08d2f3ee1"
1020
1008
 
1021
1009
  [[package]]
1022
1010
  name = "jiff"
@@ -1180,12 +1168,6 @@ dependencies = [
1180
1168
  "simd-adler32",
1181
1169
  ]
1182
1170
 
1183
- [[package]]
1184
- name = "multi-stash"
1185
- version = "0.2.0"
1186
- source = "registry+https://github.com/rust-lang/crates.io-index"
1187
- checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f"
1188
-
1189
1171
  [[package]]
1190
1172
  name = "ndarray"
1191
1173
  version = "0.16.1"
@@ -1336,9 +1318,9 @@ dependencies = [
1336
1318
 
1337
1319
  [[package]]
1338
1320
  name = "quote"
1339
- version = "1.0.42"
1321
+ version = "1.0.45"
1340
1322
  source = "registry+https://github.com/rust-lang/crates.io-index"
1341
- checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
1323
+ checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
1342
1324
  dependencies = [
1343
1325
  "proc-macro2",
1344
1326
  ]
@@ -1634,9 +1616,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
1634
1616
 
1635
1617
  [[package]]
1636
1618
  name = "string-interner"
1637
- version = "0.18.0"
1619
+ version = "0.19.0"
1638
1620
  source = "registry+https://github.com/rust-lang/crates.io-index"
1639
- checksum = "1a3275464d7a9f2d4cac57c89c2ef96a8524dba2864c8d6f82e3980baf136f9b"
1621
+ checksum = "23de088478b31c349c9ba67816fa55d9355232d63c3afea8bf513e31f0f1d2c0"
1640
1622
  dependencies = [
1641
1623
  "hashbrown 0.15.5",
1642
1624
  "serde",
@@ -1702,9 +1684,9 @@ dependencies = [
1702
1684
 
1703
1685
  [[package]]
1704
1686
  name = "tinystr"
1705
- version = "0.8.2"
1687
+ version = "0.8.3"
1706
1688
  source = "registry+https://github.com/rust-lang/crates.io-index"
1707
- checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
1689
+ checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d"
1708
1690
  dependencies = [
1709
1691
  "databake",
1710
1692
  "displaydoc",
@@ -1841,53 +1823,50 @@ dependencies = [
1841
1823
 
1842
1824
  [[package]]
1843
1825
  name = "wasmi"
1844
- version = "0.40.0"
1826
+ version = "1.0.9"
1845
1827
  source = "registry+https://github.com/rust-lang/crates.io-index"
1846
- checksum = "a19af97fcb96045dd1d6b4d23e2b4abdbbe81723dbc5c9f016eb52145b320063"
1828
+ checksum = "22bf475363d09d960b48275c4ea9403051add498a9d80c64dbc91edabab9d1d0"
1847
1829
  dependencies = [
1848
- "arrayvec",
1849
- "multi-stash",
1850
- "smallvec",
1851
1830
  "spin",
1852
1831
  "wasmi_collections",
1853
1832
  "wasmi_core",
1854
1833
  "wasmi_ir",
1855
- "wasmparser 0.221.3",
1834
+ "wasmparser 0.228.0",
1835
+ "wat",
1856
1836
  ]
1857
1837
 
1858
1838
  [[package]]
1859
1839
  name = "wasmi_collections"
1860
- version = "0.40.0"
1840
+ version = "1.0.9"
1861
1841
  source = "registry+https://github.com/rust-lang/crates.io-index"
1862
- checksum = "e80d6b275b1c922021939d561574bf376613493ae2b61c6963b15db0e8813562"
1842
+ checksum = "85851acbdffd675a9b699b3590406a1d37fc1e1fd073743c7c9cf47c59caacba"
1863
1843
  dependencies = [
1864
1844
  "string-interner",
1865
1845
  ]
1866
1846
 
1867
1847
  [[package]]
1868
1848
  name = "wasmi_core"
1869
- version = "0.40.0"
1849
+ version = "1.0.9"
1870
1850
  source = "registry+https://github.com/rust-lang/crates.io-index"
1871
- checksum = "3a8c51482cc32d31c2c7ff211cd2bedd73c5bd057ba16a2ed0110e7a96097c33"
1851
+ checksum = "ef64cf60195d1f937dbaed592a5afce3e6d86868fb8070c5255bc41539d68f9d"
1872
1852
  dependencies = [
1873
- "downcast-rs",
1874
1853
  "libm",
1875
1854
  ]
1876
1855
 
1877
1856
  [[package]]
1878
1857
  name = "wasmi_ir"
1879
- version = "0.40.0"
1858
+ version = "1.0.9"
1880
1859
  source = "registry+https://github.com/rust-lang/crates.io-index"
1881
- checksum = "6e431a14c186db59212a88516788bd68ed51f87aa1e08d1df742522867b5289a"
1860
+ checksum = "5dcb572ce4400e06b5475819f3d6b9048513efbca785f0b9ef3a41747f944fd8"
1882
1861
  dependencies = [
1883
1862
  "wasmi_core",
1884
1863
  ]
1885
1864
 
1886
1865
  [[package]]
1887
1866
  name = "wasmparser"
1888
- version = "0.221.3"
1867
+ version = "0.228.0"
1889
1868
  source = "registry+https://github.com/rust-lang/crates.io-index"
1890
- checksum = "d06bfa36ab3ac2be0dee563380147a5b81ba10dd8885d7fbbc9eb574be67d185"
1869
+ checksum = "4abf1132c1fdf747d56bbc1bb52152400c70f336870f968b85e89ea422198ae3"
1891
1870
  dependencies = [
1892
1871
  "bitflags",
1893
1872
  "indexmap",
@@ -2114,9 +2093,9 @@ dependencies = [
2114
2093
 
2115
2094
  [[package]]
2116
2095
  name = "yoke"
2117
- version = "0.8.1"
2096
+ version = "0.8.2"
2118
2097
  source = "registry+https://github.com/rust-lang/crates.io-index"
2119
- checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
2098
+ checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca"
2120
2099
  dependencies = [
2121
2100
  "stable_deref_trait",
2122
2101
  "yoke-derive",
@@ -2125,9 +2104,9 @@ dependencies = [
2125
2104
 
2126
2105
  [[package]]
2127
2106
  name = "yoke-derive"
2128
- version = "0.8.1"
2107
+ version = "0.8.2"
2129
2108
  source = "registry+https://github.com/rust-lang/crates.io-index"
2130
- checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
2109
+ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
2131
2110
  dependencies = [
2132
2111
  "proc-macro2",
2133
2112
  "quote",
@@ -2164,9 +2143,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
2164
2143
 
2165
2144
  [[package]]
2166
2145
  name = "zerotrie"
2167
- version = "0.2.3"
2146
+ version = "0.2.4"
2168
2147
  source = "registry+https://github.com/rust-lang/crates.io-index"
2169
- checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
2148
+ checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf"
2170
2149
  dependencies = [
2171
2150
  "databake",
2172
2151
  "displaydoc",
@@ -2179,9 +2158,9 @@ dependencies = [
2179
2158
 
2180
2159
  [[package]]
2181
2160
  name = "zerovec"
2182
- version = "0.11.5"
2161
+ version = "0.11.6"
2183
2162
  source = "registry+https://github.com/rust-lang/crates.io-index"
2184
- checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
2163
+ checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239"
2185
2164
  dependencies = [
2186
2165
  "databake",
2187
2166
  "serde",
@@ -2192,9 +2171,9 @@ dependencies = [
2192
2171
 
2193
2172
  [[package]]
2194
2173
  name = "zerovec-derive"
2195
- version = "0.11.2"
2174
+ version = "0.11.3"
2196
2175
  source = "registry+https://github.com/rust-lang/crates.io-index"
2197
- checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
2176
+ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
2198
2177
  dependencies = [
2199
2178
  "proc-macro2",
2200
2179
  "quote",
data/README.md CHANGED
@@ -114,7 +114,7 @@ lf.format(%w[Apple Banana Cherry])
114
114
  # Relative time formatting
115
115
  rtf = ICU4X::RelativeTimeFormat.new(locale, provider:)
116
116
  rtf.format(-3, :day)
117
- # => "3日前"
117
+ # => "3 日前"
118
118
 
119
119
  # Display names
120
120
  dn = ICU4X::DisplayNames.new(locale, provider:, type: :language)
data/ext/icu4x/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "icu4x"
3
- version = "0.9.0"
3
+ version = "0.10.0"
4
4
  edition = "2024"
5
5
  publish = false
6
6
 
@@ -10,14 +10,14 @@ crate-type = ["cdylib"]
10
10
  [dependencies]
11
11
  magnus = "0.8"
12
12
  writeable = "0.6"
13
- icu_locale = "2.1"
14
- icu_provider = "2.1"
15
- icu_provider_blob = { version = "2.1", features = ["alloc", "export"] }
16
- icu_provider_source = { version = "2.1", features = ["networking", "experimental"] }
17
- icu_provider_export = "2.1"
18
- icu_provider_registry = "2.1"
19
- icu_provider_adapters = "2.1"
20
- icu = { version = "2.1", features = ["experimental"] }
13
+ icu_locale = "2.2"
14
+ icu_provider = "2.2"
15
+ icu_provider_blob = { version = "2.2", features = ["alloc", "export"] }
16
+ icu_provider_source = { version = "2.2", features = ["networking", "unstable"] }
17
+ icu_provider_export = "2.2"
18
+ icu_provider_registry = "2.2"
19
+ icu_provider_adapters = "2.2"
20
+ icu = { version = "2.2", features = ["unstable"] }
21
21
  fixed_decimal = "0.7"
22
22
  tinystr = "0.8"
23
23
  jiff = "0.2"
@@ -19,7 +19,7 @@ fn marker_lookup() -> &'static HashMap<&'static str, DataMarkerInfo> {
19
19
  LOOKUP.get_or_init(|| {
20
20
  let mut map = HashMap::new();
21
21
  macro_rules! cb {
22
- ($($marker_ty:ty:$marker:ident,)+ #[experimental] $($emarker_ty:ty:$emarker:ident,)+) => {
22
+ ($($marker_ty:ty:$marker:ident,)+ #[unstable] $($emarker_ty:ty:$emarker:ident,)+) => {
23
23
  $(
24
24
  // Add both the full type name and the short marker name
25
25
  map.insert(stringify!($marker_ty), <$marker_ty>::INFO);
@@ -8,7 +8,7 @@ use icu::datetime::fieldsets::enums::{
8
8
  TimeFieldSet,
9
9
  };
10
10
  use icu::datetime::fieldsets::{self};
11
- use icu::datetime::options::Length;
11
+ use icu::datetime::options::{Length, YearStyle as IcuYearStyle};
12
12
  use icu::datetime::input::DateTime;
13
13
  use icu::datetime::parts as dt_parts;
14
14
  use icu::datetime::{DateTimeFormatter, DateTimeFormatterPreferences};
@@ -65,6 +65,26 @@ enum YearStyle {
65
65
  TwoDigit,
66
66
  }
67
67
 
68
+ /// Era display option
69
+ #[derive(Clone, Copy, PartialEq, Eq, RubySymbol)]
70
+ enum EraStyle {
71
+ Auto,
72
+ Full,
73
+ WithEra,
74
+ Never,
75
+ }
76
+
77
+ impl EraStyle {
78
+ fn to_icu_year_style(self) -> IcuYearStyle {
79
+ match self {
80
+ EraStyle::Auto => IcuYearStyle::Auto,
81
+ EraStyle::Full => IcuYearStyle::Full,
82
+ EraStyle::WithEra => IcuYearStyle::WithEra,
83
+ EraStyle::Never => IcuYearStyle::NoEra,
84
+ }
85
+ }
86
+ }
87
+
68
88
  /// Month component option
69
89
  #[derive(Clone, Copy, PartialEq, Eq, RubySymbol)]
70
90
  enum MonthStyle {
@@ -218,7 +238,7 @@ impl Calendar {
218
238
  | AnyCalendarKind::HijriTabularTypeIIThursday
219
239
  | AnyCalendarKind::HijriUmmAlQura => Calendar::Islamic,
220
240
  AnyCalendarKind::Iso => Calendar::Gregory,
221
- AnyCalendarKind::Japanese | AnyCalendarKind::JapaneseExtended => Calendar::Japanese,
241
+ AnyCalendarKind::Japanese => Calendar::Japanese,
222
242
  AnyCalendarKind::Persian => Calendar::Persian,
223
243
  AnyCalendarKind::Roc => Calendar::Roc,
224
244
  _ => Calendar::Gregory,
@@ -264,6 +284,8 @@ pub struct DateTimeFormat {
264
284
  jiff_timezone: Option<TimeZone>,
265
285
  calendar: Calendar,
266
286
  hour_cycle: Option<HourCycle>,
287
+ hour12: Option<bool>,
288
+ era: Option<EraStyle>,
267
289
  component_options: Option<ComponentOptions>,
268
290
  }
269
291
 
@@ -379,15 +401,11 @@ impl DateTimeFormat {
379
401
  let hour_cycle =
380
402
  helpers::extract_symbol(ruby, &kwargs, "hour_cycle", HourCycle::from_ruby_symbol)?;
381
403
 
382
- // Extract hour12 option and convert to hour_cycle if hour_cycle is not specified
383
- // hour12: true → :h12, hour12: false → :h23
384
404
  let hour12: Option<bool> = kwargs.lookup::<_, Option<bool>>(ruby.to_symbol("hour12"))?;
385
- let hour_cycle = match (hour_cycle, hour12) {
386
- (Some(hc), _) => Some(hc), // hour_cycle takes precedence
387
- (None, Some(true)) => Some(HourCycle::H12),
388
- (None, Some(false)) => Some(HourCycle::H23),
389
- (None, None) => None,
390
- };
405
+
406
+ // Extract era option
407
+ let era =
408
+ helpers::extract_symbol(ruby, &kwargs, "era", EraStyle::from_ruby_symbol)?;
391
409
 
392
410
  // Get the error exception class
393
411
  let error_class = helpers::get_exception_class(ruby, "ICU4X::Error");
@@ -402,9 +420,9 @@ impl DateTimeFormat {
402
420
 
403
421
  // Create field set based on options
404
422
  let field_set = if has_component_options {
405
- Self::create_field_set_from_components(ruby, &component_options)?
423
+ Self::create_field_set_from_components(ruby, &component_options, era)?
406
424
  } else {
407
- Self::create_field_set_from_style(date_style, time_style)
425
+ Self::create_field_set_from_style(date_style, time_style, era)
408
426
  };
409
427
 
410
428
  // Create formatter with calendar and hour_cycle preferences
@@ -414,6 +432,8 @@ impl DateTimeFormat {
414
432
  }
415
433
  if let Some(hc) = hour_cycle {
416
434
  prefs.hour_cycle = Some(hc.to_icu_hour_cycle());
435
+ } else if let Some(h12) = hour12 {
436
+ prefs.hour_cycle = Some(if h12 { IcuHourCycle::Clock12 } else { IcuHourCycle::Clock24 });
417
437
  }
418
438
 
419
439
  let formatter =
@@ -437,6 +457,8 @@ impl DateTimeFormat {
437
457
  jiff_timezone,
438
458
  calendar: resolved_calendar,
439
459
  hour_cycle,
460
+ hour12,
461
+ era,
440
462
  component_options: if has_component_options {
441
463
  Some(component_options)
442
464
  } else {
@@ -477,6 +499,7 @@ impl DateTimeFormat {
477
499
  fn create_field_set_from_components(
478
500
  ruby: &Ruby,
479
501
  opts: &ComponentOptions,
502
+ era: Option<EraStyle>,
480
503
  ) -> Result<CompositeDateTimeFieldSet, Error> {
481
504
  let has_date = opts.has_date_components();
482
505
  let has_time = opts.has_time_components();
@@ -485,9 +508,9 @@ impl DateTimeFormat {
485
508
  match (has_date, has_time) {
486
509
  (true, true) => {
487
510
  // Date and time components
488
- Ok(CompositeDateTimeFieldSet::DateTime(
489
- DateAndTimeFieldSet::YMDT(fieldsets::YMDT::for_length(length)),
490
- ))
511
+ let fs = fieldsets::YMDT::for_length(length);
512
+ let fs = if let Some(s) = era { fs.with_year_style(s.to_icu_year_style()) } else { fs };
513
+ Ok(CompositeDateTimeFieldSet::DateTime(DateAndTimeFieldSet::YMDT(fs)))
491
514
  }
492
515
  (true, false) => {
493
516
  // Date only - choose field set based on which components are specified
@@ -498,13 +521,17 @@ impl DateTimeFormat {
498
521
 
499
522
  match (has_year, has_month, has_day, has_weekday) {
500
523
  // Year + Month + Day + Weekday
501
- (true, true, true, true) => Ok(CompositeDateTimeFieldSet::Date(
502
- DateFieldSet::YMDE(fieldsets::YMDE::for_length(length)),
503
- )),
524
+ (true, true, true, true) => {
525
+ let fs = fieldsets::YMDE::for_length(length);
526
+ let fs = if let Some(s) = era { fs.with_year_style(s.to_icu_year_style()) } else { fs };
527
+ Ok(CompositeDateTimeFieldSet::Date(DateFieldSet::YMDE(fs)))
528
+ }
504
529
  // Year + Month + Day
505
- (true, true, true, false) => Ok(CompositeDateTimeFieldSet::Date(
506
- DateFieldSet::YMD(fieldsets::YMD::for_length(length)),
507
- )),
530
+ (true, true, true, false) => {
531
+ let fs = fieldsets::YMD::for_length(length);
532
+ let fs = if let Some(s) = era { fs.with_year_style(s.to_icu_year_style()) } else { fs };
533
+ Ok(CompositeDateTimeFieldSet::Date(DateFieldSet::YMD(fs)))
534
+ }
508
535
  // Month + Day + Weekday
509
536
  (false, true, true, true) => Ok(CompositeDateTimeFieldSet::Date(
510
537
  DateFieldSet::MDE(fieldsets::MDE::for_length(length)),
@@ -514,9 +541,11 @@ impl DateTimeFormat {
514
541
  DateFieldSet::MD(fieldsets::MD::for_length(length)),
515
542
  )),
516
543
  // Year + Month (calendar period)
517
- (true, true, false, _) => Ok(CompositeDateTimeFieldSet::CalendarPeriod(
518
- CalendarPeriodFieldSet::YM(fieldsets::YM::for_length(length)),
519
- )),
544
+ (true, true, false, _) => {
545
+ let fs = fieldsets::YM::for_length(length);
546
+ let fs = if let Some(s) = era { fs.with_year_style(s.to_icu_year_style()) } else { fs };
547
+ Ok(CompositeDateTimeFieldSet::CalendarPeriod(CalendarPeriodFieldSet::YM(fs)))
548
+ }
520
549
  // Month only (calendar period)
521
550
  (false, true, false, _) => Ok(CompositeDateTimeFieldSet::CalendarPeriod(
522
551
  CalendarPeriodFieldSet::M(fieldsets::M::for_length(length)),
@@ -534,13 +563,17 @@ impl DateTimeFormat {
534
563
  DateFieldSet::E(fieldsets::E::for_length(length)),
535
564
  )),
536
565
  // Year only (calendar period)
537
- (true, false, false, _) => Ok(CompositeDateTimeFieldSet::CalendarPeriod(
538
- CalendarPeriodFieldSet::Y(fieldsets::Y::for_length(length)),
539
- )),
566
+ (true, false, false, _) => {
567
+ let fs = fieldsets::Y::for_length(length);
568
+ let fs = if let Some(s) = era { fs.with_year_style(s.to_icu_year_style()) } else { fs };
569
+ Ok(CompositeDateTimeFieldSet::CalendarPeriod(CalendarPeriodFieldSet::Y(fs)))
570
+ }
540
571
  // Year + Day (not a standard combination, use YMD as fallback)
541
- (true, false, true, _) => Ok(CompositeDateTimeFieldSet::Date(
542
- DateFieldSet::YMD(fieldsets::YMD::for_length(length)),
543
- )),
572
+ (true, false, true, _) => {
573
+ let fs = fieldsets::YMD::for_length(length);
574
+ let fs = if let Some(s) = era { fs.with_year_style(s.to_icu_year_style()) } else { fs };
575
+ Ok(CompositeDateTimeFieldSet::Date(DateFieldSet::YMD(fs)))
576
+ }
544
577
  // Should not happen - we checked has_date_components
545
578
  (false, false, false, false) => unreachable!(),
546
579
  }
@@ -562,6 +595,7 @@ impl DateTimeFormat {
562
595
  fn create_field_set_from_style(
563
596
  date_style: Option<DateStyle>,
564
597
  time_style: Option<TimeStyle>,
598
+ era: Option<EraStyle>,
565
599
  ) -> CompositeDateTimeFieldSet {
566
600
  match (date_style, time_style) {
567
601
  (Some(ds), Some(ts)) => {
@@ -571,6 +605,7 @@ impl DateTimeFormat {
571
605
  (DateStyle::Medium, _) => fieldsets::YMDT::medium(),
572
606
  (DateStyle::Short, _) => fieldsets::YMDT::short(),
573
607
  };
608
+ let ymdt = if let Some(s) = era { ymdt.with_year_style(s.to_icu_year_style()) } else { ymdt };
574
609
  CompositeDateTimeFieldSet::DateTime(DateAndTimeFieldSet::YMDT(ymdt))
575
610
  }
576
611
  (Some(ds), None) => {
@@ -580,6 +615,7 @@ impl DateTimeFormat {
580
615
  DateStyle::Medium => fieldsets::YMD::medium(),
581
616
  DateStyle::Short => fieldsets::YMD::short(),
582
617
  };
618
+ let ymd = if let Some(s) = era { ymd.with_year_style(s.to_icu_year_style()) } else { ymd };
583
619
  CompositeDateTimeFieldSet::Date(DateFieldSet::YMD(ymd))
584
620
  }
585
621
  (None, Some(ts)) => {
@@ -721,7 +757,7 @@ impl DateTimeFormat {
721
757
  /// Get the resolved options
722
758
  ///
723
759
  /// # Returns
724
- /// A hash with :locale, :calendar, :date_style, :time_style, and optionally :time_zone, :hour_cycle
760
+ /// A hash with :locale, :calendar, :date_style, :time_style, and optionally :time_zone, :hour_cycle, :hour12
725
761
  fn resolved_options(&self) -> Result<RHash, Error> {
726
762
  let ruby = Ruby::get().expect("Ruby runtime should be available");
727
763
  let hash = ruby.hash_new();
@@ -757,6 +793,17 @@ impl DateTimeFormat {
757
793
  )?;
758
794
  }
759
795
 
796
+ if let Some(h12) = self.hour12 {
797
+ hash.aset(ruby.to_symbol("hour12"), h12)?;
798
+ }
799
+
800
+ if let Some(era) = self.era {
801
+ hash.aset(
802
+ ruby.to_symbol("era"),
803
+ ruby.to_symbol(era.to_symbol_name()),
804
+ )?;
805
+ }
806
+
760
807
  // Add component options if they were used
761
808
  if let Some(ref opts) = self.component_options {
762
809
  if let Some(year) = opts.year {
@@ -1,8 +1,8 @@
1
1
  use crate::data_provider::DataProvider;
2
2
  use crate::helpers;
3
- use icu::experimental::displaynames::{
4
- DisplayNamesOptions, Fallback, LanguageDisplayNames, LocaleDisplayNamesFormatter,
5
- RegionDisplayNames, ScriptDisplayNames, Style,
3
+ use icu::experimental::displaynames::{DisplayNamesOptions, Fallback, Style};
4
+ use icu::experimental::displaynames::multi::{
5
+ LanguageDisplayNames, LocaleDisplayNamesFormatter, RegionDisplayNames, ScriptDisplayNames,
6
6
  };
7
7
  use icu_locale::LanguageIdentifier;
8
8
  use icu_provider::buf::AsDeserializingBufferProvider;
@@ -1,5 +1,6 @@
1
1
  use crate::helpers;
2
2
  use icu_locale::{Locale as IcuLocale, LocaleExpander, TransformResult};
3
+ use icu_locale::subtags::Variant;
3
4
  use magnus::{Error, RHash, RModule, Ruby, function, method, prelude::*, typed_data::Obj};
4
5
  use std::cell::RefCell;
5
6
 
@@ -204,6 +205,57 @@ impl Locale {
204
205
  inner: RefCell::new(IcuLocale::from(new_id)),
205
206
  }
206
207
  }
208
+
209
+ /// Get the list of variants
210
+ fn variants(&self) -> Vec<String> {
211
+ self.inner
212
+ .borrow()
213
+ .id
214
+ .variants
215
+ .iter()
216
+ .map(|v| v.to_string())
217
+ .collect()
218
+ }
219
+
220
+ fn parse_variant(s: &str) -> Result<Variant, Error> {
221
+ let ruby = Ruby::get().expect("Ruby runtime should be available");
222
+ s.parse::<Variant>().map_err(|e| {
223
+ Error::new(
224
+ helpers::get_exception_class(&ruby, "ICU4X::LocaleError"),
225
+ format!("Invalid variant: {e}"),
226
+ )
227
+ })
228
+ }
229
+
230
+ /// Add a variant in place; returns self if added, nil if already present
231
+ fn add_variant_bang(rb_self: Obj<Self>, variant_str: String) -> Result<Option<Obj<Self>>, Error> {
232
+ let variant = Self::parse_variant(&variant_str)?;
233
+ let added = rb_self.inner.borrow_mut().id.variants.push(variant);
234
+ Ok(if added { Some(rb_self) } else { None })
235
+ }
236
+
237
+ /// Return a new Locale with the variant added
238
+ fn add_variant(&self, variant_str: String) -> Result<Self, Error> {
239
+ let variant = Self::parse_variant(&variant_str)?;
240
+ let mut new_locale = self.inner.borrow().clone();
241
+ new_locale.id.variants.push(variant);
242
+ Ok(Self { inner: RefCell::new(new_locale) })
243
+ }
244
+
245
+ /// Remove a variant in place; returns self if removed, nil if not present
246
+ fn remove_variant_bang(rb_self: Obj<Self>, variant_str: String) -> Result<Option<Obj<Self>>, Error> {
247
+ let variant = Self::parse_variant(&variant_str)?;
248
+ let removed = rb_self.inner.borrow_mut().id.variants.remove(&variant);
249
+ Ok(if removed { Some(rb_self) } else { None })
250
+ }
251
+
252
+ /// Return a new Locale with the variant removed
253
+ fn remove_variant(&self, variant_str: String) -> Result<Self, Error> {
254
+ let variant = Self::parse_variant(&variant_str)?;
255
+ let mut new_locale = self.inner.borrow().clone();
256
+ new_locale.id.variants.remove(&variant);
257
+ Ok(Self { inner: RefCell::new(new_locale) })
258
+ }
207
259
  }
208
260
 
209
261
  pub fn init(ruby: &Ruby, module: &RModule) -> Result<(), Error> {
@@ -221,5 +273,10 @@ pub fn init(ruby: &Ruby, module: &RModule) -> Result<(), Error> {
221
273
  class.define_method("maximize", method!(Locale::maximize, 0))?;
222
274
  class.define_method("minimize!", method!(Locale::minimize_bang, 0))?;
223
275
  class.define_method("minimize", method!(Locale::minimize, 0))?;
276
+ class.define_method("variants", method!(Locale::variants, 0))?;
277
+ class.define_method("add_variant!", method!(Locale::add_variant_bang, 1))?;
278
+ class.define_method("add_variant", method!(Locale::add_variant, 1))?;
279
+ class.define_method("remove_variant!", method!(Locale::remove_variant_bang, 1))?;
280
+ class.define_method("remove_variant", method!(Locale::remove_variant, 1))?;
224
281
  Ok(())
225
282
  }
@@ -298,7 +298,7 @@ impl NumberFormat {
298
298
  FormatterKind::Decimal(formatter) => formatter.format(&decimal).to_string(),
299
299
  FormatterKind::Percent(formatter) => formatter.format(&decimal).to_string(),
300
300
  FormatterKind::Currency(formatter, currency_code) => formatter
301
- .format_fixed_decimal(&decimal, *currency_code)
301
+ .format_fixed_decimal(&decimal, currency_code)
302
302
  .to_string(),
303
303
  };
304
304
  Ok(formatted)
@@ -331,7 +331,7 @@ impl NumberFormat {
331
331
  }
332
332
  FormatterKind::Currency(formatter, currency_code) => {
333
333
  formatter
334
- .format_fixed_decimal(&decimal, *currency_code)
334
+ .format_fixed_decimal(&decimal, currency_code)
335
335
  .write_to_parts(&mut collector)
336
336
  .map_err(|e| Error::new(ruby.exception_runtime_error(), format!("{}", e)))?;
337
337
  }
@@ -399,11 +399,7 @@ impl NumberFormat {
399
399
 
400
400
  /// Check if value is a BigDecimal
401
401
  fn is_big_decimal(ruby: &Ruby, value: Value) -> bool {
402
- // Try to get BigDecimal class; if bigdecimal is not loaded, return false
403
- if let Ok(bigdecimal_class) = ruby.eval::<Value>("defined?(BigDecimal) && BigDecimal") {
404
- if bigdecimal_class.is_nil() {
405
- return false;
406
- }
402
+ if let Ok(bigdecimal_class) = ruby.eval::<Value>("BigDecimal") {
407
403
  if let Ok(class) = magnus::RClass::try_convert(bigdecimal_class) {
408
404
  return value.is_kind_of(class);
409
405
  }
@@ -146,9 +146,8 @@ impl RelativeTimeFormat {
146
146
  })?;
147
147
 
148
148
  // Build formatter options
149
- let options = RelativeTimeFormatterOptions {
150
- numeric: numeric.to_icu_numeric(),
151
- };
149
+ let mut options = RelativeTimeFormatterOptions::default();
150
+ options.numeric = numeric.to_icu_numeric();
152
151
  let prefs: RelativeTimeFormatterPreferences = (&icu_locale).into();
153
152
 
154
153
  // Create formatters for all units based on style
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "icu4x_macros"
3
- version = "0.9.0"
3
+ version = "0.10.0"
4
4
  edition = "2024"
5
5
 
6
6
  [lib]
data/lib/icu4x/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ICU4X
4
- VERSION = "0.9.0"
4
+ VERSION = "0.10.0"
5
5
  public_constant :VERSION
6
6
  end
data/lib/icu4x.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bigdecimal"
3
4
  require "dry-configurable"
4
5
  require "pathname"
5
6
 
@@ -52,15 +53,9 @@ module ICU4X
52
53
 
53
54
  # Error raised when data generation fails
54
55
  class DataGeneratorError < Error; end
55
- end
56
56
 
57
- # Define FormattedPart data class for format_to_parts methods
58
- module ICU4X
59
57
  FormattedPart = Data.define(:type, :value)
60
- end
61
58
 
62
- # Enhance the FormattedPart data class
63
- module ICU4X
64
59
  # Represents a part of a formatted string.
65
60
  #
66
61
  # Used by format_to_parts methods in DateTimeFormat, NumberFormat,
@@ -74,18 +69,10 @@ module ICU4X
74
69
  # @return [String] Human-readable representation
75
70
  def inspect = "#<ICU4X::FormattedPart type=#{type.inspect} value=#{value.inspect}>"
76
71
  end
77
- end
78
72
 
79
- # Define Segment data class for Segmenter
80
- module ICU4X
81
73
  class Segmenter
82
74
  Segment = Data.define(:segment, :index, :word_like)
83
- end
84
- end
85
75
 
86
- # Enhance the Segment data class
87
- module ICU4X
88
- class Segmenter
89
76
  # Represents a segment of text.
90
77
  #
91
78
  # @!attribute [r] segment
@@ -100,12 +87,36 @@ module ICU4X
100
87
  private :word_like
101
88
  end
102
89
  end
103
- end
104
90
 
105
- # Enhance the native Locale class
106
- module ICU4X
107
91
  # Represents a BCP 47 locale identifier.
108
92
  class Locale
93
+ POSIX_CATEGORIES = %i[collate ctype messages monetary numeric time].freeze
94
+ private_constant :POSIX_CATEGORIES
95
+
96
+ # Creates a Locale from environment variables.
97
+ #
98
+ # Checks LC_ALL, LC_{category}, and LANG in order,
99
+ # parsing each as a POSIX locale. Falls back to "C" if none are valid.
100
+ #
101
+ # @param category [Symbol] POSIX locale category (default: :messages)
102
+ # @return [Locale]
103
+ # @raise [ArgumentError] if category is not a valid POSIX category
104
+ def self.from_env(category: :messages)
105
+ unless POSIX_CATEGORIES.include?(category)
106
+ raise ArgumentError, "unknown locale category: #{category.inspect}"
107
+ end
108
+
109
+ env_name = "LC_#{category.to_s.upcase}"
110
+ [ENV["LC_ALL"], ENV[env_name], ENV["LANG"]].each do |value|
111
+ next if value.nil? || value.empty?
112
+
113
+ return parse_posix(value)
114
+ rescue LocaleError
115
+ next
116
+ end
117
+ parse_posix("C")
118
+ end
119
+
109
120
  # @return [String] Human-readable representation
110
121
  def inspect = "#<ICU4X::Locale:#{self}>"
111
122
 
data/sig/icu4x.rbs CHANGED
@@ -35,7 +35,10 @@ module ICU4X
35
35
  def self.available_markers: () -> Array[String]
36
36
  end
37
37
 
38
+ type locale_category = :collate | :ctype | :messages | :monetary | :numeric | :time
39
+
38
40
  class Locale
41
+ def self.from_env: (?category: locale_category) -> Locale
39
42
  def self.parse_bcp47: (String locale_str) -> Locale
40
43
  alias self.parse self.parse_bcp47
41
44
  def self.parse_posix: (String posix_str) -> Locale
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: icu4x
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OZAWA Sakuro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-01 00:00:00.000000000 Z
11
+ date: 2026-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bigdecimal
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: dry-configurable
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +114,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
100
114
  requirements:
101
115
  - - ">="
102
116
  - !ruby/object:Gem::Version
103
- version: '3.2'
117
+ version: '3.3'
104
118
  required_rubygems_version: !ruby/object:Gem::Requirement
105
119
  requirements:
106
120
  - - ">="
107
121
  - !ruby/object:Gem::Version
108
122
  version: '0'
109
123
  requirements: []
110
- rubygems_version: 3.4.19
124
+ rubygems_version: 3.5.22
111
125
  signing_key:
112
126
  specification_version: 4
113
127
  summary: Ruby bindings for ICU4X Unicode internationalization library