hl run translates editable text layers in Lottie JSON and dotLottie archives, and can copy a whole target catalog from another locale with locales.copies. sync push and sync pull honor optional cloud_path aliases so Cloud file identity stays stable when local paths move. PO parse/marshal, Liquid scanning, and eval scoring are faster.
View the GitHub release · Full changelog
Breaking changes
None.Features
- Add Lottie and dotLottie support. Text layers (
ty: 5), including those inside precompositions, are keyed as JSON paths such aslayers[1].t.d.k[0].s.t. A.jsonfile whose root hasv,fr,ip,op, andlayersis treated as a Lottie animation rather than a JSON catalog..lottiearchives translate every animation underanimations/(dotLottie 1.0) ora/(dotLottie 2.0); keys are prefixed with the entry name. Writeback replaces only text string literals. Shapes, keyframes, fonts, timing, manifests, images, themes, and state machines stay unchanged. - Add
locales.copiesso a target locale can ship as a copy of another catalog, for exampleen-AU: en-GB.hl runstill writes the copy locale’s files. It skips LLM and MT for that locale and copies origin values instead. The origin must belocales.sourceor another target that is not itself a copy. Copy locales cannot share atopath with their origin, combine withlocales.fallbackson the same locale, or copy another copy.hl run --locale en-AUreads existing origin files; missing origin files fail with an instruction to translate the origin first. Image copies convert origin bytes when the destination extension differs (banner.png→banner-en-AU.webp). - Add optional
files[].cloud_pathso Hyperlocalise Cloudsync pushandsync pullkeep the existing Cloud source identity when localfrom/topaths change. The alias accepts{{source}}and the same glob suffix asfrom. Recursive mappings preserve nested relative paths. Distinct local files need distinct Cloud paths; collisions and unsafe segments fail before network requests. Localrun,check,status, andpackkeep using the local paths.
Fixes
None.Performance
- GNU gettext PO parse/marshal uses
strings.IndexByteinstead ofstrings.ContainsAnywhen unquoting values: about 35% faster parse and 23% faster marshal. - Liquid tag-name scanning matches skipped block names on raw bytes without
strings.ToLower, and skips placeholder-token extraction when no Liquid sentinels are present. - Eval scoring reuses source text analysis when the candidate matches the source, inlines brace/printf token scans, and returns static strings for common HTML tags.
Tests
- Lottie JSON detection, text-layer extract/writeback (including precomps and indented templates), and byte-stable no-op marshal.
- dotLottie v1
animations/and v2a/extract, rewrite of only changed animations, entry names that contain#, and deterministic archive rebuild. locales.copiesconfig validation, planning marks copy tasks,runtranslates the origin once, copy-only--localereuses origin files, copy-from-source writes source text with no provider calls, and image extension conversion.cloud_pathvalidation, collision rejection, and Cloud sync push/pull identity vs local write paths.- Liquid skip-block Bolt edges.
Maintenance
- Bump Go dependencies, including the Crowdin API client to v0.19.0, Phrase Go to v4.32.0, OpenAI Go to v3.71.1, goldmark to v2.1.6, and OpenTelemetry to v1.47.0. (#2665)

