Работа с локализацией в Globalize строится вокруг разделения данных по наборам сообщений, календарям, числам и форматам дат, основанных на CLDR-данных. Ключевой аспект масштабируемых приложений — грамотная организация файлов переводов, позволяющая минимизировать размер бандла, упростить сопровождение и обеспечить предсказуемую загрузку языковых ресурсов.
Типичная организация переводов в проекте с Globalize строится вокруг разделения по локалям и типам данных.
/locales
/en
messages.json
numbers.json
date.json
/ru
messages.json
numbers.json
date.json
/kk
messages.json
numbers.json
date.json
Такой подход обеспечивает:
Каждая локаль рассматривается как самостоятельный модуль данных, содержащий только необходимые фрагменты CLDR и пользовательские сообщения.
Globalize использует несколько категорий данных, которые логически разделяются на разные файлы.
Файл messages.json содержит ключи переводов
пользовательского интерфейса.
{
"app.title": "My Application",
"button.save": "Save",
"button.cancel": "Cancel"
}
Особенность организации сообщений заключается в их ключевой структуре. Используются:
button.save)button.*,
form.*)Плоская структура упрощает кэширование и динамическую подмену.
Файл numbers.json содержит CLDR-данные, необходимые для
форматирования чисел.
{
"minimumGroupingDigits": 1,
"symbols": {
"decimal": ".",
"group": ","
},
"numberFormat": {
"standard": "#,##0.###"
}
}
Данный файл часто генерируется автоматически из CLDR-источников и не редактируется вручную.
Файл date.json включает данные о календарях, периодах и
форматах отображения дат.
{
"months": {
"wide": ["January", "February", "March"]
},
"days": {
"wide": ["Sunday", "Monday", "Tuesday"]
},
"dateFormats": {
"short": "MM/dd/yy",
"long": "MMMM d, y"
}
}
Разделение по категориям внутри файла позволяет избегать избыточной загрузки данных календаря.
При масштабировании приложения применяется разбиение сообщений на доменные модули.
/locales
/ru
auth.json
profile.json
dashboard.json
Пример auth.json:
{
"login.title": "Вход",
"login.button": "Войти",
"error.invalidCredentials": "Неверный логин или пароль"
}
Такое разделение позволяет:
Одним из ключевых подходов является lazy loading языковых ресурсов.
import Globalize from "globalize";
async function loadLocale(locale) {
const messages = await import(`./locales/${locale}/messages.json`);
const numbers = await import(`./locales/${locale}/numbers.json`);
const date = await import(`./locales/${locale}/date.json`);
Globalize.load(messages.default);
Globalize.load(numbers.default);
Globalize.load(date.default);
return Globalize(locale);
}
Такой подход снижает начальный размер бандла и позволяет загружать только нужную локаль.
Globalize зависит от CLDR (Common Locale Data Repository). В проектной структуре обычно выделяется отдельный слой для CLDR-данных:
/cldr
/supplemental
likelySubtags.json
plurals.json
/main
/ru
numbers.json
dates.json
Рекомендуемая стратегия:
При больших проектах важно контролировать изменения переводов.
Распространённый подход:
/locales
/ru
v1
messages.json
v2
messages.json
Или использование версий в ключах:
{
"v2.login.title": "Вход",
"v2.login.button": "Войти"
}
Версионирование позволяет:
При использовании Webpack или Vite применяется стратегия разделения чанков.
export default {
resolve: {
alias: {
"@locales": "/src/locales"
}
}
};
Далее языковые файлы автоматически попадают в отдельные чанки:
Это уменьшает размер основного бандла и ускоряет старт приложения.
При росте проекта возникает необходимость унификации ключей.
Рекомендуемая модель:
<domain>.<component>.<element>
Примеры:
auth.login.title
auth.login.error
profile.settings.save
dashboard.stats.users
Преимущества:
В крупных системах переводы часто выносятся в отдельные репозитории или CMS.
Варианты хранения:
Пример загрузки через API:
async function fetchMessages(locale) {
const res = await fetch(`/i18n/${locale}/messages`);
return res.json();
}
Такой подход позволяет обновлять переводы без релиза приложения.
Globalize допускает многослойную загрузку данных.
Globalize.load(baseMessages);
Globalize.load(featureMessages);
Globalize.load(overrides);
Порядок важен: последующие слои переопределяют предыдущие.
Типичная схема:
При отсутствии полной локализации используется цепочка fallback:
ru-KZ → ru → en
Файловая структура отражает это:
/locales
/ru
/en
Частичные локали содержат только отличающиеся значения, остальные наследуются.
Для уменьшения количества запросов применяется объединение данных:
ru.bundle.json
en.bundle.json
Однако при этом теряется гранулярная загрузка. Баланс достигается через гибридную модель:
При изменении переводов важно управлять кэшированием.
Практика:
добавление хэша в имя файла
messages.ru.8f3a1.jsonлибо версия в URL
/locales/ru/messages?v=12Это предотвращает использование устаревших переводов в браузере.
Для обеспечения совместимости между системами используется единый формат:
Допустимая параметризация:
{
"welcome.user": "Hello, {name}"
}
При увеличении количества локалей и модулей структура эволюционирует в сторону доменно-ориентированной модели:
/i18n
/core
/auth
/billing
/profile
/shared
Каждый домен содержит собственные переводы для всех локалей.
Это позволяет: