rebar3_erli18n_extract_forms (rebar3_erli18n v0.1.0)

Copy Markdown View Source

Abstract-form extractor for erli18n facade call sites.

Reads an Erlang source file through epp (NOT text scanning), so every macro — including the public ?GETTEXT_DOMAIN from include/erli18n.hrl — is expanded to a literal node BEFORE the walk. It then walks the parsed forms looking for remote calls erli18n:Fn(Args) whose {Fn, Arity} is in the keyword spec (rebar3_erli18n_keywords), and pulls the literal msgid/msgid_plural/msgctxt and the literal-atom Domain.

What is extractable, what is skipped

Only COMPILE-TIME-CONSTANT operands are extracted, exactly as Elixir Gettext documents the dynamic-key caveat:

  • msgid/msgid_plural/msgctxt must be a literal string ("...") or a literal binary (<<"...">> / ~"..."). A variable, concatenation, or any other expression in those slots SKIPS the whole call site — never errors.
  • Domain (d/dc families) must be a literal atom after expansion. A non-literal Domain SKIPS the call site rather than mis-domaining it. The bare families (no Domain slot) are keyed under the module's ?GETTEXT_DOMAIN, which epp has already expanded to a literal atom.

This is what guarantees the check gate never false-fails on a legitimately dynamic key: a dynamic operand simply produces no .pot entry.

Output

extract_file/2 returns a list of extracted() records — one per recognized call site — carrying the source reference {File, Line} so the .pot writer can emit #: reference lines.

Summary

Types

One extracted catalog entry plus its source location.

Functions

Parse File through epp and extract every recognized erli18n call site, using the module's own ?GETTEXT_DOMAIN for bare-family calls.

Parse File through epp ONCE, returning both the module's expanded ?GETTEXT_DOMAIN and the extracted call sites.

Types

extracted()

-type extracted() ::
          #{domain := atom(),
            kind := rebar3_erli18n_keywords:kind(),
            context := undefined | binary(),
            msgid := binary(),
            plural := undefined | binary(),
            reference := {file:filename(), pos_integer()}}.

One extracted catalog entry plus its source location.

domain is the resolved literal atom. kind is singular or plural. context is undefined or the literal binary msgctxt. msgid is the literal binary. plural is undefined (singular) or the literal binary msgid_plural. reference is {RelPath, Line} for the #: line.

Functions

extract_file(File, IncludeDirs)

-spec extract_file(file:filename(), [file:filename()]) -> {ok, [extracted()]} | {error, term()}.

Parse File through epp and extract every recognized erli18n call site, using the module's own ?GETTEXT_DOMAIN for bare-family calls.

A thin wrapper over scan_file/2 that drops the resolved domain. Returns {ok, [extracted()]} on success, or {error, Reason} if epp cannot open the file.

scan_file(File, IncludeDirs)

-spec scan_file(file:filename(), [file:filename()]) -> {ok, atom(), [extracted()]} | {error, term()}.

Parse File through epp ONCE, returning both the module's expanded ?GETTEXT_DOMAIN and the extracted call sites.

This is the single-pass entry point the provider walk uses: it opens one epp handle, drains every form (so all -define/-include directives are applied), reads ?GETTEXT_DOMAIN from the macro table, and walks the drained forms for facade call sites — avoiding a second parse and the redundant error branch a two-call sequence would carry.

Returns {ok, Domain, [extracted()]} or {error, Reason} when epp cannot open the file.