Интернационализация и локализация
Версия: 1.0 Дата: 26.04.2026 Статус: Готов к обсуждению
Назначение документа
Документ определяет кросс-доменный слой интернационализации и локализации (internationalization and localization, i18n/L10n) Vitiana — единые каноничные правила работы с языками, валютами, часовыми поясами, форматами дат и чисел, юрисдикциями и регуляторными режимами для всей платформы. Включает:
- Каноничную модель:
SupportedLanguage,SupportedCurrency,RegionLocale,LocaleResolutionPolicy,FxRateSnapshot,TimezonePolicy. - Базовый набор языков и валют первой волны.
- Каноничные различения (source vs presentation, supplier currency vs settlement currency vs display currency).
- Политику разрешения локали (locale resolution policy) — как платформа выбирает язык, валюту, часовой пояс для конкретного запроса.
- Политику валютных операций (foreign exchange, FX) — фиксация курсов в момент коммерческой фиксации, отдельная от внутренних взаиморасчётов.
- Форматирование дат, чисел, валют, телефонов, адресов.
- Многоязычный контент через
ContentTranslation(отсылка к Медиа и контент). - Юрисдикционные следствия (расширение по странам — расширение compliance-обязательств).
- Фазы развёртывания.
Документ читается после:
- Архитектурный якорь и бизнес-модель — базовый набор языков и валют первой волны.
- API Contracts → разделы «Локализация и валюты» — уже зафиксированные каноничные различения.
- Уведомления и коммуникации — локализация в шаблонах сообщений.
- Медиа и контент —
ContentTranslationкак сущность. - Поиск и обнаружение — многоязычный поиск и локализация фасетов.
- Платёжный домен — multi-currency и FX-policy.
- Соответствие требованиям регуляторов — юрисдикционные обязательства по странам.
В корневых документах зафиксированы отдельные локализационные правила для своих доменов. Этот документ собирает их в единую каноничную модель, обеспечивающую консистентность между контурами.
Интернационализация и локализация — сквозной кросс-доменный слой. Без него каждый домен решает локализацию по-своему: поисковая выдача в одном формате, уведомления — в другом, платёжные документы — в третьем. Это разрушает целостность платформы и создаёт регуляторные риски (несоответствие в форматах документов разных контуров).
Реальное состояние реализации (home-to-go-api): уже работают locations и translations ru/uk для 182 стран, выполнен полный geo chain. Это сильный стартовый актив для географической части. Платформа продолжает этот актив, добавляя единый слой управления валютами, часовыми поясами и форматированием.
Правило 00000 (платформа главенствует над поставщиками) применяется здесь напрямую: каноничный набор языков и валют — выбор платформы, не наследование от поставщиков. Stuba отдаёт цены в EUR — платформа конвертирует. HomeToGo отдаёт описания на английском — платформа переводит. Никакой поставщик не диктует, какие языки и валюты поддерживает платформа.
Главное решение
Интернационализация и локализация — единый кросс-доменный слой с каноничными сущностями, едиными правилами разрешения и единой политикой fallback.
Это означает:
- Каноничный набор поддерживаемых языков и валют — фиксированное множество, расширяемое по плану расширения географии.
- Единые каноничные различения — source language ≠ canonical language ≠ presentation language. Применимо ко всем контурам (поиск, контент, уведомления, документы).
- Единая политика разрешения локали —
LocaleResolutionPolicyопределяет, какой язык, валюта, часовой пояс используется для конкретного запроса. Не каждый контур придумывает свою. - Единая политика fallback — при отсутствии перевода или валюты — каноничный путь: запрос → предпочитаемая → fallback страны → английский.
- Валюта коммерческой фиксации фиксируется в момент
Quote— после фиксации цена в этой валюте не меняется ни при каких обстоятельствах. Конвертация — отдельная операция со своим следом. - Многоязычный контент через
ContentTranslation— единая сущность для всех контентных доменов. - Часовой пояс — первоклассный атрибут для всех временных полей платформы. Отображение в локальном времени получателя, хранение в UTC.
- Юрисдикция — определяющий фактор для compliance, налогов, форматов документов. Каждое расширение географии — расширение юрисдикционной модели.
Правило «один язык внутри одного предложения» (фиксация в feedback_language_rules для документации) применяется и к контенту платформы — пользователь видит только свой язык, без вкраплений английского без расшифровки.
Каноничная модель i18n/L10n
Главные сущности
SupportedLanguage — поддерживаемый язык
Сущность, представляющая язык, который платформа официально поддерживает.
{
language_code: string (ISO 639-1, two-letter),
language_code_full: string (BCP 47, например ru-UA),
display_name_native: string,
display_name_english: string,
text_direction: enum,
active_in_phase: integer,
fallback_chain: array,
applicable_surfaces: array,
is_active: boolean,
created_at: timestamp,
updated_at: timestamp
}
Поля:
language_code— двухбуквенный ISO 639-1 (uk,ru,cs,pl,en,kk).language_code_full— BCP 47 с региональным вариантом, если значимо (ru-UAпротивru-RU).display_name_native— название на самом языке (українська,русский,čeština,polski,English,қазақ тілі).display_name_english— название на английском.text_direction— направление текста (ltr— слева направо для всех языков первой волны;rtl— справа налево для арабского, иврита в фазе 4+).active_in_phase— с какой фазы поддерживается.fallback_chain— каноничная цепочка fallback (например, дляuk:uk → ru → en; дляkk:kk → ru → en).applicable_surfaces— на каких поверхностях используется (некоторые языки могут быть только для интерфейсов агентств, не для конечных клиентов).
SupportedCurrency — поддерживаемая валюта
{
currency_code: string (ISO 4217),
display_name_native: object,
symbol: string,
decimal_places: integer,
rounding_increment: numeric,
display_format_template: object,
applicable_phase: integer,
is_settlement_currency: boolean,
is_display_currency: boolean,
applicable_regions: array,
is_active: boolean,
created_at: timestamp,
updated_at: timestamp
}
Поля:
currency_code— ISO 4217 (UAH,EUR,CZK,PLN,KZT,USD).display_name_native— объект с названием на каждом поддерживаемом языке ({uk: "гривня", ru: "гривна", en: "hryvnia"}).symbol— символ валюты (₴,€,Kč,zł,₸,$).decimal_places— число дробных разрядов (типично 2;0для японской иены — для будущих фаз).rounding_increment— шаг округления (например,0.05для CHF).display_format_template— каноничный шаблон форматирования по локалям (например, дляEUR:de—1.234,56 €;en—€1,234.56).is_settlement_currency— может ли быть валютой взаиморасчёта с поставщиком.is_display_currency— может ли быть валютой отображения клиенту.
RegionLocale — региональная локаль
Сущность, представляющая сочетание языка, валюты, часового пояса и форматных правил для конкретного региона.
{
locale_id: UUID,
region_code: string (ISO 3166-1 alpha-2),
language_code: string,
currency_code: string,
timezone_id: string (IANA, например, Europe/Kyiv),
date_format: string,
time_format: string,
number_format: object,
phone_format: object,
address_format: object,
first_day_of_week: enum,
is_default_for_region: boolean,
is_active: boolean
}
Каждая страна первой волны имеет одну или несколько RegionLocale:
- Украина (UA):
uk-UA(главная) +ru-UA(вторая). - Чехия (CZ):
cs-CZ(главная) +en-CZ(для иностранных клиентов). - Польша (PL):
pl-PL(главная) +en-PL. - Казахстан (KZ):
kk-KZ(главная) +ru-KZ(вторая).
LocaleResolutionPolicy — политика разрешения локали
Сущность, представляющая алгоритм выбора применимой локали для запроса.
{
policy_id: UUID,
applicable_surfaces: array,
resolution_rules: array,
default_locale_id: UUID,
fallback_locale_id: UUID,
apply_subject_preferences: boolean,
apply_tenant_preferences: boolean,
apply_geo_inference: boolean,
apply_browser_hints: boolean,
is_active: boolean
}
Политика определяет, в каком порядке учитываются источники предпочтения:
- Явно переданная клиентом локаль (через параметр запроса или заголовок
Accept-Language). - Сохранённое предпочтение субъекта (для авторизованного клиента из
RecipientPreferences). - Конфигурация тенанта (тенант может задать локаль по умолчанию для своей поверхности).
- Геогеогра́фический вывод (по IP-адресу или явному региону).
- Подсказки браузера (
Accept-Language). - Глобальный default (
en-USили специфический для платформы).
FxRateSnapshot — снимок курса валют
Сущность, представляющая зафиксированный на момент времени курс конвертации валют для конкретной операции.
{
snapshot_id: UUID,
base_currency: string,
quote_currency: string,
rate: numeric,
rate_source: string,
rate_timestamp: timestamp,
margin_applied: numeric,
applicable_purpose: enum,
associated_entity_type: enum,
associated_entity_id: UUID,
expires_at: timestamp
}
Каждая конвертация валют — со своим снимком, не «текущий курс на момент чтения».
Поля:
rate_source— источник курса (provider:stripe/provider:adyen/provider:central_bank_eu/provider:central_bank_ua/internal_aggregated).margin_applied— маржа платформы поверх курса источника (если применима, открыто фиксируется).applicable_purpose— для чего используется (quote_display/booking_payment/supplier_settlement/partner_billing/internal_reporting).associated_entity_type— к какой сущности привязан снимок (quote,booking,settlement).expires_at— срок действия снимка (для отображения в поиске — типично минуты; для коммерческой фиксации — на весь срок коммерческой фиксации; для бронирования — навсегда).
TimezonePolicy — политика часовых поясов
Сущность, определяющая правила применения часовых поясов в каждом контуре платформы.
{
policy_id: UUID,
applicable_surface: string,
applicable_context: enum,
storage_format: enum,
display_timezone_source: enum,
is_dst_aware: boolean
}
Каноничные правила:
- Хранение — все временные метки хранятся в UTC. Без исключений.
- Отображение пользователю — в локальном часовом поясе субъекта.
- Источник часового пояса для отображения — приоритет: явное предпочтение субъекта → часовой пояс из
RegionLocale→ часовой пояс из IP/геолокации → UTC. - Учёт перехода на летнее время (DST) — обязательный через библиотеку IANA timezones (без жёсткого зашивания смещений).
Связь с другими каноничными сущностями
Quote(см. Семантика предложений, цены, бронирования) хранит ссылку наFxRateSnapshot, зафиксированный в момент создания.Bookingхранит ссылку наFxRateSnapshotплатежа клиента и отдельную ссылку на снимок взаиморасчёта с поставщиком (если валюты разные).Tenantимеет конфигурациюdefault_locale_idи списокsupported_locales(что предлагать конечному клиенту).RecipientPreferences(см. Уведомления и коммуникации) хранит предпочтительную локаль получателя.ContentTranslation(см. Медиа и контент) — связан сSupportedLanguage.SearchSession.client_locale(см. Поиск и обнаружение) — заполняется черезLocaleResolutionPolicy.
Базовый набор языков первой волны
| Код | BCP 47 | Native name | Английское имя | Применение | Fallback |
|---|---|---|---|---|---|
uk | uk-UA | українська | Ukrainian | Главный для UA | uk → ru → en |
ru | ru-UA, ru-KZ | русский | Russian | UA, KZ, частично PL | ru → en |
cs | cs-CZ | čeština | Czech | Главный для CZ | cs → en |
pl | pl-PL | polski | Polish | Главный для PL | pl → en |
en | en-US, en-GB | English | English | Глобальный fallback, разработчики | en → en-US |
kk | kk-KZ | қазақ тілі | Kazakh | Главный для KZ | kk → ru → en |
Правила расширения языкового набора
Расширение языков по фазам, по триггерам:
- Фаза 2 — добавляются
de(Германия) иsk(Словакия) при подходе к расширению в широкую Европу. - Фаза 3 —
tr(Турция),hr(Хорватия),bg(Болгария),hu(Венгрия),ro(Румыния),sl(Словения). - Фаза 4 —
ar(арабский, для расширения в сторону MENA),zh(китайский, для расширения в сторону Азии). Эти языки добавляют требованиеtext_direction: rtlдля арабского и иной системы письма для китайского.
Каждое добавление языка — архитектурное решение с обоснованием в реестре. Не «по запросу», а по триггеру.
Запрет на «временные» языки
Язык, добавленный в SupportedLanguage, остаётся в нём без обратного хода — нельзя «отключить» язык после того, как пользователи начали его использовать. Это нарушает право на услугу и ломает работу.
Допустимо: is_active: false для нового языка во время предварительного тестирования (пока не было пользователей).
Базовый набор валют первой волны
| Код | Symbol | Native name (ru) | Применение | Применение в первой волне |
|---|---|---|---|---|
UAH | ₴ | гривна | Главная для UA | Display + Settlement в UA |
EUR | € | евро | Главная для CZ, PL, EU broader | Display + Settlement в CZ, PL |
CZK | Kč | чешская крона | Альтернативная для CZ | Display, ограниченно Settlement |
PLN | zł | польский злотый | Альтернативная для PL | Display, ограниченно Settlement |
KZT | ₸ | тенге | Главная для KZ | Display + Settlement в KZ |
USD | $ | доллар США | Кросс-валютный референс, USD-цены поставщиков | Settlement reference |
Правила расширения валютного набора
- Фаза 2 —
GBPпри выходе на UK;RON(Румыния),HUF(Венгрия),BGN(Болгария) при расширении в широкую Европу. - Фаза 3 —
TRY(Турция),GEL(Грузия),AZN(Азербайджан),AMD(Армения). - Фаза 4 —
AED(ОАЭ),CNY(Китай), и другие при выходе в новые регионы.
Каноничные различения для валют
В платформе разводятся пять разных значений валюты для одного и того же бронирования (фиксация из api-contracts.md Локализация и валюты):
- Supplier currency — валюта, в которой поставщик выставляет счёт платформе.
- Canonical settlement currency — валюта взаиморасчёта платформы с поставщиком (может отличаться от supplier currency, если поставщик принимает несколько).
- Quote display currency — валюта, в которой клиенту показывается цена при коммерческой фиксации.
- Booking payment currency — валюта, в которой клиент платит (может отличаться от display currency, если клиент платит через провайдер платёжных услуг с другой валютой счёта).
- Conversion reference — валюта-ориентир для исторических сравнений и аналитики (типично USD).
Каждая разница между ними — отдельная конвертация с собственным FxRateSnapshot и собственной маржой.
Запрет на скрытую FX-маржу
- ❌ Маржа платформы, не отражённая в
FxRateSnapshot.margin_applied. - ❌ Курс отображения, отличающийся от курса фиксации без объяснения клиенту.
- ❌ Двойная конвертация (USD → EUR → UAH вместо USD → UAH) без обоснования и без отражения в снимках.
Политика валютных операций
Фиксация курса в момент коммерческой фиксации
Главный закон — курс конвертации фиксируется в момент создания Quote и не меняется до конца жизненного цикла этой коммерческой фиксации:
SearchProjection.indicative_price (UAH)
↓ — клиент выбрал предложение
Quote.created
↓ — фиксируется FxRateSnapshot для конвертации supplier_currency → display_currency
Quote.confirmed
↓ — клиент платит
Booking.payment_initiated
↓ — если payment_currency ≠ display_currency, фиксируется второй FxRateSnapshot
Booking.confirmed
↓ — для взаиморасчёта с поставщиком используется fixed FxRateSnapshot
Settlement.cleared
Окна актуальности курсов
| Цель использования | Окно актуальности | Источник |
|---|---|---|
Отображение в поиске (indicative_price) | Минуты | Платформенный кэш курсов с обновлением каждые 5 минут |
Коммерческая фиксация (Quote) | Срок жизни Quote (типично 5–30 минут) | Снимок на момент создания, никогда не пересчитывается |
Бронирование (Booking) | Навсегда | Снимок на момент платежа |
Взаиморасчёт (Settlement) | Навсегда | Снимок на момент создания Settlement |
| Аналитика (DWH) | Навсегда | Дневной средний курс или конкретный снимок |
Источники курсов
Внешние источники
- Центральные банки (Европейский ЦБ, НБУ, НБК) — официальные курсы для compliance-отчётности.
- Провайдеры платёжных услуг (Stripe, Adyen) — реальные курсы конвертации платежа.
- Финансовые провайдеры (Wise, Revolut Business, специализированные FX-провайдеры) — для оптимизации стоимости.
- Финансовые агрегаторы (XE.com, OpenExchangeRates) — для индикативных курсов.
Каноничный приоритет источника
| Цель | Главный источник | Резервный |
|---|---|---|
| Платёж клиента | Курс провайдера платёжных услуг | Курс центрального банка |
| Взаиморасчёт с поставщиком | Курс банка платформы | Курс центрального банка |
| Compliance-отчётность | Курс центрального банка применимой юрисдикции | — |
| Поиск (отображение) | Платформенный агрегированный курс | Финансовый агрегатор |
| Аналитика | Дневной средний курс центрального банка | — |
Защита от арбитража
При изменении курса между моментом отображения в поиске и моментом коммерческой фиксации — клиент может попытаться использовать рассогласование (выбрать предложение с устаревшей выгодной ценой). Защита:
- Окно индикативной цены в поиске — короткое (минуты).
- При создании коммерческой фиксации — пересчёт цены на текущий курс (с отображением клиенту, если изменилось значимо).
- Допустимое отклонение — каноничный порог (например, 1%); при превышении клиент видит обновлённую цену и явно подтверждает.
Политика разрешения локали
Алгоритм по приоритету
1. Явный параметр запроса (?locale=ru-UA или Accept-Language)
↓
2. Сохранённое предпочтение субъекта (из RecipientPreferences для авторизованного)
↓
3. Конфигурация тенанта (для запросов через партнёрский интерфейс)
↓
4. Геогеографический вывод по IP-адресу
↓
5. Подсказки браузера (вторичные Accept-Language)
↓
6. Глобальный default (en для разработчиков, ru для UA, и т.д.)
Применение по поверхностям
Каждая поверхность имеет свою LocaleResolutionPolicy:
- Партнёрская поверхность (Partner API Surface) — главный приоритет: параметр запроса. Без явного параметра — fallback на конфигурацию партнёра. Геогеографический вывод не применяется (партнёр может работать из любой страны).
- Потребительская витрина (B2C Storefront Surface) — главный приоритет: сохранённое предпочтение субъекта; для нового пользователя — геогеографический вывод по IP.
- Поверхность для агентств (Agency Working Surface) — главный приоритет: предпочтение агента (из настройки рабочего места).
- Tour Builder Closed Surface — главный приоритет: конфигурация тенанта (тур обычно создаётся в одной локали и не меняется).
Запрет смешения локалей
В рамках одной сессии (SearchSession, диалог поддержки, цепочка запросов в Tour Builder) — одна локаль на всю сессию. Изменение локали посередине ломает консистентность (часть результатов на одном языке, часть на другом).
Допустимо: пользователь явно меняет локаль через UI — создаётся новая сессия с новой локалью, текущая сессия завершается.
Forsetage forwarding policy и fallback
Каноничный путь fallback для контента
Когда запрашивается контент на языке X, но перевода нет:
Перевод на X отсутствует
↓
Попытка fallback по цепочке (например, для uk: uk → ru → en)
↓
Перевод на резервном языке отображается с пометкой языка
↓
В метаданные ответа включается признак fallback_used: true
Метаданные позволяют клиенту:
- Показать визуальный индикатор «перевод на запасном языке».
- Логировать пропущенный перевод для последующего восполнения.
Fallback для валют
При запросе цены в валюте Y, не поддерживаемой платформой:
- Возвращается цена в ближайшей поддерживаемой валюте.
- В ответе включается признак
currency_fallback_applied: true. - Указывается причина (запрашиваемая валюта не поддерживается).
Fallback для часовых поясов
При неопределённом часовом поясе субъекта:
- Используется часовой пояс из
RegionLocaleтенанта. - Если и его нет — UTC с явной пометкой.
Форматирование
Каноничные форматы дат
| Контекст | Формат для ru-UA | Формат для cs-CZ | Формат для en-US |
|---|---|---|---|
| Краткая дата | 15.06.2026 | 15.06.2026 | 06/15/2026 |
| Длинная дата | 15 июня 2026 г. | 15. června 2026 | June 15, 2026 |
| День недели + дата | пн, 15 июня 2026 | po, 15. června 2026 | Mon, June 15, 2026 |
| Время | 14:30 | 14:30 | 2:30 PM |
| Дата + время | 15.06.2026, 14:30 | 15. 06. 2026, 14:30 | June 15, 2026, 2:30 PM |
| ISO 8601 (для API) | 2026-06-15T14:30:00+03:00 | то же | то же |
Каноничные форматы чисел
| Контекст | Формат для ru-UA/uk-UA | Формат для cs-CZ | Формат для en-US |
|---|---|---|---|
| Целое | 1 234 567 | 1 234 567 | 1,234,567 |
| Дробное | 1 234 567,89 | 1 234 567,89 | 1,234,567.89 |
| Процент | 12,5 % | 12,5 % | 12.5% |
Каноничные форматы валют
Применяется display_format_template валюты для конкретной локали:
| Локаль | UAH | EUR | USD |
|---|---|---|---|
uk-UA | 1 234,56 ₴ | 1 234,56 € | $1 234,56 |
cs-CZ | 1 234,56 ₴ | 1 234,56 € | 1 234,56 $ |
en-US | ₴1,234.56 | €1,234.56 | $1,234.56 |
Адреса и телефоны
Форматы адресов
Адресные поля каноничны (улица, дом, индекс, город, регион, страна), но порядок отображения различается по локали:
uk-UA,ru-UA— Страна, индекс, город, улица, дом.cs-CZ,pl-PL— Имя, улица + дом, индекс + город, страна.en-US— Имя, улица + дом, город, штат, индекс, страна.
Форматы телефонов
E.164 для хранения (+380441234567), форматирование для отображения по RegionLocale:
uk-UA—+38 (044) 123-45-67cs-CZ—+420 123 456 789en-US—+1 (212) 555-1234
Юрисдикционные следствия
Юрисдикция определяет много правил
Расширение в новую страну — это не просто добавление языка и валюты. Это:
- Новые регуляторные обязательства (см. Соответствие требованиям регуляторов).
- Новые налоговые режимы (НДС, налог с продаж, маржинальный режим Tour Operators').
- Новые правила формата документов (счёт, чек, акт сверки).
- Новые требования к согласию (например, для некоторых стран — двойной opt-in для маркетинга).
- Новые провайдеры платёжных услуг (см. Платёжный домен, Развилка 1).
- Новые требования к локализации данных (для определённых стран — данные клиентов должны храниться внутри страны).
Каноничный процесс расширения географии
Каждое расширение проходит через стандартный поток:
- Бизнес-обоснование (рынок, размер, конкурентная позиция).
- Регуляторный анализ (compliance, налоги, соглашение об обработке данных).
- Локализация (язык, валюта, часовой пояс, форматы).
- Платёжный анализ (провайдеры платёжных услуг, лицензирование).
- Контентная локализация (переводы, культурная адаптация).
- Pilot — закрытое тестирование с ограниченным набором тенантов.
- Production launch.
Без прохождения всех 7 шагов — расширение в страну не выпускается.
Многоязычный контент
Полная политика — в Медиа и контент, раздел ContentTranslation. Здесь — кросс-доменное правило:
- Все контентные сущности платформы (
ContentBundle,NotificationTemplate,RankingPolicy.diversity_rules, документы интерфейсов и т.д.) используют одну и ту же сущностьContentTranslationдля управления переводами. - Все домены используют одни и те же правила fallback и
language_payloadsструктуру. - Не допускаются локальные системы переводов в отдельных доменах (например, отдельная база переводов для уведомлений).
Часовые пояса в каждом контуре
Где имеет значение часовой пояс
- Бронирование — даты заезда/выезда в локальном часовом поясе объекта (а не клиента).
- Платёж — момент платежа в UTC, отображение в часовом поясе клиента.
- Уведомления — отправка с учётом часового пояса получателя (окна тишины — см. Уведомления и коммуникации).
- Аналитика — агрегация по дням в часовом поясе тенанта (например, для расчёта дневных квот).
- Tour Builder — расписание сегментов тура в часовом поясе локации каждого сегмента.
- Платёжный цикл — расчётные периоды в часовом поясе валюты взаиморасчёта.
Запрет на «локальное время без указания пояса»
Любое временное поле без часового пояса — архитектурная ошибка. Все временные поля либо в UTC (для хранения), либо с явной зоной (для отображения).
Учёт потребления
Локализационные операции — типично дешёвые для платформы:
- Конвертация валют — кэширование, низкая стоимость в реальном времени.
- Форматирование — на стороне клиента или edge-слоя.
- Переводы — обрабатываются единожды через
ContentTranslationи переиспользуются.
Заметные расходы возникают только при обработке новых переводов (платное API машинного перевода или человеческие переводчики). Учёт ведётся через ml_inference_calls (для машинного перевода) и через журнал переводческих сервисов.
События платформы локализации
| Событие | Когда | Главные потребители |
|---|---|---|
locale.resolution.completed | Разрешение локали для запроса | Платформа данных (для аналитики) |
locale.fallback.applied | Применён fallback (пропущенный перевод, неподдерживаемая валюта) | Команда локализации, восполнение переводов |
language.added | Добавлен новый язык в SupportedLanguage | Контур документации, команды контента |
language.deactivated | Язык переведён в неактивное состояние | Контур аудита |
currency.added | Добавлена новая валюта в SupportedCurrency | Платёжный контур, команда финансов |
region_locale.created | Создана новая RegionLocale | Все контуры, использующие локаль |
fx.rate.snapshotted | Создан снимок курса для коммерческой фиксации или взаиморасчёта | Контур аудита, контур finance |
fx.rate.divergence_detected | Расхождение между источниками курса превышает порог | Команда finance, оперативная команда |
timezone.policy.applied | Применена политика часового пояса для отображения | Платформа данных |
Полная таксономия — в Первоначальная таксономия событий.
Технологический выбор по фазам
| Фаза | Реестр локалей | Машинный перевод | Источник курсов | Часовые пояса |
|---|---|---|---|---|
| Bootstrap | Хранение в основной БД | Сторонний сервис (DeepL/Google) | Финансовый агрегатор | Библиотека IANA (tzdata) |
| 2 | Расширенный реестр с api-as-product поддержкой | Сторонний с пост-редактированием | Несколько источников с резервированием | То же |
| 3 | Multi-region реестр | Собственная модель для travel-семантики | Прямые интеграции с банками и платёжными провайдерами | Локализованные правила DST для каждого региона |
| 4 | Federated реестр | LLM-based контекстный перевод | Полная экосистема FX-сервисов | Edge-aware расчёты часовых поясов |
Фазы развёртывания
Фаза Bootstrap (0–6 месяцев)
Что разворачивается:
- Каноничная модель (
SupportedLanguage,SupportedCurrency,RegionLocale,LocaleResolutionPolicy,FxRateSnapshot,TimezonePolicy) зафиксирована в схеме хранения. - Базовый набор 6 языков и 6 валют первой волны.
- 4 каноничные
RegionLocale(UA, CZ, PL, KZ). - Простой
LocaleResolutionPolicy(явный параметр + fallback). - Базовый сторонний машинный перевод.
- Источник курсов от одного финансового агрегатора.
- Все временные поля в UTC.
Триггер выхода:
- Готовность к первому боевому запуску — нужны зрелые правила обработки коммерческих фиксаций с FX.
- Появление расхождений между источниками курсов — нужна резервная политика.
Фаза 2 — Production i18n (6–18 месяцев)
Что разворачивается:
- Несколько источников курсов с резервированием.
- Полная политика fallback со всеми каноничными цепочками.
- Расширенная
LocaleResolutionPolicyper-surface. - Журнал расхождений курсов с алертами.
- Расширенное форматирование (адреса, телефоны).
- Расширение языков по плану (de, sk при подходе к широкой Европе).
- Партнёрский программный интерфейс выбора локали (для партнёров, обслуживающих своих клиентов в нескольких странах).
Триггер выхода:
- Появление платформенной модели перевода (фаза 3).
- Расширение в страны с сложной юрисдикцией (Турция, Великобритания).
Фаза 3 — Smart i18n (18–30 месяцев)
Что разворачивается:
- Платформенная модель перевода для travel-семантики.
- Multi-region хранение с локализацией данных.
- Прямые интеграции с банками для курсов (без посредников).
- Расширение в
tr,hr,bg,hu,ro,slязыки. - Локализованные DST-правила.
- Контекстная конвертация курсов (с учётом источника платежа клиента, типа карты).
Фаза 4 — Глобальная i18n (30+ месяцев)
Что разворачивается:
- LLM-based контекстный перевод.
- Поддержка
rtlязыков (арабский). - Поддержка иной системы письма (китайский — традиционный/упрощённый).
- Полная экосистема FX-сервисов.
- Edge-aware расчёты часовых поясов.
Архитектурные решения с тезисным обоснованием
Решение 1. Единый кросс-доменный слой, не локальные локализации
Цель: обеспечить консистентность платформы по всем поверхностям и доменам.
Тезисы:
- Без единого слоя каждый домен решает локализацию по-своему — поиск в одной форме, уведомления в другой. Это разрушает целостность.
- Юрисдикционные обязательства требуют единых форматов документов через все контуры.
- Современные платформы (Booking.com с десятками языков, Airbnb, Stripe) — все строят i18n как единый слой.
Решение 2. Каноничные различения валют (5 значений вместо одного)
Цель: обеспечить точную трассировку конвертаций и финансовую корректность.
Тезисы:
- Без различения возникают финансовые неточности (например, partner billing в одной валюте, а supplier settlement в другой — компенсация конвертацией невозможна).
- Регуляторы требуют прозрачности FX-операций — без снимков курсов компенсация невозможна.
- Каноничные различения уже зафиксированы в API Contracts. Этот документ их структурирует и привязывает к снимкам курсов.
Решение 3. Фиксация курса в момент коммерческой фиксации
Цель: обеспечить неизменность цены для клиента во время жизненного цикла коммерческой фиксации.
Тезисы:
- Цена — это коммерческое обещание. Клиент видит цену и решает покупать. Изменение цены до платежа разрушает доверие.
- Снимок курса — единственный надёжный механизм; «пересчёт по текущему курсу» приводит к жалобам и спорам.
- Современные платежные платформы (Stripe, Adyen) — все фиксируют курс в момент создания платёжного намерения.
Решение 4. Все временные поля в UTC, отображение в локальном часовом поясе
Цель: избежать класса ошибок «дата без зоны» и обеспечить корректные расчёты периодов через зоны.
Тезисы:
- «Локальное время без указания пояса» — самая распространённая ошибка в распределённых системах. Особенно критично с DST.
- UTC как универсальный формат хранения — стандарт индустрии.
- Локализация на отображении (через
RegionLocaleили предпочтение субъекта) — единственный корректный путь.
Решение 5. Цепочки fallback с явной пометкой результата
Цель: позволить отображение пользователю даже при отсутствии перевода без молчаливой подмены.
Тезисы:
- Полностью отсутствующий контент — хуже, чем переведённый на резервный язык.
- Молчаливая подмена создаёт впечатление «всё работает», в то время как переводы накапливают пропуски.
- Явная пометка fallback позволяет пользователю понять (через UI-индикатор), что это резервный язык, а команде — собрать данные о пропущенных переводах.
Открытые развилки
Развилка 1. Платформенная модель перевода — собственная или через партнёров
В фазе 3 — собственная модель для travel-семантики. Альтернатива — партнёрство с переводчиками или с сервисами специализированного перевода.
Эскалируется: при выходе из фазы 2.
Развилка 2. Локализация документов compliance
Налоговые документы (счета, чеки) и юридические документы (соглашения, политики) — формируются по правилам конкретной юрисдикции. Глубина локализации (только перевод vs. адаптация формата vs. полная переработка по локальным шаблонам) — открытая развилка.
Эскалируется: при детальной проработке compliance-документов в фазе 2 (production launch).
Развилка 3. Поддержка rtl языков и иных систем письма
Арабский, иврит, китайский, японский — открытый вопрос фазы 4. Требует значительной переработки UI-компонентов.
Эскалируется: при бизнес-обосновании выхода в эти регионы.
Развилка 4. Crowd-sourced улучшения переводов
Возможность получения улучшений переводов от партнёров и агентств для своих регионов. Коммерческие следствия (плата агентам за качественные правки).
Эскалируется: при появлении масштабных партнёров с региональной экспертизой.
Развилка 5. Конкретные провайдеры FX
В фазе 3 — выбор конкретных банков и финансовых провайдеров для прямых интеграций. Зависит от объёма платёжного оборота и от регулятивной квалификации платформы.
Эскалируется: при достижении объёма платежей, оправдывающего прямые интеграции.
Связанная документация
Корневые архитектурные документы
- Архитектурный якорь и бизнес-модель — базовый набор языков и валют первой волны.
- Каноничная доменная ось — каноничные сущности, к которым применяется локализация.
- Поверхности взаимодействия — поверхности, использующие политики разрешения локали.
- Платформа как продукт — локализация как продуктовый атрибут.
- Связь с реализацией — текущее состояние geo chain в
home-to-go-api. - Операционная ось — наблюдаемость локализационных событий.
Связанные доменные документы
- API Contracts — каноничные различения локализации и валют, на которые опирается этот документ.
- Платёжный домен — multi-currency и FX-policy в платёжном контуре.
- Поиск и обнаружение — многоязычный поиск, локализация фасетов.
- Уведомления и коммуникации — локализация в шаблонах сообщений.
- Медиа и контент —
ContentTranslationкак сущность. - Семантика предложений, цены, бронирования — фиксация валюты в
Quote. - Партнёрские взаиморасчёты — расчётные периоды в часовых поясах.
- Tour Builder Domain — расписание сегментов тура в часовых поясах.
- Соответствие требованиям регуляторов — юрисдикционные обязательства.
- Тенантная настройка — конфигурация локали тенанта.
- Платформа машинного обучения — модели перевода и кросс-язычные эмбеддинги.
Реализационная база home-to-go-api
GEO_DATABASE.md— модель локаций с переводами для 182 стран.GEO_CHAIN.md— реализация геоцепочки.AMENITY_PLAN.md— справочник удобств с переводами на ru/uk.
Документы развития
- Первоначальная таксономия событий — таксономия событий локализации.
Операционная сторона
- Наблюдаемость и реагирование на инциденты — наблюдаемость FX-расхождений.
- Дорожная карта инфраструктурного масштабирования — фазы развёртывания multi-region.
Архитектурные правила
- Закон 00000 — платформа главенствует над поставщиками — платформа задаёт каноничный набор языков и валют.
- Современные лучшие практики верхнеуровневых платформ — Booking.com, Airbnb, Stripe как ориентиры i18n.
- Развитие без деградации — расширение языков и валют как развитие, не миграция.
- Эластичное масштабирование и упаковка по фазам — фазы развёртывания i18n.
- Тезисное обоснование архитектурных решений — формат принятия решений.