Patch release fixing data loss in mix gettext_ops.translate. If you are on
v0.1.0 and have ever run translate, upgrade and check your catalogues.
Fixed
-
Catalogue corruption in
translate(data loss). Entries were keyed by
msgid alone, but gettext identifies an entry by the pair{msgctxt, msgid}.
Any two entries sharing a msgid collapsed onto whichever one won, so a
contextlessmsgid "Active"was rewritten to carrymsgctxt "token status".
The resulting file has two identical entries andExpo.PO.parse_file!/1
refuses to read it, breaking compilation of the whole application.This fired on every write, including a single-string call, and on msgids
that were never in the translation input — translating one unrelated string
silently collapsed every duplicate-msgid pair in the catalogue. -
Silent corruption in
change_msgid. Renaming a msgid onto one the file
already used produced an unreadable catalogue and still reported{:ok, ...}.
The rename is now refused and the file left untouched. -
Writer.update_translations/2overwriting the wrong entries. A bare msgid
overwrote every entry sharing it, including context-carrying siblings that are
distinct translations.
Added
GettextOps.Entry.get_msgctxt/1andGettextOps.Entry.key/1, exposing the
{msgctxt, msgid}identity of an entry.nil,[]and""all normalise to
"no context", matching Expo.GettextOps.Writer.check_duplicates/1, run before every write so a would-be
corruption surfaces as a loud error instead of an unreadable .po file.translatereports an:ambiguouslist for msgids that exist only under two
or more different contexts, rather than silently picking one. Without
--forcethis is an error; with--forcethey are skipped and listed.msgctxtis included in text and JSON output, sosearchand
list_untranslatedresults distinguish entries that share a msgid.
Changed
translateresolves a bare msgid to the contextless entry when several
entries share that msgid. Previously the choice was arbitrary.Writer.update_translations/2accepts{msgctxt, msgid}tuple keys to target
a context-carrying entry. A bare msgid string now matches only the contextless
entry — it no longer overwrites context-carrying siblings.
Upgrading
Additive to the result map — existing result.updated / result.not_found
access is unaffected. Two behaviour changes to be aware of:
translatewithout--forcenow returns{:error, ...}for a msgid that
exists only under two or more contexts, instead of writing a corrupt file.change_msgidnow returns{:error, ...}where it previously returned
{:ok, ...}and corrupted the file.
Full Changelog: v0.1.0...v0.1.1