Skip to content

Commit 73035de

Browse files
committed
feat(cli): add --check-plurals to view and CLI tests
- Validate plural completeness per locale with exit status - Add tests for missing and complete English plural forms - Validate plural completeness per locale with exit status - Add tests for missing and complete English plural forms - Replace match-based rules with lazy_static BTreeMap keyed by base language - Remove region/script variants unreachable with base-language selection - Keep conservative default to {Other} - Add PluralValidationReport with missing/have sets - Add collect_resource_plural_issues and Codec::collect_plural_issues - Refactor validate_plurals to fold reports into an Error
1 parent c77af4d commit 73035de

2 files changed

Lines changed: 97 additions & 1 deletion

File tree

langcodec-cli/src/main.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ enum Commands {
7474
/// Display full value without truncation (even in terminal)
7575
#[arg(long)]
7676
full: bool,
77+
78+
/// Validate plural completeness against CLDR category sets
79+
#[arg(long, default_value_t = false)]
80+
check_plurals: bool,
7781
},
7882

7983
/// Merge multiple localization files into one output file with automatic format detection and conversion.
@@ -187,7 +191,7 @@ fn main() {
187191
},
188192
);
189193
}
190-
Commands::View { input, lang, full } => {
194+
Commands::View { input, lang, full, check_plurals } => {
191195
// Create validation context
192196
let mut context = ValidationContext::new().with_input_file(input.clone());
193197

@@ -223,6 +227,16 @@ fn main() {
223227
}
224228

225229
print_view(&codec, &lang, full);
230+
231+
if check_plurals {
232+
match codec.validate_plurals() {
233+
Ok(()) => println!("\n✅ Plural validation passed"),
234+
Err(e) => {
235+
eprintln!("\n❌ Plural validation failed: {}", e);
236+
std::process::exit(2);
237+
}
238+
}
239+
}
226240
}
227241
Commands::Merge {
228242
inputs,
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use std::fs;
2+
use std::process::Command;
3+
use tempfile::TempDir;
4+
5+
#[test]
6+
fn test_cli_view_check_plurals_fails_on_missing() {
7+
let temp_dir = TempDir::new().unwrap();
8+
let input_file = temp_dir.path().join("strings.xml");
9+
10+
// English requires 'one' and 'other'; provide only 'other'
11+
let xml = r#"
12+
<resources>
13+
<plurals name="apples" translatable="true">
14+
<item quantity="other">%d apples</item>
15+
</plurals>
16+
</resources>
17+
"#;
18+
fs::write(&input_file, xml).unwrap();
19+
20+
let output = Command::new("cargo")
21+
.args([
22+
"run",
23+
"--quiet",
24+
"--",
25+
"view",
26+
"-i",
27+
input_file.to_str().unwrap(),
28+
"--lang",
29+
"en",
30+
"--check-plurals",
31+
])
32+
.output()
33+
.unwrap();
34+
35+
assert!(
36+
!output.status.success(),
37+
"CLI unexpectedly succeeded: {}",
38+
String::from_utf8_lossy(&output.stdout)
39+
);
40+
let stderr = String::from_utf8_lossy(&output.stderr);
41+
assert!(stderr.contains("Plural validation failed"), "stderr: {}", stderr);
42+
}
43+
44+
#[test]
45+
fn test_cli_view_check_plurals_passes_when_complete() {
46+
let temp_dir = TempDir::new().unwrap();
47+
let input_file = temp_dir.path().join("strings.xml");
48+
49+
// English: provide 'one' and 'other'
50+
let xml = r#"
51+
<resources>
52+
<plurals name="apples" translatable="true">
53+
<item quantity="one">One apple</item>
54+
<item quantity="other">%d apples</item>
55+
</plurals>
56+
</resources>
57+
"#;
58+
fs::write(&input_file, xml).unwrap();
59+
60+
let output = Command::new("cargo")
61+
.args([
62+
"run",
63+
"--quiet",
64+
"--",
65+
"view",
66+
"-i",
67+
input_file.to_str().unwrap(),
68+
"--lang",
69+
"en",
70+
"--check-plurals",
71+
])
72+
.output()
73+
.unwrap();
74+
75+
assert!(
76+
output.status.success(),
77+
"CLI failed: {}",
78+
String::from_utf8_lossy(&output.stderr)
79+
);
80+
let stdout = String::from_utf8_lossy(&output.stdout);
81+
assert!(stdout.contains("✅ Plural validation passed"));
82+
}

0 commit comments

Comments
 (0)