mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 15:25:16 +00:00
i18n: term checks match whole words and the Info row's Tracking label
The Leading check now matches each word of the Leading field as a whole
word in languages that separate words with spaces, so a longer word such
as "liderlik" no longer stands in for "lider". Chinese, Japanese and
other unspaced scripts keep substring matching.
The Info row check now looks for the whole Tracking name in the label in
front of {tracking}, after taking out a Kerning or Leading name that
contains it. A word of the name found in the Size label, or a Kerning
label that contains the Tracking name, no longer passes.
The Czech Auto Leading row uses the singular "proklad", as the Leading
field does.
This commit is contained in:
@@ -5657,7 +5657,7 @@ mark-style Japanese Japonské
|
||||
Word Spacing: Mezery mezi slovy:
|
||||
Letter Spacing: Mezery mezi písmeny:
|
||||
Glyph Scaling: Změna velikosti glyfů:
|
||||
Auto Leading: Automatické proklady:
|
||||
Auto Leading: Automatický proklad:
|
||||
Single Word Justification: Zarovnání jednoho slova:
|
||||
Full Justify Zarovnat do bloku
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Minimum nesmí překročit požadovanou hodnotu ani požadovaná hodnota maximum.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -524,9 +524,36 @@ fn zh_hans_is_simplified_and_mainland() {
|
||||
assert!(bad.is_empty(), "in zh-hans.tsv:\n{}", bad.join("\n"));
|
||||
}
|
||||
|
||||
/// Whether `text` holds `term`. In a script that separates words with spaces the term must stand as
|
||||
/// whole words, so "liderlik" does not hold "lider"; in Chinese, Japanese, Thai, Lao, Khmer and
|
||||
/// Myanmar text any occurrence counts.
|
||||
fn contains_term(text: &str, term: &str) -> bool {
|
||||
let unspaced = |c: char| matches!(c as u32, 0x0E00..=0x0EFF | 0x1000..=0x109F | 0x1780..=0x17FF | 0x3040..=0x30FF | 0x3400..=0x4DBF | 0x4E00..=0x9FFF | 0xF900..=0xFAFF);
|
||||
if term.chars().any(unspaced) {
|
||||
return text.contains(term);
|
||||
}
|
||||
text.match_indices(term).any(|(at, m)| {
|
||||
!text[..at].chars().next_back().is_some_and(char::is_alphanumeric) && !text[at + m.len()..].chars().next().is_some_and(char::is_alphanumeric)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_term_matches_whole_words_where_words_are_spaced() {
|
||||
assert!(contains_term("tepeden tepeye lider", "lider"));
|
||||
assert!(contains_term("boyut/lider:", "lider"));
|
||||
assert!(contains_term("réinitialiser l’approche", "approche"));
|
||||
assert!(!contains_term("tepeden tepeye liderlik", "lider"));
|
||||
assert!(!contains_term("automatické proklady:", "proklad"));
|
||||
assert!(contains_term("kích thước: giãn chữ:", "giãn chữ"));
|
||||
assert!(!contains_term("kích thước chữ: giãn:", "giãn chữ"));
|
||||
assert!(contains_term("自動行送り:", "行送り"));
|
||||
assert!(contains_term("大小:字距微調:", "字距"));
|
||||
}
|
||||
|
||||
/// Each catalog names leading with one term: every word of the Character panel's Leading field
|
||||
/// (the text before " (", ignoring case) appears in the Auto Leading, Size/Leading, Top-to-Top
|
||||
/// Leading and Bottom-to-Bottom Leading rows outside their placeholders.
|
||||
/// (the text before " (", ignoring case) appears as a whole word (see [`contains_term`]) in the
|
||||
/// Auto Leading, Size/Leading, Top-to-Top Leading and Bottom-to-Bottom Leading rows outside their
|
||||
/// placeholders.
|
||||
/// A catalog without the Leading row, or without one of the others, is skipped for that check.
|
||||
#[test]
|
||||
fn leading_term_agrees_within_each_catalog() {
|
||||
@@ -540,7 +567,7 @@ fn leading_term_agrees_within_each_catalog() {
|
||||
for src in ["Auto Leading:", "Size/Leading", "Top-to-Top Leading", "Bottom-to-Bottom Leading"] {
|
||||
if let Some(text) = row(src) {
|
||||
let bare = placeholders(&text).iter().fold(text.clone(), |t, p| t.replace(&format!("{{{p}}}"), " "));
|
||||
for word in leading.split_whitespace().filter(|w| !bare.contains(*w)) {
|
||||
for word in leading.split_whitespace().filter(|w| !contains_term(&bare, w)) {
|
||||
bad.push(format!("{}: {src:?} → {text:?} lacks {word:?} from the Leading field {leading:?}", l.code));
|
||||
}
|
||||
}
|
||||
@@ -576,10 +603,12 @@ fn no_translated_word_mixes_latin_cyrillic_and_greek_letters() {
|
||||
}
|
||||
|
||||
/// Each catalog gives the Character panel's Kerning, Leading and Tracking fields three different
|
||||
/// names, every word of the Tracking and Kerning names appears in the Reset Tracking and Kerning
|
||||
/// row, and every word of the Tracking name appears in the Info panel's type line outside its
|
||||
/// placeholders (ignoring case). Each word is matched once, the longer name first, so a name
|
||||
/// that contains the other name does not count for both.
|
||||
/// names, and every word of the Tracking and Kerning names appears in the Reset Tracking and
|
||||
/// Kerning row (ignoring case). Each word is matched once, the longer name first, so a name that
|
||||
/// contains the other name does not count for both. The Info panel's type line labels
|
||||
/// `{tracking}` with the whole Tracking name: the text between the placeholder before it and
|
||||
/// `{tracking}` holds the name (see [`contains_term`]) once any Kerning or Leading name that
|
||||
/// contains it has been taken out.
|
||||
/// A catalog without one of these rows is skipped for the checks that need it.
|
||||
#[test]
|
||||
fn character_panel_terms_agree_within_each_catalog() {
|
||||
@@ -613,7 +642,16 @@ fn character_panel_terms_agree_within_each_catalog() {
|
||||
}
|
||||
};
|
||||
uses("Reset Tracking and Kerning", &[&tracking, &kerning]);
|
||||
uses("Size: {size} Tracking: {tracking}", &[&tracking]);
|
||||
if let (Some(text), Some(tracking)) = (row("Size: {size} Tracking: {tracking}"), &tracking) {
|
||||
let before = text.split("{tracking}").next().unwrap_or_default();
|
||||
let mut label = before.rsplit('}').next().unwrap_or_default().to_string();
|
||||
for other in [&kerning, &leading].into_iter().flatten().filter(|o| *o != tracking && o.contains(tracking.as_str())) {
|
||||
label = label.replace(other.as_str(), " ");
|
||||
}
|
||||
if !contains_term(&label, tracking) {
|
||||
bad.push(format!("{}: the Info row {text:?} labels {{tracking}} {label:?}, not the field {tracking:?}", l.code));
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(bad.is_empty(), "Character panel terms that disagree:\n{}", bad.join("\n"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user