# `PhoenixKitCatalogue.AITranslatable`
[🔗](https://github.com/BeamLabEU/phoenix_kit_catalogue/blob/0.8.0/lib/phoenix_kit_catalogue/ai_translatable.ex#L1)

`PhoenixKitAI.Translatable` adapter for catalogue resources —
the small per-module hook into PhoenixKitAI's generic AI-translation pipeline.

Serves three resource types (`"catalogue"`, `"catalogue_category"`,
`"catalogue_item"`), each translating `name` + `description`. Source text
and translations live in the shared `data` JSONB via
`PhoenixKit.Utils.Multilang` (primary value as base, per-language
overrides), so AI-filled languages round-trip through the multilang form
unchanged.

## Field-key convention

The multilang form stores each per-language override under an
**underscore-prefixed** key (`data[lang]["_name"]`, `data[lang]["_description"]`
— see `PhoenixKitWeb.Components.MultilangForm`). The AI engine, however,
speaks plain field names (`"name"` / `"description"`) for prompt
variables + `---MARKER---` parsing. So `source_fields/2` returns plain
keys (engine contract) and `put_translation/4` re-prefixes them to the
`_`-form before writing, so the secondary-language inputs actually render
the result.

Registered via the host module's `ai_translatables` callback (see
`PhoenixKitCatalogue`). The enqueue, the AI call, broadcasts, retry policy,
and the audit log all live in core.

# `force_put_language`

```elixir
@spec force_put_language(map(), String.t(), map()) :: map()
```

Store a secondary language's values **verbatim**, like
`PhoenixKit.Utils.Multilang.put_language_data/3` but WITHOUT dropping
fields that happen to equal the primary.

The multilang form normally keeps only the diff-from-primary as an
override. For AI translation that's wrong: a result that comes back
identical to the source (a product code, text already in the target
language) would store nothing, leaving the field blank — the user reads
that as "translation failed", and the language keeps showing as missing.
Force-storing populates the field and keeps the missing-count honest.

`full_field_data` is the already-`_`-prefixed map for `lang`.

---

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