From 0c56e644e3a57404c35e42a93130ff522f2e6634 Mon Sep 17 00:00:00 2001 From: Zibi Braniecki Date: Wed, 13 Dec 2023 23:32:49 -0800 Subject: [PATCH] Switch to use ICU4X --- Cargo.toml | 8 +-- fluent-bundle/Cargo.toml | 12 +++-- fluent-bundle/README.md | 2 +- fluent-bundle/benches/resolver.rs | 2 +- fluent-bundle/benches/resolver_iai.rs | 2 +- fluent-bundle/examples/custom_formatter.rs | 2 +- fluent-bundle/examples/custom_type.rs | 2 +- fluent-bundle/examples/external_arguments.rs | 2 +- fluent-bundle/examples/functions.rs | 2 +- fluent-bundle/examples/simple-app.rs | 2 +- fluent-bundle/src/bundle.rs | 20 +++---- fluent-bundle/src/concurrent.rs | 4 +- fluent-bundle/src/errors.rs | 2 +- fluent-bundle/src/lib.rs | 2 +- fluent-bundle/src/memoizer.rs | 2 +- fluent-bundle/src/types/mod.rs | 24 ++++----- fluent-bundle/src/types/number.rs | 17 ++---- fluent-bundle/src/types/plural.rs | 20 +++---- fluent-bundle/tests/bundle.rs | 2 +- fluent-bundle/tests/custom_types.rs | 2 +- fluent-bundle/tests/function.rs | 3 +- fluent-bundle/tests/resolver_fixtures.rs | 2 +- fluent-bundle/tests/types_test.rs | 56 +++++++++++++++++--- fluent-fallback/Cargo.toml | 3 +- fluent-fallback/examples/simple-fallback.rs | 2 +- fluent-fallback/src/env.rs | 4 +- fluent-fallback/src/errors.rs | 2 +- fluent-fallback/src/generator.rs | 2 +- fluent-fallback/src/lib.rs | 4 +- fluent-fallback/tests/localization_test.rs | 2 +- fluent-pseudo/README.md | 2 +- fluent-resmgr/Cargo.toml | 3 +- fluent-resmgr/examples/simple-resmgr.rs | 2 +- fluent-resmgr/src/resource_manager.rs | 4 +- fluent-resmgr/tests/localization_test.rs | 2 +- fluent/Cargo.toml | 2 +- fluent/README.md | 2 +- fluent/src/lib.rs | 2 +- intl-memoizer/Cargo.toml | 11 ++-- intl-memoizer/examples/numberformat.rs | 2 +- intl-memoizer/examples/pluralrules.rs | 16 ++++-- intl-memoizer/src/lib.rs | 47 ++++++++-------- 42 files changed, 176 insertions(+), 130 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8896988f..93fcfc45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "fluent-syntax", "fluent-bundle", @@ -16,16 +17,17 @@ exclude = [ [workspace.dependencies] criterion = "0.3" -fluent-langneg = "0.13" +fluent-langneg = "0.14" futures = "0.3" iai = "0.1" -intl_pluralrules = "7.0.1" rustc-hash = "1" serde = "1.0" serde_json = "1.0" thiserror = "1.0" tokio = "1.0" -unic-langid = "0.9" +icu_locid = "1.4" +icu_plurals = { version = "1.4", features = ["experimental"] } +icu_provider = "1.4" fluent-bundle = { path = "fluent-bundle" } fluent-fallback = { path = "fluent-fallback" } diff --git a/fluent-bundle/Cargo.toml b/fluent-bundle/Cargo.toml index 3ae7ca2e..c993f245 100644 --- a/fluent-bundle/Cargo.toml +++ b/fluent-bundle/Cargo.toml @@ -26,11 +26,13 @@ include = [ ] [dependencies] -fluent-langneg.workspace = true +fluent-langneg = "0.14" fluent-syntax.workspace = true -intl_pluralrules.workspace = true rustc-hash.workspace = true -unic-langid.workspace = true +icu_locid.workspace = true +icu_plurals.workspace = true +icu_provider.workspace = true +fixed_decimal = { version = "0.5.5", features = ["ryu"] } intl-memoizer = { path = "../intl-memoizer" } self_cell = "0.10" smallvec = "1" @@ -39,12 +41,12 @@ smallvec = "1" criterion.workspace = true iai.workspace = true serde = { workspace = true, features = ["derive"]} -unic-langid = { workspace = true, features = ["macros"] } rand = "0.8" serde_yaml = "0.8" [features] -default = [] +default = ["icu_provider/sync"] +sync = ["icu_provider/sync"] all-benchmarks = [] [[bench]] diff --git a/fluent-bundle/README.md b/fluent-bundle/README.md index cd1e62e9..038beb92 100644 --- a/fluent-bundle/README.md +++ b/fluent-bundle/README.md @@ -23,7 +23,7 @@ Usage ```rust use fluent_bundle::{FluentBundle, FluentResource}; -use unic_langid::langid; +use icu_locid::langid; fn main() { let ftl_string = "hello-world = Hello, world!".to_owned(); diff --git a/fluent-bundle/benches/resolver.rs b/fluent-bundle/benches/resolver.rs index b27c365e..47cf1459 100644 --- a/fluent-bundle/benches/resolver.rs +++ b/fluent-bundle/benches/resolver.rs @@ -10,7 +10,7 @@ use std::rc::Rc; use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue}; use fluent_syntax::ast; -use unic_langid::langid; +use icu_locid::langid; fn read_file(path: &str) -> Result { let mut f = File::open(path)?; diff --git a/fluent-bundle/benches/resolver_iai.rs b/fluent-bundle/benches/resolver_iai.rs index dd7892c5..31d75e35 100644 --- a/fluent-bundle/benches/resolver_iai.rs +++ b/fluent-bundle/benches/resolver_iai.rs @@ -1,6 +1,6 @@ use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue}; use fluent_syntax::ast; -use unic_langid::{langid, LanguageIdentifier}; +use icu_locid::{langid, LanguageIdentifier}; const LANG_EN: LanguageIdentifier = langid!("en"); diff --git a/fluent-bundle/examples/custom_formatter.rs b/fluent-bundle/examples/custom_formatter.rs index a634b0cc..51379986 100644 --- a/fluent-bundle/examples/custom_formatter.rs +++ b/fluent-bundle/examples/custom_formatter.rs @@ -2,7 +2,7 @@ // to format selected types of values. // // This allows users to plug their own number formatter to Fluent. -use unic_langid::LanguageIdentifier; +use icu_locid::LanguageIdentifier; use fluent_bundle::memoizer::MemoizerKind; use fluent_bundle::types::{FluentNumber, FluentNumberOptions}; diff --git a/fluent-bundle/examples/custom_type.rs b/fluent-bundle/examples/custom_type.rs index 8feeed11..b438674c 100644 --- a/fluent-bundle/examples/custom_type.rs +++ b/fluent-bundle/examples/custom_type.rs @@ -9,8 +9,8 @@ // Lastly, we'll also create a new formatter which will be memoizable. // // The type and its options are modelled after ECMA402 Intl.DateTimeFormat. +use icu_locid::LanguageIdentifier; use intl_memoizer::Memoizable; -use unic_langid::LanguageIdentifier; use fluent_bundle::types::FluentType; use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue}; diff --git a/fluent-bundle/examples/external_arguments.rs b/fluent-bundle/examples/external_arguments.rs index fa9250ab..86bfc9ac 100644 --- a/fluent-bundle/examples/external_arguments.rs +++ b/fluent-bundle/examples/external_arguments.rs @@ -1,5 +1,5 @@ use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue}; -use unic_langid::langid; +use icu_locid::langid; fn main() { let ftl_string = String::from( diff --git a/fluent-bundle/examples/functions.rs b/fluent-bundle/examples/functions.rs index 4e1c5892..0a0dd22d 100644 --- a/fluent-bundle/examples/functions.rs +++ b/fluent-bundle/examples/functions.rs @@ -1,5 +1,5 @@ use fluent_bundle::{FluentBundle, FluentResource, FluentValue}; -use unic_langid::langid; +use icu_locid::langid; fn main() { // We define the resources here so that they outlive diff --git a/fluent-bundle/examples/simple-app.rs b/fluent-bundle/examples/simple-app.rs index 3a537a52..ec6cf5c4 100644 --- a/fluent-bundle/examples/simple-app.rs +++ b/fluent-bundle/examples/simple-app.rs @@ -19,6 +19,7 @@ //! default one. use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue}; use fluent_langneg::{negotiate_languages, NegotiationStrategy}; +use icu_locid::{langid, LanguageIdentifier}; use std::env; use std::fs; use std::fs::File; @@ -26,7 +27,6 @@ use std::io; use std::io::prelude::*; use std::path::Path; use std::str::FromStr; -use unic_langid::{langid, LanguageIdentifier}; /// We need a generic file read helper function to /// read the localization resource file. diff --git a/fluent-bundle/src/bundle.rs b/fluent-bundle/src/bundle.rs index 0b74c22d..cdaacfed 100644 --- a/fluent-bundle/src/bundle.rs +++ b/fluent-bundle/src/bundle.rs @@ -12,8 +12,8 @@ use std::default::Default; use std::fmt; use fluent_syntax::ast; +use icu_locid::LanguageIdentifier; use intl_memoizer::IntlLangMemoizer; -use unic_langid::LanguageIdentifier; use crate::args::FluentArgs; use crate::entry::Entry; @@ -32,7 +32,7 @@ use crate::types::FluentValue; /// /// ``` /// use fluent_bundle::{FluentBundle, FluentResource, FluentValue, FluentArgs}; -/// use unic_langid::langid; +/// use icu_locid::langid; /// /// // 1. Create a FluentResource /// @@ -163,7 +163,7 @@ impl FluentBundle { /// /// ``` /// use fluent_bundle::{FluentBundle, FluentResource}; - /// use unic_langid::langid; + /// use icu_locid::langid; /// /// let ftl_string = String::from(" /// hello = Hi! @@ -253,7 +253,7 @@ impl FluentBundle { /// /// ``` /// use fluent_bundle::{FluentBundle, FluentResource}; - /// use unic_langid::langid; + /// use icu_locid::langid; /// /// let ftl_string = String::from(" /// hello = Hi! @@ -359,7 +359,7 @@ impl FluentBundle { /// /// ``` /// use fluent_bundle::{FluentBundle, FluentResource}; - /// use unic_langid::langid; + /// use icu_locid::langid; /// /// let ftl_string = String::from("hello = Hi!"); /// let resource = FluentResource::try_new(ftl_string) @@ -384,7 +384,7 @@ impl FluentBundle { /// /// ``` /// use fluent_bundle::{FluentBundle, FluentResource}; - /// use unic_langid::langid; + /// use icu_locid::langid; /// /// let ftl_string = String::from("hello-world = Hello World!"); /// let resource = FluentResource::try_new(ftl_string) @@ -412,7 +412,7 @@ impl FluentBundle { /// /// ``` /// use fluent_bundle::{FluentBundle, FluentResource}; - /// use unic_langid::langid; + /// use icu_locid::langid; /// /// let ftl_string = String::from("hello-world = Hello World!"); /// let resource = FluentResource::try_new(ftl_string) @@ -459,7 +459,7 @@ impl FluentBundle { /// /// ``` /// use fluent_bundle::{FluentBundle, FluentResource}; - /// use unic_langid::langid; + /// use icu_locid::langid; /// /// let ftl_string = String::from("hello-world = Hello World!"); /// let resource = FluentResource::try_new(ftl_string) @@ -508,7 +508,7 @@ impl FluentBundle { /// /// ``` /// use fluent_bundle::{FluentBundle, FluentResource, FluentValue}; - /// use unic_langid::langid; + /// use icu_locid::langid; /// /// let ftl_string = String::from("length = { STRLEN(\"12345\") }"); /// let resource = FluentResource::try_new(ftl_string) @@ -567,7 +567,7 @@ impl FluentBundle { /// ``` /// use fluent_bundle::FluentBundle; /// use fluent_bundle::FluentResource; - /// use unic_langid::langid; + /// use icu_locid::langid; /// /// let langid_en = langid!("en-US"); /// let mut bundle: FluentBundle = FluentBundle::new(vec![langid_en]); diff --git a/fluent-bundle/src/concurrent.rs b/fluent-bundle/src/concurrent.rs index 40a28945..b4caa534 100644 --- a/fluent-bundle/src/concurrent.rs +++ b/fluent-bundle/src/concurrent.rs @@ -1,6 +1,6 @@ +use icu_locid::LanguageIdentifier; use intl_memoizer::{concurrent::IntlLangMemoizer, Memoizable}; use rustc_hash::FxHashMap; -use unic_langid::LanguageIdentifier; use crate::memoizer::MemoizerKind; use crate::types::FluentType; @@ -23,7 +23,7 @@ impl FluentBundle { /// ``` /// use fluent_bundle::concurrent::FluentBundle; /// use fluent_bundle::FluentResource; - /// use unic_langid::langid; + /// use icu_locid::langid; /// /// let langid_en = langid!("en-US"); /// let mut bundle: FluentBundle = diff --git a/fluent-bundle/src/errors.rs b/fluent-bundle/src/errors.rs index 58b1754b..4d2e4601 100644 --- a/fluent-bundle/src/errors.rs +++ b/fluent-bundle/src/errors.rs @@ -33,7 +33,7 @@ pub enum FluentError { /// /// ``` /// use fluent_bundle::{FluentBundle, FluentResource}; - /// use unic_langid::langid; + /// use icu_locid::langid; /// /// let ftl_string = String::from("intro = Welcome, { $name }."); /// let res1 = FluentResource::try_new(ftl_string) diff --git a/fluent-bundle/src/lib.rs b/fluent-bundle/src/lib.rs index 4e180aec..9de1ba4d 100644 --- a/fluent-bundle/src/lib.rs +++ b/fluent-bundle/src/lib.rs @@ -18,7 +18,7 @@ //! ``` //! use fluent_bundle::{FluentBundle, FluentValue, FluentResource, FluentArgs}; //! // Used to provide a locale for the bundle. -//! use unic_langid::langid; +//! use icu_locid::langid; //! //! // 1. Crate a FluentResource //! diff --git a/fluent-bundle/src/memoizer.rs b/fluent-bundle/src/memoizer.rs index 1d6d4918..287016e9 100644 --- a/fluent-bundle/src/memoizer.rs +++ b/fluent-bundle/src/memoizer.rs @@ -1,6 +1,6 @@ use crate::types::FluentType; +use icu_locid::LanguageIdentifier; use intl_memoizer::Memoizable; -use unic_langid::LanguageIdentifier; /// This trait contains thread-safe methods which extend [intl_memoizer::IntlLangMemoizer]. /// It is used as the generic bound in this crate when a memoizer is needed. diff --git a/fluent-bundle/src/types/mod.rs b/fluent-bundle/src/types/mod.rs index eb6c8eeb..77931c17 100644 --- a/fluent-bundle/src/types/mod.rs +++ b/fluent-bundle/src/types/mod.rs @@ -22,7 +22,7 @@ use std::borrow::{Borrow, Cow}; use std::fmt; use std::str::FromStr; -use intl_pluralrules::{PluralCategory, PluralRuleType}; +use icu_plurals::{PluralCategory, PluralRuleType}; use crate::memoizer::MemoizerKind; use crate::resolver::Scope; @@ -157,10 +157,10 @@ impl<'source> FluentValue<'source> { /// ``` /// use fluent_bundle::resolver::Scope; /// use fluent_bundle::{types::FluentValue, FluentBundle, FluentResource}; - /// use unic_langid::langid; + /// use icu_locid::langid; /// - /// let langid_ars = langid!("en"); - /// let bundle: FluentBundle = FluentBundle::new(vec![langid_ars]); + /// let langid_en = langid!("en"); + /// let bundle: FluentBundle = FluentBundle::new(vec![langid_en]); /// let scope = Scope::new(&bundle, None, None); /// /// // Matching examples: @@ -189,12 +189,12 @@ impl<'source> FluentValue<'source> { (&FluentValue::Number(ref a), &FluentValue::Number(ref b)) => a == b, (&FluentValue::String(ref a), &FluentValue::Number(ref b)) => { let cat = match a.as_ref() { - "zero" => PluralCategory::ZERO, - "one" => PluralCategory::ONE, - "two" => PluralCategory::TWO, - "few" => PluralCategory::FEW, - "many" => PluralCategory::MANY, - "other" => PluralCategory::OTHER, + "zero" => PluralCategory::Zero, + "one" => PluralCategory::One, + "two" => PluralCategory::Two, + "few" => PluralCategory::Few, + "many" => PluralCategory::Many, + "other" => PluralCategory::Other, _ => return false, }; // This string matches a plural rule keyword. Check if the number @@ -203,8 +203,8 @@ impl<'source> FluentValue<'source> { .bundle .intls .with_try_get_threadsafe::( - (PluralRuleType::CARDINAL,), - |pr| pr.0.select(b) == Ok(cat), + (PluralRuleType::Cardinal,), + |pr| pr.0.category_for(b) == cat, ) .unwrap() } diff --git a/fluent-bundle/src/types/number.rs b/fluent-bundle/src/types/number.rs index a81d15e3..492fd036 100644 --- a/fluent-bundle/src/types/number.rs +++ b/fluent-bundle/src/types/number.rs @@ -1,9 +1,8 @@ use std::borrow::Cow; -use std::convert::TryInto; use std::default::Default; use std::str::FromStr; -use intl_pluralrules::operands::PluralOperands; +use icu_plurals::PluralOperands; use crate::args::FluentArgs; use crate::types::FluentValue; @@ -219,18 +218,12 @@ macro_rules! from_num { impl From<&FluentNumber> for PluralOperands { fn from(input: &FluentNumber) -> Self { - let mut operands: Self = input - .value - .try_into() - .expect("Failed to generate operands out of FluentNumber"); + use fixed_decimal::{FixedDecimal, FloatPrecision}; + let mut fd = FixedDecimal::try_from_f64(input.value, FloatPrecision::Floating).unwrap(); if let Some(mfd) = input.options.minimum_fraction_digits { - if mfd > operands.v { - operands.f *= 10_u64.pow(mfd as u32 - operands.v as u32); - operands.v = mfd; - } + fd.pad_end(-(mfd as i16)); } - // XXX: Add support for other options. - operands + (&fd).into() } } diff --git a/fluent-bundle/src/types/plural.rs b/fluent-bundle/src/types/plural.rs index 1151fd6d..80fe7cb4 100644 --- a/fluent-bundle/src/types/plural.rs +++ b/fluent-bundle/src/types/plural.rs @@ -1,7 +1,6 @@ -use fluent_langneg::{negotiate_languages, NegotiationStrategy}; +use icu_locid::LanguageIdentifier; +use icu_plurals::{PluralRuleType, PluralRules as IntlPluralRules}; use intl_memoizer::Memoizable; -use intl_pluralrules::{PluralRuleType, PluralRules as IntlPluralRules}; -use unic_langid::LanguageIdentifier; pub struct PluralRules(pub IntlPluralRules); @@ -9,14 +8,11 @@ impl Memoizable for PluralRules { type Args = (PluralRuleType,); type Error = &'static str; fn construct(lang: LanguageIdentifier, args: Self::Args) -> Result { - let default_lang: LanguageIdentifier = "en".parse().unwrap(); - let pr_lang = negotiate_languages( - &[lang], - &IntlPluralRules::get_locales(args.0), - Some(&default_lang), - NegotiationStrategy::Lookup, - )[0] - .clone(); - Ok(Self(IntlPluralRules::create(pr_lang, args.0)?)) + let inner = match args.0 { + PluralRuleType::Cardinal => IntlPluralRules::try_new_cardinal(&lang.into()), + PluralRuleType::Ordinal => IntlPluralRules::try_new_ordinal(&lang.into()), + _ => todo!(), + }; + Ok(Self(inner.unwrap())) } } diff --git a/fluent-bundle/tests/bundle.rs b/fluent-bundle/tests/bundle.rs index c23866ea..42679a67 100644 --- a/fluent-bundle/tests/bundle.rs +++ b/fluent-bundle/tests/bundle.rs @@ -1,6 +1,6 @@ use fluent_bundle::{FluentArgs, FluentBundle, FluentResource}; +use icu_locid::langid; use std::borrow::Cow; -use unic_langid::langid; #[test] fn add_resource_override() { diff --git a/fluent-bundle/tests/custom_types.rs b/fluent-bundle/tests/custom_types.rs index be534700..34f603da 100644 --- a/fluent-bundle/tests/custom_types.rs +++ b/fluent-bundle/tests/custom_types.rs @@ -4,7 +4,7 @@ use fluent_bundle::FluentArgs; use fluent_bundle::FluentBundle; use fluent_bundle::FluentResource; use fluent_bundle::FluentValue; -use unic_langid::langid; +use icu_locid::langid; #[test] fn fluent_custom_type() { diff --git a/fluent-bundle/tests/function.rs b/fluent-bundle/tests/function.rs index 04cf3f3d..f96069bb 100644 --- a/fluent-bundle/tests/function.rs +++ b/fluent-bundle/tests/function.rs @@ -1,5 +1,6 @@ use fluent_bundle::types::FluentNumber; use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue}; +use icu_locid::langid; #[test] fn test_function_resolve() { @@ -21,7 +22,7 @@ liked-count2 = { NUMBER($num) -> ); let res = FluentResource::try_new(ftl_string).expect("Could not parse an FTL string."); - let mut bundle = FluentBundle::default(); + let mut bundle = FluentBundle::new(vec![langid!("en")]); bundle .add_function("NUMBER", |positional, named| match positional.get(0) { diff --git a/fluent-bundle/tests/resolver_fixtures.rs b/fluent-bundle/tests/resolver_fixtures.rs index 81e0e6eb..11c52e79 100644 --- a/fluent-bundle/tests/resolver_fixtures.rs +++ b/fluent-bundle/tests/resolver_fixtures.rs @@ -10,9 +10,9 @@ use fluent_bundle::resolver::ResolverError; use fluent_bundle::FluentArgs; use fluent_bundle::FluentError; use fluent_bundle::{FluentBundle, FluentResource, FluentValue}; +use icu_locid::LanguageIdentifier; use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; -use unic_langid::LanguageIdentifier; use helpers::*; diff --git a/fluent-bundle/tests/types_test.rs b/fluent-bundle/tests/types_test.rs index 57a4d6de..25fd530a 100644 --- a/fluent-bundle/tests/types_test.rs +++ b/fluent-bundle/tests/types_test.rs @@ -6,8 +6,8 @@ use fluent_bundle::FluentArgs; use fluent_bundle::FluentBundle; use fluent_bundle::FluentResource; use fluent_bundle::FluentValue; -use intl_pluralrules::operands::PluralOperands; -use unic_langid::langid; +use icu_locid::langid; +use icu_plurals::PluralOperands; #[test] fn fluent_value_try_number() { @@ -17,10 +17,10 @@ fn fluent_value_try_number() { #[test] fn fluent_value_matches() { - // We'll use `ars` locale since it happens to have all + // We'll use `ar` locale since it happens to have all // plural rules categories. - let langid_ars = langid!("ars"); - let bundle: FluentBundle = FluentBundle::new(vec![langid_ars]); + let langid_ar = langid!("ar"); + let bundle: FluentBundle = FluentBundle::new(vec![langid_ar]); let scope = Scope::new(&bundle, None, None); let string_val = FluentValue::from("string1"); @@ -139,18 +139,60 @@ fn fluent_number_style() { #[test] fn fluent_number_to_operands() { + use icu_plurals::rules::RawPluralOperands; + let num = FluentNumber::new(2.81, FluentNumberOptions::default()); let operands: PluralOperands = (&num).into(); assert_eq!( operands, - PluralOperands { - n: 2.81, + RawPluralOperands { i: 2, v: 2, w: 2, f: 81, t: 81, + c: 0, + } + .into() + ); +} + +#[test] +fn fluent_number_to_float_vs_int() { + // This test verifies that we coalesce f64 `1.0` to usize `1`. + // See `From for PluralOperands` for more details. + use icu_plurals::rules::RawPluralOperands; + + let num: FluentNumber = 1.0.into(); + let operands: PluralOperands = (&num).into(); + + assert_eq!( + operands, + RawPluralOperands { + i: 1, + v: 0, + w: 0, + f: 0, + t: 0, + c: 0, + } + .into() + ); + + let num: FluentNumber = 1.into(); + let operands: PluralOperands = (&num).into(); + + assert_eq!( + operands, + RawPluralOperands { + i: 1, + v: 0, + w: 0, + f: 0, + t: 0, + c: 0, } + .into() ); } diff --git a/fluent-fallback/Cargo.toml b/fluent-fallback/Cargo.toml index c0c83f0e..c08fa1cd 100644 --- a/fluent-fallback/Cargo.toml +++ b/fluent-fallback/Cargo.toml @@ -21,7 +21,7 @@ categories = ["localization", "internationalization"] fluent-bundle.workspace = true futures.workspace = true rustc-hash.workspace = true -unic-langid.workspace = true +icu_locid.workspace = true async-trait = "0.1" chunky-vec = "0.1" once_cell = "1.9" @@ -29,6 +29,5 @@ pin-cell = "0.2" [dev-dependencies] fluent-langneg.workspace = true -unic-langid = { workspace = true, features = ["macros"] } tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } fluent-resmgr = { path = "../fluent-resmgr" } diff --git a/fluent-fallback/examples/simple-fallback.rs b/fluent-fallback/examples/simple-fallback.rs index 7585a5d0..d753419d 100644 --- a/fluent-fallback/examples/simple-fallback.rs +++ b/fluent-fallback/examples/simple-fallback.rs @@ -29,7 +29,7 @@ use fluent_fallback::{ use fluent_langneg::{negotiate_languages, NegotiationStrategy}; use rustc_hash::FxHashSet; -use unic_langid::{langid, LanguageIdentifier}; +use icu_locid::{langid, LanguageIdentifier}; /// This helper struct holds the scheme for converting /// resource paths into full paths. It is used to customise diff --git a/fluent-fallback/src/env.rs b/fluent-fallback/src/env.rs index cf340fcf..4d69ffa1 100644 --- a/fluent-fallback/src/env.rs +++ b/fluent-fallback/src/env.rs @@ -13,7 +13,7 @@ //! are available. The list should also be sorted according to the user //! preference, as the order is significant for how [`Localization`](crate::Localization) performs //! fallbacking. -use unic_langid::LanguageIdentifier; +use icu_locid::LanguageIdentifier; /// A trait used to provide a selection of locales to be used by the /// [`Localization`](crate::Localization) instance for runtime @@ -23,7 +23,7 @@ use unic_langid::LanguageIdentifier; /// ``` /// use fluent_fallback::{Localization, env::LocalesProvider}; /// use fluent_resmgr::ResourceManager; -/// use unic_langid::LanguageIdentifier; +/// use icu_locid::LanguageIdentifier; /// use std::{ /// rc::Rc, /// cell::RefCell diff --git a/fluent-fallback/src/errors.rs b/fluent-fallback/src/errors.rs index 704bc84f..2643d5f6 100644 --- a/fluent-fallback/src/errors.rs +++ b/fluent-fallback/src/errors.rs @@ -1,6 +1,6 @@ use fluent_bundle::FluentError; use std::error::Error; -use unic_langid::LanguageIdentifier; +use icu_locid::LanguageIdentifier; #[derive(Debug, PartialEq, Eq)] pub enum LocalizationError { diff --git a/fluent-fallback/src/generator.rs b/fluent-fallback/src/generator.rs index f13af63c..d5efff14 100644 --- a/fluent-fallback/src/generator.rs +++ b/fluent-fallback/src/generator.rs @@ -2,7 +2,7 @@ use fluent_bundle::{FluentBundle, FluentError, FluentResource}; use futures::Stream; use rustc_hash::FxHashSet; use std::borrow::Borrow; -use unic_langid::LanguageIdentifier; +use icu_locid::LanguageIdentifier; use crate::types::ResourceId; diff --git a/fluent-fallback/src/lib.rs b/fluent-fallback/src/lib.rs index 14069069..633ba1b9 100644 --- a/fluent-fallback/src/lib.rs +++ b/fluent-fallback/src/lib.rs @@ -26,7 +26,7 @@ //! ``` //! use fluent_fallback::{Localization, types::{ResourceType, ToResourceId}}; //! use fluent_resmgr::ResourceManager; -//! use unic_langid::langid; +//! use icu_locid::langid; //! //! let res_mgr = ResourceManager::new("./tests/resources/{locale}/".to_string()); //! @@ -96,7 +96,7 @@ //! As a long lived structure, the [`Localization`] is intended to handle runtime locale //! management. //! -//! In the example above, [`Vec`](unic_langid::LanguageIdentifier) +//! In the example above, [`Vec`](icu_locid::LanguageIdentifier) //! provides a static list of locales that the [`Localization`] handles, but that's just the //! simplest implementation of the [`env::LocalesProvider`], and one can implement //! a much more sophisticated one that reacts to user or environment driven changes, and diff --git a/fluent-fallback/tests/localization_test.rs b/fluent-fallback/tests/localization_test.rs index 616440e1..57868dbc 100644 --- a/fluent-fallback/tests/localization_test.rs +++ b/fluent-fallback/tests/localization_test.rs @@ -14,7 +14,7 @@ use fluent_fallback::{ use rustc_hash::FxHashSet; use std::cell::RefCell; use std::rc::Rc; -use unic_langid::{langid, LanguageIdentifier}; +use icu_locid::{langid, LanguageIdentifier}; struct InnerLocales { locales: RefCell>, diff --git a/fluent-pseudo/README.md b/fluent-pseudo/README.md index 3d204e44..11097f3e 100644 --- a/fluent-pseudo/README.md +++ b/fluent-pseudo/README.md @@ -13,7 +13,7 @@ Usage ```rust use fluent_bundle::{FluentBundle, FluentResource}; -use unic_langid::langid; +use icu_locid::langid; use fluent_pseudo::transform; fn transform_wrapper(s: &str) -> Cow { diff --git a/fluent-resmgr/Cargo.toml b/fluent-resmgr/Cargo.toml index 0846001a..7732a5b1 100644 --- a/fluent-resmgr/Cargo.toml +++ b/fluent-resmgr/Cargo.toml @@ -22,9 +22,8 @@ fluent-fallback.workspace = true futures.workspace = true rustc-hash.workspace = true thiserror.workspace = true -unic-langid.workspace = true +icu_locid.workspace = true elsa = "1.5" [dev-dependencies] fluent-langneg.workspace = true -unic-langid = { workspace = true, features = ["macros"] } diff --git a/fluent-resmgr/examples/simple-resmgr.rs b/fluent-resmgr/examples/simple-resmgr.rs index 81b1fdd1..191a3f43 100644 --- a/fluent-resmgr/examples/simple-resmgr.rs +++ b/fluent-resmgr/examples/simple-resmgr.rs @@ -25,7 +25,7 @@ use std::fs; use std::io; use std::path::PathBuf; use std::str::FromStr; -use unic_langid::LanguageIdentifier; +use icu_locid::LanguageIdentifier; /// This helper function allows us to read the list /// of available locales by reading the list of diff --git a/fluent-resmgr/src/resource_manager.rs b/fluent-resmgr/src/resource_manager.rs index 166feed2..5d06eb29 100644 --- a/fluent-resmgr/src/resource_manager.rs +++ b/fluent-resmgr/src/resource_manager.rs @@ -9,7 +9,7 @@ use rustc_hash::FxHashSet; use std::io; use std::{fs, iter}; use thiserror::Error; -use unic_langid::LanguageIdentifier; +use icu_locid::LanguageIdentifier; fn read_file(path: &str) -> Result { fs::read_to_string(path) @@ -222,7 +222,7 @@ impl BundleGenerator for ResourceManager { #[cfg(test)] mod test { use super::*; - use unic_langid::langid; + use icu_locid::langid; #[test] fn caching() { diff --git a/fluent-resmgr/tests/localization_test.rs b/fluent-resmgr/tests/localization_test.rs index d1534f29..0c9a0f21 100644 --- a/fluent-resmgr/tests/localization_test.rs +++ b/fluent-resmgr/tests/localization_test.rs @@ -1,7 +1,7 @@ use fluent_fallback::Localization; use fluent_resmgr::resource_manager::ResourceManager; use std::borrow::Cow; -use unic_langid::langid; +use icu_locid::langid; #[test] fn localization_format_value() { diff --git a/fluent/Cargo.toml b/fluent/Cargo.toml index 1aa07116..ea981ea8 100644 --- a/fluent/Cargo.toml +++ b/fluent/Cargo.toml @@ -28,4 +28,4 @@ include = [ [dependencies] fluent-bundle.workspace = true fluent-pseudo = { workspace = true, optional = true } -unic-langid.workspace = true +icu_locid.workspace = true diff --git a/fluent/README.md b/fluent/README.md index 9f4140ea..55a95565 100644 --- a/fluent/README.md +++ b/fluent/README.md @@ -23,7 +23,7 @@ Usage ```rust use fluent::{FluentBundle, FluentResource}; -use unic_langid::langid; +use icu_locid::langid; fn main() { let ftl_string = "hello-world = Hello, world!".to_owned(); diff --git a/fluent/src/lib.rs b/fluent/src/lib.rs index 1cbefc00..91c1be93 100644 --- a/fluent/src/lib.rs +++ b/fluent/src/lib.rs @@ -20,7 +20,7 @@ //! use fluent::{FluentBundle, FluentValue, FluentResource, FluentArgs}; //! //! // Used to provide a locale for the bundle. -//! use unic_langid::LanguageIdentifier; +//! use icu_locid::LanguageIdentifier; //! //! let ftl_string = String::from(" //! hello-world = Hello, world! diff --git a/intl-memoizer/Cargo.toml b/intl-memoizer/Cargo.toml index a840b379..921b3cd9 100644 --- a/intl-memoizer/Cargo.toml +++ b/intl-memoizer/Cargo.toml @@ -26,9 +26,14 @@ include = [ ] [dependencies] -unic-langid.workspace = true +icu_locid = { workspace = true } +icu_plurals = { workspace = true } +icu_provider = { workspace = true } type-map = "0.5" [dev-dependencies] -intl_pluralrules.workspace = true -fluent-langneg.workspace = true +fluent-langneg = "0.14" + +[features] +default = [] +sync = ["icu_provider/sync"] diff --git a/intl-memoizer/examples/numberformat.rs b/intl-memoizer/examples/numberformat.rs index 793c890c..01aa1519 100644 --- a/intl-memoizer/examples/numberformat.rs +++ b/intl-memoizer/examples/numberformat.rs @@ -1,5 +1,5 @@ +use icu_locid::LanguageIdentifier; use intl_memoizer::{IntlMemoizer, Memoizable}; -use unic_langid::LanguageIdentifier; #[derive(Clone, Hash, PartialEq, Eq)] struct NumberFormatOptions { diff --git a/intl-memoizer/examples/pluralrules.rs b/intl-memoizer/examples/pluralrules.rs index a37f8d1a..b07d3b0d 100644 --- a/intl-memoizer/examples/pluralrules.rs +++ b/intl-memoizer/examples/pluralrules.rs @@ -1,12 +1,18 @@ +use icu_locid::LanguageIdentifier; +use icu_plurals::{PluralCategory, PluralRuleType, PluralRules as IntlPluralRules}; use intl_memoizer::{IntlMemoizer, Memoizable}; -use intl_pluralrules::{PluralCategory, PluralRuleType, PluralRules as IntlPluralRules}; -use unic_langid::LanguageIdentifier; struct PluralRules(pub IntlPluralRules); impl PluralRules { pub fn new(lang: LanguageIdentifier, pr_type: PluralRuleType) -> Result { - Ok(Self(IntlPluralRules::create(lang, pr_type)?)) + let locale = lang.into(); + let inner = match pr_type { + PluralRuleType::Cardinal => IntlPluralRules::try_new_cardinal(&locale), + PluralRuleType::Ordinal => IntlPluralRules::try_new_ordinal(&locale), + _ => todo!(), + }; + Ok(Self(inner.unwrap())) } } @@ -24,8 +30,8 @@ fn main() { let lang: LanguageIdentifier = "en".parse().unwrap(); let lang_memoizer = memoizer.get_for_lang(lang); let result = lang_memoizer - .with_try_get::((PluralRuleType::CARDINAL,), |pr| pr.0.select(5)) + .with_try_get::((PluralRuleType::Cardinal,), |pr| pr.0.category_for(5)) .unwrap(); - assert_eq!(result, Ok(PluralCategory::OTHER)); + assert_eq!(result, PluralCategory::Other); } diff --git a/intl-memoizer/src/lib.rs b/intl-memoizer/src/lib.rs index 685971e1..7a0a5a65 100644 --- a/intl-memoizer/src/lib.rs +++ b/intl-memoizer/src/lib.rs @@ -4,12 +4,12 @@ //! //! The [IntlMemoizer] is the main struct that creates a per-locale [IntlLangMemoizer]. +use icu_locid::LanguageIdentifier; use std::cell::RefCell; use std::collections::hash_map::Entry; use std::collections::HashMap; use std::hash::Hash; use std::rc::{Rc, Weak}; -use unic_langid::LanguageIdentifier; pub mod concurrent; @@ -47,7 +47,7 @@ pub trait Memoizable { /// /// ``` /// use intl_memoizer::{IntlLangMemoizer, Memoizable}; -/// use unic_langid::LanguageIdentifier; +/// use icu_locid::LanguageIdentifier; /// /// // Create a static counter so that we can demonstrate the side effects of when /// // the memoizer re-constructs an API. @@ -249,7 +249,7 @@ impl IntlLangMemoizer { /// /// ``` /// # use intl_memoizer::{IntlMemoizer, IntlLangMemoizer, Memoizable}; -/// # use unic_langid::LanguageIdentifier; +/// # use icu_locid::LanguageIdentifier; /// # use std::rc::Rc; /// # /// # struct ExampleFormatter { @@ -353,9 +353,7 @@ impl IntlMemoizer { #[cfg(test)] mod tests { use super::*; - use fluent_langneg::{negotiate_languages, NegotiationStrategy}; - use intl_pluralrules::{PluralCategory, PluralRuleType, PluralRules as IntlPluralRules}; - use std::{sync::Arc, thread}; + use icu_plurals::{PluralCategory, PluralRuleType, PluralRules as IntlPluralRules}; struct PluralRules(pub IntlPluralRules); @@ -364,16 +362,12 @@ mod tests { lang: LanguageIdentifier, pr_type: PluralRuleType, ) -> Result { - let default_lang: LanguageIdentifier = "en".parse().unwrap(); - let pr_lang = negotiate_languages( - &[lang], - &IntlPluralRules::get_locales(pr_type), - Some(&default_lang), - NegotiationStrategy::Lookup, - )[0] - .clone(); - - Ok(Self(IntlPluralRules::create(pr_lang, pr_type)?)) + let inner = match pr_type { + PluralRuleType::Cardinal => IntlPluralRules::try_new_cardinal(&lang.into()), + PluralRuleType::Ordinal => IntlPluralRules::try_new_ordinal(&lang.into()), + _ => todo!(), + }; + Ok(Self(inner.unwrap())) } } @@ -394,23 +388,30 @@ mod tests { let en_memoizer = memoizer.get_for_lang(lang.clone()); let result = en_memoizer - .with_try_get::((PluralRuleType::CARDINAL,), |cb| cb.0.select(5)) + .with_try_get::((PluralRuleType::Cardinal,), |cb| { + cb.0.category_for(5) + }) .unwrap(); - assert_eq!(result, Ok(PluralCategory::OTHER)); + assert_eq!(result, PluralCategory::Other); } { let en_memoizer = memoizer.get_for_lang(lang); let result = en_memoizer - .with_try_get::((PluralRuleType::CARDINAL,), |cb| cb.0.select(5)) + .with_try_get::((PluralRuleType::Cardinal,), |cb| { + cb.0.category_for(5) + }) .unwrap(); - assert_eq!(result, Ok(PluralCategory::OTHER)); + assert_eq!(result, PluralCategory::Other); } } + #[cfg(feature = "sync")] #[test] fn test_concurrent() { + use std::{sync::Arc, thread}; + let lang: LanguageIdentifier = "en".parse().unwrap(); let memoizer = Arc::new(concurrent::IntlLangMemoizer::new(lang)); let mut threads = vec![]; @@ -420,8 +421,8 @@ mod tests { let memoizer = Arc::clone(&memoizer); threads.push(thread::spawn(move || { memoizer - .with_try_get::((PluralRuleType::CARDINAL,), |cb| { - cb.0.select(5) + .with_try_get::((PluralRuleType::Cardinal,), |cb| { + cb.0.category_for(5) }) .expect("Failed to get a PluralRules result.") })); @@ -429,7 +430,7 @@ mod tests { for thread in threads.drain(..) { let result = thread.join().expect("Failed to join thread."); - assert_eq!(result, Ok(PluralCategory::OTHER)); + assert_eq!(result, PluralCategory::Other); } } }