use crate::phonetic::llev::RuleSetChar;
use std::sync::OnceLock;
pub fn base() -> &'static RuleSetChar {
static RULESET: OnceLock<RuleSetChar> = OnceLock::new();
RULESET.get_or_init(|| {
let content = include_str!("../../../data/rules/dutch/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded dutch/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Dutch base rules - this is a bug in liblevenshtein")
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_base_loads() {
let rules = base();
assert!(!rules.is_empty(), "Dutch base rules should not be empty");
assert!(
rules.len() > 40,
"expected >40 base rules, got {}",
rules.len()
);
}
#[test]
fn test_ij_digraph() {
let rules = base();
let result = rules.apply("wijn");
assert!(result.contains('ɛ'), "ij should become ɛi, got: {}", result);
}
#[test]
fn test_ij_uppercase() {
let rules = base();
let result = rules.apply("IJsberg");
assert!(
result.starts_with('ɛ'),
"IJ should become ɛi, got: {}",
result
);
}
#[test]
fn test_g_guttural() {
let rules = base();
let result = rules.apply("goed");
assert!(
result.starts_with('x'),
"g should become x (guttural), got: {}",
result
);
}
#[test]
fn test_ch_guttural() {
let rules = base();
let result = rules.apply("acht");
assert!(
result.contains('x'),
"ch should become x (guttural), got: {}",
result
);
}
#[test]
fn test_sch_pattern() {
let rules = base();
let result = rules.apply("school");
assert!(
result.starts_with("sx"),
"sch should become sx (not sh like German), got: {}",
result
);
}
#[test]
fn test_oe_vowel() {
let rules = base();
let result = rules.apply("boek");
assert!(result.contains('u'), "oe should become u, got: {}", result);
}
#[test]
fn test_eu_vowel() {
let rules = base();
let result = rules.apply("neus");
assert!(result.contains('ø'), "eu should become ø, got: {}", result);
}
#[test]
fn test_ui_diphthong() {
let rules = base();
let result = rules.apply("huis");
assert!(result.contains('œ'), "ui should become œy, got: {}", result);
}
#[test]
fn test_w_pronunciation() {
let rules = base();
let result = rules.apply("water");
assert!(
result.starts_with('ʋ'),
"w should become ʋ, got: {}",
result
);
}
#[test]
fn test_final_devoicing_d() {
let rules = base();
let result = rules.apply("hond");
assert!(
result.ends_with('t'),
"final d should become t, got: {}",
result
);
}
#[test]
fn test_final_devoicing_b() {
let rules = base();
let result = rules.apply("web");
assert!(
result.ends_with('p'),
"final b should become p, got: {}",
result
);
}
#[test]
fn test_long_vowel_aa() {
let rules = base();
let result = rules.apply("naam");
assert!(
!result.contains("aa"),
"aa should become a, got: {}",
result
);
}
#[test]
fn test_long_vowel_ee() {
let rules = base();
let result = rules.apply("been");
assert!(
!result.contains("ee"),
"ee should become e, got: {}",
result
);
}
#[test]
fn test_long_vowel_oo() {
let rules = base();
let result = rules.apply("boom");
assert!(
!result.contains("oo"),
"oo should become o, got: {}",
result
);
}
#[test]
fn test_ei_diphthong() {
let rules = base();
let result = rules.apply("klein");
assert!(result.contains('ɛ'), "ei should become ɛi, got: {}", result);
}
#[test]
fn test_au_diphthong() {
let rules = base();
let result = rules.apply("blauw");
assert!(result.contains('ɔ'), "au should become ɔu, got: {}", result);
}
#[test]
fn test_ou_diphthong() {
let rules = base();
let result = rules.apply("oud");
assert!(result.contains('ɔ'), "ou should become ɔu, got: {}", result);
}
#[test]
fn test_ie_vowel() {
let rules = base();
let result = rules.apply("niet");
assert!(
!result.contains("ie"),
"ie should become i, got: {}",
result
);
}
#[test]
fn test_double_consonants() {
let rules = base();
let result = rules.apply("koffie");
assert!(
!result.contains("ff"),
"ff should become f, got: {}",
result
);
}
}