v2.3.0 — Linter-friendly file writes
Added
- Linter-friendly writes — File handlers (PHP, JSON, CSV) now compare the new content against what's already on disk before writing. If the result is identical, including key order, the write is skipped entirely. A file already formatted by the user's linter (Pint, PHP-CS-Fixer, Prettier, …) is left untouched as long as its translations and ordering match the new state.
Concerns\ComparesTranslationstrait — strict-equality check (viajson_encode) plus a leaf-level diff counter, used by all three file handlers.- Idempotency tests — every file handler now has a
returns 0 when content is unchangedregression test.
Changed
- Return semantics of
put()/set()— the integer returned now represents the number of translations actually changed (added, modified, or removed), not the total count in the input collection. A no-op write returns0. sync()/import()/export()return type — changed frombooltofalse|int.falsesignals an actual failure (the source has no translations to read); any integer (including0) signals success and reports how many translations were changed in the destination.SyncCommand,ImportCommand,ExportCommand, and the deprecated bareCommand— after the main success message, the command now prints eitherAlready in sync.orN translation(s) changed..SetCommand— whenset()returns0, the command checks whether the current value already matches the requested one. If it does, the command printsTranslation already set!and returnsSUCCESS(previously this case was reported asFAILURE).- MCP tools —
set-translation-toolnow also exposes the integercountfield next towritten;sync-translations-toolnow exposessuccess(bool) andcount(int).
Why
The previous behavior rewrote every file on every operation, even when nothing had changed. Combined with code formatters that normalize array syntax / indentation / quoting, this produced spurious diffs in git on every sync and forced the formatter to run again afterwards. Comparing parsed content (not raw bytes) makes the operation a true no-op when the resulting state matches.
Full Changelog: v2.2.0...v2.3.0