+ use std::env;
+
+ enum PosixLocaleCategory {
+ CType,
+ Collate,
+ Messages,
+ Monetary,
+ Numeric,
+ Time,
+ Address,
+ Identification,
+ Measurement,
+ Name,
+ Paper,
+ Telephone,
+ }
+
+ impl PosixLocaleCategory {
+ fn as_str(&self) -> &str {
+ match self {
+ Self::CType => "LC_CTYPE",
+ Self::Collate => "LC_COLLATE",
+ Self::Messages => "LC_MESSAGES",
+ Self::Monetary => "LC_MONETARY",
+ Self::Numeric => "LC_NUMERIC",
+ Self::Time => "LC_TIME",
+ Self::Address => "LC_ADDRESS",
+ Self::Identification => "LC_IDENTIFICATION",
+ Self::Measurement => "LC_MEASUREMENT",
+ Self::Name => "LC_NAME",
+ Self::Paper => "LC_PAPER",
+ Self::Telephone => "LC_TELEPHONE",
+ }
+ }
+ }
+
+ impl PosixLocaleCategory {
+ /// Query the locale following the POSIX spec:
+ /// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_02
+ ///
+ /// Order of precedence:
+ /// 1. LC_ALL
+ /// 2. LC_{NUMERIC, TIME, etc}
+ /// 3. LANG
+ /// 4. Default locale (handled by caller, this function will return None)
+ fn get_locale(&self) -> Option<String> {
+ if let Ok(global_locale) = env::var("LC_ALL") {
+ Some(global_locale)
+ } else if let Ok(category_locale) = env::var(self.as_str()) {
+ Some(category_locale)
+ } else if let Ok(lang) = env::var("LANG") {
+ Some(lang)
+ } else {
+ None
+ }
+ }
+ }