PhoenixKitAI.Translatable adapter for projects resources —
the small per-module hook into PhoenixKitAI's generic AI-translation pipeline.
Serves four resource types — "project", "template" (a Project with
is_template: true), "task", and "assignment" — each translating the
fields its schema declares via translatable_fields/0 (project/template:
name + description; task: title + description; assignment:
description).
Storage
Translations live in each schema's translations JSONB column, shaped
%{lang => %{field => value}} with plain field keys (no underscore
prefix — unlike catalogue's multilang data). Source text comes from
translations[source_lang][field] when present, else the resource's
primary column (name/title/description). Because the per-language
map stores values verbatim, an AI result identical to the source (a code,
text already in the target language) is still persisted — the field fills
in and the language stops reading as "missing", with no extra handling.
Registered via the PhoenixKitProjects.ai_translatables/0 function, which
PhoenixKitAI discovers by duck-typing. The enqueue, the
AI call, the per-resource PubSub broadcasts, the retry policy, and the
audit log all live in PhoenixKitAI — this module only reads source fields
and merges results back atomically.