aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/quotes.rs
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2025-04-19 12:17:03 +0200
committerGitHub <noreply@github.com>2025-04-19 10:17:03 +0000
commit7787cab521ccc6b4d8533ebe9b45563046e0463d (patch)
treed1277fa3846f24cc99859310da3d7f099c73bfc5 /components/layout/quotes.rs
parent3ab5b8c4472129798b63cfb40b63ae672763b653 (diff)
downloadservo-7787cab521ccc6b4d8533ebe9b45563046e0463d.tar.gz
servo-7787cab521ccc6b4d8533ebe9b45563046e0463d.zip
layout: Combine `layout_2020` and `layout_thread_2020` into a crate called `layout` (#36613)
Now that legacy layout has been removed, the name `layout_2020` doesn't make much sense any longer, also it's 2025 now for better or worse. The split between the "layout thread" and "layout" also doesn't make as much sense since layout doesn't run on it's own thread. There's a possibility that it will in the future, but that should be something that the user of the crate controls rather than layout iself. This is part of the larger layout interface cleanup and optimization that @Looriool and I are doing. Testing: Covered by existing tests as this is just code movement. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Diffstat (limited to 'components/layout/quotes.rs')
-rw-r--r--components/layout/quotes.rs427
1 files changed, 427 insertions, 0 deletions
diff --git a/components/layout/quotes.rs b/components/layout/quotes.rs
new file mode 100644
index 00000000000..05e9e06fe89
--- /dev/null
+++ b/components/layout/quotes.rs
@@ -0,0 +1,427 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+// Quotes data is obtained from ICU CLDR data file /tmp/cldr-common-46.0.zip.
+
+// TODO(xiaochengh): This file should better be moved to elsewhere and maintained automatically.
+// Or even better, extend the icu create to provide the data directly.
+
+use std::collections::HashMap;
+use std::sync::OnceLock;
+
+use icu_locid::Locale;
+
+#[derive(Clone, Copy, Debug)]
+pub struct QuotePair {
+ pub opening: char,
+ pub closing: char,
+}
+
+#[derive(Clone, Copy, Debug)]
+struct QuotesData {
+ quotes: QuotePair,
+ alternative_quotes: QuotePair,
+}
+
+impl QuotesData {
+ const fn from(chars: (char, char, char, char)) -> Self {
+ QuotesData {
+ quotes: QuotePair {
+ opening: chars.0,
+ closing: chars.1,
+ },
+ alternative_quotes: QuotePair {
+ opening: chars.2,
+ closing: chars.3,
+ },
+ }
+ }
+}
+
+static DEFAULT_QUOTES: QuotesData =
+ QuotesData::from(('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}'));
+
+static QUOTES_MAP: OnceLock<HashMap<&'static str, QuotesData>> = OnceLock::new();
+
+fn create_quotes_map() -> HashMap<&'static str, QuotesData> {
+ let input = [
+ ("aa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ab", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("af", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ak", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("an", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ann", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("apc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("arn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("as", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("asa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("az", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ba", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("bal", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("bem", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("bew", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("bez", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("bgc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("bgn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("bho", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("blt", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("bn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("bo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("brx", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("bss", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("byn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("cad", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("cch", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ccp", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ce", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ceb", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("cgg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("cho", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("chr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("cic", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ckb", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("co", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("csw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("cu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("cy", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("da", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("dav", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("dje", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("doi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("dv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("dz", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ebu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ee", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("en", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("eo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("es", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("fil", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("fo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("frr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("fur", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("fy", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ga", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("gaa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("gd", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("gez", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("gl", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("gn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("gu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("guz", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("gv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ha", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("haw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("hi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("hnj", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("id", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ig", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ii", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("io", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("iu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("jbo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("jmc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("jv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kaa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kaj", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kam", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kcg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kde", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kea", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ken", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kgp", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("khq", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ki", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kl", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kln", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("km", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ko", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kok", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kpe", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ks", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ksb", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ksh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ku", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("kxv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("la", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("lg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("lkt", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("lmo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ln", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("lo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("lrc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ltg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("lu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("luo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("lv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mai", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mas", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mdf", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mer", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mfe", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mgh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mgo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mhn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mic", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ml", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mni", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("moh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ms", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mt", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("mus", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("my", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("myv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("naq", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("nb", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("nd", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("nds", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ne", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("nn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("nqo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("nr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("nus", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("nv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ny", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("nyn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("oc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("om", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("or", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("os", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("osa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("pa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("pap", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("pcm", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("pis", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("prg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ps", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("pt", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("qu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("quc", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("raj", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("rhg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("rif", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("rm", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("rof", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("rwk", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("sa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("saq", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("sat", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("sbp", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("scn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("sd", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("se", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("seh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ses", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("shn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("si", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("sid", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("skr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("sma", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("smj", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("smn", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("sms", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("so", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ss", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ssy", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("su", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("sw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("szl", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ta", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("te", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("teo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("tg", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("th", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("tig", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("to", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("tok", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("tpi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("tr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("trv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("trw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ts", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("tt", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("twq", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("tyv", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("tzm", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ug", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("vai", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("ve", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("vec", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("vi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("vmw", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("vo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("vun", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("wa", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("wae", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("wal", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("wbp", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("wo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("xh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("xnr", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("xog", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("yi", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("yo", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("yrl", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("za", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("zh", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("zu", ('\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("agq", ('\u{201e}', '\u{201d}', '\u{201a}', '\u{2019}')),
+ ("ff", ('\u{201e}', '\u{201d}', '\u{201a}', '\u{2019}')),
+ ("am", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
+ ("az-Arab", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
+ ("az-Cyrl", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
+ ("fa", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
+ ("fr-CH", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
+ ("gsw", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
+ ("jgo", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
+ ("kkj", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
+ ("mzn", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
+ ("sdh", ('\u{ab}', '\u{bb}', '\u{2039}', '\u{203a}')),
+ ("ar", ('\u{201d}', '\u{201c}', '\u{2019}', '\u{2018}')),
+ ("lld", ('\u{201d}', '\u{201c}', '\u{2019}', '\u{2018}')),
+ ("ms-Arab", ('\u{201d}', '\u{201c}', '\u{2019}', '\u{2018}')),
+ ("syr", ('\u{201d}', '\u{201c}', '\u{2019}', '\u{2018}')),
+ ("ur", ('\u{201d}', '\u{201c}', '\u{2019}', '\u{2018}')),
+ ("ast", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("blo", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("bm", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("br", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("ca", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("dyo", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("el", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("es-US", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("eu", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("ewo", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("ie", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("it", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("kab", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("kk", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("lij", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("mg", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("mua", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("nnh", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("pt-PT", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("sc", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("sg", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("sq", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("ti", ('\u{ab}', '\u{bb}', '\u{201c}', '\u{201d}')),
+ ("bas", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
+ ("be", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
+ ("cv", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
+ ("ky", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
+ ("ru", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
+ ("sah", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
+ ("uk", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201c}')),
+ ("bg", ('\u{201e}', '\u{201c}', '\u{201e}', '\u{201c}')),
+ ("lt", ('\u{201e}', '\u{201c}', '\u{201e}', '\u{201c}')),
+ ("bs-Cyrl", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("cs", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("de", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("dsb", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("et", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("hr", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("hsb", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("is", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("lb", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("luy", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("mk", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("sk", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("sl", ('\u{201e}', '\u{201c}', '\u{201a}', '\u{2018}')),
+ ("bs", ('\u{201e}', '\u{201d}', '\u{2018}', '\u{2019}')),
+ ("dua", ('\u{ab}', '\u{bb}', '\u{2018}', '\u{2019}')),
+ ("el-POLYTON", ('\u{ab}', '\u{bb}', '\u{2018}', '\u{2019}')),
+ ("ksf", ('\u{ab}', '\u{bb}', '\u{2018}', '\u{2019}')),
+ ("no", ('\u{ab}', '\u{bb}', '\u{2018}', '\u{2019}')),
+ ("rw", ('\u{ab}', '\u{bb}', '\u{2018}', '\u{2019}')),
+ ("fi", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
+ ("he", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
+ ("lag", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
+ ("rn", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
+ ("sn", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
+ ("sv", ('\u{201d}', '\u{201d}', '\u{2019}', '\u{2019}')),
+ ("fr-CA", ('\u{ab}', '\u{bb}', '\u{201d}', '\u{201c}')),
+ ("fr", ('\u{ab}', '\u{bb}', '\u{ab}', '\u{bb}')),
+ ("hy", ('\u{ab}', '\u{bb}', '\u{ab}', '\u{bb}')),
+ ("yav", ('\u{ab}', '\u{bb}', '\u{ab}', '\u{bb}')),
+ ("hu", ('\u{201e}', '\u{201d}', '\u{bb}', '\u{ab}')),
+ ("ia", ('\u{2018}', '\u{2019}', '\u{201c}', '\u{201d}')),
+ ("nso", ('\u{2018}', '\u{2019}', '\u{201c}', '\u{201d}')),
+ ("ti-ER", ('\u{2018}', '\u{2019}', '\u{201c}', '\u{201d}')),
+ ("tn", ('\u{2018}', '\u{2019}', '\u{201c}', '\u{201d}')),
+ ("ja", ('\u{300c}', '\u{300d}', '\u{300e}', '\u{300f}')),
+ ("yue", ('\u{300c}', '\u{300d}', '\u{300e}', '\u{300f}')),
+ ("zh-Hant", ('\u{300c}', '\u{300d}', '\u{300e}', '\u{300f}')),
+ ("ka", ('\u{201e}', '\u{201c}', '\u{ab}', '\u{bb}')),
+ ("nl", ('\u{2018}', '\u{2019}', '\u{2018}', '\u{2019}')),
+ ("nmg", ('\u{201e}', '\u{201d}', '\u{ab}', '\u{bb}')),
+ ("pl", ('\u{201e}', '\u{201d}', '\u{ab}', '\u{bb}')),
+ ("ro", ('\u{201e}', '\u{201d}', '\u{ab}', '\u{bb}')),
+ ("shi", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201d}')),
+ ("zgh", ('\u{ab}', '\u{bb}', '\u{201e}', '\u{201d}')),
+ ("sr", ('\u{201e}', '\u{201d}', '\u{2019}', '\u{2019}')),
+ ("st", ('\u{201c}', '\u{2019}', '\u{201c}', '\u{201d}')),
+ ("tk", ('\u{201c}', '\u{201d}', '\u{201c}', '\u{201d}')),
+ ("uz", ('\u{201c}', '\u{201d}', '\u{2019}', '\u{2018}')),
+ ]
+ .map(|(lang, chars)| (lang, QuotesData::from(chars)));
+ HashMap::from(input)
+}
+
+fn quotes_data_for_lang(lang: &str) -> QuotesData {
+ // All valid language codes are at least two bytes long.
+ if lang.len() < 2 {
+ return DEFAULT_QUOTES;
+ }
+
+ let quotes_map = QUOTES_MAP.get_or_init(create_quotes_map);
+
+ // Found an exact match for the requested lang.
+ if let Some(quotes_data) = quotes_map.get(lang) {
+ return *quotes_data;
+ }
+
+ // Try parsing lang as a Locale and canonicalizing the subtags, then see if
+ // we can match it with region or script subtags, if present, or just the
+ // primary language tag.
+ let locale = match lang.parse::<Locale>() {
+ Err(_) => return DEFAULT_QUOTES,
+ Ok(locale) => locale,
+ };
+
+ let lang = locale.id.language.to_string();
+
+ if let Some(quotes_data) = quotes_map.get(lang.as_str()) {
+ return *quotes_data;
+ }
+
+ if let Some(quotes_data) = locale
+ .id
+ .region
+ .and_then(|region| quotes_map.get(format!("{lang}-{region}").as_str()))
+ {
+ return *quotes_data;
+ }
+
+ if let Some(quotes_data) = locale
+ .id
+ .script
+ .and_then(|script| quotes_map.get(format!("{lang}-{script}").as_str()))
+ {
+ return *quotes_data;
+ }
+
+ DEFAULT_QUOTES
+}
+
+pub fn quotes_for_lang(lang: &str, depth: usize) -> QuotePair {
+ let quotes_data = quotes_data_for_lang(lang);
+ match depth {
+ 0 => quotes_data.quotes,
+ _ => quotes_data.alternative_quotes,
+ }
+}