# `PhoenixKitEcommerce.TranslationSweepSettings`
[🔗](https://github.com/BeamLabEU/phoenix_kit_ecommerce/blob/0.5.11/lib/phoenix_kit_ecommerce/translation_sweep_settings.ex#L1)

Settings that drive the AI-translation reconciliation sweep (design §4.3,
§4.6). Read-only, like `PhoenixKitEcommerce.Policy` — writing these keys
is the admin UI's job (design §4.5's operational panel, §4.6's existence
card), through the same `Settings.update_setting_with_module/3` /
`update_boolean_setting_with_module/3` / `update_json_setting_with_module/3`
recipe every other shop setting uses. This module exists so the worker
(and, later, the management page) never hand-roll a key string or a
default twice.

## Keys

| Setting | Type | Default | Meaning |
|---|---|---|---|
| `shop_translations_enabled` | bool | `false` | The translations feature exists at all: page, menu entry, manual actions. Owned by the `/admin/shop/settings` existence card — the sweep only reads it. |
| `shop_translation_sweep_enabled` | bool | `false` | The background tick is allowed to enqueue work on its own. |
| `shop_translation_interval_minutes` | int | `60` | Minutes between ticks. |
| `shop_translation_batch` | int | `3` | Resources (products + categories combined) a tick may select. |
| `shop_translation_max_in_flight` | int | `6` | Ceiling on incomplete `TranslateWorker` **jobs** (not resources) contributed by the shop, counted across `available`/`scheduled`/`executing`/`retryable` — the same states `PhoenixKitAI.Translations` itself dedups against. |
| `shop_translation_languages` | json | every enabled language except the primary | Target languages the sweep translates into. |
| `shop_translation_statuses` | json | `["active"]` | Product statuses the sweep considers. Categories are never filtered by this (design §4.3: a hidden category would otherwise ship translated navigation before it's visible). |

`shop_translations_enabled` gates `shop_translation_sweep_enabled`
one-directionally (design §12.4): the sweep never runs without the
section, but the section can exist with the sweep off ("manual only").
Enforcing that direction is the tick's job (`TranslationSweepWorker`
checks both), not this module's — a reader here has no side effects.

Every reader tolerates a missing or malformed stored value by falling
back to its documented default rather than raising, mirroring `Policy`:
a hand-edited settings row must degrade the sweep to "off", never crash
the tick or open it wider than configured.

# `batch_size`

```elixir
@spec batch_size() :: non_neg_integer()
```

Resources (products + categories combined) a tick may select. Default `3`.

# `interval_minutes`

```elixir
@spec interval_minutes() :: pos_integer()
```

Minutes between ticks. Default `60`. Never below 1.

# `languages`

```elixir
@spec languages() :: [String.t()]
```

Target languages, intersected with currently-enabled languages on every
read (design §4.6): a language disabled after this setting was saved
silently drops out here rather than being sweep-queued for a language
the storefront no longer serves. When nothing is stored, defaults to
every enabled language except the primary.

Blank codes are dropped whatever their source. `languages_config` will
hand one back verbatim if a row was ever saved with an empty `code`, and
a blank target is worse than useless downstream: the candidate SQL
matches EVERY resource for it (`nullif(p.<F>->>'','')` is always null),
while `PhoenixKitAI.Translations.enqueue/1` rejects every resulting job
as `{:invalid, [:target_lang]}` — a sweep that fills its batch with the
same resources every tick and never enqueues anything.

# `max_in_flight`

```elixir
@spec max_in_flight() :: non_neg_integer()
```

Ceiling on incomplete `TranslateWorker` jobs the shop may have in flight
at once. Default `6`.

# `statuses`

```elixir
@spec statuses() :: [String.t()]
```

Product statuses the sweep considers (design §4.3: categories are never
filtered this way). Default `["active"]`.

# `sweep_enabled?`

```elixir
@spec sweep_enabled?() :: boolean()
```

May the background tick enqueue work on its own? Default `false`.

# `translations_enabled?`

```elixir
@spec translations_enabled?() :: boolean()
```

Does the translations feature exist (page, menu, manual actions)? Default `false`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
