From 8a102e447672dd4e28144ce03986aad3ce623d76 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 8 Feb 2026 20:50:55 +0000 Subject: [PATCH] feat(i18n): complete en_GB translations and add completeness test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fill all 568 missing translation keys in en_GB.json (765→1357 lines): - 97 --help description keys (collect, ci, docs, dev, php, pkg, sdk, vm) - 471 runtime keys (labels, errors, hints, progress, status messages) - Add common.flag.follow, common.flag.tag, common.prompt.abort Add completeness_test.go that scans all T() calls in source code and verifies every cmd.*/common.* key exists using ModeStrict (panics on missing). Catches translation gaps at test time instead of showing raw keys in the CLI. Co-Authored-By: Claude Opus 4.6 --- pkg/i18n/completeness_test.go | 114 +++++++ pkg/i18n/locales/en_GB.json | 618 +++++++++++++++++++++++++++++++++- 2 files changed, 719 insertions(+), 13 deletions(-) create mode 100644 pkg/i18n/completeness_test.go diff --git a/pkg/i18n/completeness_test.go b/pkg/i18n/completeness_test.go new file mode 100644 index 00000000..b2ad721f --- /dev/null +++ b/pkg/i18n/completeness_test.go @@ -0,0 +1,114 @@ +package i18n + +import ( + "os" + "path/filepath" + "regexp" + "sort" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +// TestTranslationCompleteness_Good verifies every T() key in the source code +// has a translation in en_GB.json. Catches missing keys at test time instead +// of showing raw keys like "cmd.collect.short" in the CLI. +func TestTranslationCompleteness_Good(t *testing.T) { + svc, err := New(WithMode(ModeStrict)) + require.NoError(t, err) + + // Find repo root (walk up from pkg/i18n/ to find go.mod) + root := findRepoRoot(t) + + // Extract all T("key") calls from Go source + keys := extractTranslationKeys(t, root) + require.NotEmpty(t, keys, "should find translation keys in source code") + + var missing []string + for _, key := range keys { + // ModeStrict panics on missing — use recover to collect them all + func() { + defer func() { + if r := recover(); r != nil { + missing = append(missing, key) + } + }() + svc.T(key) + }() + } + + if len(missing) > 0 { + sort.Strings(missing) + t.Errorf("found %d missing translation keys in en_GB.json:\n %s", + len(missing), strings.Join(missing, "\n ")) + } +} + +// findRepoRoot walks up from the test directory to find the repo root (containing go.mod). +func findRepoRoot(t *testing.T) string { + t.Helper() + dir, err := os.Getwd() + require.NoError(t, err) + + for { + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { + return dir + } + parent := filepath.Dir(dir) + if parent == dir { + t.Fatal("could not find repo root (no go.mod found)") + } + dir = parent + } +} + +// tCallRegex matches i18n.T("key"), T("key"), and cli.T("key") patterns. +var tCallRegex = regexp.MustCompile(`(?:i18n|cli)\.T\("([^"]+)"`) + +// extractTranslationKeys scans all .go files (excluding tests and vendors) +// for T() calls and returns the unique set of translation keys. +func extractTranslationKeys(t *testing.T, root string) []string { + t.Helper() + seen := make(map[string]bool) + + err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return nil // skip errors + } + // Skip vendor, .git, and test files + if info.IsDir() { + base := info.Name() + if base == "vendor" || base == ".git" || base == "node_modules" { + return filepath.SkipDir + } + return nil + } + if !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") { + return nil + } + + data, err := os.ReadFile(path) + if err != nil { + return nil + } + + matches := tCallRegex.FindAllSubmatch(data, -1) + for _, m := range matches { + key := string(m[1]) + // Only track cmd.* and common.* keys (skip dynamic/template keys) + if strings.HasPrefix(key, "cmd.") || strings.HasPrefix(key, "common.") { + seen[key] = true + } + } + return nil + }) + require.NoError(t, err) + + keys := make([]string, 0, len(seen)) + for k := range seen { + keys = append(keys, k) + } + sort.Strings(keys) + return keys +} diff --git a/pkg/i18n/locales/en_GB.json b/pkg/i18n/locales/en_GB.json index b901d3de..e3d7c6f1 100644 --- a/pkg/i18n/locales/en_GB.json +++ b/pkg/i18n/locales/en_GB.json @@ -157,7 +157,53 @@ "metrics.short": "View AI and security event metrics", "metrics.long": "View collected metrics from AI tasks, security scans, and job creation events. Reads JSONL event logs from ~/.core/ai/metrics/.", "metrics.flag.since": "Time period to show (e.g. 7d, 24h, 30d)", - "metrics.none_found": "No events recorded in this period." + "metrics.none_found": "No events recorded in this period.", + "label.blocked_by": "Blocked by:", + "label.claimed_by": "Claimed by:", + "label.created": "Created:", + "label.description": "Description:", + "label.id": "ID:", + "label.labels": "Labels:", + "label.priority": "Priority:", + "label.related_files": "Related files:", + "label.title": "Title:", + "priority.critical": "Critical", + "priority.high": "High", + "priority.low": "Low", + "priority.medium": "Medium", + "status.blocked": "Blocked", + "status.completed": "Completed", + "status.in_progress": "In Progress", + "status.pending": "Pending", + "task.claiming": "Claiming task...", + "task_commit.flag.message": "Commit message override", + "task_commit.flag.push": "Push after committing", + "task_commit.flag.scope": "Scope prefix for commit message", + "task_commit.long": "Automatically commit staged changes with a message referencing the current task ID and title.", + "task_complete.failed": "Failed to mark task as completed.", + "task_complete.flag.error": "Error message if task failed", + "task_complete.flag.failed": "Mark task as failed instead of completed", + "task_complete.flag.output": "Output or result summary", + "task_complete.long": "Mark a claimed task as completed or failed. Updates the task status in the agentic queue.", + "task_pr.flag.base": "Base branch for the pull request", + "task_pr.flag.draft": "Create as draft pull request", + "task_pr.flag.labels": "Comma-separated labels to add", + "task_pr.flag.title": "Pull request title override", + "task_pr.long": "Create a pull request for the current task. Auto-generates title and description from the task context.", + "task_update.flag.notes": "Notes to add to the task", + "task_update.flag.progress": "Progress percentage (0-100)", + "task_update.flag.status": "New status (pending, in_progress, blocked)", + "task_update.flag_required": "At least one of --status, --progress, or --notes is required.", + "task_update.long": "Update the status, progress, or notes on a claimed task in the agentic queue.", + "tasks.flag.labels": "Filter by labels", + "tasks.flag.limit": "Maximum number of tasks to show", + "tasks.flag.priority": "Filter by priority (critical, high, medium, low)", + "tasks.flag.project": "Filter by project name", + "tasks.flag.status": "Filter by status (pending, in_progress, blocked)", + "tasks.found": "Found {{.Count}} task(s)", + "tasks.hint": "Use 'core ai task ' to view details or 'core ai task --auto' to claim the next one.", + "tasks.long": "List available tasks from the core-agentic task queue. Supports filtering by status, priority, labels, and project.", + "tasks.none_found": "No tasks found matching the criteria." }, "build": { "short": "Build projects with auto-detection and cross-compilation", @@ -256,8 +302,61 @@ "dry_run_hint": "(dry-run) use --we-are-go-for-launch to publish", "go_for_launch": "GO FOR LAUNCH", "init.short": "Initialize release configuration", + "init.long": "Initialize release configuration for the current project. Creates a default release config file.", "changelog.short": "Generate changelog", - "version.short": "Show or set version" + "changelog.long": "Generate a changelog from git history between two refs. Uses conventional commit messages to categorise changes.", + "changelog.flag.from": "Starting ref (tag or commit SHA)", + "changelog.flag.to": "Ending ref (tag or commit SHA, default: HEAD)", + "version.short": "Show or set version", + "version.long": "Show the current project version or set a new one. Reads from and writes to the version file.", + "changelog.generating": "Generating changelog...", + "changelog.no_tags": "No tags found in repository.", + "error.no_publishers": "No publish targets configured.", + "init.already_initialized": "Release configuration already exists.", + "init.created_config": "Created release configuration.", + "init.edit_config": "Edit .core/release.yaml to configure your release pipeline.", + "init.initializing": "Initialising release configuration...", + "init.next_steps": "Next steps:", + "init.run_ci": "Run 'core ci' to publish a release.", + "label.artifacts": "Artifacts:", + "label.ci": "CI", + "label.published": "Published:", + "publish_completed": "Release published successfully.", + "publishing": "Publishing release..." + }, + "collect": { + "short": "Data collection and research tools", + "long": "Data collection tools for gathering information from forums, GitHub, academic papers, and market sources. Process and organise collected data.", + "flag.dry_run": "Show what would be collected without writing files", + "flag.output": "Output directory for collected data", + "bitcointalk.short": "Collect BitcoinTalk forum threads", + "bitcointalk.long": "Scrape and archive a BitcoinTalk topic thread by ID or URL. Saves posts with metadata.", + "bitcointalk.flag.pages": "Number of pages to collect", + "dispatch.short": "Dispatch collection events", + "dispatch.long": "Dispatch and manage data collection events via webhook hooks.", + "dispatch.hooks.short": "Manage dispatch hooks", + "dispatch.hooks.list.short": "List registered dispatch hooks", + "dispatch.hooks.register.short": "Register a new dispatch hook", + "excavate.short": "Deep-dig a project's history", + "excavate.long": "Excavate a project's full history across forums, repos, and archives. Discovers related resources and builds a timeline.", + "excavate.flag.resume": "Resume a previously interrupted excavation", + "excavate.flag.scan_only": "Scan for resources without downloading", + "github.short": "Collect GitHub issues and PRs", + "github.long": "Collect issues, pull requests, and metadata from a GitHub repository or organisation.", + "github.flag.issues_only": "Collect only issues", + "github.flag.org": "Collect all repos in the organisation", + "github.flag.prs_only": "Collect only pull requests", + "market.short": "Collect cryptocurrency market data", + "market.long": "Collect market data for a cryptocurrency including price, volume, and market cap from aggregator APIs.", + "market.flag.from": "Start date for historical data (YYYY-MM-DD)", + "market.flag.historical": "Collect full historical data", + "papers.short": "Collect academic papers", + "papers.long": "Search for and collect academic papers from arxiv, IACR, and other sources. Downloads PDFs and extracts metadata.", + "papers.flag.category": "Paper category to filter by", + "papers.flag.query": "Search query for finding papers", + "papers.flag.source": "Source to search (arxiv, iacr, all)", + "process.short": "Process collected raw data", + "process.long": "Process previously collected raw data from a source directory. Normalises, deduplicates, and generates summaries." }, "deploy": { "short": "Infrastructure deployment via Coolify", @@ -270,7 +369,10 @@ "workflow.short": "Manage GitHub Actions workflows", "workflow.long": "Manage GitHub Actions workflows across repositories. List, sync, and update workflow files.", "workflow.list.short": "List workflows across repos", + "workflow.list.long": "List GitHub Actions workflow files across all repositories in the workspace.", "workflow.sync.short": "Sync workflow files across repos", + "workflow.sync.long": "Sync a GitHub Actions workflow file to all repositories that match the pattern.", + "workflow.sync.flag.dry_run": "Show what would be synced without making changes", "vm.boot.short": "Boot development VM", "vm.claude.short": "Run Claude in development VM", "vm.install.short": "Install development VM", @@ -359,13 +461,152 @@ "apply.error.script_not_found": "Script not found: {{.Path}}", "apply.error.no_repos": "No repos found", "apply.error.no_registry": "No repos.yaml found", - "apply.error.command_failed": "Command failed (use --continue to skip failures)" + "apply.error.command_failed": "Command failed (use --continue to skip failures)", + "apply.cancelled": "Apply cancelled.", + "apply.confirm": "Apply to {{.Count}} repo(s)?", + "apply.flag.yes": "Skip confirmation prompt", + "apply.warning": "This will modify files in the target repos.", + "ci.failing": "Failing", + "ci.flag.branch": "Branch to check (default: main)", + "ci.flag.failed": "Show only failing repos", + "ci.long": "Check CI/CD pipeline status across all repos in the workspace. Shows pass/fail state for the latest run.", + "ci.no_ci": "No CI configured", + "ci.passing": "Passing", + "ci.repos_checked": "Repos checked", + "commit.committing": "Committing {{.Repo}}...", + "commit.flag.all": "Commit all repos with changes", + "commit.long": "Create Claude-assisted commits across all repos with uncommitted changes. Generates descriptive commit messages.", + "committed": "Committed", + "committing": "Committing...", + "done_succeeded": "{{.Count}} succeeded", + "impact.analysis_for": "Impact analysis for {{.Repo}}", + "impact.changes_affect": "Changes to this repo affect:", + "impact.direct_dependents": "Direct dependents:", + "impact.long": "Show which repos are affected by changes to a given repo. Uses dependency information from repos.yaml.", + "impact.no_dependents": "No dependents found.", + "impact.transitive_dependents": "Transitive dependents:", + "issues.flag.assignee": "Filter by assignee", + "issues.flag.limit": "Maximum issues per repo", + "issues.long": "List open issues across all repos in the workspace. Shows issue number, title, labels, and assignee.", + "issues.no_issues": "No open issues found.", + "issues.open_issues": "Open issues", + "pull.all_up_to_date": "All repos are up to date.", + "pull.commits_behind": "{{.Count}} commit(s) behind", + "pull.done_pulled": "Pulled {{.Count}} repo(s)", + "pull.flag.all": "Pull all repos including clean ones", + "pull.long": "Pull the latest changes from remote across all repos in the workspace.", + "pull.pulling": "Pulling...", + "pull.pulling_repos": "Pulling {{.Count}} repo(s)...", + "pull.repos_behind": "{{.Count}} repo(s) behind remote", + "push.confirm": "Push {{.Count}} repo(s)?", + "repos_with_changes": "{{.Count}} repo(s) with changes", + "reviews.approved": "Approved", + "reviews.changes_requested": "Changes requested", + "reviews.draft": "Draft", + "reviews.flag.all": "Show all PRs, not just yours", + "reviews.flag.author": "Filter by PR author", + "reviews.long": "List pull requests needing review across all repos in the workspace.", + "reviews.no_prs": "No open PRs found.", + "reviews.open_prs": "Open PRs", + "reviews.status_approved": "Approved", + "reviews.status_changes": "Changes Requested", + "reviews.status_pending": "Review Pending", + "scanning_label": "Scanning...", + "sync.long": "Synchronise public service APIs with their internal implementations. Copies interface definitions to keep packages in sync.", + "vm.already_installed": "Dev environment already installed.", + "vm.boot.flag.cpus": "Number of CPUs to allocate", + "vm.boot.flag.fresh": "Boot fresh (discard existing state)", + "vm.boot.flag.memory": "Memory in MB to allocate", + "vm.boot.long": "Boot the development VM. Creates and starts the container if not already running.", + "vm.booting": "Booting dev environment...", + "vm.check_updates": "Checking for updates...", + "vm.claude.flag.auth": "Authentication token for Claude", + "vm.claude.flag.model": "Claude model to use", + "vm.claude.flag.no_auth": "Run without authentication", + "vm.claude.long": "Run Claude Code inside the development VM with the current project mounted.", + "vm.config_label": "Config:", + "vm.config_value": "{{.Key}}: {{.Value}}", + "vm.connect_with": "Connect with: {{.Command}}", + "vm.container_label": "Container:", + "vm.cpus_label": "CPUs:", + "vm.downloading": "Downloading dev environment...", + "vm.downloading_update": "Downloading update...", + "vm.install.long": "Install the development VM image. Downloads and sets up the container environment.", + "vm.install_with": "Install with: {{.Command}}", + "vm.installed_in": "Installed in {{.Path}}", + "vm.installed_label": "Installed:", + "vm.installed_no": "No", + "vm.installed_yes": "Yes", + "vm.latest_label": "Latest:", + "vm.memory_label": "Memory:", + "vm.progress_label": "Progress:", + "vm.run_to_update": "Run 'core dev update' to update.", + "vm.running": "Running", + "vm.serve.flag.path": "Path to serve", + "vm.serve.flag.port": "Port to expose", + "vm.serve.long": "Start development services inside the VM (web server, database, queue worker, etc.).", + "vm.shell.flag.console": "Open a Tinker console instead of shell", + "vm.shell.long": "Open an interactive shell session in the development VM.", + "vm.ssh_port": "SSH port:", + "vm.start_with": "Start with: {{.Command}}", + "vm.status.long": "Show the status of the development VM including resource usage and connectivity.", + "vm.status_title": "Dev Environment Status", + "vm.stop.long": "Stop the running development VM container.", + "vm.stopping": "Stopping dev environment...", + "vm.stopping_current": "Stopping current dev environment...", + "vm.test.flag.name": "Test name pattern to match", + "vm.test.long": "Run the project test suite inside the development VM.", + "vm.up_to_date": "Already up to date.", + "vm.update.flag.apply": "Apply the update immediately", + "vm.update.long": "Check for and apply updates to the development VM image.", + "vm.update_available": "Update available: {{.Version}}", + "vm.updated_in": "Updated in {{.Path}}", + "vm.uptime_label": "Uptime:", + "work.all_up_to_date": "All repos are up to date.", + "work.error_prefix": "Error:", + "work.flag.commit": "Commit changes with Claude", + "work.flag.status": "Show status only", + "work.long": "Multi-repo git operations. Shows status across all repos and optionally commits with Claude assistance.", + "work.table_ahead": "Ahead", + "work.table_modified": "Modified", + "work.table_staged": "Staged", + "work.table_untracked": "Untracked", + "workflow.dry_run_mode": "(dry run)", + "workflow.failed_count": "{{.Count}} failed", + "workflow.header.repo": "Repository", + "workflow.no_workflows": "No workflows found.", + "workflow.read_template_error": "Failed to read workflow template.", + "workflow.run_without_dry_run": "Run without --dry-run to apply changes.", + "workflow.skipped_count": "{{.Count}} skipped", + "workflow.synced": "Synced", + "workflow.synced_count": "{{.Count}} synced", + "workflow.template_not_found": "Workflow template not found.", + "workflow.up_to_date": "Up to date", + "workflow.would_sync": "Would sync", + "workflow.would_sync_count": "{{.Count}} would sync" }, "docs": { "short": "Documentation management", "long": "Documentation management tools for listing and syncing documentation across repositories.", "list.short": "List documentation across repos", - "sync.short": "Sync documentation to core-php/docs/packages/" + "list.long": "List documentation files across all repositories in the workspace registry.", + "sync.short": "Sync documentation to core-php/docs/packages/", + "sync.long": "Sync documentation files from each package into the core-php docs directory. Copies README and doc files into a unified documentation tree.", + "sync.flag.dry_run": "Show what would be synced without copying files", + "sync.flag.output": "Output directory for synced documentation", + "list.coverage_summary": "Documentation coverage: {{.Percent}}%", + "list.header.changelog": "Changelog", + "list.header.claude": "CLAUDE.md", + "list.header.docs": "Docs", + "list.header.readme": "README", + "sync.confirm": "Sync documentation from {{.Count}} repo(s)?", + "sync.dry_run_notice": "(dry run) no files will be written", + "sync.files_count": "{{.Count}} file(s)", + "sync.found_label": "Found:", + "sync.no_docs_found": "No documentation found.", + "sync.repos_with_docs": "{{.Count}} repo(s) with documentation", + "sync.synced_packages": "Synced {{.Count}} package(s)", + "sync.total_summary": "Total: {{.Count}} file(s) synced" }, "doctor": { "short": "Check development environment", @@ -375,7 +616,42 @@ "no_repos_yaml": "No repos.yaml found (run from workspace directory)", "install_missing": "Install missing tools:", "install_macos": "brew install git gh php composer node pnpm docker", - "ssh_missing": "SSH key missing - run: ssh-keygen && gh ssh-key add" + "ssh_missing": "SSH key missing - run: ssh-keygen && gh ssh-key add", + "check.claude.description": "Claude Code CLI for AI-assisted development", + "check.claude.name": "Claude Code", + "check.composer.description": "PHP dependency manager", + "check.composer.name": "Composer", + "check.docker.description": "Container runtime", + "check.docker.name": "Docker", + "check.gh.description": "GitHub CLI for repo management", + "check.gh.name": "GitHub CLI", + "check.git.description": "Version control system", + "check.git.name": "Git", + "check.node.description": "Node.js runtime for frontend tooling", + "check.node.name": "Node.js", + "check.php.description": "PHP runtime", + "check.php.name": "PHP", + "check.pnpm.description": "Fast Node.js package manager", + "check.pnpm.name": "pnpm", + "cli_auth": "CLI authenticated", + "cli_auth_missing": "CLI not authenticated", + "github": "GitHub", + "install_linux_gh": "sudo apt install gh", + "install_linux_git": "sudo apt install git", + "install_linux_header": "Install on Linux:", + "install_linux_node": "sudo apt install nodejs npm", + "install_linux_php": "sudo apt install php php-cli", + "install_linux_pnpm": "npm install -g pnpm", + "install_macos_cask": "brew install --cask", + "install_other": "See installation docs", + "issues": "{{.Count}} issue(s) found", + "issues_error": "{{.Count}} error(s)", + "optional": "Optional", + "repos_cloned": "{{.Count}} repo(s) cloned", + "repos_yaml_found": "repos.yaml found", + "required": "Required", + "ssh_found": "SSH key found", + "workspace": "Workspace" }, "git": { "short": "Git workflow commands", @@ -400,7 +676,16 @@ }, "php": { "short": "Laravel/PHP development tools", + "long": "Laravel and PHP development tools including testing, formatting, static analysis, security scanning, and deployment.", "dev.short": "Start Laravel development environment", + "dev.long": "Start a full Laravel development environment with Vite, Horizon, Redis, and Reverb. Services can be individually disabled with flags.", + "dev.flag.domain": "Custom domain for the development server", + "dev.flag.https": "Enable HTTPS with mkcert certificates", + "dev.flag.no_horizon": "Skip starting Laravel Horizon", + "dev.flag.no_redis": "Skip starting Redis", + "dev.flag.no_reverb": "Skip starting Laravel Reverb", + "dev.flag.no_vite": "Skip starting Vite dev server", + "dev.flag.port": "Port for the development server", "dev.press_ctrl_c": "Press Ctrl+C to stop all services", "test.short": "Run PHP tests (PHPUnit/Pest)", "test.flag.parallel": "Run tests in parallel", @@ -436,6 +721,15 @@ "qa.flag.quick": "Run quick checks only (audit, fmt, stan)", "qa.flag.full": "Run all stages including slow checks", "build.short": "Build Docker or LinuxKit image", + "build.long": "Build a Docker or LinuxKit image for the PHP application. Supports custom Dockerfiles, multi-platform builds, and LinuxKit templates.", + "build.flag.dockerfile": "Path to custom Dockerfile", + "build.flag.format": "Build format (docker, linuxkit)", + "build.flag.name": "Image name", + "build.flag.no_cache": "Build without using cache", + "build.flag.output": "Output directory for build artifacts", + "build.flag.platform": "Target platform (e.g., linux/amd64)", + "build.flag.template": "LinuxKit template to use", + "build.flag.type": "Build type override", "deploy.short": "Deploy to Coolify", "deploy.long": "Deploy the PHP application to Coolify", "deploy.deploying": "Deploying to {{.Environment}}", @@ -465,10 +759,29 @@ "label.deploy": "Deploy", "error.deploy_failed": "Deployment failed", "serve.short": "Run production container", + "serve.long": "Run the PHP application in a production Docker container with configurable ports and environment.", + "serve.flag.container": "Container runtime to use", + "serve.flag.detach": "Run container in the background", + "serve.flag.env_file": "Path to environment file", + "serve.flag.https_port": "HTTPS port to expose", + "serve.flag.name": "Container name", + "serve.flag.port": "HTTP port to expose", "ssl.short": "Setup SSL certificates with mkcert", "packages.short": "Manage local PHP packages", + "packages.long": "Manage locally-developed PHP packages. Link, unlink, list, and update packages used by the application.", + "packages.link.short": "Link local packages into the application", + "packages.link.long": "Symlink local PHP packages into the application's vendor directory for development.", + "packages.list.short": "List linked local packages", + "packages.list.long": "List all locally-linked PHP packages and their paths.", + "packages.unlink.short": "Unlink local packages", + "packages.unlink.long": "Remove symlinks to local PHP packages and restore the published versions.", + "packages.update.short": "Update local packages", + "packages.update.long": "Update locally-linked PHP packages to their latest versions.", "logs.short": "View application logs", + "logs.long": "View application logs from running containers. Supports following logs in real-time and filtering by service.", + "logs.flag.service": "Service name to filter logs", "shell.short": "Open shell in container", + "shell.long": "Open an interactive shell session inside a running PHP container.", "status.short": "Show container status", "stop.short": "Stop running containers", "stan.short": "Run PHPStan static analysis", @@ -478,23 +791,211 @@ "ci.flag.summary": "Output markdown summary (for PR comments)", "ci.flag.sarif": "Generate SARIF files for static analysis", "ci.flag.upload_sarif": "Upload SARIF to GitHub Security tab", - "ci.flag.fail_on": "Severity level to fail on (critical, high, warning)" + "ci.flag.fail_on": "Severity level to fail on (critical, high, warning)", + "analyse.long": "Run PHPStan static analysis on the codebase. Detects type errors, undefined methods, and other issues.", + "analyse.no_analyser": "No static analyser found. Install PHPStan or Psalm.", + "audit.all_secure": "All dependencies are secure.", + "audit.completed_errors": "Audit completed with {{.Count}} error(s).", + "audit.error": "Audit error", + "audit.flag.fix": "Attempt to fix vulnerabilities automatically", + "audit.found_vulns": "Found {{.Count}} vulnerability(ies)", + "audit.long": "Run a security audit on Composer dependencies using the Symfony Security Advisories database.", + "audit.scanning": "Scanning dependencies...", + "audit.secure": "Secure", + "audit.vulnerabilities": "Vulnerabilities", + "build.building_docker": "Building Docker image...", + "build.building_linuxkit": "Building LinuxKit image...", + "build.docker_run_with": "Run with: docker run {{.Image}}", + "build.extensions": "Extensions:", + "build.format": "Format:", + "build.frontend": "Frontend:", + "build.laravel": "Laravel:", + "build.octane": "Octane:", + "build.php_version": "PHP version:", + "build.platform": "Platform:", + "dev.all_stopped": "All services stopped.", + "dev.detected_services": "Detected services:", + "dev.services_started": "All services started.", + "dev.shutting_down": "Shutting down services...", + "dev.starting": "Starting development environment...", + "dev.stop_error": "Error stopping {{.Service}}", + "error.analysis_issues": "Static analysis found {{.Count}} issue(s).", + "error.audit_failed": "Security audit failed.", + "error.critical_high_issues": "{{.Count}} critical/high severity issue(s) found.", + "error.fmt_failed": "Formatting check failed.", + "error.fmt_issues": "{{.Count}} formatting issue(s) found.", + "error.infection_failed": "Mutation testing failed.", + "error.infection_not_installed": "Infection not installed.", + "error.mkcert_not_installed": "mkcert not installed.", + "error.not_laravel": "Not a Laravel project (no artisan file found).", + "error.not_laravel_short": "Not a Laravel project.", + "error.not_php": "Not a PHP project (no composer.json found).", + "error.psalm_issues": "Psalm found {{.Count}} issue(s).", + "error.psalm_not_installed": "Psalm not installed.", + "error.rector_failed": "Rector refactoring failed.", + "error.rector_not_installed": "Rector not installed.", + "error.rollback_failed": "Rollback failed.", + "error.security_failed": "Security scan failed.", + "error.update_packages": "Run 'composer update' to fix.", + "error.vulns_found": "{{.Count}} vulnerability(ies) found.", + "fmt.formatting": "Formatting code...", + "fmt.long": "Format PHP code using Laravel Pint. Shows a diff of changes or applies them with --fix.", + "fmt.no_formatter": "No formatter found. Install Laravel Pint.", + "fmt.no_issues": "No formatting issues found.", + "infection.complete": "Mutation testing complete.", + "infection.install": "Install with: composer require --dev infection/infection", + "infection.long": "Run mutation testing with Infection to measure test suite quality. Introduces small changes and checks if tests catch them.", + "infection.not_found": "Infection not found.", + "infection.note": "Note: Mutation testing can be slow on large codebases.", + "label.app_url": "App URL:", + "label.audit": "Audit", + "label.branch": "Branch:", + "label.commit": "Commit:", + "label.completed": "Completed", + "label.duration": "Duration:", + "label.id": "ID:", + "label.infection": "Infection", + "label.info": "Info", + "label.message": "Message:", + "label.php": "PHP", + "label.psalm": "Psalm", + "label.rector": "Rector", + "label.running": "Running", + "label.security": "Security", + "label.services": "Services:", + "label.setup": "Setup:", + "label.vite": "Vite", + "packages.link.done": "Packages linked successfully.", + "packages.link.linking": "Linking {{.Package}}...", + "packages.list.linked": "Linked packages:", + "packages.list.none_found": "No linked packages found.", + "packages.list.unknown": "Unknown", + "packages.unlink.done": "Packages unlinked successfully.", + "packages.unlink.unlinking": "Unlinking {{.Package}}...", + "packages.update.done": "Packages updated successfully.", + "packages.update.updating": "Updating {{.Package}}...", + "psalm.analysing": "Running Psalm analysis...", + "psalm.analysing_fixing": "Running Psalm analysis with fixes...", + "psalm.install": "Install with: composer require --dev vimeo/psalm", + "psalm.long": "Run Psalm static analysis for type checking and error detection. Supports baseline generation and auto-fixing.", + "psalm.not_found": "Psalm not found.", + "psalm.setup": "Run 'vendor/bin/psalm --init' to set up.", + "qa.long": "Run the full QA pipeline: audit, format, static analysis, and tests. Use --quick for fast checks or --full for everything.", + "rector.analysing": "Running Rector analysis...", + "rector.changes_suggested": "{{.Count}} change(s) suggested.", + "rector.install": "Install with: composer require --dev rector/rector", + "rector.long": "Run automated code refactoring with Rector. Preview changes or apply them with --fix.", + "rector.no_changes": "No refactoring changes suggested.", + "rector.not_found": "Rector not found.", + "rector.refactoring": "Applying refactoring changes...", + "rector.setup": "Run 'vendor/bin/rector init' to set up.", + "security.checks_suffix": "check(s)", + "security.critical": "Critical", + "security.high": "High", + "security.long": "Run security vulnerability scanning on the PHP project. Checks dependencies, code patterns, and HTTP headers.", + "security.low": "Low", + "security.medium": "Medium", + "security.passed": "All security checks passed.", + "security.summary": "Security summary:", + "serve.name_required": "Container name is required.", + "serve.stopped": "Container stopped.", + "shell.opening": "Opening shell...", + "ssl.cert_label": "Certificate:", + "ssl.certs_created": "SSL certificates created successfully.", + "ssl.certs_exist": "SSL certificates already exist.", + "ssl.flag.domain": "Domain for the certificate", + "ssl.install_linux": "Install mkcert: sudo apt install mkcert", + "ssl.install_macos": "Install mkcert: brew install mkcert", + "ssl.key_label": "Key:", + "ssl.mkcert_not_installed": "mkcert is not installed.", + "ssl.setting_up": "Setting up SSL certificates...", + "status.detected_services": "Detected services:", + "status.error": "Error", + "status.octane_server": "Octane server:", + "status.package_manager": "Package manager:", + "status.pid": "PID:", + "status.port": "Port:", + "status.running": "Running", + "status.ssl_certs": "SSL certificates:", + "status.ssl_installed": "Installed", + "status.ssl_not_setup": "Not configured", + "status.stopped": "Stopped", + "stop.stopping": "Stopping containers...", + "test.long": "Run PHPUnit or Pest tests with optional coverage, parallelism, and filtering." }, "pkg": { "short": "Package management for core-* repos", "long": "Package management for core-* repositories. Clone, list, update, and search for packages.", "install.short": "Clone a package from GitHub", + "install.long": "Clone a package repository from GitHub into the workspace packages directory.", + "install.flag.add": "Add to repos.yaml after cloning", + "install.flag.dir": "Directory to clone into", "list.short": "List installed packages", + "list.long": "List all packages currently installed in the workspace.", "update.short": "Update installed packages", + "update.long": "Pull the latest changes for installed packages.", + "update.flag.all": "Update all packages", "outdated.short": "Check for outdated packages", + "outdated.long": "Check which installed packages have newer versions available on the remote.", "search.short": "Search GitHub for packages", - "error.invalid_repo_format": "invalid repo format: use org/repo (e.g., host-uk/core-php)" + "search.long": "Search GitHub for packages matching a pattern. Filters by organisation and package type.", + "search.flag.limit": "Maximum number of results to return", + "search.flag.org": "GitHub organisation to search within", + "search.flag.pattern": "Name pattern to filter results", + "search.flag.refresh": "Refresh the cached package index", + "search.flag.type": "Package type filter (go, php, node)", + "error.invalid_repo_format": "invalid repo format: use org/repo (e.g., host-uk/core-php)", + "error.auth_failed": "Authentication failed.", + "error.gh_not_authenticated": "GitHub CLI not authenticated. Run: gh auth login", + "error.no_repos_yaml": "No repos.yaml found.", + "error.no_repos_yaml_workspace": "No repos.yaml found in workspace.", + "error.repo_required": "Repository name is required.", + "error.search_failed": "Search failed.", + "error.specify_package": "Specify a package name.", + "install.add_to_registry": "Add to repos.yaml?", + "install.added_to_registry": "Added to repos.yaml.", + "install.already_exists": "Package already exists: {{.Name}}", + "install.installed": "Installed {{.Name}}", + "install.installing_label": "Installing:", + "list.install_missing": "Run 'core pkg install' to add packages.", + "list.no_packages": "No packages installed.", + "list.summary": "{{.Count}} package(s) installed", + "list.title": "Installed packages:", + "no_description": "No description", + "outdated.all_up_to_date": "All packages are up to date.", + "outdated.commits_behind": "{{.Count}} commit(s) behind", + "outdated.outdated_label": "Outdated:", + "outdated.summary": "{{.Count}} package(s) outdated", + "outdated.update_with": "Run 'core pkg update' to update.", + "search.cache_label": "Cache:", + "search.fetching_label": "Fetching...", + "search.found_repos": "Found {{.Count}} repo(s)", + "search.gh_token_unset": "GITHUB_TOKEN not set.", + "search.gh_token_warning": "Set GITHUB_TOKEN for higher API limits.", + "search.no_repos_found": "No repos found.", + "search.private_label": "Private", + "update.not_installed": "Package not installed: {{.Name}}", + "update.summary": "{{.Count}} package(s) updated", + "update.update_label": "Updated:", + "update.updating": "Updating {{.Name}}..." }, "sdk": { "short": "SDK validation and API compatibility tools", "long": "SDK validation and API compatibility tools. Check for breaking changes and validate OpenAPI specifications.", "diff.short": "Check for breaking API changes", - "validate.short": "Validate OpenAPI spec" + "diff.long": "Compare two OpenAPI specifications and report breaking changes. Useful for CI checks before merging API changes.", + "diff.flag.base": "Base spec file to compare against", + "diff.flag.spec": "Current spec file to check", + "validate.short": "Validate OpenAPI spec", + "validate.long": "Validate an OpenAPI specification file for correctness and completeness.", + "diff.base_label": "Base:", + "diff.breaking": "Breaking changes detected", + "diff.error.base_required": "Base spec file is required for comparison.", + "diff.label": "Diff", + "label.ok": "OK", + "label.sdk": "SDK", + "validate.valid": "Specification is valid.", + "validate.validating": "Validating specification..." }, "setup": { "short": "Bootstrap workspace or clone packages from registry", @@ -533,7 +1034,31 @@ "github.run_without_check": "Run without --check to apply changes", "github.error.not_authenticated": "GitHub CLI not authenticated. Run: gh auth login", "github.error.config_not_found": "GitHub config file not found", - "github.error.conflicting_flags": "Cannot use --repo and --all together" + "github.error.conflicting_flags": "Cannot use --repo and --all together", + "already_exist_count": "{{.Count}} already exist", + "already_exists": "Already exists: {{.Name}}", + "cancelled": "Setup cancelled.", + "cloned": "Cloned {{.Name}}", + "cloned_count": "{{.Count}} cloned", + "cloning_current_dir": "Cloning into current directory...", + "creating_project_dir": "Creating project directory...", + "done": "Setup complete.", + "exist": "exists", + "org_label": "Organisation:", + "repo.created": "Repository created.", + "repo.detected_type": "Detected type: {{.Type}}", + "repo.setting_up": "Setting up {{.Name}}...", + "repo.would_create": "Would create: {{.Name}}", + "to_clone": "{{.Count}} to clone", + "wizard.confirm_clone": "Clone {{.Count}} package(s)?", + "wizard.git_repo_title": "Git Repository", + "wizard.package_selection": "Package Selection", + "wizard.project_name_desc": "Name for the new project directory", + "wizard.project_name_title": "Project Name", + "wizard.selection_hint": "Use space to select, enter to confirm.", + "would_clone": "Would clone: {{.Name}}", + "would_clone_list": "Would clone {{.Count}} package(s):", + "would_load_registry": "Would load registry from: {{.Path}}" }, "security": { "short": "Security alerts and vulnerability scanning", @@ -632,17 +1157,68 @@ "flag.race": "Enable race detector", "flag.run": "Run only tests matching pattern", "flag.short": "Run only short tests", - "flag.verbose": "Verbose output" + "flag.verbose": "Verbose output", + "coverage_by_package": "Coverage by package:", + "error.no_go_mod": "No go.mod found in current directory.", + "failed_packages": "Failed packages:", + "label.average": "Average:", + "tests_failed": "{{.Count}} test(s) failed." }, "vm": { "short": "LinuxKit VM management", "long": "LinuxKit VM management for running isolated development environments. Create, run, and manage lightweight VMs.", "run.short": "Run a LinuxKit image or template", + "run.long": "Run a LinuxKit image or pre-defined template as a lightweight VM. Supports resource allocation and SSH access.", + "run.flag.cpus": "Number of CPUs to allocate", + "run.flag.detach": "Run VM in the background", + "run.flag.memory": "Memory in MB to allocate", + "run.flag.name": "Name for the VM instance", + "run.flag.ssh_port": "Host port to forward to VM SSH", + "run.flag.template": "Template name to use", + "run.flag.var": "Template variable (key=value)", "ps.short": "List running VMs", + "ps.long": "List all running LinuxKit VM instances with their status and resource usage.", + "ps.flag.all": "Show all VMs including stopped ones", "stop.short": "Stop a running VM", + "stop.long": "Stop a running LinuxKit VM by container ID.", "logs.short": "View VM logs", + "logs.long": "View console output logs from a LinuxKit VM instance.", "exec.short": "Execute a command in a VM", - "templates.short": "Manage LinuxKit templates" + "exec.long": "Execute a command inside a running LinuxKit VM.", + "templates.short": "Manage LinuxKit templates", + "templates.long": "List available LinuxKit templates that can be used with 'core vm run'.", + "templates.show.short": "Show template details", + "templates.show.long": "Show the full configuration of a LinuxKit template.", + "templates.vars.short": "Show template variables", + "templates.vars.long": "Show the configurable variables for a LinuxKit template.", + "error.id_and_cmd_required": "Container ID and command are required.", + "error.id_required": "Container ID is required.", + "error.linuxkit_not_found": "LinuxKit not found. Install from https://github.com/linuxkit/linuxkit", + "error.multiple_match": "Multiple containers match '{{.Name}}'. Be more specific.", + "error.no_image_found": "No image found: {{.Name}}", + "error.no_match": "No container matches '{{.Name}}'.", + "error.template_required": "Template name is required.", + "hint.stop": "Stop with: core vm stop {{.ID}}", + "hint.view_logs": "View logs with: core vm logs {{.ID}}", + "label.building": "Building...", + "label.container_stopped": "Container stopped.", + "label.hypervisor": "Hypervisor:", + "label.name": "Name:", + "label.pid": "PID:", + "ps.header": "Running VMs:", + "ps.no_containers": "No containers found.", + "ps.no_running": "No running VMs.", + "run.error.image_required": "Image or template name is required.", + "stop.stopping": "Stopping {{.Name}}...", + "templates.header": "Available templates:", + "templates.hint.run": "Run with: core vm run --template {{.Name}}", + "templates.hint.show": "Show details: core vm templates show {{.Name}}", + "templates.hint.vars": "Show variables: core vm templates vars {{.Name}}", + "templates.no_templates": "No templates found.", + "templates.title": "LinuxKit Templates", + "templates.vars.none": "No configurable variables.", + "templates.vars.optional": "Optional", + "templates.vars.required": "Required" }, "monitor": { "short": "Aggregate security findings from GitHub", @@ -689,6 +1265,9 @@ "status": { "dirty": "dirty", "clean": "clean", + "cloning": "Cloning...", + "running": "Running", + "stopped": "Stopped", "synced": "synced", "up_to_date": "up to date" }, @@ -699,11 +1278,15 @@ "warning": "Warning", "info": "Info", "fix": "Fix:", + "image": "Image:", "install": "Install:", + "spec": "Spec:", + "started": "Started:", "summary": "Summary:", "setup": "Setup:", "config": "Config:", "repo": "Repo:", + "template": "Template:", "test": "Running tests...", "package": "Package:", "coverage": "Coverage:" @@ -711,16 +1294,22 @@ "flag": { "fix": "Auto-fix issues where possible", "diff": "Show diff of changes", + "follow": "Follow log output in real-time", "json": "Output as JSON", "sarif": "Output as SARIF for GitHub Security tab", + "tag": "Container image tag", "verbose": "Show detailed output", "registry": "Path to repos.yaml registry file", "coverage": "Generate coverage report", "spec": "Path to OpenAPI specification file" }, + "prompt": { + "abort": "Aborted." + }, "progress": { "running": "Running {{.Task}}...", - "checking": "Checking {{.Item}}..." + "checking": "Checking {{.Item}}...", + "checking_updates": "Checking for updates..." }, "result": { "no_issues": "No issues found", @@ -734,9 +1323,12 @@ "json_sarif_exclusive": "--json and --sarif flags are mutually exclusive" }, "hint": { - "fix_deps": "Update dependencies to fix vulnerabilities" + "fix_deps": "Update dependencies to fix vulnerabilities", + "install_with": "Install with: {{.Command}}" }, "count": { + "files": "{{.Count}} file(s)", + "pending": "{{.Count}} pending", "succeeded": "{{.Count}} succeeded", "failed": "{{.Count}} failed", "skipped": "{{.Count}} skipped",