Detect, validate, synchronize, and auto-translate missing entries in locale JSON files.
LocaleSync is a Python CLI tool that keeps your i18n locale files in sync. It scans a directory of JSON translation files, detects missing keys, and fills them — optionally translating values into the correct target language automatically.
Teams maintaining en.json, pl.json, de.json, etc. no longer need to manually track which keys are missing where. Run locale-sync check in CI to catch drift early, or locale-sync translate to auto-fill gaps with real translations. Works with any project type — Angular, React, Vue, Node.js, or plain static sites.
- Scan — discover locale files in any directory
- Check — validate completeness, fail CI if keys are missing
- Sync — fill missing keys with English source text (for manual translation later)
- Translate — fill missing keys and translate values via Google Translate
- Safe — atomic writes, dry-run mode, backup support, stable sorted output
- Extensible — architecture supports custom translation providers, reporters, and file formats
Auto-translating locale files via Google Translate — with progress, ETA, and language counter.
- Quick Start
- Installation
- Commands
- Update Strategies
- Key Features
- CI/CD Integration
- Cross-Project Usage
- Playground
- Architecture
- Project Structure
- Development
- Testing Philosophy
- Documentation
- Author
- License
pip install -e ".[dev]"
locale-sync scan ./locales # Discover locale files
locale-sync check ./locales # Validate (exit code 1 if incomplete)
locale-sync sync ./locales # Fill missing keys (copies English text)
locale-sync translate ./locales # Fill missing keys AND translate to target language
syncvstranslate:syncadds missing keys with English source text (for manual translation later).translateadds missing keys and translates them into Polish, German, French, etc.
Requirements: Python 3.12+
| Method | Command | Best for |
|---|---|---|
| From source | pip install -e ".[dev]" |
Contributing to LocaleSync |
| From GitHub | pip install git+https://github.com/polprog-tech/LocaleSync.git |
CI pipelines, direct use |
| Via pipx | pipx install git+https://github.com/polprog-tech/LocaleSync.git |
Developer machines (isolated CLI) |
| Pinned version | pip install git+https://github.com/polprog-tech/LocaleSync.git@v0.1.0 |
Reproducible CI builds |
git clone https://github.com/polprog-tech/LocaleSync.git
cd LocaleSync
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
locale-sync --versionWhy
pip install -e ".[dev]"works: The repository root contains a PEP 621pyproject.tomlwith a complete package definition. The[dev]extra includes pytest, pytest-cov, and ruff. The-eflag enables editable mode.
Use pipx for an isolated system-wide install — no virtual environment needed:
pipx install git+https://github.com/polprog-tech/LocaleSync.git
locale-sync --versionSee Cross-Project Usage for npm integration and CI setup.
locale-sync scan ./locales
locale-sync scan ./locales --format json
locale-sync scan # auto-discovers locale directories from CWDIf the specified directory doesn't exist or contains no locale files, LocaleSync automatically searches subdirectories to find locale file groups. Files are recognized as locale files only if their name matches a valid locale code pattern (e.g., en.json, pl.json, zh-Hans.json). Non-locale JSON files like manifest.json or package.json are ignored.
locale-sync check ./locales
locale-sync check ./locales --source en.json
locale-sync check ./locales --target pl.json --target de.json
locale-sync check ./locales --format jsonlocale-sync sync ./locales
locale-sync sync ./locales --strategy fill_empty
locale-sync sync ./locales --strategy force_overwrite
locale-sync sync ./locales --dry-run
locale-sync sync ./locales --backup
locale-sync sync ./locales --sort-keys # always sort alphabetically
locale-sync sync ./locales --no-sort-keys # never sort, new keys at end
locale-sync sync ./locales --indent 4By default, key ordering is automatic: files with ≤200 keys are sorted alphabetically, larger files preserve insertion order with new keys appended at the end. Use --sort-keys or --no-sort-keys to override.
locale-sync translate ./locales
locale-sync translate ./locales --provider demo
locale-sync translate ./locales --dry-run
locale-sync translate ./locales --strategy fill_emptyUses Google Translate by default. A built-in DemoTranslator is available for offline/testing use (--provider demo). Phrases the demo translator can't handle fall back to source text.
locale-sync translate ./locales # Google Translate (default)
locale-sync translate ./locales --provider demo # Offline dictionary (5 languages)
locale-sync translate ./locales --dry-run # Preview without writingsync vs translate:
sync |
translate |
|
|---|---|---|
| Adds missing keys | ✅ | ✅ |
| Translates values | ❌ (copies English) | ✅ (language-specific) |
| Preserves existing | ✅ | ✅ |
All commands accept --source, --target, --format, and --verbose flags. Run locale-sync <command> --help for full details.
| Strategy | Behavior |
|---|---|
fill_missing |
Only add keys that don't exist in target (default — safe) |
fill_empty |
Add missing keys AND fill empty string values |
force_overwrite |
Overwrite all values from source — use with caution |
Fully supports deeply nested locale structures. Keys are compared as dot-paths internally (auth.login.title) and reconstructed as nested JSON on write.
{
"auth": {
"login": { "title": "Sign In", "subtitle": "Welcome back" },
"logout": "Sign Out"
}
}Preserves placeholders during translation: {name}, {{count}}, ${value}, %s, %d, {0}. Dedicated detection, protection, restoration, and validation pipeline.
Preview all changes without modifying files:
locale-sync sync ./locales --dry-runAtomic file writes (temp file + os.replace), optional .bak backups, UTF-8 encoding with human-readable non-ASCII output.
Consistent formatting produces minimal, predictable diffs — ideal for PR review workflows. Small files (≤200 keys) are sorted by default; large files preserve order to avoid noisy diffs.
LocaleSync is fully non-interactive when invoked with CLI arguments: no prompts, deterministic output, meaningful exit codes.
| Code | Meaning |
|---|---|
0 |
Success — all locale files are complete |
1 |
Validation failure — missing keys detected |
2 |
Input error — bad path, malformed JSON, missing source |
3 |
Runtime error — unexpected failure |
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install git+https://github.com/polprog-tech/LocaleSync.git
- run: locale-sync check ./locales --source en.jsonFor full CI workflow examples, see docs/usage.md and docs/integration.md.
LocaleSync works with any repository that has JSON locale files. It makes no assumptions about the surrounding project structure, framework, or build system.
{
"scripts": {
"locales:check": "locale-sync check src/assets/i18n --source en.json",
"locales:sync": "locale-sync sync src/assets/i18n --source en.json",
"locales:translate": "locale-sync translate src/assets/i18n --source en.json",
"locales:sync:preview": "locale-sync sync src/assets/i18n --source en.json --dry-run"
}
}{
"scripts": {
"locales:check": "locale-sync check public/locales",
"locales:sync": "locale-sync sync public/locales",
"locales:translate": "locale-sync translate public/locales",
"locales:scan": "locale-sync scan public/locales"
}
}npm run locales:check
npm run locales:translateLocaleSync is not an npm package. These scripts invoke it as an external CLI command. Install it separately via
piporpipxbefore running npm scripts.
# GitHub Actions — works in any repository
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install git+https://github.com/polprog-tech/LocaleSync.git
- run: locale-sync check src/assets/i18n --source en.jsonThe examples/ directory contains ready-to-use integration templates:
| Example | Description |
|---|---|
examples/angular-project/ |
Angular app with package.json scripts and CI workflow |
examples/react-project/ |
React app with react-i18next, package.json scripts, and CI workflow |
examples/generic-project/ |
Generic non-Python project with Makefile and CI workflow |
# Try them directly
locale-sync check examples/angular-project/src/assets/i18n --source en.json
locale-sync check examples/react-project/public/locales --source en.json
locale-sync check examples/generic-project/locales --source en.json| Guide | Covers |
|---|---|
| Cross-Project Integration | Installation models, npm integration, standalone vs embedded, frontend team onboarding |
| Angular Guide | Angular i18n setup, package.json scripts, CI workflows, team conventions |
| React Guide | React i18next setup, package.json scripts, CI workflow, Vite/Next.js notes |
| Best Practices | Design rationale, trade-offs, architectural decisions |
The playground/ directory provides a hands-on demo environment with realistic locale files:
locale-sync scan playground/locales # Discover 4 locale files
locale-sync check playground/locales # Find missing keys across targets
locale-sync sync playground/locales --dry-run # Preview sync changes (English fill)
locale-sync translate playground/locales --dry-run # Preview translated output
locale-sync translate playground/locales # Actually translate to pl/de/fr
bash playground/scripts/demo.sh # Run interactive demo
git checkout -- playground/locales/ # Reset after experimentingIncludes 4 locale files (en.json, pl.json, de.json, fr.json) with nested structures, placeholder patterns ({name}, {{count}}, ${amount}, %d), and varying completeness levels. The translate command fills missing keys with real language-specific translations — Polish in pl.json, German in de.json, French in fr.json.
See playground/README.md for full details.
LocaleSync uses a four-layer architecture with strict separation of concerns:
src/locale_sync/
├── domain/ # Core models, contracts (Protocols), policies, comparator, placeholder
├── application/ # Use cases — scan, check, sync orchestration
├── infrastructure/ # File I/O, JSON parsing/writing, translators, reporters
└── cli/ # Typer commands, formatters, interactive prompts
Key design choices:
- Protocol-based contracts — structural subtyping, no import dependencies between layers
- Dependency injection — use cases accept any implementation satisfying the protocol
- Strategy pattern — enum-backed update policies, no scattered conditionals
- Decorator pattern — placeholder-aware translator wraps any translation provider
- Atomic writes — temp file +
os.replacefor crash-safe file operations - Generic core — no project-type assumptions; Angular/React/Vue awareness lives only in documentation
See docs/architecture.md for the full architectural overview.
LocaleSync/
├── pyproject.toml # Package configuration (PEP 621)
├── Makefile # Convenience commands
├── README.md # This file
├── LICENSE # MIT license
├── CONTRIBUTING.md # Contributor guide
├── CODE_OF_CONDUCT.md # Community standards
├── .gitignore
│
├── .github/
│ ├── workflows/ci.yml # CI pipeline (test + lint)
│ ├── ISSUE_TEMPLATE/ # Bug report, feature request
│ └── pull_request_template.md
│
├── src/locale_sync/ # Source package
│ ├── domain/ # Models, contracts, policies, exceptions
│ ├── application/ # Use cases (scan, check, sync)
│ ├── infrastructure/ # Parsers, writers, translators, reporters
│ └── cli/ # Typer commands, formatters
│
├── tests/ # pytest suite (265+ tests)
│ ├── unit/{domain,infrastructure,application}/
│ └── integration/
│
├── playground/ # Demo environment with sample locales
│ ├── locales/ # en.json, pl.json, de.json, fr.json
│ └── scripts/demo.sh
│
├── examples/ # Integration examples
│ ├── angular-project/ # Angular + package.json + CI
│ ├── react-project/ # React + react-i18next + CI
│ └── generic-project/ # Generic project + Makefile + CI
│
└── docs/ # Documentation
├── architecture.md # Layered architecture overview
├── usage.md # Detailed usage guide
├── extensibility.md # Adding translators, parsers, formats
├── testing.md # Test strategy and instructions
├── integration.md # Cross-project integration
├── angular-guide.md # Angular-specific guide
├── react-guide.md # React-specific guide
└── best-practices.md # Design rationale
git clone https://github.com/polprog-tech/LocaleSync.git
cd LocaleSync
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
locale-sync --version # locale-sync 0.1.0
pytest # 265+ passedmake quickstart
⚠️ This shortcut may not work in every environment due to differences in shell, OS, Python installation, or local configuration. If it fails, use the step-by-step instructions above.
make test # Run tests
make test-cov # Run tests with coverage
make lint # Run ruff linter
make format # Auto-format code
make playground-demo # Run interactive demo
make playground-reset # Reset playground files
make clean # Remove build artifacts
make help # Show all available commandspytest
pytest --cov=locale_sync --cov-report=term-missing
ruff check src/ tests/
ruff format src/ tests/See CONTRIBUTING.md for the full contributor guide.
All tests follow the GIVEN / WHEN / THEN structure with explicit docstring markers:
def test_sync_fills_missing_keys(self, tmp_path: Path) -> None:
"""GIVEN source with keys, target missing some"""
(tmp_path / "en.json").write_text('{"a": "A", "b": "B"}')
(tmp_path / "pl.json").write_text('{"a": "X"}')
"""WHEN sync is executed"""
self._make_use_case().execute(config)
"""THEN target contains both keys with existing value preserved"""
pl = json.loads((tmp_path / "pl.json").read_text())
assert pl["a"] == "X"
assert pl["b"] == "B"This structure is applied consistently across the entire test suite (265+ tests) to ensure:
- Readability — any engineer can immediately understand what a test does.
- Traceability — preconditions, actions, and expectations are explicitly separated.
- Review quality — reviewers can validate each section independently.
See docs/testing.md for the full testing strategy.
| Document | Description |
|---|---|
| Usage Guide | Detailed command reference, source/target selection, output formats |
| Architecture | Layer responsibilities, design decisions, extension points |
| Extensibility | Adding translators, parsers, file formats, reporters |
| Testing | Test strategy, running tests, writing new tests |
| Integration | Cross-project usage, npm scripts, CI for non-Python repos |
| Angular Guide | Angular-specific setup, workflows, team conventions |
| React Guide | React i18next setup, CI workflow, Vite/Next.js notes |
| Best Practices | Design rationale, trade-offs, engineering decisions |
Created and maintained by POLPROG (@POLPROG).
MIT — see LICENSE