1use isolang::Language;
2
3pub fn parse_language_code(code: &str) -> Result<Language, String> {
4 let code = code.trim();
5 if code.is_empty() {
6 return Err("Invalid language code: empty".to_string());
7 }
8
9 let normalized = code.to_ascii_lowercase();
11
12 if let Some(lang) = Language::from_639_1(&normalized) {
14 return Ok(lang);
15 }
16
17 if let Some(lang) = Language::from_639_3(&normalized) {
19 return Ok(lang);
20 }
21
22 let separator = if normalized.contains('_') { '_' } else { '-' };
24 if let Some((lang_code, _country_code)) = normalized.split_once(separator)
25 && let Some(lang) = Language::from_639_1(lang_code)
26 {
27 return Ok(lang);
28 }
29
30 Err(format!("Invalid language code: {}", code))
31}
32
33pub fn is_valid_language_code(code: &str) -> bool {
34 parse_language_code(code).is_ok()
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40
41 #[test]
42 fn test_parse_iso_639_1() {
43 assert!(parse_language_code("en").is_ok());
44 assert!(parse_language_code("pl").is_ok());
45 }
46
47 #[test]
48 fn test_parse_iso_639_3() {
49 assert!(parse_language_code("eng").is_ok());
50 assert!(parse_language_code("pol").is_ok());
51 }
52
53 #[test]
54 fn test_parse_with_country_code() {
55 assert!(parse_language_code("en_US").is_ok());
56 assert!(parse_language_code("en-UK").is_ok());
57 assert!(parse_language_code("pl_PL").is_ok());
58 }
59
60 #[test]
61 fn test_invalid_code() {
62 assert!(parse_language_code("invalid").is_err());
63 assert!(parse_language_code("xx_YY").is_err());
64 }
65}