Files
jellybit/docs/adr/ADR-2026-08-07-tvdb-locale-reads-response.md
T
av fdbc781197 metadata: TVDB отдаёт локализованное название и оригинал
- локаль из [general].language применяется при разборе ответа /search, а в
  запрос не уходит: параметр language у TVDB — фильтр выдачи, а не селектор
  перевода (ADR-2026-08-07)
- Title берётся из блока translations с тотальным фолбэком на primary name,
  OriginalTitle — из primary name; форма ответа сверена по документации и
  живым прогоном не подтверждена (docs/research)
- неожиданная форма ответа даёт WARN: признак — отсутствие во всей выдаче
  ключей языка ожидаемого вида, а не неудача разбора блока
2026-08-07 15:17:05 +03:00

5.5 KiB
Raw Blame History

Локаль TVDB читается из ответа поиска, а не передаётся в запрос

Контекст

Глобальная настройка [general].language правит промпт LLM и клиент TMDB (ADR решения 2), но до клиента TVDB не доезжала. TVDB отдавал primary name — название на языке оригинала, — и оно попадало в карточку ревью и в имя папки Jellyfin как есть.

Очевидный подход, записанный прямо в постановке задачи и в её критерии приёмки: добавить параметр языка в запрос /search, как это сделано для TMDB. От него отказались.

Решение

Параметр языка в запрос поиска TVDB не передаётся. Локаль применяется только при разборе ответа: Candidate.Title берётся из блока переводов, OriginalTitle — из primary name.

Цитата решения 1 архивного design.md:

По [swagger TVDB v4, версия 4.7.10] у /search есть параметр language с описанием «Restrict results to a specific primary language. Should include the 3 character language code» — это фильтр выдачи, а не селектор перевода. Передача language=rus отсекла бы записи, основной язык которых не русский, то есть ровно наблюдаемый случай (Ne Zha, основной язык zho). Сужение выдачи — это изменение входа гейта матча, а задача такое явно запретила.

Тем самым два провайдера намеренно устроены по-разному: у TMDB локаль едет в запрос, у TVDB читается из ответа. Асимметрия оставлена в клиентах, а не поднята в общий тип: у TMDB карты названий в ответе нет вовсе, и общий тип пришлось бы заполнять единственным ключом (решение 1a, форма B).

Рассмотренные варианты

  • Слать language и мириться с сужением выдачи. Ломает основной сценарий: иноязычные записи, ради которых задача заводилась, пропадут из поиска.
  • Отдельный запрос /movies/{id}/translations/{lang} на каждого кандидата. Цена в лимитах ключа не окупает косметическое поле.
  • Заголовок Accept-Language. Для v4 не документирован — была бы догадка.
  • Candidate несёт карту названий, выбор делает потребитель (форма B). Язык у потребителя уже есть, плюмбинг не нужен, но у TMDB карты в ответе нет — внутри одного доменного типа завелись бы две формы.
  • TVDB не локализуется вовсе, заполняется только OriginalTitle (форма C). Тогда наблюдаемый случай чинится только при включённом TMDB, давшем матч, — поведение молча зависело бы от набора включённых провайдеров.

Последствия

  • Критерий приёмки задачи «запрос поиска содержит параметр языка» выполнен быть не может и отменён этим решением. Расхождение вынесено вопросом человеку — разведка tvdb-search-response-live-check.
  • Решение опирается на документацию, а не на замер. Семантика параметра и форма блока переводов живым API не подтверждены — research/tvdb-search-translations.md. Если ручной прогон под ключом покажет иное, эта запись пересматривается новой, а не правится.
  • Заполнение OriginalTitle дало кандидату TVDB две оси сравнения вместо одной. Логика гейта не менялась, но его вход изменился в обе стороны: запись, которую отсекал иероглифический primary name, теперь может пройти по переводу, а две разные записи могут совпасть с планом разными названиями и увести задачу в review. Инвариант «авто-раскладка только при подтверждённом матче» не двигается.