lgtm
This commit is contained in:
parent
084117cea8
commit
a8de0a614d
36 changed files with 1329 additions and 522 deletions
101
server-rs/src/language.rs
Normal file
101
server-rs/src/language.rs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
pub const DEFAULT_LANGUAGE: &str = "en";
|
||||
|
||||
const SUPPORTED_LANGUAGES: &[&str] = &["en", "fr", "de", "zh", "hi", "hu"];
|
||||
|
||||
pub fn supported_language(value: &str) -> Option<&'static str> {
|
||||
let value = value.trim().to_ascii_lowercase();
|
||||
if value.is_empty() || value == "*" {
|
||||
return None;
|
||||
}
|
||||
|
||||
let primary = value.split('-').next().unwrap_or("");
|
||||
SUPPORTED_LANGUAGES
|
||||
.iter()
|
||||
.copied()
|
||||
.find(|language| value == *language || primary == *language)
|
||||
}
|
||||
|
||||
pub fn language_from_accept_language(header: Option<&str>) -> &'static str {
|
||||
let Some(header) = header else {
|
||||
return DEFAULT_LANGUAGE;
|
||||
};
|
||||
|
||||
let mut best_language = None;
|
||||
let mut best_quality = 0.0f32;
|
||||
|
||||
for item in header.split(',') {
|
||||
let mut parts = item.split(';');
|
||||
let tag = parts.next().unwrap_or("").trim();
|
||||
let mut quality = 1.0f32;
|
||||
|
||||
for param in parts {
|
||||
let param = param.trim();
|
||||
if let Some(value) = param.strip_prefix("q=") {
|
||||
quality = value.parse::<f32>().unwrap_or(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
if quality <= 0.0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(language) = supported_language(tag) {
|
||||
if quality > best_quality {
|
||||
best_language = Some(language);
|
||||
best_quality = quality;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
best_language.unwrap_or(DEFAULT_LANGUAGE)
|
||||
}
|
||||
|
||||
pub fn query_string_with_language(query_string: &str, language: &str) -> String {
|
||||
if url::form_urlencoded::parse(query_string.as_bytes()).any(|(key, _)| key == "lang") {
|
||||
return query_string.to_string();
|
||||
}
|
||||
|
||||
if query_string.is_empty() {
|
||||
format!("lang={language}")
|
||||
} else {
|
||||
format!("{query_string}&lang={language}")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn maps_browser_language_tags_to_supported_languages() {
|
||||
assert_eq!(supported_language("fr-CA"), Some("fr"));
|
||||
assert_eq!(supported_language("zh-Hans-CN"), Some("zh"));
|
||||
assert_eq!(supported_language("es"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chooses_highest_quality_supported_language() {
|
||||
assert_eq!(
|
||||
language_from_accept_language(Some("en-US;q=0.6, fr-FR;q=0.9, de;q=0.7")),
|
||||
"fr"
|
||||
);
|
||||
assert_eq!(
|
||||
language_from_accept_language(Some("es-ES, hi-IN;q=0.8")),
|
||||
"hi"
|
||||
);
|
||||
assert_eq!(language_from_accept_language(Some("es-ES")), "en");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn appends_language_without_overriding_explicit_query_language() {
|
||||
assert_eq!(query_string_with_language("", "de"), "lang=de");
|
||||
assert_eq!(
|
||||
query_string_with_language("lat=51.5&lon=-0.1", "de"),
|
||||
"lat=51.5&lon=-0.1&lang=de"
|
||||
);
|
||||
assert_eq!(
|
||||
query_string_with_language("lang=fr&lat=1", "de"),
|
||||
"lang=fr&lat=1"
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue