Skip to main content

oca_ast/utils/
mod.rs

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    // Normalize language portion to lowercase for lookup.
10    let normalized = code.to_ascii_lowercase();
11
12    // Try ISO 639-1 first
13    if let Some(lang) = Language::from_639_1(&normalized) {
14        return Ok(lang);
15    }
16
17    // Try ISO 639-3
18    if let Some(lang) = Language::from_639_3(&normalized) {
19        return Ok(lang);
20    }
21
22    // Handle language code with country code (e.g., "en_UK" or "en-UK")
23    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}