"""CLI module for i18n-guardian.""" import os from typing import Optional import click from i18n_guardian.config import ConfigLoader from i18n_guardian.version import __version__ @click.group() @click.option( "--config", "-c", type=click.Path(exists=True), help="Path to configuration file", ) @click.option( "--verbose", "-v", is_flag=True, help="Enable verbose output", ) @click.option( "--path", "-p", type=click.Path(exists=True), help="Path to scan (defaults to current directory)", ) @click.version_option(version=__version__, prog_name="i18n-guardian") @click.pass_context def main( ctx: click.Context, config: Optional[str], verbose: bool, path: Optional[str], ) -> None: """i18n-guardian: Scan codebases for internationalization issues.""" ctx.ensure_object(dict) ctx.obj["config"] = config ctx.obj["verbose"] = verbose ctx.obj["path"] = path or os.getcwd() @main.command() @click.option( "--output", "-o", type=click.Choice(["text", "json"]), default="text", help="Output format", ) @click.option( "--exclude", multiple=True, help="Exclude patterns (glob)", ) @click.option( "--min-length", type=int, default=3, help="Minimum string length to flag", ) @click.pass_context def scan( ctx: click.Context, output: str, exclude: tuple, min_length: int, ) -> None: """Scan codebase for hardcoded strings.""" path = ctx.obj["path"] config_path = ctx.obj["config"] verbose = ctx.obj["verbose"] config_loader = ConfigLoader() config = config_loader.load(config_path, path) click.echo(f"Scanning {path}...") if verbose: click.echo(f"Config: {config}") click.echo(f"Output format: {output}") click.echo(f"Exclude patterns: {exclude}") click.echo(f"Min length: {min_length}") @main.command() @click.option( "--dry-run", is_flag=True, help="Preview changes without applying", ) @click.option( "--output", "-o", type=click.Choice(["text", "json"]), default="text", help="Output format", ) @click.pass_context def fix( ctx: click.Context, dry_run: bool, output: str, ) -> None: """Auto-fix i18n issues.""" path = ctx.obj["path"] click.echo(f"Fixing i18n issues in {path}...") if dry_run: click.echo("Dry run mode - no changes will be applied") @main.command() @click.option( "--output", "-o", type=click.Path(), default=".i18n-guardian.yaml", help="Output file path", ) def init(output: str) -> None: """Initialize configuration file.""" click.echo(f"Initializing configuration in {output}") @main.command() @click.option( "--fail-level", type=click.Choice(["error", "warning", "info"]), default="error", help="Minimum level to fail CI build", ) @click.option( "--output", "-o", type=click.Choice(["text", "json"]), default="text", help="Output format", ) @click.pass_context def check( ctx: click.Context, fail_level: str, output: str, ) -> None: """Check i18n compliance (for CI/CD).""" path = ctx.obj["path"] click.echo(f"Checking i18n compliance in {path}...") def cli() -> None: """Entry point for the CLI.""" main() if __name__ == "__main__": main()