1 | // This file is part of ICU4X. For terms of use, please see the file |
2 | // called LICENSE at the top level of the ICU4X source tree |
3 | // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). |
4 | |
5 | //! Options to define fallback behaviour. |
6 | //! |
7 | //! These options are consumed by the `LocaleFallbacker` in the `icu_locid_transforms` crate |
8 | //! (or the `icu::locid_transforms` module), but are defined here because they are used by `DataKey`. |
9 | |
10 | use icu_locid::extensions::unicode::Key; |
11 | |
12 | /// Hint for which subtag to prioritize during fallback. |
13 | /// |
14 | /// For example, `"en-US"` might fall back to either `"en"` or `"und-US"` depending |
15 | /// on this enum. |
16 | #[derive (Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] |
17 | #[non_exhaustive ] |
18 | pub enum LocaleFallbackPriority { |
19 | /// Prioritize the language. This is the default behavior. |
20 | /// |
21 | /// For example, `"en-US"` should go to `"en"` and then `"und"`. |
22 | Language, |
23 | /// Prioritize the region. |
24 | /// |
25 | /// For example, `"en-US"` should go to `"und-US"` and then `"und"`. |
26 | Region, |
27 | /// Collation-specific fallback rules. Similar to language priority. |
28 | /// |
29 | /// For example, `"zh-Hant"` goes to `"zh"` before `"und"`. |
30 | Collation, |
31 | } |
32 | |
33 | impl LocaleFallbackPriority { |
34 | /// Const-friendly version of [`Default::default`]. |
35 | pub const fn const_default() -> Self { |
36 | Self::Language |
37 | } |
38 | } |
39 | |
40 | impl Default for LocaleFallbackPriority { |
41 | fn default() -> Self { |
42 | Self::const_default() |
43 | } |
44 | } |
45 | |
46 | /// What additional data is required to load when performing fallback. |
47 | #[derive (Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] |
48 | #[non_exhaustive ] |
49 | pub enum LocaleFallbackSupplement { |
50 | /// Collation supplement |
51 | Collation, |
52 | } |
53 | |
54 | /// Configuration settings for a particular fallback operation. |
55 | #[derive (Debug, Clone, PartialEq, Eq, Copy)] |
56 | #[non_exhaustive ] |
57 | pub struct LocaleFallbackConfig { |
58 | /// Strategy for choosing which subtags to drop during locale fallback. |
59 | /// |
60 | /// # Examples |
61 | /// |
62 | /// Retain the language and script subtags until the final step: |
63 | /// |
64 | /// ``` |
65 | /// use icu_locid::locale; |
66 | /// use icu_locid_transform::fallback::LocaleFallbackConfig; |
67 | /// use icu_locid_transform::fallback::LocaleFallbackPriority; |
68 | /// use icu_locid_transform::LocaleFallbacker; |
69 | /// |
70 | /// // Set up the fallback iterator. |
71 | /// let fallbacker = LocaleFallbacker::new(); |
72 | /// let mut config = LocaleFallbackConfig::default(); |
73 | /// config.priority = LocaleFallbackPriority::Language; |
74 | /// let mut fallback_iterator = fallbacker |
75 | /// .for_config(config) |
76 | /// .fallback_for(locale!("ca-ES-valencia" ).into()); |
77 | /// |
78 | /// // Run the algorithm and check the results. |
79 | /// assert_eq!(fallback_iterator.get(), &locale!("ca-ES-valencia" ).into()); |
80 | /// fallback_iterator.step(); |
81 | /// assert_eq!(fallback_iterator.get(), &locale!("ca-ES" ).into()); |
82 | /// fallback_iterator.step(); |
83 | /// assert_eq!(fallback_iterator.get(), &locale!("ca-valencia" ).into()); |
84 | /// fallback_iterator.step(); |
85 | /// assert_eq!(fallback_iterator.get(), &locale!("ca" ).into()); |
86 | /// fallback_iterator.step(); |
87 | /// assert_eq!(fallback_iterator.get(), &locale!("und" ).into()); |
88 | /// ``` |
89 | /// |
90 | /// Retain the region subtag until the final step: |
91 | /// |
92 | /// ``` |
93 | /// use icu_locid::locale; |
94 | /// use icu_locid_transform::fallback::LocaleFallbackConfig; |
95 | /// use icu_locid_transform::fallback::LocaleFallbackPriority; |
96 | /// use icu_locid_transform::LocaleFallbacker; |
97 | /// |
98 | /// // Set up the fallback iterator. |
99 | /// let fallbacker = LocaleFallbacker::new(); |
100 | /// let mut config = LocaleFallbackConfig::default(); |
101 | /// config.priority = LocaleFallbackPriority::Region; |
102 | /// let mut fallback_iterator = fallbacker |
103 | /// .for_config(config) |
104 | /// .fallback_for(locale!("ca-ES-valencia" ).into()); |
105 | /// |
106 | /// // Run the algorithm and check the results. |
107 | /// assert_eq!(fallback_iterator.get(), &locale!("ca-ES-valencia" ).into()); |
108 | /// fallback_iterator.step(); |
109 | /// assert_eq!(fallback_iterator.get(), &locale!("ca-ES" ).into()); |
110 | /// fallback_iterator.step(); |
111 | /// assert_eq!(fallback_iterator.get(), &locale!("und-ES-valencia" ).into()); |
112 | /// fallback_iterator.step(); |
113 | /// assert_eq!(fallback_iterator.get(), &locale!("und-ES" ).into()); |
114 | /// fallback_iterator.step(); |
115 | /// assert_eq!(fallback_iterator.get(), &locale!("und" ).into()); |
116 | /// ``` |
117 | pub priority: LocaleFallbackPriority, |
118 | /// An extension keyword to retain during locale fallback. |
119 | /// |
120 | /// # Examples |
121 | /// |
122 | /// ``` |
123 | /// use icu_locid::locale; |
124 | /// use icu_locid_transform::fallback::LocaleFallbackConfig; |
125 | /// use icu_locid_transform::LocaleFallbacker; |
126 | /// |
127 | /// // Set up the fallback iterator. |
128 | /// let fallbacker = LocaleFallbacker::new(); |
129 | /// let mut config = LocaleFallbackConfig::default(); |
130 | /// config.extension_key = Some(icu_locid::extensions::unicode::key!("nu" )); |
131 | /// let mut fallback_iterator = fallbacker |
132 | /// .for_config(config) |
133 | /// .fallback_for(locale!("ar-EG-u-nu-latn" ).into()); |
134 | /// |
135 | /// // Run the algorithm and check the results. |
136 | /// assert_eq!(fallback_iterator.get(), &locale!("ar-EG-u-nu-latn" ).into()); |
137 | /// fallback_iterator.step(); |
138 | /// assert_eq!(fallback_iterator.get(), &locale!("ar-EG" ).into()); |
139 | /// fallback_iterator.step(); |
140 | /// assert_eq!(fallback_iterator.get(), &locale!("ar-u-nu-latn" ).into()); |
141 | /// fallback_iterator.step(); |
142 | /// assert_eq!(fallback_iterator.get(), &locale!("ar" ).into()); |
143 | /// fallback_iterator.step(); |
144 | /// assert_eq!(fallback_iterator.get(), &locale!("und" ).into()); |
145 | /// ``` |
146 | pub extension_key: Option<Key>, |
147 | /// Fallback supplement data key to customize fallback rules. |
148 | /// |
149 | /// For example, most data keys for collation add additional parent locales, such as |
150 | /// "yue" to "zh-Hant", and data used for the `"-u-co"` extension keyword fallback. |
151 | /// |
152 | /// Currently the only supported fallback supplement is `LocaleFallbackSupplement::Collation`, but more may be |
153 | /// added in the future. |
154 | /// |
155 | /// # Examples |
156 | /// |
157 | /// ``` |
158 | /// use icu_locid::locale; |
159 | /// use icu_locid_transform::fallback::LocaleFallbackConfig; |
160 | /// use icu_locid_transform::fallback::LocaleFallbackPriority; |
161 | /// use icu_locid_transform::fallback::LocaleFallbackSupplement; |
162 | /// use icu_locid_transform::LocaleFallbacker; |
163 | /// |
164 | /// // Set up the fallback iterator. |
165 | /// let fallbacker = LocaleFallbacker::new(); |
166 | /// let mut config = LocaleFallbackConfig::default(); |
167 | /// config.priority = LocaleFallbackPriority::Collation; |
168 | /// config.fallback_supplement = Some(LocaleFallbackSupplement::Collation); |
169 | /// let mut fallback_iterator = fallbacker |
170 | /// .for_config(config) |
171 | /// .fallback_for(locale!("yue-HK" ).into()); |
172 | /// |
173 | /// // Run the algorithm and check the results. |
174 | /// // TODO(#1964): add "zh" as a target. |
175 | /// assert_eq!(fallback_iterator.get(), &locale!("yue-HK" ).into()); |
176 | /// fallback_iterator.step(); |
177 | /// assert_eq!(fallback_iterator.get(), &locale!("yue" ).into()); |
178 | /// fallback_iterator.step(); |
179 | /// assert_eq!(fallback_iterator.get(), &locale!("zh-Hant" ).into()); |
180 | /// fallback_iterator.step(); |
181 | /// assert_eq!(fallback_iterator.get(), &locale!("und" ).into()); |
182 | /// ``` |
183 | pub fallback_supplement: Option<LocaleFallbackSupplement>, |
184 | } |
185 | |
186 | impl LocaleFallbackConfig { |
187 | /// Const version of [`Default::default`]. |
188 | pub const fn const_default() -> Self { |
189 | Self { |
190 | priority: LocaleFallbackPriority::const_default(), |
191 | extension_key: None, |
192 | fallback_supplement: None, |
193 | } |
194 | } |
195 | } |
196 | |
197 | impl Default for LocaleFallbackConfig { |
198 | fn default() -> Self { |
199 | Self::const_default() |
200 | } |
201 | } |
202 | |