// This file is part of ICU4X. For terms of use, please see the file // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use crate::parser::*; use crate::subtags::Subtag; use crate::{extensions, subtags, LanguageIdentifier}; #[cfg(feature = "alloc")] use alloc::borrow::Cow; use core::cmp::Ordering; #[cfg(feature = "alloc")] use core::str::FromStr; /// A core struct representing a [`Unicode Locale Identifier`]. /// /// A locale is made of two parts: /// * Unicode Language Identifier /// * A set of Unicode Extensions /// /// [`Locale`] exposes all of the same fields and methods as [`LanguageIdentifier`], and /// on top of that is able to parse, manipulate and serialize unicode extension fields. /// /// # Ordering /// /// This type deliberately does not implement `Ord` or `PartialOrd` because there are /// multiple possible orderings. Depending on your use case, two orderings are available: /// /// 1. A string ordering, suitable for stable serialization: [`Locale::strict_cmp`] /// 2. A struct ordering, suitable for use with a BTreeSet: [`Locale::total_cmp`] /// /// See issue: /// /// # Parsing /// /// Unicode recognizes three levels of standard conformance for a locale: /// /// * *well-formed* - syntactically correct /// * *valid* - well-formed and only uses registered language subtags, extensions, keywords, types... /// * *canonical* - valid and no deprecated codes or structure. /// /// Any syntactically invalid subtags will cause the parsing to fail with an error. /// /// This operation normalizes syntax to be well-formed. No legacy subtag replacements is performed. /// For validation and canonicalization, see `LocaleCanonicalizer`. /// /// ICU4X's Locale parsing does not allow for non-BCP-47-compatible locales [allowed by UTS 35 for backwards compatability][tr35-bcp]. /// Furthermore, it currently does not allow for language tags to have more than three characters. /// /// # Serde /// /// This type implements `serde::Serialize` and `serde::Deserialize` if the /// `"serde"` Cargo feature is enabled on the crate. /// /// The value will be serialized as a string and parsed when deserialized. /// For tips on efficient storage and retrieval of locales, see [`crate::zerovec`]. /// /// # Examples /// /// Simple example: /// /// ``` /// use icu::locale::{ /// extensions::unicode::{key, value}, /// locale, /// subtags::{language, region}, /// }; /// /// let loc = locale!("en-US-u-ca-buddhist"); /// /// assert_eq!(loc.id.language, language!("en")); /// assert_eq!(loc.id.script, None); /// assert_eq!(loc.id.region, Some(region!("US"))); /// assert_eq!(loc.id.variants.len(), 0); /// assert_eq!( /// loc.extensions.unicode.keywords.get(&key!("ca")), /// Some(&value!("buddhist")) /// ); /// ``` /// /// More complex example: /// /// ``` /// use icu::locale::{subtags::*, Locale}; /// /// let loc: Locale = "eN-latn-Us-Valencia-u-hC-H12" /// .parse() /// .expect("Failed to parse."); /// /// assert_eq!(loc.id.language, "en".parse::().unwrap()); /// assert_eq!(loc.id.script, "Latn".parse::