mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-08 19:42:12 +00:00
CP6.13: craft-libs#495 review — tr: Ignore words in UPPERCASE reaches Turkish's own check; a comma after de/da, ne or ya is fine; repeated numbers are no repeated words; table suggestions keep the word's case
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
This commit is contained in:
1 parent
c5daa8d16c
commit
cb5d7310ec
3 files changed
+41
-13
No files matched your search
@@ -128,7 +128,7 @@ const ABBREVIATIONS: &[&str] = &[
|
||||
const CONJUNCTIONS_NO_PRE_COMMA: &[&str] = &["ve", "veya", "yahut", "velev", "veyahut", "de", "da"];
|
||||
|
||||
/// Conjunctions that must not be followed by a comma.
|
||||
const CONJUNCTIONS_NO_POST_COMMA: &[&str] = &["ve", "veya", "yahut", "veyahut", "hem", "ne", "ya", "gerek", "ister", "de", "da"];
|
||||
const CONJUNCTIONS_NO_POST_COMMA: &[&str] = &["ve", "veya", "yahut", "veyahut", "hem", "gerek", "ister"];
|
||||
|
||||
/// Check grammar and punctuation in a Turkish text block.
|
||||
pub fn check(text: &str) -> Vec<Issue> {
|
||||
@@ -154,7 +154,7 @@ pub fn check_with(text: &str, capital_first: bool) -> Vec<Issue> {
|
||||
let only_spaces = gap.chars().all(|c| c == ' ' || c == '\t');
|
||||
let lower1 = w1.to_lowercase();
|
||||
let lower2 = w2.to_lowercase();
|
||||
if only_spaces && lower1 == lower2 && !ALLOWED_REPEATS.contains(&lower1.as_str()) {
|
||||
if only_spaces && w1.chars().all(char::is_alphabetic) && lower1 == lower2 && !ALLOWED_REPEATS.contains(&lower1.as_str()) {
|
||||
v.push(Issue {
|
||||
start: pair[1].0,
|
||||
end: pair[1].1,
|
||||
@@ -395,10 +395,27 @@ mod tests {
|
||||
assert_eq!(issues.len(), 1);
|
||||
assert!(issues[0].message.contains("virgül konulmaz"));
|
||||
|
||||
let text2 = "Bana kalırsa bu mesele de, haklı olan taraf bizdik.";
|
||||
let text2 = "Elma ve, armut.";
|
||||
let issues2 = check(text2);
|
||||
assert_eq!(issues2.len(), 1);
|
||||
assert!(issues2[0].message.contains("'de' bağlacından sonra virgül konulmaz"));
|
||||
assert!(issues2[0].message.contains("'ve' bağlacından sonra virgül konulmaz"));
|
||||
}
|
||||
|
||||
/// `de`/`da`, `ne` and `ya` often take a comma after them in correct Turkish, so no mark
|
||||
/// (craft-libs#488 review).
|
||||
#[test]
|
||||
fn a_comma_after_de_ne_or_ya_is_fine() {
|
||||
for text in ["Ali de, Veli de geldi.", "Ne, sen mi geldin?", "Ya, bilmiyorum.", "Bu mesele de, haklı olan bizdik."] {
|
||||
assert!(check(text).is_empty(), "{text}: {:?}", check(text));
|
||||
}
|
||||
}
|
||||
|
||||
/// Repeated numbers are not repeated words (craft-libs#488 review).
|
||||
#[test]
|
||||
fn repeated_numbers_are_not_flagged() {
|
||||
for text in ["Skor 1 1 bitti.", "Toplam 100 100 değil.", "Oda A1 A1 değil."] {
|
||||
assert!(check(text).is_empty(), "{text}: {:?}", check(text));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -78,12 +78,8 @@ fn check(d: &TrDict, word: &str, opts: &crate::Options) -> bool {
|
||||
}
|
||||
let w = word.trim_matches(|c: char| !c.is_alphanumeric() && c != '\'' && c != '’');
|
||||
let w = w.trim_matches(['\'', '’']);
|
||||
let n = w.chars().count();
|
||||
if n <= 1 || (opts.ignore_numbers && w.chars().any(|c| c.is_ascii_digit())) || !w.chars().any(char::is_alphabetic) {
|
||||
return true;
|
||||
}
|
||||
// Check user dictionary first
|
||||
if crate::in_user_dictionary(&suggest::turkish_to_lower(w)) || crate::in_user_dictionary(&w.to_lowercase()) {
|
||||
// One letter, no letters, digits, capitals (Ignore words in UPPERCASE) or the user dictionary.
|
||||
if crate::accepted_by_options(w, opts) || crate::in_user_dictionary(&suggest::turkish_to_lower(w)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -161,4 +157,15 @@ mod tests {
|
||||
assert!(crate::is_correct_in_with("2026", lang, &check_digits), "numbers alone stay correct");
|
||||
assert!(is_correct("kitapp2"), "direct checks keep the defaults");
|
||||
}
|
||||
|
||||
/// Ignore words in UPPERCASE reaches Turkish's own entry points too, so `NATO` and `TBMM` are
|
||||
/// right by default and checked when the option is off (craft-libs#495 review).
|
||||
#[test]
|
||||
fn turkish_ignores_capitals_unless_told_otherwise() {
|
||||
test_dict::install();
|
||||
let check_caps = crate::Options { ignore_uppercase: false, ..crate::Options::default() };
|
||||
assert!(is_correct("TBMMX") && is_correct_with_options("TBMMX", &crate::Options::default()));
|
||||
assert!(!is_correct_with_options("TBMMX", &check_caps));
|
||||
assert!(is_correct_with_options("KİTAP", &check_caps), "a word in Turkish capitals is still looked up");
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,7 @@ pub fn suggest_with(d: &TrDict, word: &str, max: usize) -> Vec<String> {
|
||||
// 1. Check direct common replacement table
|
||||
for &(wrong, right) in COMMON_REPLACEMENTS {
|
||||
if lower == wrong && seen.insert(right.to_string()) {
|
||||
suggestions.push(right.to_string());
|
||||
suggestions.push(match_casing(word, right));
|
||||
if suggestions.len() >= max {
|
||||
return suggestions;
|
||||
}
|
||||
@@ -270,7 +270,8 @@ pub fn turkish_to_upper(s: &str) -> String {
|
||||
|
||||
/// Match original casing on suggestion.
|
||||
fn match_casing(orig: &str, cand: &str) -> String {
|
||||
if orig.chars().all(char::is_uppercase) {
|
||||
let mut letters = orig.chars().filter(|c| c.is_alphabetic()).peekable();
|
||||
if letters.peek().is_some() && letters.all(char::is_uppercase) {
|
||||
turkish_to_upper(cand)
|
||||
} else if orig.chars().next().is_some_and(char::is_uppercase) {
|
||||
super::grammar::turkish_capitalize(cand)
|
||||
@@ -329,7 +330,10 @@ mod tests {
|
||||
fn two_words_get_only_the_tables_replacement() {
|
||||
let d = TrDict::from_hunspell("SET UTF-8\n", "2\nbirkaç\nsonra\n").unwrap();
|
||||
assert_eq!(suggest_with(&d, "bir kaç", 3), vec!["birkaç".to_string()]);
|
||||
assert_eq!(suggest_with(&d, "Bir kaç", 3), vec!["birkaç".to_string()]);
|
||||
// craft-libs#487 review: the table keeps the word's case.
|
||||
assert_eq!(suggest_with(&d, "Bir kaç", 3), vec!["Birkaç".to_string()]);
|
||||
assert_eq!(suggest_with(&d, "BİR KAÇ", 3), vec!["BİRKAÇ".to_string()]);
|
||||
assert_eq!(suggest_with(&d, "Herşey", 3), vec!["Her şey".to_string()]);
|
||||
assert!(suggest_with(&d, "sorna sorna", 3).is_empty());
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user