Skip to content

Commit df29a4b

Browse files
authored
Merge pull request #10 from WendellXY/codex/view-status-filter
Add status-based filtering to view
2 parents f0443b9 + 560345f commit df29a4b

7 files changed

Lines changed: 1127 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on Keep a Changelog and this project follows Semantic Versioning while APIs remain in 0.x evolution.
66

7+
## [Unreleased]
8+
9+
### Added
10+
- CLI `view` status-based filtering with `--status`, `--keys-only`, and `--json` output modes for listing untranslated/review-needed entries.
11+
12+
### Changed
13+
- `view --status` now supports strict metadata gating: `langcodec --strict view ... --status ...` requires explicit status metadata (v1 support: `.xcstrings`).
14+
715
## [0.7.0] - 2026-02-17
816

917
### Added

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ This is a `0.7.0` release available on [crates.io](https://crates.io/crates/lang
6262
- Normalize and detect drift: `langcodec normalize -i 'locales/**/*.{strings,xml,csv,tsv,xcstrings}' --check`
6363
- Sync existing keys only: `langcodec sync --source A.xcstrings --target B.xcstrings --match-lang en`
6464
- View: `langcodec view -i strings.xml --full`
65+
- View filtered untranslated/review-needed keys: `langcodec view -i Localizable.xcstrings --status new,needs_review --keys-only`
66+
- View filtered results as JSON: `langcodec view -i Localizable.xcstrings --status new --lang fr --json`
6567
- Stats (JSON): `langcodec stats -i Localizable.xcstrings --json`
6668
- See full options: langcodec-cli/README.md#stats
6769
- Example output:
@@ -99,6 +101,7 @@ This is a `0.7.0` release available on [crates.io](https://crates.io/crates/lang
99101
- Normalize `--continue-on-error` processes all inputs and returns non-zero if any file fails.
100102
- Android path inference: `values/strings.xml` (no qualifier) defaults to English (`en`).
101103
- When converting to `.xcstrings`, if `source_language` or `version` metadata is missing, the CLI defaults them to `en` and `1.0` respectively (overridable via flags).
104+
- Strict status filtering note: `langcodec --strict view --status ...` requires explicit status metadata (supported in v1: `.xcstrings`).
102105

103106
#### Plurals
104107

langcodec-cli/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,21 @@ CI-oriented options:
6363

6464
```sh
6565
langcodec view -i values/strings.xml --full
66+
langcodec view -i Localizable.xcstrings --status new,needs_review
67+
langcodec view -i Localizable.xcstrings --status new --lang fr --json
68+
langcodec view -i Localizable.xcstrings --status new,needs_review --keys-only
6669
```
6770

6871
Prints entries. Plurals are labeled with `Type: Plural` and show categories.
6972

73+
View options:
74+
75+
- `--status`: Filter by one or more statuses (`translated|needs_review|new|do_not_translate|stale`), comma-separated.
76+
- `--keys-only`: Print only keys in text mode (`lang<TAB>key` when `--lang` is not set).
77+
- `--json`: Output machine-readable JSON (`summary` + `entries` or `keys` payload).
78+
- `--lang`: Restrict results to a specific language before status filtering.
79+
- `--strict`: With `--status`, requires explicit status metadata (supported in v1: `.xcstrings`).
80+
7081
### stats
7182

7283
```sh

langcodec-cli/src/main.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::merge::{ConflictStrategy, run_merge_command};
2020
use crate::normalize::{NormalizeCliOptions, run_normalize_command};
2121
use crate::sync::{SyncOptions, run_sync_command};
2222
use crate::validation::{ValidationContext, validate_context, validate_language_code};
23-
use crate::view::print_view;
23+
use crate::view::{ViewOptions, print_view, validate_status_filter};
2424
use clap::{CommandFactory, Parser, Subcommand};
2525
use clap_complete::{Shell, generate};
2626

@@ -167,6 +167,18 @@ enum Commands {
167167
#[arg(long)]
168168
full: bool,
169169

170+
/// Filter entries by status (e.g. translated, needs_review, stale, new, do_not_translate)
171+
#[arg(long)]
172+
status: Option<String>,
173+
174+
/// Print keys only
175+
#[arg(long, default_value_t = false)]
176+
keys_only: bool,
177+
178+
/// Output JSON instead of human-readable text
179+
#[arg(long, default_value_t = false)]
180+
json: bool,
181+
170182
/// Validate plural completeness against CLDR category sets
171183
#[arg(long, default_value_t = false)]
172184
check_plurals: bool,
@@ -323,6 +335,13 @@ fn is_custom_input_extension(input: &str) -> bool {
323335
|| input.ends_with(".langcodec")
324336
}
325337

338+
fn input_supports_explicit_status_metadata(input: &str) -> bool {
339+
std::path::Path::new(input)
340+
.extension()
341+
.and_then(|ext| ext.to_str())
342+
.is_some_and(|ext| ext.eq_ignore_ascii_case("xcstrings"))
343+
}
344+
326345
fn load_codec_for_readonly_command(
327346
input: &str,
328347
lang: &Option<String>,
@@ -515,6 +534,9 @@ fn main() {
515534
input,
516535
lang,
517536
full,
537+
status,
538+
keys_only,
539+
json,
518540
check_plurals,
519541
} => {
520542
// Create validation context
@@ -530,6 +552,18 @@ fn main() {
530552
std::process::exit(1);
531553
}
532554

555+
if let Err(e) = validate_status_filter(&status) {
556+
eprintln!("❌ {}", e);
557+
std::process::exit(1);
558+
}
559+
560+
if strict && status.is_some() && !input_supports_explicit_status_metadata(&input) {
561+
eprintln!(
562+
"❌ Strict mode with --status requires explicit status metadata. Supported in v1: .xcstrings"
563+
);
564+
std::process::exit(1);
565+
}
566+
533567
let codec = match load_codec_for_readonly_command(&input, &lang, strict) {
534568
Ok(codec) => codec,
535569
Err(e) => {
@@ -538,11 +572,24 @@ fn main() {
538572
}
539573
};
540574

541-
print_view(&codec, &lang, full);
575+
let view_options = ViewOptions {
576+
full,
577+
status,
578+
keys_only,
579+
json,
580+
};
581+
582+
print_view(&codec, &lang, &view_options);
542583

543584
if check_plurals {
544585
match codec.validate_plurals() {
545-
Ok(()) => println!("\n✅ Plural validation passed"),
586+
Ok(()) => {
587+
if json || keys_only {
588+
eprintln!("✅ Plural validation passed");
589+
} else {
590+
println!("\n✅ Plural validation passed");
591+
}
592+
}
546593
Err(e) => {
547594
eprintln!("\n❌ Plural validation failed: {}", e);
548595
std::process::exit(2);

0 commit comments

Comments
 (0)