Generic Oban worker that translates one resource's fields into a single target language, shared by every consumer module.
Resolves a PhoenixKitAI.Translatable adapter from the
job's resource_type (registered via ai_translatables/0 and
discovered through PhoenixKitAI.Translatables), then runs:
adapter.fetch/3-or-2 → adapter.source_fields/2 →
Translation.translate_fields/6 → adapter.put_translation/4broadcasting {:ai_translation, event, payload} at each lifecycle step
(see PhoenixKitAI.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,
"resource_scope" => scope_or_nil
}resource_scope is an optional, opaque, JSON-safe string partitioning a
resource's jobs (e.g. a version number). When present and the adapter exports
fetch/3, it's passed through so the adapter loads that exact slice; nil
(or absent) means the default slice via fetch/2.
De-duplication
De-dup is app-level in PhoenixKitAI.Translations.enqueue/1
(one in-flight job per (resource_type, resource_uuid, resource_scope, 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.