|
| 1 | +# Implementation Plan: Multilanguage Support for gdb-cli |
| 2 | + |
| 3 | +**Source Spec**: `docs/superpowers/specs/2026-04-04-multilanguage-support-design.md` |
| 4 | +**Target Languages**: `en`, `zh-CN`, `ru` |
| 5 | +**Date**: 2026-04-04 |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Requirements Summary |
| 10 | + |
| 11 | +Implement first-version multilanguage support for gdb-cli covering: |
| 12 | +- Runtime CLI help text and user-facing messages |
| 13 | +- JSON response messages, hints, warnings, suggestions |
| 14 | +- Repository README files (en, zh-CN, ru) |
| 15 | + |
| 16 | +## Current State Analysis |
| 17 | + |
| 18 | +| File | Current State | Action Required | |
| 19 | +|------|---------------|-----------------| |
| 20 | +| `cli.py` | Hardcoded Chinese help text | Full i18n conversion | |
| 21 | +| `errors.py` | `ERROR_SUGGESTIONS` dict with Chinese text | i18n catalog integration | |
| 22 | +| `env_check.py` | Hardcoded English suggestions/warnings | i18n catalog integration | |
| 23 | +| `README.md` | English, existing | Add language switcher with ru | |
| 24 | +| `README.zh-CN.md` | Chinese, existing | Add language switcher with ru | |
| 25 | +| `README.ru.md` | Missing | Create from README.md | |
| 26 | + |
| 27 | +--- |
| 28 | + |
| 29 | +## Implementation Steps |
| 30 | + |
| 31 | +### Phase 1: i18n Infrastructure (Foundation) |
| 32 | + |
| 33 | +#### Step 1.1: Create locale package structure |
| 34 | + |
| 35 | +**Files to create**: |
| 36 | +- `src/gdb_cli/locales/__init__.py` |
| 37 | +- `src/gdb_cli/locales/en.py` |
| 38 | +- `src/gdb_cli/locales/zh_cn.py` |
| 39 | +- `src/gdb_cli/locales/ru.py` |
| 40 | + |
| 41 | +**Implementation**: |
| 42 | +``` |
| 43 | +src/gdb_cli/locales/ |
| 44 | +├── __init__.py # Package init, exposes get_catalog() |
| 45 | +├── en.py # ENGLISH_CATALOG dict (source language) |
| 46 | +├── zh_cn.py # ZH_CN_CATALOG dict |
| 47 | +└── ru.py # RU_CATALOG dict |
| 48 | +``` |
| 49 | + |
| 50 | +#### Step 1.2: Create i18n module |
| 51 | + |
| 52 | +**File**: `src/gdb_cli/i18n.py` |
| 53 | + |
| 54 | +**Functions**: |
| 55 | +- `resolve_locale() -> str` - Detect locale from env/system |
| 56 | +- `normalize_locale(locale_str: str) -> str` - Normalize aliases |
| 57 | +- `t(key: str, **params) -> str` - Translation lookup with interpolation |
| 58 | +- `get_current_locale() -> str` - Return active locale |
| 59 | + |
| 60 | +**Locale precedence**: |
| 61 | +1. `GDB_CLI_LANG` environment variable |
| 62 | +2. System locale (`LANG`, `LC_ALL`, `LC_MESSAGES`) |
| 63 | +3. Default to `en` |
| 64 | + |
| 65 | +**Normalization rules** (per spec): |
| 66 | +- `en`, `en_US`, `en-US` -> `en` |
| 67 | +- `zh`, `zh_CN`, `zh-CN`, `zh_Hans_CN` -> `zh-CN` |
| 68 | +- `ru`, `ru_RU`, `ru-RU` -> `ru` |
| 69 | +- Unknown -> `en` |
| 70 | + |
| 71 | +#### Step 1.3: Define stable key families |
| 72 | + |
| 73 | +**Key naming convention**: `{module}.{context}.{item}` |
| 74 | + |
| 75 | +Example keys (to be defined in catalogs): |
| 76 | +``` |
| 77 | +cli.group.help |
| 78 | +cli.load.binary_help |
| 79 | +cli.load.core_help |
| 80 | +cli.load.sysroot_help |
| 81 | +cli.attach.pid_help |
| 82 | +cli.threads.session_help |
| 83 | +cli.threads.range_help |
| 84 | +
|
| 85 | +errors.session_not_found |
| 86 | +errors.connection_error |
| 87 | +errors.ptrace_denied.suggestion |
| 88 | +errors.memory_access_failed.suggestion |
| 89 | +
|
| 90 | +env_check.gdb_not_found |
| 91 | +env_check.gdb_below_minimum |
| 92 | +env_check.ptrace_restricted |
| 93 | +env_check.debuginfo_install_hint |
| 94 | +``` |
| 95 | + |
| 96 | +--- |
| 97 | + |
| 98 | +### Phase 2: Catalog Content (Translation Files) |
| 99 | + |
| 100 | +#### Step 2.1: English catalog (source) |
| 101 | + |
| 102 | +**File**: `src/gdb_cli/locales/en.py` |
| 103 | + |
| 104 | +Extract all user-facing strings from: |
| 105 | +- `cli.py`: 40+ help texts, error messages |
| 106 | +- `errors.py`: 15 suggestion templates |
| 107 | +- `env_check.py`: 20+ warning/suggestion texts |
| 108 | + |
| 109 | +#### Step 2.2: Chinese catalog |
| 110 | + |
| 111 | +**File**: `src/gdb_cli/locales/zh_cn.py` |
| 112 | + |
| 113 | +Many existing texts are already Chinese. Preserve them with key mapping. |
| 114 | + |
| 115 | +#### Step 2.3: Russian catalog |
| 116 | + |
| 117 | +**File**: `src/gdb_cli/locales/ru.py` |
| 118 | + |
| 119 | +Translate all keys from English catalog. |
| 120 | + |
| 121 | +--- |
| 122 | + |
| 123 | +### Phase 3: CLI Integration |
| 124 | + |
| 125 | +#### Step 3.1: Update cli.py Click decorators |
| 126 | + |
| 127 | +**Challenge**: Click evaluates help text at import time. |
| 128 | + |
| 129 | +**Solution**: Use lazy translation helper. |
| 130 | + |
| 131 | +```python |
| 132 | +# Pattern for Click help text |
| 133 | +from .i18n import t |
| 134 | + |
| 135 | +@click.option("--binary", "-b", required=True, help=t("cli.load.binary_help")) |
| 136 | +``` |
| 137 | + |
| 138 | +**Alternative if needed** (deferred evaluation): |
| 139 | +```python |
| 140 | +def lazy_help(key: str): |
| 141 | + return lambda: t(key) |
| 142 | + |
| 143 | +@click.option("--binary", "-b", required=True, help=lazy_help("cli.load.binary_help")) |
| 144 | +``` |
| 145 | + |
| 146 | +#### Step 3.2: Update print_error/print_json messages |
| 147 | + |
| 148 | +Replace hardcoded strings with `t()` calls: |
| 149 | + |
| 150 | +```python |
| 151 | +# Before |
| 152 | +print_error("Session not found", session) |
| 153 | + |
| 154 | +# After |
| 155 | +print_error(t("errors.session_not_found", session_id=session), session) |
| 156 | +``` |
| 157 | + |
| 158 | +#### Step 3.3: Update env_check.py suggestions |
| 159 | + |
| 160 | +Replace all hardcoded suggestions: |
| 161 | + |
| 162 | +```python |
| 163 | +# Before |
| 164 | +report.suggestions.append("Install GDB: 'brew install gdb' (macOS)...") |
| 165 | + |
| 166 | +# After |
| 167 | +report.suggestions.append(t("env_check.gdb_install_suggestion")) |
| 168 | +``` |
| 169 | + |
| 170 | +--- |
| 171 | + |
| 172 | +### Phase 4: README Localization |
| 173 | + |
| 174 | +#### Step 4.1: Update language switchers |
| 175 | + |
| 176 | +**Files**: `README.md`, `README.zh-CN.md` |
| 177 | + |
| 178 | +Add Russian to existing switcher: |
| 179 | +```markdown |
| 180 | +[English](README.md) | [中文](README.zh-CN.md) | [Русский](README.ru.md) |
| 181 | +``` |
| 182 | + |
| 183 | +#### Step 4.2: Create README.ru.md |
| 184 | + |
| 185 | +**Source**: Translate from `README.md` |
| 186 | + |
| 187 | +**Sections to translate**: |
| 188 | +- Title and badges (preserve badge URLs) |
| 189 | +- Features |
| 190 | +- Requirements |
| 191 | +- Installation |
| 192 | +- Quick Start (all 4 subsections) |
| 193 | +- Full Command Reference |
| 194 | +- Output Examples |
| 195 | +- Security Mechanisms |
| 196 | +- Cross-Machine Debugging |
| 197 | +- Development |
| 198 | +- Known Limitations |
| 199 | +- Remote Debugging via SSH |
| 200 | +- License |
| 201 | + |
| 202 | +**Preserve unchanged**: |
| 203 | +- Code blocks (commands, JSON output) |
| 204 | +- URLs and links |
| 205 | +- Badge markdown |
| 206 | + |
| 207 | +--- |
| 208 | + |
| 209 | +### Phase 5: Testing |
| 210 | + |
| 211 | +#### Step 5.1: Unit tests for i18n module |
| 212 | + |
| 213 | +**File**: `tests/test_i18n.py` |
| 214 | + |
| 215 | +**Coverage**: |
| 216 | +- `normalize_locale()` for all alias formats (en_US, zh_CN, ru_RU, etc.) |
| 217 | +- `resolve_locale()` precedence (env var > system > default) |
| 218 | +- `t()` lookup for all three languages |
| 219 | +- `t()` fallback to English on missing key |
| 220 | +- `t()` interpolation with parameters |
| 221 | +- Missing catalog falls back gracefully |
| 222 | + |
| 223 | +#### Step 5.2: Integration tests for CLI |
| 224 | + |
| 225 | +**File**: `tests/test_cli_i18n.py` |
| 226 | + |
| 227 | +**Coverage**: |
| 228 | +- `gdb-cli --help` output in different locales |
| 229 | +- Error messages translated |
| 230 | +- `env-check` suggestions in different locales |
| 231 | +- Key set consistency across catalogs (all have same keys) |
| 232 | + |
| 233 | +#### Step 5.3: Update existing tests |
| 234 | + |
| 235 | +Update `test_env_check.py`, `test_cli_async.py` to use i18n keys instead of hardcoded string matching. |
| 236 | + |
| 237 | +--- |
| 238 | + |
| 239 | +### Phase 6: Rollout Sequence |
| 240 | + |
| 241 | +**Order** (per spec Migration Strategy): |
| 242 | + |
| 243 | +1. Introduce `i18n.py` and `locales/` package |
| 244 | +2. Convert central CLI entry points (`cli.py` main group, load, attach) |
| 245 | +3. Convert remaining CLI commands |
| 246 | +4. Convert `env_check.py` suggestions/warnings |
| 247 | +5. Convert `errors.py` ERROR_SUGGESTIONS |
| 248 | +6. Create `README.ru.md`, update all README switchers |
| 249 | +7. Add tests |
| 250 | + |
| 251 | +--- |
| 252 | + |
| 253 | +## Risks and Mitigations |
| 254 | + |
| 255 | +| Risk | Mitigation | |
| 256 | +|------|------------| |
| 257 | +| Click help evaluated at import time | Use lambda wrapper for deferred evaluation | |
| 258 | +| Catalog key drift across languages | Add test comparing key sets | |
| 259 | +| Partial translation = mixed output | English fallback + prioritize shared wrappers first | |
| 260 | +| README divergence over time | English as source document, sync structure | |
| 261 | + |
| 262 | +--- |
| 263 | + |
| 264 | +## Acceptance Criteria |
| 265 | + |
| 266 | +- [ ] `src/gdb_cli/i18n.py` exists with `t()`, `resolve_locale()`, `normalize_locale()` |
| 267 | +- [ ] `src/gdb_cli/locales/` package with `en.py`, `zh_cn.py`, `ru.py` |
| 268 | +- [ ] Locale precedence: `GDB_CLI_LANG` > system locale > `en` |
| 269 | +- [ ] Normalization: `en_US`->`en`, `zh_CN`->`zh-CN`, `ru_RU`->`ru` |
| 270 | +- [ ] CLI help text in English, Chinese, Russian based on locale |
| 271 | +- [ ] JSON hints/suggestions translated for supported languages |
| 272 | +- [ ] `README.ru.md` exists with language switcher |
| 273 | +- [ ] All READMEs have 3-language switcher |
| 274 | +- [ ] Tests: locale normalization, fallback, representative CLI outputs |
| 275 | +- [ ] Test: key sets match across all catalogs |
| 276 | + |
| 277 | +--- |
| 278 | + |
| 279 | +## Estimated Files Changed |
| 280 | + |
| 281 | +| Category | Count | |
| 282 | +|----------|-------| |
| 283 | +| New files | 5 (`i18n.py`, 3 locales, `README.ru.md`) | |
| 284 | +| Modified files | 4 (`cli.py`, `errors.py`, `env_check.py`, `README.md`, `README.zh-CN.md`) | |
| 285 | +| Test files | 2 new (`test_i18n.py`, `test_cli_i18n.py`) + 2 updated | |
| 286 | + |
| 287 | +--- |
| 288 | + |
| 289 | +## Verification Steps |
| 290 | + |
| 291 | +1. `GDB_CLI_LANG=en gdb-cli --help` -> English output |
| 292 | +2. `GDB_CLI_LANG=zh-CN gdb-cli --help` -> Chinese output |
| 293 | +3. `GDB_CLI_LANG=ru gdb-cli --help` -> Russian output |
| 294 | +4. `GDB_CLI_LANG=invalid gdb-cli --help` -> English (fallback) |
| 295 | +5. `pytest tests/test_i18n.py tests/test_cli_i18n.py -v` -> all pass |
| 296 | +6. `README.ru.md` exists and has valid language switcher |
0 commit comments