Simple rule-based English grapheme→IPA fallback for OOV words.
(&self, word: &str)
| 163 | |
| 164 | /// Simple rule-based English grapheme→IPA fallback for OOV words. |
| 165 | fn rules_fallback(&self, word: &str) -> String { |
| 166 | let mut ipa = String::new(); |
| 167 | let chars: Vec<char> = word.chars().collect(); |
| 168 | let mut i = 0; |
| 169 | |
| 170 | while i < chars.len() { |
| 171 | let remaining = &word[i..]; |
| 172 | // Try digraphs first |
| 173 | let (phoneme, advance) = if remaining.len() >= 2 { |
| 174 | match &remaining[..2] { |
| 175 | "th" => ("\u{03B8}", 2), // θ |
| 176 | "sh" => ("\u{0283}", 2), // ʃ |
| 177 | "ch" => ("t\u{0283}", 2), // tʃ |
| 178 | "ng" => ("\u{014B}", 2), // ŋ |
| 179 | "ph" => ("f", 2), |
| 180 | "wh" => ("w", 2), |
| 181 | "ck" => ("k", 2), |
| 182 | "ee" => ("i\u{02D0}", 2), // iː |
| 183 | "oo" => ("u\u{02D0}", 2), // uː |
| 184 | "ou" => ("a\u{028A}", 2), // aʊ |
| 185 | "ow" => ("a\u{028A}", 2), // aʊ |
| 186 | "ai" => ("e\u{026A}", 2), // eɪ |
| 187 | "ay" => ("e\u{026A}", 2), // eɪ |
| 188 | "ea" => ("i\u{02D0}", 2), // iː |
| 189 | _ => ("", 0), |
| 190 | } |
| 191 | } else { |
| 192 | ("", 0) |
| 193 | }; |
| 194 | |
| 195 | if advance > 0 { |
| 196 | ipa.push_str(phoneme); |
| 197 | i += advance; |
| 198 | continue; |
| 199 | } |
| 200 | |
| 201 | // Single character mapping |
| 202 | let phoneme = match chars[i] { |
| 203 | 'a' => "\u{00E6}", // æ |
| 204 | 'b' => "b", |
| 205 | 'c' => "k", |
| 206 | 'd' => "d", |
| 207 | 'e' => "\u{025B}", // ɛ |
| 208 | 'f' => "f", |
| 209 | 'g' => "g", |
| 210 | 'h' => "h", |
| 211 | 'i' => "\u{026A}", // ɪ |
| 212 | 'j' => "d\u{0292}", // dʒ |
| 213 | 'k' => "k", |
| 214 | 'l' => "l", |
| 215 | 'm' => "m", |
| 216 | 'n' => "n", |
| 217 | 'o' => "\u{0251}", // ɑ |
| 218 | 'p' => "p", |
| 219 | 'q' => "k", |
| 220 | 'r' => "\u{0279}", // ɹ |
| 221 | 's' => "s", |
| 222 | 't' => "t", |
no outgoing calls