1 | //! A library to safely and easily obtain the current locale on the system or for an application. |
2 | //! |
3 | //! This library currently supports the following platforms: |
4 | //! - Android |
5 | //! - iOS (and derivatives such as watchOS, tvOS, and visionOS) |
6 | //! - macOS |
7 | //! - Linux, BSD, and other UNIX variations |
8 | //! - WebAssembly on the web (via the `js` feature) |
9 | //! - Windows |
10 | #![cfg_attr (any(not(unix), target_vendor = "apple" , target_os = "android" ), no_std)] |
11 | extern crate alloc; |
12 | use alloc::string::String; |
13 | |
14 | #[cfg (target_os = "android" )] |
15 | mod android; |
16 | #[cfg (target_os = "android" )] |
17 | use android as provider; |
18 | |
19 | #[cfg (target_vendor = "apple" )] |
20 | mod apple; |
21 | #[cfg (target_vendor = "apple" )] |
22 | use apple as provider; |
23 | |
24 | #[cfg (all(unix, not(any(target_vendor = "apple" , target_os = "android" ))))] |
25 | mod unix; |
26 | #[cfg (all(unix, not(any(target_vendor = "apple" , target_os = "android" ))))] |
27 | use unix as provider; |
28 | |
29 | #[cfg (all(target_family = "wasm" , feature = "js" , not(unix)))] |
30 | mod wasm; |
31 | #[cfg (all(target_family = "wasm" , feature = "js" , not(unix)))] |
32 | use wasm as provider; |
33 | |
34 | #[cfg (windows)] |
35 | mod windows; |
36 | #[cfg (windows)] |
37 | use windows as provider; |
38 | |
39 | #[cfg (not(any(unix, all(target_family = "wasm" , feature = "js" , not(unix)), windows)))] |
40 | mod provider { |
41 | pub fn get() -> impl Iterator<Item = alloc::string::String> { |
42 | core::iter::empty() |
43 | } |
44 | } |
45 | |
46 | /// Returns the most preferred locale for the system or application. |
47 | /// |
48 | /// This is equivalent to `get_locales().next()` (the first entry). |
49 | /// |
50 | /// # Returns |
51 | /// |
52 | /// Returns [`Some(String)`] with a BCP 47 language tag inside. |
53 | /// If the locale couldn't be obtained, [`None`] is returned instead. |
54 | /// |
55 | /// # Example |
56 | /// |
57 | /// ```no_run |
58 | /// use sys_locale::get_locale; |
59 | /// |
60 | /// let current_locale = get_locale().unwrap_or_else(|| String::from("en-US" )); |
61 | /// |
62 | /// println!("The locale is {}" , current_locale); |
63 | /// ``` |
64 | pub fn get_locale() -> Option<String> { |
65 | get_locales().next() |
66 | } |
67 | |
68 | /// Returns the preferred locales for the system or application, in descending order of preference. |
69 | /// |
70 | /// # Returns |
71 | /// |
72 | /// Returns an [`Iterator`] with any number of BCP 47 language tags inside. |
73 | /// If no locale preferences could be obtained, the iterator will be empty. |
74 | /// |
75 | /// # Example |
76 | /// |
77 | /// ```no_run |
78 | /// use sys_locale::get_locales; |
79 | /// |
80 | /// let mut locales = get_locales(); |
81 | /// |
82 | /// println!("The most preferred locale is {}" , locales.next().unwrap_or("en-US" .to_string())); |
83 | /// println!("The least preferred locale is {}" , locales.last().unwrap_or("en-US" .to_string())); |
84 | /// ``` |
85 | pub fn get_locales() -> impl Iterator<Item = String> { |
86 | provider::get() |
87 | } |
88 | |
89 | #[cfg (test)] |
90 | mod tests { |
91 | use super::{get_locale, get_locales}; |
92 | extern crate std; |
93 | |
94 | #[cfg (all(target_family = "wasm" , feature = "js" , not(unix)))] |
95 | use wasm_bindgen_test::wasm_bindgen_test as test; |
96 | #[cfg (all(target_family = "wasm" , feature = "js" , not(unix)))] |
97 | wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); |
98 | |
99 | #[test ] |
100 | fn can_obtain_locale() { |
101 | assert!(get_locale().is_some(), "no locales were returned" ); |
102 | let locales = get_locales(); |
103 | for (i, locale) in locales.enumerate() { |
104 | assert!(!locale.is_empty(), "locale string {} was empty" , i); |
105 | assert!( |
106 | !locale.ends_with(' \0' ), |
107 | "locale {} contained trailing NUL" , |
108 | i |
109 | ); |
110 | } |
111 | } |
112 | } |
113 | |