@@ -0,0 +1,81 @@
|
||||
//! Language-code normalization — ISO 639 alias folding, **not** filename
|
||||
//! parsing.
|
||||
//!
|
||||
//! This lives apart from [`crate::filename_meta`] on purpose: it doesn't read a
|
||||
//! release title, it canonicalizes a *language code* (an indexer's declared
|
||||
//! language, a query's `languages:` filter, a title-derived stamp) onto the
|
||||
//! single ISO 639-2/B alpha-3 vocabulary the rest of the stack compares against.
|
||||
//! It is the one piece of the old `filename_meta` module that has no equivalent
|
||||
//! in the `metamesh-plugin-filename-parser` plugin — because it isn't filename
|
||||
//! parsing — so it stays in Rust while the title-parsing algorithm itself is
|
||||
//! owned by the plugin. Callers in the **request hot path** (e.g. the torznab
|
||||
//! indexer-language fan-out skip) need it synchronously, with no network hop.
|
||||
|
||||
/// Normalize a language code to the ISO 639-2/B alpha-3 vocabulary the stack
|
||||
/// emits (`fre`/`ger`/`chi`, **not** the 639-2/T `fra`/`deu`/`zho` nor the
|
||||
/// 639-1 two-letter forms), lowercased. This is the space meta-share's
|
||||
/// "languages I read" preference uses and that the title-derived language stamps
|
||||
/// write, so an operator who declares an indexer's language as `fra`/`de`/`zh`
|
||||
/// still lines up with a `fre`/`ger`/`chi` query filter. Unknown /
|
||||
/// already-canonical codes pass through lowercased+trimmed unchanged.
|
||||
pub fn normalize_lang_code(code: &str) -> String {
|
||||
let c = code.trim().to_ascii_lowercase();
|
||||
let mapped = match c.as_str() {
|
||||
// 639-2/T and 639-1 → 639-2/B for the codes that actually differ.
|
||||
"fra" | "fr" => "fre",
|
||||
"deu" | "de" => "ger",
|
||||
"zho" | "zh" => "chi",
|
||||
"nld" | "nl" => "dut",
|
||||
"ell" | "el" => "gre",
|
||||
"ron" | "ro" => "rum",
|
||||
"slk" | "sk" => "slo",
|
||||
"ces" | "cs" => "cze",
|
||||
// 639-1 → 639-2 for the rest of the language-tag output space (these
|
||||
// share the same /B and /T alpha-3, so only the two-letter form maps).
|
||||
"en" => "eng",
|
||||
"ja" => "jpn",
|
||||
"it" => "ita",
|
||||
"es" => "spa",
|
||||
"pt" => "por",
|
||||
"ko" => "kor",
|
||||
"ru" => "rus",
|
||||
"pl" => "pol",
|
||||
"hu" => "hun",
|
||||
"uk" => "ukr",
|
||||
"bg" => "bul",
|
||||
"sv" => "swe",
|
||||
"no" => "nor",
|
||||
"da" => "dan",
|
||||
"fi" => "fin",
|
||||
"tr" => "tur",
|
||||
"ar" => "ara",
|
||||
"hi" => "hin",
|
||||
"ta" => "tam",
|
||||
"te" => "tel",
|
||||
"ml" => "mal",
|
||||
"vi" => "vie",
|
||||
"th" => "tha",
|
||||
_ => return c,
|
||||
};
|
||||
mapped.to_string()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn normalize_lang_maps_to_639_2b_vocabulary() {
|
||||
// 639-2/T and 639-1 spellings collapse onto the /B forms the stack uses.
|
||||
assert_eq!(normalize_lang_code("fra"), "fre");
|
||||
assert_eq!(normalize_lang_code("FR"), "fre");
|
||||
assert_eq!(normalize_lang_code("deu"), "ger");
|
||||
assert_eq!(normalize_lang_code("zh"), "chi");
|
||||
assert_eq!(normalize_lang_code("nld"), "dut");
|
||||
// Already-canonical / unknown codes pass through trimmed + lowercased.
|
||||
assert_eq!(normalize_lang_code(" ENG "), "eng");
|
||||
assert_eq!(normalize_lang_code("fre"), "fre");
|
||||
assert_eq!(normalize_lang_code("mul"), "mul");
|
||||
assert_eq!(normalize_lang_code("xyz"), "xyz");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user