- локаль из [general].language применяется при разборе ответа /search, а в запрос не уходит: параметр language у TVDB — фильтр выдачи, а не селектор перевода (ADR-2026-08-07) - Title берётся из блока translations с тотальным фолбэком на primary name, OriginalTitle — из primary name; форма ответа сверена по документации и живым прогоном не подтверждена (docs/research) - неожиданная форма ответа даёт WARN: признак — отсутствие во всей выдаче ключей языка ожидаемого вида, а не неудача разбора блока
6.4 KiB
6.4 KiB
Why
Глобальная настройка [general].language правит только промпт LLM и клиент TMDB;
до клиента TVDB она не доезжает вовсе. TVDB отдаёт primary name — название на
языке оригинала, — и оно попадает в карточку ревью и в имя папки Jellyfin как
есть: у movie 131155 это 哪吒之魔童降世
вместо «Нэчжа», хотя русский перевод у записи есть. Плюс Candidate.OriginalTitle
у TVDB не заполняется вовсе, хотя это ось сравнения при матче: сегодня TVDB
сравнивается только по одному названию из двух возможных.
What Changes
TVDBConfigполучает полеLanguage— абстрактный код (ru|en) изcfg.ContentLanguage(), как уже сделано для TMDB. Диалект (у TVDB это трёхбуквенный код ISO 639-2:rus/eng) выводит самinternal/metadata/tvdb.goтотальнымswitchс default-веткой — по решению 2 архивного design content-language-switch.- Разбор ответа
/searchдополняется картойtranslations(код языка → название).Candidate.Titleберётся изtranslations[код], при отсутствии перевода — из primaryname(молчаливой пустоты быть не должно). Candidate.OriginalTitleзаполняется primaryname.- Параметр
languageв запрос/searchНЕ добавляется. По swagger TVDB v4 4.7.10 этот параметр — фильтр («Restrict results to a specific primary language»), а не селектор перевода: он сузил бы выдачу и отрезал именно те записи, ради которых задача заводилась. Разбор ведётся по ответу, а не по запросу. Расхождение с критерием приёмки задачи вынесено вопросом человеку — см.## Открытый вопрос. - Форма ответа TVDB живым API не сверялась — только по публичной документации
(см.
docs/research/tvdb-search-translations.md). Интеграционный тест за env-гейтомTVDB_API_KEYнаписан, но не запускался.
Ломающих изменений нет: конфиг не меняется, новых настроек не появляется.
Capabilities
New Capabilities
Новых нет.
Modified Capabilities
metadata-match: требование «Локаль запроса к TMDB» получает соседа — «Локализованное название кандидата TVDB». Обобщать существующее требование на всех провайдеров нельзя: механика у TMDB и TVDB разная (параметр запроса против разбора ответа), и одно требование на двоих скрыло бы эту разницу.
Impact
internal/metadata/tvdb.go—TVDBConfig.Language, вывод кода языка, разборtranslationsвtvdbSearchResp, заполнениеTitle/OriginalTitle.internal/metadata/tvdb_test.go— стендhttptestс блокомtranslations, табличный тест на перевод/фолбэк/OriginalTitle.internal/metadata/integration_test.go— интеграционный тест заTVDB_API_KEYпечатаетTitleиOriginalTitle. Пишется, но не запускается.cmd/jellybit/serve.go— сборка провайдера TVDB получаетLanguage.internal/config/config.go— вvalidateживёт единственный перечень потребителей кода языка («при добавлении кода синхронно расширь мапперыmetadata.tmdbLocaleиrecognize.languageDirective»); третий маппер дописывается в этот перечень.docs/research/tvdb-search-translations.md— новая записка о форме ответа/searchс честным провенансом.- Поведение матча:
strongMatchesсравнивает план и сTitle, и сOriginalTitle. У TVDB сегодняOriginalTitleпуст, поэтому сравнение идёт по одному названию; после изменения их станет два (локализованное + оригинальное). Логика гейта не трогается, но его вход меняется, и следствие двустороннее: запись, которую отсекал иероглифический primary name, теперь может пройти по переводу (задача уйдёт в авто вместо review) — и наоборот, две разные записи могут совпасть с планом разными названиями, тогда единичный сильный матч станет двумя и задача уйдёт в review вместо авто. Второе направление — в сторону человека, то есть безопасную. Инвариант «авто-раскладка только при подтверждённом матче» не двигается. - Внешний контракт: TheTVDB API v4
/search. Живых запросов в рамках задачи не делалось (запретCLAUDE.md→ «Запреты»: лимиты метабаз не расходуем).
Открытый вопрос
Форма ответа /search не сверена живым API. Вопрос человеку записан в
docs/tasks/items/tvdb-title-locale.md → раздел «Вопросы».