mix phoenix_kit_ecommerce.backfill_translation_fingerprints (PhoenixKitEcommerce v0.5.11)

Copy Markdown View Source

ONE-SHOT backfill (design §4.1, owner's decision 2026-09-03): stamps the CURRENT source text as the reference fingerprint for every existing shop translation. Every product/category that already has a translation for a language moves to :fresh the moment this runs, so the staleness sweep (design §4.3) starts from an empty queue instead of re-translating the entire catalog on its first tick — 634 resources (627 products + 7 categories, per the design doc's §2 measurement) is the concrete number this was written against.

Deliberately blunt: it does not check whether a stored translation is ACTUALLY faithful to its source — it declares "whatever is live today is the reference," which is the accepted cost (design §4.1: "если какой-то из существующих переводов уже разошёлся с источником, это расхождение замораживается"). Never run this a second time against a catalog that has been live under the sweep — it would re-freeze any drift the sweep had since correctly caught as :stale, silently un-flagging it. It IS safe to re-run against a catalog that has acquired brand-new translations no reference exists for yet (a fresh import, a manual translation done outside this pipeline) — for those, stamping a reference is exactly the intended, idempotent behavior.

A field with no source, or no translation, is left alone — nothing to stamp; per design §4.1 it still resolves as :missing or has no state at all, never :stale.

Usage

mix phoenix_kit_ecommerce.backfill_translation_fingerprints
mix phoenix_kit_ecommerce.backfill_translation_fingerprints --dry-run
mix phoenix_kit_ecommerce.backfill_translation_fingerprints --source-lang en-US --languages de-DE,fr-FR

Options

  • --dry-run — report how many rows per table WOULD be touched, without writing.
  • --source-lang — defaults to PhoenixKitEcommerce.Translations.default_language/0.
  • --languages — comma-separated target languages; defaults to every enabled language except the source (mirrors design §4.6's default for the shop_translation_languages setting).

Safety

This task touches ONLY the metadata column (the _translation_fingerprints key within it) — it never writes translated content, slugs, or any other field. Each table gets exactly one UPDATE, matching the cost design §2 measured for a full-catalog hash pass (tens of milliseconds, not a per-row loop). Run it against the shared stand only as the project's own separate, explicitly announced live-verification step (see the project's worktree instructions) — never as a byproduct of running this package's tests, and never against the dev database from a throwaway checkout.

Summary

Functions

The backfill itself, factored out of run/1 so it can be exercised directly against a test database without going through Mix.Task.run("app.start"). One UPDATE (or, with dry_run: true, one SELECT count(*)) per table — see the moduledoc for exactly what it touches. Returns [{table_name, affected_row_count}].

Functions

backfill(repo, source_lang, target_langs, opts \\ [])

@spec backfill(Ecto.Repo.t(), String.t(), [String.t()], keyword()) :: [
  {String.t(), non_neg_integer()}
]

The backfill itself, factored out of run/1 so it can be exercised directly against a test database without going through Mix.Task.run("app.start"). One UPDATE (or, with dry_run: true, one SELECT count(*)) per table — see the moduledoc for exactly what it touches. Returns [{table_name, affected_row_count}].