# Локаль 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. Инвариант «авто-раскладка только при подтверждённом матче» не двигается.