/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
usesuper::language_info::LanguageInfo; usesuper::zip::{read_archive_file_as_string, read_zip, Archive}; usecrate::config::installation_resource_path; usecrate::prefs_parser::find_string_pref; usecrate::std::path::{Path, PathBuf}; use anyhow::Context;
/// Select the langpack to use based on profile settings, the useragent locale, and the existence /// of langpack files. /// Returns `Ok(None)` if no locales are found in pref and from useragent locale. Also return /// `Ok(None)` if the locale specified is the base installation locale, as there is no langpack for /// the base installation locale. fn select_langpack(
profile_dir: &Path,
base_locales: &[String],
useragent_locale: Option<&str>,
) -> anyhow::Result<Option<(String, PathBuf)>> { letmut locales = locales_from_prefs(profile_dir)?
.into_iter()
.flatten()
.chain(useragent_locale.map(str::to_string));
if locales.clone().count() == 0 { return Ok(None);
}
// Use the first language that is either the base locale or we can find a langpack extension for
locales
.find_map(|lang| { if base_locales.contains(&lang) {
Some(None)
} else {
find_langpack_extension(profile_dir, &lang).map(|path| Some((lang, path)))
}
})
.with_context(|| format!("couldn't locate langpack for requested locales ({locales:?})"))
}
fn locales_from_prefs(profile_dir: &Path) -> anyhow::Result<Option<Vec<String>>> { let prefs = profile_dir.join("prefs.js"); if !prefs.exists() {
log::debug!( "no prefs.js exists in {}; not reading localization info",
profile_dir.display()
); return Ok(None);
}
let prefs_contents = std::fs::read_to_string(&prefs)
.with_context(|| format!("while reading {}", prefs.display()))?;
let Some(langs) = parse_requested_locales(&prefs_contents) else { // If the pref is unset, the installation locale should be used.
log::debug!( "no locale pref set in {}; using installation locale",
prefs.display()
); return Ok(None);
};
Ok(Some(if langs.is_empty() { // If the pref is an empty string, use the OS locale settings. let os_locales: Vec<String> = sys_locale::get_locales().collect(); if os_locales.is_empty() {
log::debug!("no OS locales found"); return Ok(None);
}
log::debug!( "locale pref blank in {}; using OS locale settings ({os_locales:?})",
prefs.display()
);
os_locales
} else {
langs.into_iter().map(|s| s.to_owned()).collect()
}))
}
/// Parse the language pref (if any) from the prefs file. /// /// For example: /// ```rust /// let input = r#"user_pref("intl.locale.requested", "foo , bar,,");"#; /// let expected_output = Some(vec!["foo","bar"]); /// assert_eq!(parse_requested_locales(input), output); /// ``` /// /// This will parse the locales out of the user prefs file contents, which looks like /// `user_pref("intl.locale.requested", "<LOCALE LIST>")`. fn parse_requested_locales(prefs_content: &str) -> Option<Vec<&str>> { let v = find_string_pref(prefs_content, LOCALE_PREF_KEY)?;
Some(
v.split(",")
.map(|s| s.trim())
.filter(|s| !s.is_empty())
.collect(),
)
}
/// Find the langpack extension for the given locale. fn find_langpack_extension(profile_dir: &Path, locale: &str) -> Option<PathBuf> { let path_tail = format!("extensions/langpack-{locale}@firefox.mozilla.org.xpi");
// Check profile extensions let profile_path = profile_dir.join(&path_tail); if profile_path.exists() { return Some(profile_path);
}
// Check installation extensions let install_path = installation_resource_path().join(format!("browser/{}", &path_tail)); if install_path.exists() { return Some(install_path);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.