Аліаси та нормалізація
Як будь-яке написання коду потрапляє на правильну мову — включно з поламаними.
Коди приходять із експортів TMS, клієнтських API, таблиць і десятиліття накопичених інтеграцій. Вони мало в чому згодні між собою. Нормалізація — це те, що робить їх порівнюваними.
Дві форми коду
Ключ пошуку — нижній регістр, роздільник -, пробіли зрізані. pt_BR, PT-BR, pt-br і pt - br стають pt-br. Аліаси зберігаються в цій формі й звіряються точною рівністю, тож гарячий шлях — це одне індексоване порівняння, а не LIKE-скан.
Канонічна форма — регістр BCP-47: первинний субтег нижнім регістром, скрипт із великої, регіон великими. pt-BR, zh-Hans, sr-Latn-RS. Саме це повертає API і саме це варто зберігати.
Канонізація також виправляє порядок субтегів. BCP-47 ставить скрипт перед регіоном, тож sr-RS-Latn і sr-Latn-RS парсяться в один тег і обидва рендеряться як sr-Latn-RS.
Виправлення гомогліфів
Перед обчисленням обох форм коди проходять через перевірку гомогліфів.
Це не гіпотетично. Код, перший символ якого — U+0441 CYRILLIC SMALL LETTER ES, а не ASCII c, виглядає ідентично в будь-якому шрифті; без виправлення він ніколи не збігся б із тим, що надсилає викликач, — саме такий дефект робить мову просто відсутньою.
Виправлення мапить кириличні літери, візуально ідентичні латинським — а е о р с х у і ј, — і лише коли результат стає чистим ASCII, тож справді кириличне значення лишається недоторканим, а не спотвореним. Повноширинна латиниця (en) згортається через NFKC у тому ж проході.
Що покривають аліаси
| Вид | Приклади |
|---|---|
| Власний канонічний код мови | pt-BR |
| Інші написання тієї самої мови | es-la, ES-LA для es-419 |
| ISO 639-2/3 і застарілі ISO 639-1 | deu, ger, zho, iw, in, ji, mo |
| Те, з чим приходить конкретна інтеграція | por-br |
GET /v1/languages/{code} повертає повний перелік у полі aliases, тож можна перевірити, чи написання, яке ви отримуєте, вже покрите.
Унікальність
Аліас належить рівно одній мові, глобально. Це забезпечує база даних, а не домовленість.
Це важливо, бо вхідний резолвінг мусить бути функцією: один код завжди означає одну мову — у кожному запиті й у кожному процесі. Якби код міг претендувати на дві мови, відповідь залежала б від того, який рядок прочитали першим, і та сама задача могла б зарезолвитись двічі по-різному.
Тому коли дві мови могли б обидві претендувати на одне написання, конфлікт вирішується один раз, наперед, і фіксується — а не під час запиту.
Для чого аліас не потрібен
Для варіантів регістру й роздільників. pt_BR уже збігається з аліасом pt-br; додавати pt_br окремим рядком — надлишково.
Перевірити код, не резолвлячи його
/v1/normalize відповідає на питання без провайдера — що це за мова і як ми її називаємо?
curl "https://languages.service.custom.mt/v1/normalize?language=ZH_HANS"
{ "query": "ZH_HANS", "known": true, "matched_alias": "zh-hans",
"language": { "code": "zh-CN", "name": "Chinese (Simplified)", "aliases": ["chs", "zh-hans", …] } }
На відміну від інших ендпоінтів, невідомий код тут не помилка — known: false приходить із 200. Це дозволяє класифікувати весь список за один прохід, а не ловити 404. Див. Нормалізація вхідних кодів.
Далі
- Language Catalog — що в каталозі
- Resolution Ladder — що відбувається після визначення мови