lib.rs (10814B)
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 file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use icu_locale::{ 6 langid, 7 subtags::{region, variant, Script}, 8 LanguageIdentifier, LocaleExpander, ParseError, 9 }; 10 use nsstring::{nsACString, nsAString}; 11 12 pub fn langid_for_mozilla(name: &nsACString) -> Result<LanguageIdentifier, ParseError> { 13 if name.eq_ignore_ascii_case(b"ja-jp-mac") { 14 Ok(langid!("ja-JP-macos")) 15 } else { 16 // Cut out any `.FOO` like `en-US.POSIX`. 17 let mut name: &[u8] = name.as_ref(); 18 if let Some(ptr) = name.iter().position(|b| b == &b'.') { 19 name = &name[..ptr]; 20 } 21 LanguageIdentifier::try_from_utf8(name) 22 } 23 } 24 25 /// The unicode ellipsis char "…", or "...", depending on the locale. 26 #[no_mangle] 27 pub extern "C" fn locale_service_ellipsis(name: &nsACString, out: &mut nsAString) { 28 match langid_for_mozilla(name) { 29 Ok(langid) if langid.language.as_str() == "ja" => out.assign_str("..."), 30 _ => out.assign_str("…"), 31 } 32 } 33 34 /// If true, accesskeys should always be appended for the locale. 35 #[no_mangle] 36 pub extern "C" fn locale_service_always_append_accesskeys(name: &nsACString) -> bool { 37 match langid_for_mozilla(name) { 38 Ok(langid) => match langid.language.as_str() { 39 "as" | "ja" => true, 40 "zh" if langid.region == Some(region!("TW")) => true, 41 _ => false, 42 }, 43 Err(_) => false, 44 } 45 } 46 47 /// If false, accesskeys should not be separated from the label. 48 #[no_mangle] 49 pub extern "C" fn locale_service_insert_separator_before_accesskeys(name: &nsACString) -> bool { 50 match langid_for_mozilla(name) { 51 Ok(langid) => match langid.language.as_str() { 52 "ja" | "ko" => false, 53 "zh" if langid.region == Some(region!("CN")) => false, 54 _ => true, 55 }, 56 Err(_) => true, 57 } 58 } 59 60 /// A comma-separated list of valid BCP 47 language tags. 61 /// 62 /// The default value is either 63 /// 64 /// $lang, en-US, en 65 /// 66 /// or 67 /// 68 /// $lang-$region, $lang, en-US, en 69 /// 70 /// if the current locale includes a region subtag. 71 /// 72 /// If customizing this, begin with the language tag of your locale. 73 /// Next, include language tags for other languages that you expect most users of your locale to be able to speak, 74 /// so that their browsing experience degrades gracefully if content is not available in their primary language. 75 /// 76 /// By default, "en-US, en" is appended to the end of the list, providing locales of last resort. 77 /// If you know that users of your locale would prefer a different variety of English, 78 /// or if they are not likely to understand English at all, 79 /// you may opt to include a different English language tag, 80 /// or to exclude English altogether. 81 #[no_mangle] 82 pub extern "C" fn locale_service_default_accept_languages(name: &nsACString, out: &mut nsACString) { 83 let mut add_en_us = true; 84 let lang; 85 let fmt; 86 let langs = match langid_for_mozilla(name) { 87 Ok(langid) => { 88 lang = langid.language; 89 match lang.as_str() { 90 "ace" => "ace, id", 91 "ach" => "ach, en-GB", 92 "af" => "af, en-ZA, en-GB", 93 "ak" => "ak, ak-GH", 94 "an" => "an, es-ES, es, ca", 95 "ast" => "ast, es-ES, es", 96 "az" => "az-AZ, az", 97 "bo" => "bo-CN, bo-IN, bo", 98 "br" => "br, fr-FR, fr", 99 "brx" => "brx, as", 100 "bs" => "bs-BA, bs", 101 "ca" if langid.variants.get(0) == Some(&variant!("valencia")) => "ca-valencia, ca", 102 "cak" => "cak, kaq, es", 103 "crh" => "tr-TR, tr", 104 "cs" => "cs, sk", 105 "csb" => "csb, csb-PL, pl", 106 "cy" => "cy-GB, cy", 107 "dsb" => "dsb, hsb, de", 108 "el" => "el-GR, el", 109 "en" => { 110 add_en_us = false; 111 match langid.region { 112 Some(region) => match region.as_str() { 113 "CA" => "en-CA, en-US, en", 114 "GB" => "en-GB, en", 115 "ZA" => "en-ZA, en-GB, en-US, en", 116 _ => "en-US, en", 117 }, 118 _ => "en-US, en", 119 } 120 } 121 "et" => "et, et-EE", 122 "fa" => "fa-IR, fa", 123 "ff" => "ff, fr-FR, fr, en-GB", 124 "fi" => "fi-FI, fi", 125 "fr" => "fr, fr-FR", 126 "frp" => "frp, fr-FR, fr", 127 "fur" => "fur-IT, fur, it-IT, it", 128 "fy" => "fy-NL, fy, nl", 129 "ga" => "ga-IE, ga, en-IE, en-GB", 130 "gd" => "gd-GB, gd, en-GB", 131 "gl" => "gl-ES, gl", 132 "gn" => "gn, es", 133 "gv" => "gv, en-GB", 134 "he" => "he, he-IL", 135 "hr" => "hr, hr-HR", 136 "hsb" => "hsb, dsb, de", 137 "hto" => "es-MX, es-ES, es, es-AR, es-CL", 138 "hu" => "hu-HU, hu", 139 "hye" => "hye, hy", 140 "ilo" => "ilo-PH, ilo", 141 "it" => "it-IT, it", 142 "ixl" => "ixl, es-MX, es", 143 "ja" => "ja", // Also catches ja-JP-mac 144 "ka" => "ka-GE, ka", 145 "kab" => "kab-DZ, kab, fr-FR, fr", 146 "kk" => "kk, ru, ru-RU", 147 "kn" => "kn-IN, kn", 148 "ko" => "ko-KR, ko", 149 "lb" => "lb, de-DE, de", 150 "lg" => "lg, en-GB", 151 "lij" => "lij, it", 152 "lt" => "lt, ru, pl", 153 "ltg" => "ltg, lv", 154 "mai" => "mai, hi-IN, en", 155 "meh" => "meh, es-MX, es", 156 "mix" => "mix, es-MX, es", 157 "mk" => "mk-MK, mk", 158 "ml" => "ml-IN, ml", 159 "mr" => "mr-IN, mr", 160 "my" => { 161 add_en_us = false; 162 "my, en-GB, en" 163 } 164 "nb" => "nb-NO, nb, no-NO, no, nn-NO, nn", 165 "nn" => "nn-NO, nn, no-NO, no, nb-NO, nb", 166 "nr" => "nr-ZA, nr, en-ZA, en-GB", 167 "nso" => "nso-ZA, nso, en-ZA, en-GB", 168 "oc" => "oc, ca, fr, es, it", 169 "pa" => "pa, pa-IN", 170 "ppl" => "ppl, es-MX, es", 171 "rm" => "rm, rm-CH, de-CH, de", 172 "ro" => { 173 add_en_us = false; 174 "ro-RO, ro-GB, en" 175 } 176 "ru" => "ru-RU, ru", 177 "sah" => "sah, ru-RU, ru", 178 "sc" => "sc, it-IT, it", 179 "scn" => "scn, it-IT, it", 180 "sco" => { 181 add_en_us = false; 182 "sco, en-GB, en" 183 } 184 "si" => "si-LK, si", 185 "sk" => "sk, cs", 186 "sl" => { 187 add_en_us = false; 188 "sl, en-GB, en" 189 } 190 "son" => "son, son-ML, fr", 191 "sq" => "sq, sq-AL", 192 "sr" => "sr-RS, sr", 193 "st" => "st-ZA, st, en-ZA, en-GB", 194 "szl" => { 195 add_en_us = false; 196 "szl, pl-PL, pl, en, de" 197 } 198 "ta" => "ta-IN, ta", 199 "te" => "te-IN, te", 200 "tl" => "tl-PH, tl", 201 "tr" => "tr-TR, tr", 202 "trs" => "trs, es-MX, es", 203 "ts" => "ts-ZA, ts, en-ZA, en-GB", 204 "uk" => "uk-UA, uk", 205 "ur" => "ur-PK, ur", 206 "uz" => "uz, ru", 207 "ve" => "ve-ZA, ve, en-ZA, en-GB", 208 "vi" => "vi-VN, vi", 209 "xcl" => "xcl, hy", 210 "xh" => "xh-ZA, xh", 211 "zam" => "zam, es-MX, es", 212 "zh" if langid.region == Some(region!("CN")) => "zh-CN, zh, zh-TW, zh-HK", 213 _ => { 214 if langid.region.is_some() { 215 let region = langid.region.unwrap(); 216 fmt = format!("{lang}-{region}, {lang}"); 217 fmt.as_str() 218 } else { 219 lang.as_str() 220 } 221 } 222 } 223 } 224 Err(_) => { 225 add_en_us = false; 226 "en-US, en" 227 } 228 }; 229 if add_en_us { 230 out.assign(format!("{langs}, en-US, en").as_str()) 231 } else { 232 out.assign(langs) 233 } 234 } 235 236 /// The initial setting of the language drop-down menu 237 /// in the Fonts and Colors > Advanced preference panel. 238 /// 239 /// Takes one of the values of the menuitems in the "selectLangs" menulist in 240 /// https://searchfox.org/firefox-main/source/browser/components/preferences/dialogs/fonts.xhtml 241 #[no_mangle] 242 pub extern "C" fn locale_service_default_font_language_group( 243 name: &nsACString, 244 out: &mut nsACString, 245 ) { 246 const X_WESTERN: &'static str = "x-western"; 247 let font_group = match langid_for_mozilla(name) { 248 Ok(mut langid) => match langid.language.as_str() { 249 "az" | "mai" | "sat" | "vi" => "x-unicode", 250 // These should really have their scripts correctly detected below. 251 "bo" => "x-tibt", 252 "ckb" | "skr" => "ar", 253 "hye" | "xcl" => "x-armn", 254 _ => { 255 LocaleExpander::new_common().maximize(&mut langid); 256 match langid.script.as_ref().map(Script::as_str) { 257 Some("Arab") => "ar", 258 Some("Armn") => "x-armn", 259 Some("Beng") => "x-beng", 260 Some("Cyrl") => "x-cyrillic", 261 Some("Deva") => "x-devanagari", 262 Some("Grek") => "el", 263 Some("Gujr") => "x-gujr", 264 Some("Guru") => "x-guru", 265 Some("Hans") => "zh-CN", 266 Some("Hant") => "zh-TW", 267 Some("Hebr") => "he", 268 Some("Jpan") => "ja", 269 Some("Knda") => "x-knda", 270 Some("Kore") => "ko", 271 Some("Laoo") | Some("Thai") => "th", 272 Some("Mlym") => "x-mlym", 273 Some("Sinh") => "x-sinh", 274 Some("Telu") => "x-telu", 275 Some("Tibt") => "x-tibt", 276 // "Geor" | "Khmr" | "Latn" | "Mymr" | "Taml" => X_WESTERN, 277 _ => X_WESTERN, 278 } 279 } 280 }, 281 Err(_) => X_WESTERN, 282 }; 283 out.assign(font_group) 284 }