Организация переводов в экосистеме FormatJS строится вокруг разделения сообщений по локалям и строгого соблюдения структуры идентификаторов. Основой служат JSON-файлы, содержащие пары «ключ — значение», где значение представляет собой строку в формате ICU Message Syntax, поддерживающую интерполяцию, плюрализацию и условные конструкции.
Базовый принцип организации заключается в том, что каждый язык (локаль) хранится отдельно, а структура ключей остаётся идентичной между всеми локалями. Это обеспечивает предсказуемость и упрощает масштабирование.
Простейший вариант структуры:
/locales
/en.json
/ru.json
/kk.json
Каждый файл содержит одинаковые ключи:
{
"app.title": "Application",
"app.description": "Modern interface for managing data",
"user.login": "Log in",
"user.logout": "Log out"
}
{
"app.title": "Приложение",
"app.description": "Современный интерфейс для управления данными",
"user.login": "Войти",
"user.logout": "Выйти"
}
Ключевая характеристика такого подхода — полная синхронизация структуры между локалями. Любое расхождение приводит к падению fallback-механизмов или отсутствию перевода.
По мере роста приложения плоская структура становится неудобной. В FormatJS принято использовать точечную нотацию для группировки сообщений по доменам:
auth.login.titleauth.login.buttondashboard.stats.usersdashboard.stats.revenueТакая организация позволяет логически группировать переводы, не разрывая их по отдельным файлам:
{
"auth.login.title": "Welcome back",
"auth.login.button": "Sign in"
}
{
"auth.login.title": "С возвращением",
"auth.login.button": "Войти"
}
При этом структура остаётся линейной внутри файла, что важно для совместимости с большинством загрузчиков FormatJS, не требующих вложенных объектов.
В крупных приложениях предпочтительно разделять переводы не только по локалям, но и по функциональным модулям. Это снижает размер файлов и упрощает сопровождение.
Типичная структура:
/locales
/en
common.json
auth.json
dashboard.json
/ru
common.json
auth.json
dashboard.json
Пример auth.json:
{
"login.title": "Sign in to your account",
"login.error": "Invalid credentials",
"register.title": "Create account"
}
Такой подход позволяет:
FormatJS использует ICU Message Format, что напрямую влияет на организацию содержимого файлов переводов. Вместо простых строк значения могут содержать выражения:
{
"messages.inbox": "You have {count, plural, one {# message} other {# messages}}"
}
{
"messages.inbox": "У вас {count, plural, one {# сообщение} few {# сообщения} many {# сообщений} other {# сообщения}}"
}
Такие конструкции требуют строгого единообразия ключей между локалями, поскольку изменение структуры ICU-сообщения в одной локали без соответствующих изменений в других приводит к неконсистентности UI.
Практика контекстной группировки предполагает разделение сообщений по их назначению в интерфейсе:
button, label,
placeholder)toast, alert)error)system)Пример:
{
"button.save": "Save",
"button.cancel": "Cancel",
"error.required": "This field is required",
"toast.success": "Saved successfully"
}
Такой подход упрощает поиск и предотвращает дублирование ключей.
Существует два основных подхода:
Плоский файл (flat structure) Все переводы находятся в одном JSON на локаль.
Преимущества:
Недостатки:
Модульная структура (modular structure) Переводы разбиваются по доменам и частям приложения.
Преимущества:
Недостатки:
В долгоживущих проектах структура файлов переводов может изменяться. Для контроля совместимости применяется версионирование:
/locales/v1/en.json
/locales/v2/en.json
или через метаданные:
{
"_version": "2.3",
"app.title": "Dashboard"
}
Это позволяет отслеживать изменения контрактов сообщений между релизами.
FormatJS поддерживает fallback локалей, что влияет на организацию файлов. Обычно формируется цепочка:
ru-KZruenПри отсутствии ключа в целевой локали происходит поиск в родительской.
Структура файлов должна обеспечивать:
en);При использовании FormatJS часто применяется автоматическая генерация списка сообщений из кода. В этом случае структура файлов переводов становится отражением исходного кода, а не ручной разметкой.
Типичный процесс:
babel-plugin-react-intl);Результирующий файл приобретает строгую форму:
{
"nav.home": "Home",
"nav.about": "About",
"nav.contact": "Contact"
}
Основная проблема больших систем переводов — дрейф структуры, при котором разные локали начинают расходиться по набору ключей.
Для предотвращения используются:
Структурная целостность становится критическим свойством системы, так как FormatJS предполагает идентичность ключей как базовый контракт между кодом и локализацией.
При увеличении объёма сообщений применяется нормализация структуры:
Пример shared:
common.json
{
"ok": "OK",
"cancel": "Cancel",
"loading": "Loading..."
}
Эти значения импортируются во все модули без дублирования, что снижает риск расхождения формулировок и упрощает поддержку интерфейса.