hl run reads gettext .pot templates and keeps message context and plural forms as separate keys. hl check and hl validate flag ICU plural categories the target locale never selects. Comments and notes from several catalogs travel with the string. Word and PowerPoint writeback drops placeholder names a model copied as plain text.
View the GitHub release · Full changelog
Breaking changes
- Gettext keys change shape. A singular entry with
msgctxtismsgctxt||msgid. A plural entry is one key per category, such asmsgid||oneandmsgid||other, ormsgctxt||msgid||onewhen context is set. The firsthl runafter upgrade translates those strings again and writes new lockfile entries. A lockfile entry that still uses the baremsgidfills theoneslot. See Translate gettext PO. hl entriesprints a key that has parser context as an object withtextandcontext. Keys without context stay plain strings.
Features
- Translate gettext
.pottemplates and plural catalogs. An emptymsgstrfalls back tomsgid, and an empty plural slot other thanonefalls back tomsgid_plural. A source catalog that already stores English inmsgstrkeeps usingmsgstr. AddX-Crowdin-SourceKey: msgstrto the header when an emptymsgstrmust stay empty. Translator comments (#) and extracted comments (#.) go to the model as context. Obsolete entries (#~) stay in the file and are skipped. Writeback setsLanguageto the target locale, writes the matchingPlural-Formsrule, removes afuzzyflag, and leaves other flags in place.hl syncuploads.potas gettext. See Translate gettext PO. - Flag unreachable ICU plural cases.
hl checkandhl validatereportunreachable_plural_casewhen a target keeps apluralorselectordinalcategory the locale never selects, such asonein Japanese. The check is an error.--fixcan retranslate it, and--diff-stdinincludes it with the other key-scoped checks. A custom--policy-filemay omit the check;validatethen enables it as an error. Seecheckandvalidate. - Send file comments and notes with the string.
hl runnow includes a preceding Android XML comment, an immediate YAML#comment, a RESX or RESW<comment>or<note>, a leading Apple.stringscomment, an.xcstringscomment, and an XLIFF<note>. The nexthl runtranslates a key again when that context is new.hl entriesalso returns a FormatJSdescriptionand a JSONC comment incontext. Markdown and AsciiDoc lock entries ignore structural hints, so those documents stay cached.
Fixes
- Drop leaked Office placeholder names during Word and PowerPoint writeback. A translation that copies
HLOXPH_…as plain text loses that copy, and a paragraph segment no longer keeps trailing spaces. Real placeholder tokens stay in place. See Translate Word documents and Translate PowerPoint decks. - Escape quotes in XLIFF attributes on every write path that builds a start tag, including target attributes, inline-code wrappers, and edited attributes.
Performance
- JSONC comment attachment skips key decoding for leaves that have no comment.
- Gettext parsing scans the catalog as bytes instead of splitting it into lines, and writeback quotes
msgstrvalues through one writer (#2919). - INI parsing detects unescaped quoted values with
IndexByte, and writeback grows the output buffer from the template size.
Tests
- Gettext
msgctxt, plural categories,.potmsgid fallback,X-Crowdin-SourceKey: msgstr, and localePlural-Formson writeback. unreachable_plural_caseinhl check, including--fix.hl entriescontext for FormatJS descriptions.- XLIFF attribute quoting.
- Word and PowerPoint cleanup of leaked placeholder names.
Maintenance
- Bump Go dependencies, including OpenAI Go to v3.84.0, WorkOS Go to v10.6.0, Orchestrion to v1.14.0, and
dd-trace-goto v2.11.2 (#2930).

