Структура ключей переводов в i18next напрямую влияет на читаемость, масштабируемость и удобство сопровождения интернационализации приложения. Одним из базовых архитектурных решений становится выбор между плоской (flat) и вложенной (nested) структурой ресурсов. Эти подходы не являются взаимоисключающими в рамках библиотеки, однако различия между ними существенно влияют на организацию кода и поведение функций интерполяции, пространств имён и fallback-механизмов.
Плоская структура представляет собой набор ключей, где каждый перевод определяется строкой без иерархии. Ключи обычно записываются в виде составных идентификаторов с использованием точек, подчёркиваний или других разделителей.
Пример плоской структуры:
{
"home_title": "Главная",
"home_description": "Описание главной страницы",
"button_save": "Сохранить",
"button_cancel": "Отмена"
}
1. Отсутствие вложенности
Все ключи находятся на одном уровне, что упрощает их восприятие на малых проектах, но усложняет навигацию при увеличении количества переводов.
2. Линейная адресация
Доступ к значениям осуществляется напрямую:
i18next.t('home_title');
3. Простота генерации и миграции
Плоский формат легко генерируется автоматически из таблиц, CMS или внешних сервисов локализации. Он также удобен для массовых замен и поиска по строкам.
4. Сложность масштабирования
При росте приложения количество ключей быстро увеличивается, и отсутствие структуры приводит к появлению длинных и семантически перегруженных идентификаторов:
{
"dashboard_user_profile_settings_privacy_toggle": "Приватность"
}
Такие ключи ухудшают читаемость и увеличивают риск ошибок при обращении.
Вложенная структура строится на принципе иерархии, где ключи организованы в виде объектов. Такой подход отражает структуру интерфейса, модулей или доменной логики.
Пример вложенной структуры:
{
"home": {
"title": "Главная",
"description": "Описание главной страницы"
},
"button": {
"save": "Сохранить",
"cancel": "Отмена"
}
}
1. Иерархическая организация
Ключи группируются по смыслу, что делает структуру ближе к архитектуре приложения.
Доступ осуществляется через точечную нотацию:
i18next.t('home.title');
2. Логическая группировка
Переводы объединяются по доменам, компонентам или страницам, что облегчает сопровождение и поиск:
{
"profile": {
"settings": {
"privacy": {
"title": "Приватность",
"description": "Управление настройками приватности"
}
}
}
}
3. Улучшенная масштабируемость
При росте проекта добавление новых ключей не нарушает общую структуру, а расширяет существующие узлы.
4. Сложность частичного доступа
Глубокая вложенность может усложнить динамическое формирование ключей и работу с переменными:
const section = 'profile.settings.privacy.title';
i18next.t(section);
i18next нативно поддерживает вложенные структуры и автоматически резолвит ключи с точечной нотацией.
Важный механизм — разворачивание ключей (key resolution):
i18next.t('profile.settings.privacy.title');
Библиотека последовательно проходит по объекту:
и возвращает конечное значение.
Плоская структура часто использует точки как часть ключа, что может конфликтовать с механизмом вложенности. Для предотвращения неоднозначности применяется экранирование.
{
"button.save": "Сохранить"
}
Доступ:
i18next.t('button.save', { nsSeparator: false });
или через настройку:
i18next.init({
keySeparator: false
});
При отключённом разделителе точка перестаёт интерпретироваться как вложенность, и ключи становятся строго плоскими.
В реальных проектах часто используется комбинированная модель:
{
"button": {
"save": "Сохранить",
"cancel": "Отмена"
},
"errors.network.timeout": "Превышено время ожидания"
}
Такой подход сочетает преимущества:
Структура ключей влияет на читаемость интерполяции, особенно в вложенных объектах.
Плоский вариант:
{
"welcome_user": "Добро пожаловать, {{name}}"
}
i18next.t('welcome_user', { name: 'Алексей' });
Вложенный вариант:
{
"welcome": {
"user": "Добро пожаловать, {{name}}"
}
}
i18next.t('welcome.user', { name: 'Алексей' });
Во втором случае интерполяция сохраняет ту же семантику, но ключ становится более структурированным и контекстным.
Вложенная структура часто комбинируется с namespaces, где верхний уровень уже определяет модуль.
Пример:
// common.json
{
"button": {
"save": "Сохранить"
}
}
// profile.json
{
"settings": {
"privacy": "Приватность"
}
}
В этом случае вложенность внутри namespace снижает необходимость в глобально уникальных ключах, чего требует плоская модель.
С точки зрения runtime-разрешения ключей различия между подходами минимальны, однако влияние проявляется на уровне:
Плоские структуры иногда приводят к большему количеству повторяющихся префиксов:
{
"profile_edit_title": "...",
"profile_edit_button_save": "...",
"profile_edit_button_cancel": "..."
}
Вложенность уменьшает дублирование:
{
"profile": {
"edit": {
"title": "...",
"button": {
"save": "...",
"cancel": "..."
}
}
}
}
1. Чрезмерная вложенность
Глубина более 4–5 уровней усложняет поддержку и делает ключи громоздкими:
i18next.t('app.profile.settings.privacy.security.level.high.title');
2. Псевдовложенность в плоских ключах
Использование точек без реальной структуры создаёт иллюзию иерархии:
{
"user.profile.edit.save.button.text": "Сохранить"
}
Такие ключи совмещают недостатки обеих моделей.
3. Смешение стратегий без правил
Отсутствие стандарта приводит к хаосу:
{
"button_save": "...",
"button.cancel": "...",
"profileSettingsPrivacy": "..."
}
Плоская структура оправдана при:
Вложенная структура предпочтительна при:
Гибридная модель становится стандартом для масштабируемых приложений, где структура переводов должна соответствовать структуре кода и одновременно оставаться совместимой с внешними источниками локализации.