Локализация на платформе — как устроены языки

BOLD Rewards · P14 · v4 — короткое объяснение для менеджера

1Иерархия языков: Платформа → Тенант → Сегмент

Каждый уровень — это подмножество языков уровня выше. Нельзя включить на сегменте язык, которого нет у тенанта.
PLATFORMмастер-реестр · superadmin
Все языки, которые в принципе умеет показывать платформа. Добавление = строка в БД + JSON-файл переводов в репозитории.
en-US fr-CA es-MX de-DE
▼ subset
TENANTнапр. Kohler · выбирает superadmin
Какие из языков платформы активны для этого клиента. Тенант-админ видит в CMS/LMS только эти языки.
en-US ★ fr-CA
▼ subset
SEGMENT= портал в легаси · тенант-админ
Программа / портал с одним языком. В легаси Kohler это были «Kohler Canada English» и «Kohler Canada French» — каждый сегмент привязан к одному языку.
fr-CA ★
Пример Kohler Canada. На платформе зарегистрированы английский и французский → у Kohler как у тенанта активированы оба → сегмент Kohler Canada English = en-CA, сегмент Kohler Canada French = fr-CA. Пользователь принадлежит к одному из них, и язык определяется автоматически по сегменту.
Что изменилось в v4 (2026-05-22). Уровень LOCATION убран — на локации язык больше не назначается. Язык теперь живёт на сегменте программы, как в текущей платформе Kohler. Решение: ручная привязка языка к локации не масштабируется (Kohler: 5000+ локаций приходит из CRM-feed, никто не будет руками выставлять язык каждой). Подтверждено на BOLD Team Sync 2026-05-22.

2Как платформа решает, какой язык показать пользователю

Идём сверху вниз — первое, что нашлось, побеждает. en-US — финальная страховка.
1
User choice
Пользователь сам кликнул переключатель в шапке
localStorage
2
Segment
Язык программы / портала, к которому привязан пользователь
program_segments.locale
3
Tenant default
Дефолтный язык клиента (тенанта)
tenant_settings.locale
4
Global fallback
Жёстко зашитый английский — никогда не сломается
en-US
Правило бизнеса. У пользователя нет своего поля «язык» в профиле. Язык определяется через сегмент, к которому он привязан. Сменил сегмент — язык пересчитался автоматически. «Язык — это свойство программы, а не человека.»

3Где живут сами переводы — это два разных мира

Интерфейсные строки и контент клиента переводятся по-разному и разными людьми.
STATIC UI

Кнопки, лейблы, ошибки

Где
JSON-файлы в коде (fr-CA.json)
Кто переводит
Разработчики и продакт-менеджер
Как доставляется
Только через деплой
Пример
«Save» → «Enregistrer»
DYNAMIC CONTENT

Страницы CMS и курсы LMS

Где
Существующие таблицы: content_locales / content_blocks (CMS), course_translations (LMS)
Кто переводит
Контент-менеджер тенанта
Как доставляется
Сразу из админки, без деплоя
Пример
«Welcome to Kohler Rewards…» → «Bienvenue chez Kohler…»
Почему так. Кнопка «Save» одинаковая у Kohler и Tesla — Kohler-у не нужно (и нельзя) трогать её перевод. А вот про сантехнику пишет сам Kohler и редактирует это через свою админку. Поэтому два разных хранилища.