unic_locale/lib.rs
1//! `unic-locale` is an API for parsing, manipulating, and serializing Unicode Locale
2//! Identifiers.
3//!
4//! The crate provides algorithms for parsing a string into a well-formed locale identifier
5//! as defined by [`UTS #35: Unicode LDML 3.1 Unicode Locale Identifier`].
6//!
7//! # Locale vs. LanguageIdentifier
8//!
9//! `LanguageIdentifier` is a subset of a `Locale` that only provides the basic
10//! subtags such as `language`, `script`, `region` and `variants`.
11//!
12//! `Locale` extends that with a set of extensions such as `transform`, `unicode` and `private`.
13//!
14//!
15//! # Examples
16//!
17//! ```
18//! use unic_locale::Locale;
19//!
20//! let mut loc: Locale = "en-Latn-US-u-hc-h12-t-h0-hybrid".parse()
21//! .expect("Failed to parse.");
22//!
23//! assert_eq!(loc.id.language.as_str(), "en");
24//! assert_eq!(loc.id.script, Some("Latn".parse().unwrap()));
25//! assert_eq!(loc.id.region, Some("US".parse().unwrap()));
26//! assert_eq!(loc.id.variants().len(), 0);
27//! assert_eq!(loc.extensions.unicode.keyword("hc")
28//! .expect("Getting keyword failed.")
29//! .collect::<Vec<_>>(), &["h12"]);
30//! assert_eq!(loc.extensions.transform.tfield("h0")
31//! .expect("Getting tfield failed.")
32//! .collect::<Vec<_>>(), &["hybrid"]);
33//!
34//! loc.id.script = None;
35//! loc.id.region = Some("GB".parse().expect("Region parsing failed."));
36//!
37//! assert_eq!(loc.to_string(), "en-GB-t-h0-hybrid-u-hc-h12");
38//! ```
39//!
40//! For more details, see [`Locale`].
41//!
42//! # Optional features
43//!
44//! ## `locale!` and `locale!` macros
45//!
46//! If `feature = "macros"` is selected, the crate provides a procedural macro
47//! which allows to construct build-time well-formed locale identifiers with zero-cost at runtime.
48//!
49//! ``` ignore
50//! use unic_locale::{locale, locales};
51//!
52//! let es_ar = locale!("es-AR");
53//! let en_us = locale!("en-US");
54//!
55//! assert_eq!(es_ar, "es-AR");
56//! assert_eq!(en_us, "en-US");
57//!
58//! let locales = locales!("es-AR", "en-US", "de");
59//!
60//! assert_eq!(locales.get(0), "es-AR");
61//! assert_eq!(locales.get(1), "en-US");
62//! assert_eq!(locales.get(2), "de");
63//! ```
64//!
65//! The macros produce instances of `Locale` the same way as parsing from `&str` does,
66//! but since the parsing is performed at build time, it doesn't need a `Result`.
67//!
68//! Unlike `langid!` `locale!` can't be used for const variables.
69//!
70//! The macros are optional to reduce the dependency chain and compilation time of `unic-locale`.
71//!
72//! ## Likely Subtags
73//!
74//! If `feature = "likelysubtags"` is selected, the `Locale` gains two more methods:
75//!
76//! * add_likely_subtags
77//! * remove_likely_subtags
78//!
79//! Both of them operate in place updating the existing `Locale` by either extending
80//! subtags to most likely values, or removing the subtags that are not needed.
81//!
82//! Both methods return a `bool` that indicates if the identifier has been modified.
83//!
84//! ``` ignore
85//! use unic_locale::Locale;
86//!
87//! let mut loc: Locale = "fr-FR".parse()
88//! .expect("Parsing failed.");
89//!
90//! assert_eq!(loc.add_likely_subtags(), true);
91//! assert_eq!(loc, "fr-Latn-FR");
92//!
93//! assert_eq!(loc.remove_likely_subtags(), true);
94//! assert_eq!(loc, "fr");
95//! ```
96//!
97//! The feature is optional because it increases the binary size of the library by including
98//! a data table for CLDR likelySubtags.
99//!
100//! [`UTS #35: Unicode LDML 3.1 Unicode Locale Identifier`]: https://unicode.org/reports/tr35/tr35.html#Unicode_locale_identifier
101//! [`Locale`]: ./struct.Locale.html
102pub use unic_locale_impl::*;
103
104#[cfg(feature = "unic-locale-macros")]
105pub use unic_locale_macros::locale;
106
107#[cfg(feature = "unic-locale-macros")]
108#[macro_export]
109macro_rules! locales {
110 ( $($locale:expr),* ) => {
111 vec![$(
112 $crate::locale!($locale),
113 )*]
114 };
115 ( $($locale:expr,)* ) => {
116 $crate::locales![$($locale),*]
117 };
118}