Лестница резолвинга
Точный порядок работы /v1/resolve и что означает каждое значение match.
Резолвинг — это два поиска и лестница. Всё работает на снапшоте каталога в памяти: ни одного запроса к базе на запрос пользователя.
Шаг 1 — найти провайдера
Присланное значение нормализуется и сверяется с кодами провайдеров, затем с их алиасами. Нет совпадения — provider_not_found (404).
Шаг 2 — найти язык
Присланное значение нормализуется (см. Aliases and Normalisation) и сверяется сначала с каноническими кодами, потом с алиасами. Канонические коды регистрируются первыми и никогда не перезаписываются, так что алиас не может затенить настоящий код языка.
Если точного совпадения нет, код постепенно укорачивается:
zh-Hant-HK → zh-hant → zh-hk → zh
Обе оси квалификаторов присутствуют, потому что провайдеры не согласны, какая из них важна: DeepL хочет zh-Hans, Papago хочет zh-CN. Тег с неизвестным квалификатором деградирует до языка, который он уточняет, а не падает в 404: de-AT-1996 резолвится в de-AT, что видно в matched_alias.
Всё равно ничего? language_not_found (404).
Шаг 3 — лестница
Теперь, когда оба известны, по порядку:
1. exact — явная строка для этой пары
Кто-то настроил. Возвращаем её код.
{ "provider": "deepl_api", "language": "zh-CN", "code": "ZH-HANS", "match": "exact" }
Если в строке is_supported: false — останавливаемся: supported: false, code: null. Пара известна как нерабочая, запрос делать не нужно.
2. variant — менее специфичный тег того же языка имеет строку
Нет строки для ar-EG, но есть для ar? Берём её и называем в via_language. Baidu пишет арабский как ara — такого кода не дало бы никакое укорачивание тега.
{ "provider": "baidu_translate", "language": "ar-EG", "code": "ara", "match": "variant", "via_language": "ar" }
Если найденная строка говорит is_supported: false, лестница так же останавливается, а via_language называет язык, чья строка отказала. Выигрывает самое конкретное утверждение: провайдер, который не переводит традиционный китайский, не переведёт и zh-Hant-HK, а перешагнуть отказ до zh означало бы ответить кодом упрощённого.
3. canonical — язык без квалификатора
Базовому языку маппинг не нужен: его собственный код и есть ответ.
{ "language": "uk", "code": "uk", "match": "canonical" }
Базовый язык без строки резолвится сам в себя
Конфигурация обязана говорить что-то только о региональных языках — тех, о которых провайдеры не согласны. Там, где задокументированный перечень языков провайдера записан, строки есть и у базовых языков: явный код там, где провайдер пишет язык иначе, и явное supported: false там, где он его вообще не переводит. В остальных случаях собственный код языка и есть ответ, а строка не нужна.
4. Fallback policy провайдера
Достигается только для регионального языка, для которого ничего не настроено. Как выбирать — Fallback Policies.
| Политика | Результат | match |
|---|---|---|
base_language |
код базового языка — pt-BR → pt |
base_language |
passthrough |
канонический код без изменений | passthrough |
strict |
supported: false, code: null |
— |
Все провайдеры сейчас едут на base_language. Почему strict не дефолт — Fallback Policies.
Как читать match на стороне вызывающего
match |
Уровень доверия | Что делать |
|---|---|---|
exact |
Настроено осознанно | Использовать. |
variant |
Настроено для близкого тега | Использовать. Стоит закрепить, если повторяется. |
canonical |
Нечего решать | Использовать. |
base_language |
Выведено — регион потерян | Использовать, но если региональная точность критична — проверьте пару. |
passthrough |
Выведено — не проверено против этого API | Использовать и следить за ошибками провайдера. |
match равен null ровно в одном случае: supported: false, code: null. Это не ступень лестницы, которая закончилась, — это записанный факт о паре, и запрос делать не стоит. via_language говорит, записан ли отказ против самого этого языка или унаследован от менее специфичного.
Большинство вызывающих может вообще игнорировать match и просто отправлять code. Он для тех, кто не может.
Разобранный пример
GET /v1/resolve?provider=deepl_api&language=zh_hant_hk
deepl_apiсовпадает с кодом провайдера.zh_hant_hkнормализуется вzh-hant-hk. Канонического совпадения нет, но именно это написание зарегистрировано как алиасzh-HK. Язык =zh-HK,matched_alias: "zh-hant-hk".- У DeepL есть явная строка для
zh-HK→ZH-HANT, в собственном написании DeepL заглавными.
{ "query": "zh_hant_hk", "provider": "deepl_api", "language": "zh-HK",
"code": "ZH-HANT", "supported": true, "match": "exact",
"matched_alias": "zh-hant-hk", "via_language": null }
Далее
- Fallback Policies — для чего каждая политика
- Резолвинг языка — тот же вызов, поле за полем