|
| 1 | +# AGENTS.md — Automation and Navigation Guide |
| 2 | + |
| 3 | +This document helps automation agents quickly understand, build, test, and operate this repository. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +- **Library crate**: `langcodec/` — universal localization toolkit (parse/convert Apple `.strings`, `.xcstrings`, Android `strings.xml`, CSV, TSV) |
| 8 | +- **CLI crate**: `langcodec-cli/` — end-user command-line tool built on the library |
| 9 | +- **Binary name**: `langcodec` |
| 10 | + |
| 11 | +## Repository layout (key paths) |
| 12 | + |
| 13 | +- `langcodec/src/lib.rs`: library entry; re-exports `Codec`, `convert_auto`, `FormatType`, `types::*` |
| 14 | +- `langcodec/src/formats/`: parsers/writers for `strings`, `xcstrings`, `android_strings`, `csv`, `tsv` |
| 15 | +- `langcodec/src/traits.rs`: `Parser` trait for format-agnostic IO |
| 16 | +- `langcodec-cli/src/main.rs`: CLI entry with subcommands |
| 17 | +- `langcodec-cli/src/transformers/`: one-way converters for custom JSON/YAML formats |
| 18 | +- `langcodec-cli/tests/` and `langcodec-cli/tests/fixtures/`: integration tests and sample inputs |
| 19 | + |
| 20 | +## Prerequisites |
| 21 | + |
| 22 | +- Rust toolchain with Edition 2024 support (install via rustup) |
| 23 | +- macOS/Linux shell environment for examples below |
| 24 | + |
| 25 | +Optional tooling for contributors: |
| 26 | + |
| 27 | +- `cargo fmt`, `cargo clippy` |
| 28 | + |
| 29 | +## Absolute path convention in this guide |
| 30 | + |
| 31 | +Replace `<repo>` with the absolute path to the repository root. Example: |
| 32 | + |
| 33 | +```bash |
| 34 | +REPO="/Users/wendell/Developer/langcodec" |
| 35 | +``` |
| 36 | + |
| 37 | +When running commands non-interactively, prefer absolute paths like `"$REPO/target/release/langcodec"` and explicit input/output file paths. |
| 38 | + |
| 39 | +## Build |
| 40 | + |
| 41 | +```bash |
| 42 | +cd "$REPO" |
| 43 | +cargo build --release -p langcodec-cli |
| 44 | +``` |
| 45 | + |
| 46 | +- Output binary: `"$REPO/target/release/langcodec"` |
| 47 | + |
| 48 | +Build just the library: |
| 49 | + |
| 50 | +```bash |
| 51 | +cargo build --release -p langcodec |
| 52 | +``` |
| 53 | + |
| 54 | +## Test |
| 55 | + |
| 56 | +```bash |
| 57 | +cd "$REPO" |
| 58 | +cargo test --all |
| 59 | +``` |
| 60 | + |
| 61 | +Run only CLI tests: |
| 62 | + |
| 63 | +```bash |
| 64 | +cargo test -p langcodec-cli |
| 65 | +``` |
| 66 | + |
| 67 | +## CLI quick reference |
| 68 | + |
| 69 | +Binary: `"$REPO/target/release/langcodec"` |
| 70 | + |
| 71 | +- `convert`: Convert localization files between formats (auto-detect by extension) |
| 72 | +- `edit set`: Add/update/remove entries in-place (or to `--output`) |
| 73 | +- `view`: Pretty-print entries, filter by `--lang`, optional `--check_plurals` |
| 74 | +- `merge`: Merge multiple inputs to one output with conflict strategy |
| 75 | +- `stats`: Coverage and per-status counts (text or `--json`) |
| 76 | +- `debug`: Read file and emit JSON (to stdout or `--output`) |
| 77 | +- `completions`: Generate shell completion scripts |
| 78 | + |
| 79 | +Show help for any subcommand: |
| 80 | + |
| 81 | +```bash |
| 82 | +"$REPO/target/release/langcodec" --help | cat |
| 83 | +"$REPO/target/release/langcodec" convert --help | cat |
| 84 | +``` |
| 85 | + |
| 86 | +## Supported formats |
| 87 | + |
| 88 | +Standard (read/write): |
| 89 | + |
| 90 | +- **Apple**: `.strings`, `.xcstrings` |
| 91 | +- **Android**: `strings.xml` |
| 92 | +- **CSV**, **TSV** |
| 93 | + |
| 94 | +Custom inputs (one-way into internal Resources via CLI): |
| 95 | + |
| 96 | +- `json-language-map`, `json-array-language-map`, `yaml-language-map`, `langcodec-resource-array` (`.langcodec`) |
| 97 | + |
| 98 | +## Common automation recipes (absolute paths) |
| 99 | + |
| 100 | +- Convert `.strings` → Android XML: |
| 101 | + |
| 102 | +```bash |
| 103 | +"$REPO/target/release/langcodec" convert \ |
| 104 | + --input "/abs/path/Localizable.strings" \ |
| 105 | + --output "/abs/path/values/strings.xml" |
| 106 | +``` |
| 107 | + |
| 108 | +- Convert `.xcstrings` → CSV: |
| 109 | + |
| 110 | +```bash |
| 111 | +"$REPO/target/release/langcodec" convert \ |
| 112 | + --input "/abs/path/Localizable.xcstrings" \ |
| 113 | + --output "/abs/path/translations.csv" |
| 114 | +``` |
| 115 | + |
| 116 | +- Convert custom JSON language map → `.xcstrings` with overrides: |
| 117 | + |
| 118 | +```bash |
| 119 | +"$REPO/target/release/langcodec" convert \ |
| 120 | + --input "/abs/path/translations.json" \ |
| 121 | + --output "/abs/path/Localizable.xcstrings" \ |
| 122 | + --input_format json-language-map \ |
| 123 | + --output_format xcstrings \ |
| 124 | + --source_language en \ |
| 125 | + --version 1.0 |
| 126 | +``` |
| 127 | + |
| 128 | +- Edit in place (add/update). For single-language formats, specify `--lang` as needed: |
| 129 | + |
| 130 | +```bash |
| 131 | +"$REPO/target/release/langcodec" edit set \ |
| 132 | + --inputs "/abs/path/en.lproj/Localizable.strings" \ |
| 133 | + --lang en \ |
| 134 | + --key welcome_message \ |
| 135 | + --value "Hello, World!" |
| 136 | +``` |
| 137 | + |
| 138 | +- Remove a key (omit or empty `--value`): |
| 139 | + |
| 140 | +```bash |
| 141 | +"$REPO/target/release/langcodec" edit set \ |
| 142 | + --inputs "/abs/path/values/strings.xml" \ |
| 143 | + --lang en \ |
| 144 | + --key obsolete_key \ |
| 145 | + --value "" |
| 146 | +``` |
| 147 | + |
| 148 | +- Preview changes without writing: |
| 149 | + |
| 150 | +```bash |
| 151 | +"$REPO/target/release/langcodec" edit set \ |
| 152 | + --inputs "/abs/path/en.lproj/Localizable.strings" \ |
| 153 | + --lang en \ |
| 154 | + --key welcome_message \ |
| 155 | + --value "Hello" \ |
| 156 | + --dry_run |
| 157 | +``` |
| 158 | + |
| 159 | +- View entries (full values) and check plurals: |
| 160 | + |
| 161 | +```bash |
| 162 | +"$REPO/target/release/langcodec" view \ |
| 163 | + --input "/abs/path/Localizable.xcstrings" \ |
| 164 | + --lang en \ |
| 165 | + --full \ |
| 166 | + --check_plurals |
| 167 | +``` |
| 168 | + |
| 169 | +- Merge multiple files (quote globs to avoid shell-side expansion): |
| 170 | + |
| 171 | +```bash |
| 172 | +"$REPO/target/release/langcodec" merge \ |
| 173 | + --inputs "/abs/path/**/Localizable.strings" \ |
| 174 | + --output "/abs/path/merged.xcstrings" \ |
| 175 | + --strategy last \ |
| 176 | + --lang en \ |
| 177 | + --source_language en \ |
| 178 | + --version 1.0 |
| 179 | +``` |
| 180 | + |
| 181 | +- Stats (machine-readable): |
| 182 | + |
| 183 | +```bash |
| 184 | +"$REPO/target/release/langcodec" stats \ |
| 185 | + --input "/abs/path/Localizable.xcstrings" \ |
| 186 | + --lang en \ |
| 187 | + --json |
| 188 | +``` |
| 189 | + |
| 190 | +- Debug (emit JSON to file): |
| 191 | + |
| 192 | +```bash |
| 193 | +"$REPO/target/release/langcodec" debug \ |
| 194 | + --input "/abs/path/values/strings.xml" \ |
| 195 | + --lang en \ |
| 196 | + --output "/abs/path/out.json" |
| 197 | +``` |
| 198 | + |
| 199 | +## Exit codes (for CI/non-interactive use) |
| 200 | + |
| 201 | +- `0`: success |
| 202 | +- `1`: validation or runtime failure (e.g., invalid inputs, unsupported format) |
| 203 | +- `2`: plural validation failed (when `view --check_plurals` is used) |
| 204 | + |
| 205 | +## Behavior notes for agents |
| 206 | + |
| 207 | +- All commands are non-interactive. Always pass explicit absolute paths. |
| 208 | +- Input/output formats are inferred from file extensions unless `--input_format` / `--output_format` is provided. |
| 209 | +- For single-language formats, pass `--lang` when required (e.g., ambiguous inputs). |
| 210 | +- Quote glob patterns provided to `merge --inputs` to avoid slow shell-side expansion. |
| 211 | + |
| 212 | +## Library usage (Rust) |
| 213 | + |
| 214 | +The library exposes a high-level API. Minimal example: |
| 215 | + |
| 216 | +```rust |
| 217 | +use langcodec::convert_auto; |
| 218 | + |
| 219 | +fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 220 | + convert_auto("/abs/path/Localizable.strings", "/abs/path/values/strings.xml")?; |
| 221 | + Ok(()) |
| 222 | +} |
| 223 | +``` |
| 224 | + |
| 225 | +Builder pattern and direct `Codec` manipulation are also available; see `langcodec/src/lib.rs` for more examples and re-exports. |
| 226 | + |
| 227 | +## Extension points (for contributors/agents) |
| 228 | + |
| 229 | +- Add/modify formats: edit files under `langcodec/src/formats/` and wire into `formats/mod.rs` |
| 230 | +- Implement parsing/writing: implement `Parser` in `langcodec/src/traits.rs` |
| 231 | +- Add CLI subcommands/options: edit `langcodec-cli/src/main.rs` and corresponding modules |
| 232 | +- Support new custom one-way formats: add a transformer under `langcodec-cli/src/transformers/` and register in `transformers/mod.rs` and `formats.rs` |
| 233 | + |
| 234 | +## Reproducible CI example |
| 235 | + |
| 236 | +```bash |
| 237 | +set -euo pipefail |
| 238 | +REPO="/abs/path/to/langcodec" |
| 239 | +cargo build --release -p langcodec-cli --manifest-path "$REPO/Cargo.toml" |
| 240 | +"$REPO/target/release/langcodec" --version | cat |
| 241 | +"$REPO/target/release/langcodec" convert \ |
| 242 | + --input "/abs/path/Localizable.xcstrings" \ |
| 243 | + --output "/abs/path/translations.csv" |
| 244 | +``` |
0 commit comments