impl LocaleExpander { /// Creates a [`LocaleExpander`] with compiled data for commonly-used locales /// (locales with *Basic* or higher [CLDR coverage]). /// /// Use this constructor if you want limited likely subtags for data-oriented use cases. /// /// ✨ *Enabled with the `compiled_data` Cargo feature.* /// /// [ Help choosing a constructor](icu_provider::constructors) /// /// [CLDR coverage]: https://www.unicode.org/reports/tr35/tr35-info.html#Coverage_Levels #[cfg(feature = "compiled_data")] pubconstfn new() -> Self {
LocaleExpander {
likely_subtags_l: DataPayload::from_static_ref( crate::provider::Baked::SINGLETON_LOCID_TRANSFORM_LIKELYSUBTAGS_L_V1,
),
likely_subtags_sr: DataPayload::from_static_ref( crate::provider::Baked::SINGLETON_LOCID_TRANSFORM_LIKELYSUBTAGS_SR_V1,
),
likely_subtags_ext: None,
}
}
/// Creates a [`LocaleExpander`] with compiled data for all locales. /// /// Use this constructor if you want to include data for all locales, including ones /// that may not have data for other services (i.e. [CLDR coverage] below *Basic*). /// /// ✨ *Enabled with the `compiled_data` Cargo feature.* /// /// [ Help choosing a constructor](icu_provider::constructors) /// /// [CLDR coverage]: https://www.unicode.org/reports/tr35/tr35-info.html#Coverage_Levels #[cfg(feature = "compiled_data")] pubconstfn new_extended() -> Self {
LocaleExpander {
likely_subtags_l: DataPayload::from_static_ref( crate::provider::Baked::SINGLETON_LOCID_TRANSFORM_LIKELYSUBTAGS_L_V1,
),
likely_subtags_sr: DataPayload::from_static_ref( crate::provider::Baked::SINGLETON_LOCID_TRANSFORM_LIKELYSUBTAGS_SR_V1,
),
likely_subtags_ext: Some(DataPayload::from_static_ref( crate::provider::Baked::SINGLETON_LOCID_TRANSFORM_LIKELYSUBTAGS_EXT_V1,
)),
}
}
#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::new_extended)] pubfn try_new_extended_unstable<P>(
provider: &P,
) -> Result<LocaleExpander, LocaleTransformError> where
P: DataProvider<LikelySubtagsForLanguageV1Marker>
+ DataProvider<LikelySubtagsForScriptRegionV1Marker>
+ DataProvider<LikelySubtagsExtendedV1Marker>
+ ?Sized,
{ let likely_subtags_l = provider.load(Default::default())?.take_payload()?; let likely_subtags_sr = provider.load(Default::default())?.take_payload()?; let likely_subtags_ext = Some(provider.load(Default::default())?.take_payload()?);
/// The maximize method potentially updates a passed in locale in place /// depending up the results of running the 'Add Likely Subtags' algorithm /// from <https://www.unicode.org/reports/tr35/#Likely_Subtags>. /// /// If the result of running the algorithm would result in a new locale, the /// locale argument is updated in place to match the result, and the method /// returns [`TransformResult::Modified`]. Otherwise, the method /// returns [`TransformResult::Unmodified`] and the locale argument is /// unchanged. /// /// This function does not guarantee that any particular set of subtags /// will be present in the resulting locale. /// /// # Examples /// /// ``` /// use icu::locid::locale; /// use icu::locid_transform::{LocaleExpander, TransformResult}; /// /// let lc = LocaleExpander::new(); /// /// let mut locale = locale!("zh-CN"); /// assert_eq!(lc.maximize(&mut locale), TransformResult::Modified); /// assert_eq!(locale, locale!("zh-Hans-CN")); /// /// let mut locale = locale!("zh-Hant-TW"); /// assert_eq!(lc.maximize(&mut locale), TransformResult::Unmodified); /// assert_eq!(locale, locale!("zh-Hant-TW")); /// ``` /// /// If there is no data for a particular language, the result is not /// modified. Note that [`LocaleExpander::new_extended`] supports /// more languages. /// /// ``` /// use icu::locid::locale; /// use icu::locid_transform::{LocaleExpander, TransformResult}; /// /// let lc = LocaleExpander::new(); /// /// // No subtags data for ccp in the default set: /// let mut locale = locale!("ccp"); /// assert_eq!(lc.maximize(&mut locale), TransformResult::Unmodified); /// assert_eq!(locale, locale!("ccp")); /// /// // The extended set supports it: /// let lc = LocaleExpander::new_extended(); /// let mut locale = locale!("ccp"); /// assert_eq!(lc.maximize(&mut locale), TransformResult::Modified); /// assert_eq!(locale, locale!("ccp-Cakm-BD")); /// /// // But even the extended set does not support all language subtags: /// let mut locale = locale!("mul"); /// assert_eq!(lc.maximize(&mut locale), TransformResult::Unmodified); /// assert_eq!(locale, locale!("mul")); /// ``` pubfn maximize<T: AsMut<LanguageIdentifier>>(&self, mut langid: T) -> TransformResult { let langid = langid.as_mut(); let data = self.as_borrowed();
if !langid.language.is_empty() && langid.script.is_some() && langid.region.is_some() { return TransformResult::Unmodified;
}
// We failed to find anything in the und-SR, und-S, or und-R tables, // to fall back to bare "und"
debug_assert!(langid.language.is_empty());
update_langid(
data.get_und().0,
Some(data.get_und().1),
Some(data.get_und().2),
langid,
)
}
/// This returns a new Locale that is the result of running the /// 'Remove Likely Subtags' algorithm from /// <https://www.unicode.org/reports/tr35/#Likely_Subtags>. /// /// If the result of running the algorithm would result in a new locale, the /// locale argument is updated in place to match the result, and the method /// returns [`TransformResult::Modified`]. Otherwise, the method /// returns [`TransformResult::Unmodified`] and the locale argument is /// unchanged. /// /// # Examples /// /// ``` /// use icu::locid::locale; /// use icu::locid_transform::{LocaleExpander, TransformResult}; /// /// let lc = LocaleExpander::new(); /// /// let mut locale = locale!("zh-Hans-CN"); /// assert_eq!(lc.minimize(&mut locale), TransformResult::Modified); /// assert_eq!(locale, locale!("zh")); /// /// let mut locale = locale!("zh"); /// assert_eq!(lc.minimize(&mut locale), TransformResult::Unmodified); /// assert_eq!(locale, locale!("zh")); /// ``` pubfn minimize<T: AsMut<LanguageIdentifier>>(&self, langid: T) -> TransformResult { self.minimize_impl(langid, true)
}
/// This returns a new Locale that is the result of running the /// 'Remove Likely Subtags, favoring script' algorithm from /// <https://www.unicode.org/reports/tr35/#Likely_Subtags>. /// /// If the result of running the algorithm would result in a new locale, the /// locale argument is updated in place to match the result, and the method /// returns [`TransformResult::Modified`]. Otherwise, the method /// returns [`TransformResult::Unmodified`] and the locale argument is /// unchanged. /// /// # Examples /// /// ``` /// use icu::locid::locale; /// use icu::locid_transform::{LocaleExpander, TransformResult}; /// /// let lc = LocaleExpander::new(); /// /// let mut locale = locale!("zh_TW"); /// assert_eq!( /// lc.minimize_favor_script(&mut locale), /// TransformResult::Modified /// ); /// assert_eq!(locale, locale!("zh_Hant")); /// ``` pubfn minimize_favor_script<T: AsMut<LanguageIdentifier>>(
&self,
langid: T,
) -> TransformResult { self.minimize_impl(langid, false)
}
// TODO(3492): consider turning this and a future get_likely_region/get_likely_language public #[inline] pub(crate) fn get_likely_script<T: AsRef<LanguageIdentifier>>(
&self,
langid: T,
) -> Option<Script> { let langid = langid.as_ref();
langid
.script
.or_else(|| self.infer_likely_script(langid.language, langid.region))
}
fn infer_likely_script(&self, language: Language, region: Option<Region>) -> Option<Script> { let data = self.as_borrowed();
// proceed through _all possible cases_ in order of specificity // (borrowed from LocaleExpander::maximize): // 1. language + region // 2. language // 3. region // we need to check all cases, because e.g. for "en-US" the default script is associated // with "en" but not "en-US" if language != Language::UND { iflet Some(region) = region { // 1. we know both language and region iflet Some(script) = data.get_lr(language, region) { return Some(script);
}
} // 2. we know language, but we either do not know region or knowing region did not help iflet Some((script, _)) = data.get_l(language) { return Some(script);
}
} iflet Some(region) = region { // 3. we know region, but we either do not know language or knowing language did not help iflet Some((_, script)) = data.get_r(region) { return Some(script);
}
} // we could not figure out the script from the given locale
None
}
}
#[cfg(feature = "serde")] #[cfg(test)] mod tests { usesuper::*; use icu_locid::locale;
let l = crate::provider::Baked::SINGLETON_LOCID_TRANSFORM_LIKELYSUBTAGS_L_V1; let ext = crate::provider::Baked::SINGLETON_LOCID_TRANSFORM_LIKELYSUBTAGS_EXT_V1; let sr = crate::provider::Baked::SINGLETON_LOCID_TRANSFORM_LIKELYSUBTAGS_SR_V1;
#[test] fn test_old_keys() { let provider = RejectByKeyProvider {
keys: vec![
LikelySubtagsForLanguageV1Marker::KEY,
LikelySubtagsForScriptRegionV1Marker::KEY,
LikelySubtagsExtendedV1Marker::KEY,
],
}; let lc = LocaleExpander::try_new_with_any_provider(&provider)
.expect("should create with old keys"); letmut locale = locale!("zh-CN");
assert_eq!(lc.maximize(&mut locale), TransformResult::Modified);
assert_eq!(locale, locale!("zh-Hans-CN"));
}
#[test] fn test_new_keys() { let provider = RejectByKeyProvider {
keys: vec![LikelySubtagsV1Marker::KEY],
}; let lc = LocaleExpander::try_new_with_any_provider(&provider)
.expect("should create with new keys"); letmut locale = locale!("zh-CN");
assert_eq!(lc.maximize(&mut locale), TransformResult::Modified);
assert_eq!(locale, locale!("zh-Hans-CN"));
}
#[test] fn test_mixed_keys() { // Include the old key and one of the new keys but not both new keys. // Not sure if this is a useful test. let provider = RejectByKeyProvider {
keys: vec![LikelySubtagsForScriptRegionV1Marker::KEY],
}; let lc = LocaleExpander::try_new_with_any_provider(&provider)
.expect("should create with mixed keys"); letmut locale = locale!("zh-CN");
assert_eq!(lc.maximize(&mut locale), TransformResult::Modified);
assert_eq!(locale, locale!("zh-Hans-CN"));
}
#[test] fn test_no_keys() { let provider = RejectByKeyProvider {
keys: vec![
LikelySubtagsForLanguageV1Marker::KEY,
LikelySubtagsForScriptRegionV1Marker::KEY,
LikelySubtagsV1Marker::KEY,
],
}; if LocaleExpander::try_new_with_any_provider(&provider).is_ok() {
panic!("should not create: no data present")
};
}
#[test] fn test_new_small_keys() { // Include the new small keys but not the extended key let provider = RejectByKeyProvider {
keys: vec![
LikelySubtagsExtendedV1Marker::KEY,
LikelySubtagsV1Marker::KEY,
],
}; let lc = LocaleExpander::try_new_with_any_provider(&provider)
.expect("should create with mixed keys"); letmut locale = locale!("zh-CN");
assert_eq!(lc.maximize(&mut locale), TransformResult::Modified);
assert_eq!(locale, locale!("zh-Hans-CN"));
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.15Bemerkung:
(vorverarbeitet am 2026-06-23)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.