layout/
quotes.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5// Quotes data is obtained from ICU CLDR data file /tmp/cldr-common-46.0.zip.
6
7// TODO(xiaochengh): This file should better be moved to elsewhere and maintained automatically.
8// Or even better, extend the icu create to provide the data directly.
9
10use std::collections::HashMap;
11use std::sync::OnceLock;
12
13use icu_locid::Locale;
14
15#[derive(Clone, Copy, Debug)]
16pub struct QuotePair {
17    pub opening: char,
18    pub closing: char,
19}
20
21#[derive(Clone, Copy, Debug)]
22struct QuotesData {
23    quotes: QuotePair,
24    alternative_quotes: QuotePair,
25}
26
27impl QuotesData {
28    const fn from(chars: (char, char, char, char)) -> Self {
29        QuotesData {
30            quotes: QuotePair {
31                opening: chars.0,
32                closing: chars.1,
33            },
34            alternative_quotes: QuotePair {
35                opening: chars.2,
36                closing: chars.3,
37            },
38        }
39    }
40}
41
42static DEFAULT_QUOTES: QuotesData =
43    QuotesData::from(('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}'));
44
45static QUOTES_MAP: OnceLock<HashMap<&'static str, QuotesData>> = OnceLock::new();
46
47fn create_quotes_map() -> HashMap<&'static str, QuotesData> {
48    let input = [
49        ("aa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
50        ("ab", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
51        ("af", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
52        ("ak", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
53        ("an", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
54        ("ann", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
55        ("apc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
56        ("arn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
57        ("as", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
58        ("asa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
59        ("az", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
60        ("ba", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
61        ("bal", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
62        ("bem", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
63        ("bew", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
64        ("bez", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
65        ("bgc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
66        ("bgn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
67        ("bho", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
68        ("blt", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
69        ("bn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
70        ("bo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
71        ("brx", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
72        ("bss", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
73        ("byn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
74        ("cad", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
75        ("cch", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
76        ("ccp", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
77        ("ce", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
78        ("ceb", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
79        ("cgg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
80        ("cho", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
81        ("chr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
82        ("cic", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
83        ("ckb", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
84        ("co", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
85        ("csw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
86        ("cu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
87        ("cy", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
88        ("da", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
89        ("dav", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
90        ("dje", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
91        ("doi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
92        ("dv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
93        ("dz", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
94        ("ebu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
95        ("ee", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
96        ("en", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
97        ("eo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
98        ("es", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
99        ("fil", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
100        ("fo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
101        ("frr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
102        ("fur", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
103        ("fy", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
104        ("ga", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
105        ("gaa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
106        ("gd", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
107        ("gez", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
108        ("gl", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
109        ("gn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
110        ("gu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
111        ("guz", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
112        ("gv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
113        ("ha", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
114        ("haw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
115        ("hi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
116        ("hnj", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
117        ("id", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
118        ("ig", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
119        ("ii", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
120        ("io", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
121        ("iu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
122        ("jbo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
123        ("jmc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
124        ("jv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
125        ("kaa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
126        ("kaj", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
127        ("kam", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
128        ("kcg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
129        ("kde", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
130        ("kea", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
131        ("ken", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
132        ("kgp", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
133        ("khq", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
134        ("ki", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
135        ("kl", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
136        ("kln", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
137        ("km", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
138        ("kn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
139        ("ko", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
140        ("kok", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
141        ("kpe", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
142        ("ks", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
143        ("ksb", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
144        ("ksh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
145        ("ku", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
146        ("kw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
147        ("kxv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
148        ("la", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
149        ("lg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
150        ("lkt", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
151        ("lmo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
152        ("ln", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
153        ("lo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
154        ("lrc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
155        ("ltg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
156        ("lu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
157        ("luo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
158        ("lv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
159        ("mai", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
160        ("mas", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
161        ("mdf", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
162        ("mer", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
163        ("mfe", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
164        ("mgh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
165        ("mgo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
166        ("mhn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
167        ("mi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
168        ("mic", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
169        ("ml", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
170        ("mn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
171        ("mni", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
172        ("moh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
173        ("mr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
174        ("ms", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
175        ("mt", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
176        ("mus", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
177        ("my", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
178        ("myv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
179        ("naq", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
180        ("nb", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
181        ("nd", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
182        ("nds", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
183        ("ne", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
184        ("nn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
185        ("nqo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
186        ("nr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
187        ("nus", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
188        ("nv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
189        ("ny", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
190        ("nyn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
191        ("oc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
192        ("om", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
193        ("or", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
194        ("os", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
195        ("osa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
196        ("pa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
197        ("pap", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
198        ("pcm", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
199        ("pis", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
200        ("prg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
201        ("ps", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
202        ("pt", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
203        ("qu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
204        ("quc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
205        ("raj", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
206        ("rhg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
207        ("rif", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
208        ("rm", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
209        ("rof", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
210        ("rwk", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
211        ("sa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
212        ("saq", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
213        ("sat", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
214        ("sbp", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
215        ("scn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
216        ("sd", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
217        ("se", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
218        ("seh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
219        ("ses", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
220        ("shn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
221        ("si", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
222        ("sid", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
223        ("skr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
224        ("sma", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
225        ("smj", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
226        ("smn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
227        ("sms", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
228        ("so", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
229        ("ss", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
230        ("ssy", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
231        ("su", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
232        ("sw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
233        ("szl", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
234        ("ta", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
235        ("te", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
236        ("teo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
237        ("tg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
238        ("th", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
239        ("tig", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
240        ("to", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
241        ("tok", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
242        ("tpi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
243        ("tr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
244        ("trv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
245        ("trw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
246        ("ts", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
247        ("tt", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
248        ("twq", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
249        ("tyv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
250        ("tzm", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
251        ("ug", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
252        ("vai", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
253        ("ve", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
254        ("vec", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
255        ("vi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
256        ("vmw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
257        ("vo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
258        ("vun", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
259        ("wa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
260        ("wae", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
261        ("wal", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
262        ("wbp", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
263        ("wo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
264        ("xh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
265        ("xnr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
266        ("xog", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
267        ("yi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
268        ("yo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
269        ("yrl", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
270        ("za", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
271        ("zh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
272        ("zu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
273        ("agq", ('\u{201e}', '\u{201d}', '\u{201a}', '\u{2019}')),
274        ("ff", ('\u{201e}', '\u{201d}', '\u{201a}', '\u{2019}')),
275        ("am", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
276        ("az-Arab", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
277        ("az-Cyrl", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
278        ("fa", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
279        ("fr-CH", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
280        ("gsw", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
281        ("jgo", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
282        ("kkj", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
283        ("mzn", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
284        ("sdh", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
285        ("ar", ('\u{201d}', '\u{201c}', '\u{2019}', '\u{2018}')),
286        ("lld", ('\u{201d}', '\u{201c}', '\u{2019}', '\u{2018}')),
287        ("ms-Arab", ('\u{201d}', '\u{201c}', '\u{2019}', '\u{2018}')),
288        ("syr", ('\u{201d}', '\u{201c}', '\u{2019}', '\u{2018}')),
289        ("ur", ('\u{201d}', '\u{201c}', '\u{2019}', '\u{2018}')),
290        ("ast", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
291        ("blo", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
292        ("bm", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
293        ("br", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
294        ("ca", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
295        ("dyo", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
296        ("el", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
297        ("es-US", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
298        ("eu", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
299        ("ewo", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
300        ("ie", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
301        ("it", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
302        ("kab", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
303        ("kk", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
304        ("lij", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
305        ("mg", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
306        ("mua", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
307        ("nnh", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
308        ("pt-PT", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
309        ("sc", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
310        ("sg", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
311        ("sq", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
312        ("ti", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
313        ("bas", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
314        ("be", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
315        ("cv", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
316        ("ky", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
317        ("ru", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
318        ("sah", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
319        ("uk", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
320        ("bg", ('\u{201e}', '\u{201c}', '\u{201e}', '\u{201c}')),
321        ("lt", ('\u{201e}', '\u{201c}', '\u{201e}', '\u{201c}')),
322        ("bs-Cyrl", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
323        ("cs", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
324        ("de", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
325        ("dsb", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
326        ("et", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
327        ("hr", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
328        ("hsb", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
329        ("is", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
330        ("lb", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
331        ("luy", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
332        ("mk", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
333        ("sk", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
334        ("sl", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
335        ("bs", ('\u{201e}', '\u{201d}', '\u{2018}', '\u{2019}')),
336        ("dua", ('\u{ab}', '\u{bb}', '\u{2018}', '\u{2019}')),
337        ("el-POLYTON", ('\u{ab}', '\u{bb}', '\u{2018}', '\u{2019}')),
338        ("ksf", ('\u{ab}', '\u{bb}', '\u{2018}', '\u{2019}')),
339        ("no", ('\u{ab}', '\u{bb}', '\u{2018}', '\u{2019}')),
340        ("rw", ('\u{ab}', '\u{bb}', '\u{2018}', '\u{2019}')),
341        ("fi", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
342        ("he", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
343        ("lag", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
344        ("rn", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
345        ("sn", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
346        ("sv", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
347        ("fr-CA", ('\u{ab}', '\u{bb}', '\u{201d}', '\u{201c}')),
348        ("fr", ('\u{ab}', '\u{bb}', '\u{ab}', '\u{bb}')),
349        ("hy", ('\u{ab}', '\u{bb}', '\u{ab}', '\u{bb}')),
350        ("yav", ('\u{ab}', '\u{bb}', '\u{ab}', '\u{bb}')),
351        ("hu", ('\u{201e}', '\u{201d}', '\u{bb}', '\u{ab}')),
352        ("ia", ('\u{2018}', '\u{2019}', '\u{201c}', '\u{201d}')),
353        ("nso", ('\u{2018}', '\u{2019}', '\u{201c}', '\u{201d}')),
354        ("ti-ER", ('\u{2018}', '\u{2019}', '\u{201c}', '\u{201d}')),
355        ("tn", ('\u{2018}', '\u{2019}', '\u{201c}', '\u{201d}')),
356        ("ja", ('\u{300c}', '\u{300d}', '\u{300e}', '\u{300f}')),
357        ("yue", ('\u{300c}', '\u{300d}', '\u{300e}', '\u{300f}')),
358        ("zh-Hant", ('\u{300c}', '\u{300d}', '\u{300e}', '\u{300f}')),
359        ("ka", ('\u{201e}', '\u{201c}', '\u{ab}', '\u{bb}')),
360        ("nl", ('\u{2018}', '\u{2019}', '\u{2018}', '\u{2019}')),
361        ("nmg", ('\u{201e}', '\u{201d}', '\u{ab}', '\u{bb}')),
362        ("pl", ('\u{201e}', '\u{201d}', '\u{ab}', '\u{bb}')),
363        ("ro", ('\u{201e}', '\u{201d}', '\u{ab}', '\u{bb}')),
364        ("shi", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201d}')),
365        ("zgh", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201d}')),
366        ("sr", ('\u{201e}', '\u{201d}', '\u{2019}', '\u{2019}')),
367        ("st", ('\u{201c}', '\u{2019}', '\u{201c}', '\u{201d}')),
368        ("tk", ('\u{201c}', '\u{201d}', '\u{201c}', '\u{201d}')),
369        ("uz", ('\u{201c}', '\u{201d}', '\u{2019}', '\u{2018}')),
370    ]
371    .map(|(lang, chars)| (lang, QuotesData::from(chars)));
372    HashMap::from(input)
373}
374
375fn quotes_data_for_lang(lang: &str) -> QuotesData {
376    // All valid language codes are at least two bytes long.
377    if lang.len() < 2 {
378        return DEFAULT_QUOTES;
379    }
380
381    let quotes_map = QUOTES_MAP.get_or_init(create_quotes_map);
382
383    // Found an exact match for the requested lang.
384    if let Some(quotes_data) = quotes_map.get(lang) {
385        return *quotes_data;
386    }
387
388    // Try parsing lang as a Locale and canonicalizing the subtags, then see if
389    // we can match it with region or script subtags, if present, or just the
390    // primary language tag.
391    let locale = match lang.parse::<Locale>() {
392        Err(_) => return DEFAULT_QUOTES,
393        Ok(locale) => locale,
394    };
395
396    let lang = locale.id.language.to_string();
397
398    if let Some(quotes_data) = quotes_map.get(lang.as_str()) {
399        return *quotes_data;
400    }
401
402    if let Some(quotes_data) = locale
403        .id
404        .region
405        .and_then(|region| quotes_map.get(format!("{lang}-{region}").as_str()))
406    {
407        return *quotes_data;
408    }
409
410    if let Some(quotes_data) = locale
411        .id
412        .script
413        .and_then(|script| quotes_map.get(format!("{lang}-{script}").as_str()))
414    {
415        return *quotes_data;
416    }
417
418    DEFAULT_QUOTES
419}
420
421pub fn quotes_for_lang(lang: &str, depth: usize) -> QuotePair {
422    let quotes_data = quotes_data_for_lang(lang);
423    match depth {
424        0 => quotes_data.quotes,
425        _ => quotes_data.alternative_quotes,
426    }
427}