# `PhoenixKit.Modules.AI.TranslateWorker`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.132/lib/modules/ai/translate_worker.ex#L1)

Generic Oban worker that translates one resource's fields into a single
target language, shared by every consumer module.

Resolves a `PhoenixKit.Modules.AI.Translatable` adapter from the
job's `resource_type` (registered via `ai_translatables/0` and
discovered through `PhoenixKit.ModuleRegistry`), then runs:

    adapter.fetch/2 → adapter.source_fields/2 →
    Translation.translate_fields/6 → adapter.put_translation/4

broadcasting `{:ai_translation, event, payload}` at each lifecycle step
(see `PhoenixKit.Modules.AI.Translations`) and writing one
`ai.translation_added` activity entry on success.

## Job args

    %{
      "resource_type" => "catalogue_item",
      "resource_uuid" => uuid,
      "endpoint_uuid" => uuid,
      "prompt_uuid"   => uuid,
      "source_lang"   => "en",
      "target_lang"   => "es",
      "actor_uuid"    => uuid_or_nil
    }

## De-duplication

De-dup is **app-level** in `PhoenixKit.Modules.AI.Translations.enqueue/1`
(one in-flight job per `(resource_type, resource_uuid, target_lang)`), NOT
Oban's built-in `unique:`. Oban's uniqueness query references the
`:suspended` job state, which is absent from the `oban_job_state` enum on
hosts that upgraded the Oban *lib* ahead of its *migration* — there the
query raises `22P02` and kills every enqueue. The app guard queries only
the four always-present states (`available`/`scheduled`/`executing`/
`retryable`) and fails open. Same trade-off as the catalogue PDF worker.

---

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