GettextOps.Operations.Translate (gettext_ops v0.1.1)
View SourceTranslation update operation for bulk updating msgstr values in .po files.
This module provides functionality to update translations in .po files
from various input sources (stdin, file, or inline). It accepts translations
in a simple format: msgid = msgstr (one per line).
This is the most important command for the LLM workflow, enabling bulk translation updates without manually editing .po files.
Input Format
Each line should contain a msgid and msgstr separated by =:
Sign In = Logga in
Sign Out = Logga ut
Welcome = Välkommen
Error: Invalid input = Fel: Ogiltig inmatningEmpty lines and lines starting with # are ignored.
Entries with a msgctxt
Gettext identifies an entry by the pair {msgctxt, msgid}, so a catalogue may
hold several entries with the same msgid under different contexts. The input
format carries only a msgid, which is resolved as follows:
- exactly one entry has that msgid — it is updated;
- several do — the contextless entry is updated, and context-carrying siblings are left untouched;
- the msgid exists only under two or more contexts — it cannot be resolved,
and is reported in
:ambiguousrather than guessed at.
Atomic Updates
Updates are performed atomically by writing to a temporary file and then renaming it to the original file. This prevents corruption if the operation fails midway.
Options
:locale- (required) The locale to update (e.g., "sv", "en"):domain- The domain to update (defaults to configured default_domain):force- Continue even if some msgids are not found or ambiguous (default: false)
Examples
# Parse translation input
{:ok, translations} = GettextOps.Operations.Translate.parse_translations("""
Sign In = Logga in
Sign Out = Logga ut
""")
# Apply translations
{:ok, result} = GettextOps.Operations.Translate.run(translations, locale: "sv")
# => {:ok, %{updated: 2, not_found: []}}
# With force flag (ignore missing msgids)
{:ok, result} = GettextOps.Operations.Translate.run(translations, locale: "sv", force: true)
Summary
Functions
Parse translation input in msgid = msgstr format.
Accepts a string with one translation per line. Empty lines and lines
starting with # are ignored. Lines that don't contain = are silently
skipped.
Returns {:ok, translations_map} where the map has msgid as keys and
msgstr as values.
Examples
iex> input = """
...> Sign In = Logga in
...> Sign Out = Logga ut
...> # This is a comment
...>
...> Welcome = Välkommen
...> """
iex> {:ok, translations} = GettextOps.Operations.Translate.parse_translations(input)
iex> translations
%{"Sign In" => "Logga in", "Sign Out" => "Logga ut", "Welcome" => "Välkommen"}
@spec run( map(), keyword() ) :: {:ok, %{ updated: non_neg_integer(), not_found: [String.t()], ambiguous: [{String.t(), [String.t()]}] }} | {:error, term()}
Apply translations to a .po file.
Takes a map of translations (msgid => msgstr) and updates the corresponding entries in the .po file for the given locale.
Parameters
translations- Map of msgid => msgstr to applyopts- Keyword list of options (see module documentation)
Returns
{:ok, result}- Success with update statistics{:error, reason}- Failure with error reason
The result map contains:
:updated- Number of translations successfully applied:not_found- List of msgids that were not found in the .po file:ambiguous- List of{msgid, contexts}for msgids that exist only under two or more differentmsgctxtvalues and so could not be resolved
Examples
# Update translations
translations = %{"Sign In" => "Logga in", "Sign Out" => "Logga ut"}
{:ok, result} = GettextOps.Operations.Translate.run(translations, locale: "sv")
# => {:ok, %{updated: 2, not_found: []}}
# With missing msgid (without force)
translations = %{"Nonexistent" => "Translation"}
{:error, reason} = GettextOps.Operations.Translate.run(translations, locale: "sv")
# => {:error, "msgid not found: Nonexistent"}
# With missing msgid (with force)
{:ok, result} = GettextOps.Operations.Translate.run(translations, locale: "sv", force: true)
# => {:ok, %{updated: 0, not_found: ["Nonexistent"]}}