- локаль из [general].language применяется при разборе ответа /search, а в запрос не уходит: параметр language у TVDB — фильтр выдачи, а не селектор перевода (ADR-2026-08-07) - Title берётся из блока translations с тотальным фолбэком на primary name, OriginalTitle — из primary name; форма ответа сверена по документации и живым прогоном не подтверждена (docs/research) - неожиданная форма ответа даёт WARN: признак — отсутствие во всей выдаче ключей языка ожидаемого вида, а не неудача разбора блока
67 lines
5.5 KiB
Markdown
67 lines
5.5 KiB
Markdown
# Локаль TVDB читается из ответа поиска, а не передаётся в запрос
|
||
|
||
- **Дата:** 2026-08-07
|
||
- **Источник:** [openspec/changes/archive/2026-08-07-tvdb-title-locale/design.md](../../openspec/changes/archive/2026-08-07-tvdb-title-locale/design.md),
|
||
решение 1 и решение 1a
|
||
|
||
## Контекст
|
||
|
||
Глобальная настройка `[general].language` правит промпт LLM и клиент TMDB
|
||
([ADR решения 2](../../openspec/changes/archive/2026-07-24-content-language-switch/design.md)),
|
||
но до клиента 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](../tasks/items/tvdb-search-response-live-check.md).
|
||
- **Решение опирается на документацию, а не на замер.** Семантика параметра и
|
||
форма блока переводов живым API не подтверждены —
|
||
[research/tvdb-search-translations.md](../research/tvdb-search-translations.md).
|
||
Если ручной прогон под ключом покажет иное, эта запись пересматривается новой,
|
||
а не правится.
|
||
- Заполнение `OriginalTitle` дало кандидату TVDB две оси сравнения вместо одной.
|
||
Логика гейта не менялась, но его вход изменился в обе стороны: запись, которую
|
||
отсекал иероглифический primary name, теперь может пройти по переводу, а две
|
||
разные записи могут совпасть с планом разными названиями и увести задачу в
|
||
review. Инвариант «авто-раскладка только при подтверждённом матче» не двигается.
|