Skip to main content

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