## Context

Язык локализованных полей вывода (`title`, режиссёр) сейчас задаётся неявно и в
двух местах: промпт LLM говорит модели вернуть «каноническое название» без
указания языка (модель решает сама), а клиент TMDB жёстко берёт локаль из
`[metadata.tmdb].language` с дефолтом `ru-RU`. Это два несогласованных рычага
для одного решения. Требуется один явный переключатель, единый для детектора и
метабаз.

Затрагиваемые пакеты: `internal/config` (новое поле), `internal/recognize`
(промпт), `internal/metadata` (TMDB-клиент), проброс из `cmd/jellybit` в
recognizer и TMDB. Конвенция конфига — `docs/conventions/config.md`
(самодокументируемый `config.example.toml`, валидация на старте).

## Goals / Non-Goals

**Goals:**

- Одно top-level поле `language` (`ru`|`en`, дефолт `en`) — единственный
  источник языка локализованного вывода.
- `title` от LLM и локаль TMDB (поиск + credits) следуют этому полю.
- `original_title` не затрагивается ни при каком значении.

**Non-Goals:**

- Гарантированная локализация имён режиссёров (провайдеры их почти не
  переводят — best-effort).
- Языки помимо `ru`/`en`, автоопределение языка по контенту, per-раздача
  override.
- Локаль TVDB/TVMaze: TVDB extended не параметризуем языком в текущем клиенте,
  TVMaze — англоязычный; вне охвата этого изменения (охват — LLM и TMDB).

## Decisions

**1. Место конфига — `[general].language`, значения `ru`|`en`, дефолт `en`.**
Поле кросс-каттинг (и recognition, и metadata-match) и по классу — это
presentation-настройка отображения, ровно как уже живущий в `[general]`
`timezone` («таймзона отображения времени»). Селим рядом с ним — единый дом
таких настроек, не плодим второй паттерн места. Значения — короткие языковые
коды, а не локали (`ru-RU`): локаль — диалект конкретного провайдера, его
выводит сам провайдер (см. решение 2). Значение хранится голой строкой, как
остальные enum-подобные поля конфига (`llm.type`, `log.format`) — проект
осознанно не типизирует их. Валидация: значение вне `ru`/`en` → ошибка старта
(fail-fast, **по образцу `llm.type`**, а не permissive `log.level`), форма
сообщения — `unsupported language %q (supported: ru, en)`. Нормализацию «пусто →
`en`» держим НЕ в `validate()` (он чист — только собирает ошибки), а в аксессоре
`Config` по образцу `DisplayLocation()`; `Default()` при этом сеет `"en"`.
Альтернативы отклонены: `[recognition].language` назвала бы поле по одному из
двух потребителей; top-level рядом с `timezone` не согласуется с уже сложившимся
домом presentation-настроек.

**2. `[metadata.tmdb].language` удаляется; локаль выводит провайдер.** В общий
слой (config/cmd) едет абстрактный `ru`/`en`; диалект TMDB `ru-RU`/`en-US`
выводит сам `internal/metadata/tmdb.go` — тотальным `switch` с default-веткой
`en-US` (defense in depth: невозможный вход не роняет запрос без локали). Так
знание диалекта принадлежит тому, кто на нём говорит: второй локализуемый
провайдер (TVDB с иным синтаксисом локали) добавит свой маппинг у себя, а не
расширит общий слой. Остаточный `tmdbDefaultLanguage = "ru-RU"` и его fallback в
`NewTMDB` **удаляются** — это скрытый второй дефолт, противоречащий заявленному
`en-US`. Второго способа задать язык не остаётся (нет рассинхрона). Ломающее
изменение конфига переворачивает дефолт локали TMDB `ru-RU`→`en-US`; фиксируем в
proposal и миграции. Альтернатива «оставить `[metadata.tmdb].language` как
override» отклонена: две ручки для одного решения противоречат «второго способа
быть не должно».

**3. Директива языка в промпте — только для `title`, с fallback на оригинал.**
Добавляем в промпт распознавания явную строку: вернуть `title` на языке
`language`, при отсутствии перевода — на языке оригинала (не выдумывать).
Семантически совпадает с поведением TMDB `language` (локализованное поле с
fallback на оригинал), поэтому обе стороны согласованы. Язык прокидывается в
`buildMessages`/`systemPrompt` из конфига через `Recognizer`.

**4. Режиссёр — та же локаль в запрос credits, best-effort.** Клиент TMDB уже
передаёт `language` в поиск; тем же значением параметризуем запрос credits
(`Director`). Имена людей TMDB локализует не всегда — где перевода нет, приходит
оригинал; это не ошибка и не проваливает выборку (best-effort уже закреплён
спекой metadata-match).

## Risks / Trade-offs

- [Имена режиссёров редко локализованы у провайдеров] → best-effort по спеке:
  при отсутствии перевода — оригинал; ожидание зафиксировано в proposal, отказа
  не вызывает.
- [Ломающее изменение конфига: удаление `[metadata.tmdb].language` + флип
  дефолта на `en-US`] → go-toml молча игнорирует неизвестный ключ, поэтому
  деплой с оставленным `[metadata.tmdb].language = "ru-RU"` тихо переключится на
  английский. Решение: НЕ вводим отклонение неизвестных ключей (лишняя машинерия
  ради единственного деплоя), а прописываем обязательный ручной шаг в миграции
  ниже. Существующие «русские» деплои выставляют `[general].language = "ru"` и
  убирают старый ключ.
- [Дефолт `en` переименует имена папок медиатеки на английский] → косметика:
  Jellyfin идентифицирует контент по id-тегу метабазы (TVDB/IMDb в имени папки),
  а не по языку названия, поэтому распознавание не ломается. `original_title`
  (ось поиска в базах) от `language` не зависит. Осознанный дефолт.
- [LLM может проигнорировать языковую директиву на слабой модели] → директива
  best-effort, как и весь недоверенный вывод LLM; безопасность по-прежнему на
  валидации и гейте матча, не на языке `title`.

## Migration Plan

1. Выкатка бинаря с новым полем; дефолт `en` активен сразу.
2. Деплой, где ожидались русские названия, добавляет `[general].language = "ru"`
   в конфиг и удаляет `[metadata.tmdb].language` (обязательный ручной шаг —
   валидатор про удалённый ключ не предупреждает).
3. Откат — вернуть прежний бинарь; `language` в конфиге игнорируется старой
   версией (unknown-поле go-toml не роняет парсинг), `[metadata.tmdb].language`
   при откате нужно вернуть, если он был.
