# Переводы в ответе поиска TheTVDB v4 Клиент TVDB (`internal/metadata/tvdb.go`) берёт локализованное название кандидата из ответа `/search`. Здесь записано, откуда взята форма этого ответа и чего в ней не подтверждено. **Провенанс — и он слабый.** Всё ниже сверено **по публичной документации** TheTVDB API v4, файл `docs/swagger.yml` репозитория `thetvdb/v4-api`, поле `info.version` = `4.7.10` (прочитано 2026-08-07). **Живым прогоном не подтверждено ни одно наблюдение**: `CLAUDE.md` → «Запреты» запрещает ходить в боевые метабазы из отладочных прогонов и расходовать лимиты ключа. Всё дальнейшее — **условие, а не замер**. Оракул, который это закроет, написан и ждёт человека: ``` TVDB_API_KEY=… go test ./internal/metadata/ -run Integration -v ``` Он печатает `Title` и `OriginalTitle` первых кандидатов. ## Параметр `language` у `/search` — фильтр, а не селектор перевода Дословно из swagger, параметр `language` эндпоинта `/search`: > Restrict results to a specific primary language. Should include the 3 character > language code. То есть он **сужает выдачу** по основному языку записи, а не выбирает, на каком языке вернуть название. Форум TheTVDB подтверждает направление: маршруты `/search` не возвращают записи, которых нет на указанном языке. Следствие для нас: передача `language=rus` отсекла бы ровно те записи, ради которых заводилась задача, — у `Ne Zha` основной язык `zho`. Поэтому запрос поиска параметром языка **не параметризуется**, а локаль работает только на стороне разбора ответа. Это заказано спекой (`openspec/specs/metadata-match/`, требование «Локализованное название кандидата TVDB»). Расхождение с TMDB намеренное: у TMDB `language` — именно селектор локализованного поля, и там он в запрос уходит. ## Поля `SearchResult`, относящиеся к названию Из схемы `SearchResult` того же swagger: | Поле | Тип по схеме | Что берём | |---|---|---| | `name` | `string` | primary name записи — идёт в `Candidate.OriginalTitle` и служит фолбэком для `Title` | | `translations` | `TranslationSimple` | карта «код языка → название»; из неё берём `Candidate.Title` | | `name_translated` | `string` | **не используем** | | `overviews`, `overview_translated` | описания | не используем | | `primary_language` | `string` | не используем | | `translationsWithLang` | массив строк | не используем | `TranslationSimple` в самом файле swagger описан как открытая карта (свободные ключи со строковыми значениями); **полного текста этой схемы вычитать не удалось** — документ в местах чтения обрывался. Форма «карта кода языка в строку» принята по описанию поля и по обсуждениям в трекере `thetvdb/v4-api`, где встречаются фрагменты вида `"translations": {"eng": "…"}`. Это самое слабое место записки: если реальная форма иная (список объектов, двухбуквенные ключи), разбор молча уйдёт в фолбэк. **Почему не `name_translated`.** Семантика поля в документации не описана вовсе — не сказано ни на каком языке оно приходит, ни от чего зависит. Правдоподобно, что заполняет его поисковый индекс при заданном фильтре `language`, которого мы не шлём. Взять его в фолбэк значило бы получить название на неизвестном языке молча; карта `translations` самодостаточна. ## Что известно про вырожденные значения В трекере `thetvdb/v4-api` есть подтверждённый случай, когда `name` приезжает **пустой строкой** при непустом блоке переводов (issue про `"name":"" must not be empty`). Отсюда два следствия для разбора, оба заказаны спекой: - пустая строка в этих полях реальна, поэтому пустота значения перевода проверяется после обрезки пробелов; - блок переводов может нести ключ с пустым значением — это не «перевод есть». ## Как мы защищаемся от того, что запись неверна Наблюдение не подтверждено, поэтому разбор устроен так, чтобы ошибка записки стоила как можно меньше: - блок переводов разбирается **отдельно от остального ответа** и его негодная форма гасится в фолбэк: косметическое поле не получает права уронить выдачу поиска целиком; - ключ ищется регистронезависимо; - если в выдаче не разобрался **ни один** блок переводов, клиент пишет строку DEBUG. Это единственный сигнал, отличающий «форма ответа не та, что здесь записана» от штатного «перевода на этот язык нет»: без него неверное предположение жило бы в бою неограниченно долго при зелёном гейте. ## Условие пересмотра Записка протухает от смены версии API TheTVDB (сегодня v4, swagger 4.7.10) и от любого ручного прогона интеграционного теста: первый же живой ответ обязан заменить здесь предположения на наблюдения, а слова «живым прогоном не подтверждено» — на дату и результат прогона.