Соглашения об именовании ключей

Соглашения об именовании ключей в i18next определяют устойчивость масштабируемой системы переводов и напрямую влияют на поддерживаемость локализационного слоя в больших приложениях. При отсутствии единообразной структуры ключей словари превращаются в набор несвязанных строк, усложняющих сопровождение, рефакторинг и командную работу.

Основной подход — структурирование ключей в виде вложенных пространств, отражающих доменную модель приложения.

Типичная форма:

{
  "auth": {
    "login": {
      "title": "Вход",
      "submit": "Войти"
    }
  }
}

Внутренне i18next поддерживает доступ через точечную нотацию:

t('auth.login.title')

Иерархия уменьшает коллизии и позволяет группировать переводы по функциональным зонам: auth, profile, settings, checkout.

Ключевой принцип — отражение структуры предметной области, а не структуры интерфейса. Привязка к UI-компонентам приводит к дублированию и нестабильности при рефакторинге.

Пространства имён (namespaces)

При росте проекта применяется разделение переводов по namespace:

i18n.init({
  ns: ['common', 'auth', 'dashboard'],
  defaultNS: 'common'
});

Структура ресурсов:

{
  "auth": {
    "login": "Вход",
    "logout": "Выход"
  }
}

Обращение:

t('login', { ns: 'auth' })

или с явным указанием:

t('auth:login')

Соглашение об именовании namespaces строится на принципе bounded context: каждый namespace соответствует самостоятельной функциональной области.

Flat-структура ключей

Альтернативный подход — плоская структура:

{
  "auth_login_title": "Вход",
  "auth_login_submit": "Войти"
}

Преимущества:

  • простота поиска
  • отсутствие вложенности

Недостатки:

  • рост длины ключей
  • отсутствие семантической структуры
  • высокая вероятность дублирования префиксов

В проектах с i18next flat-структура применяется редко и обычно ограничивается legacy-кодом.

Соглашения о стиле именования

snake_case

{
  "auth_login_title": "Вход"
}

Используется в проектах, ориентированных на backend-стандарты и API-совместимость. Удобен для генерации ключей.

camelCase

{
  "authLoginTitle": "Вход"
}

Применяется в frontend-экосистемах, но ухудшает читаемость при длинных составных ключах.

kebab-case

{
  "auth-login-title": "Вход"
}

Редко используется из-за неудобства обращения через точечную нотацию.

точечная структура + короткие сегменты

Наиболее устойчивый подход:

{
  "auth": {
    "login": {
      "title": "Вход"
    }
  }
}

Комбинирует читаемость и расширяемость.

Соглашения для действий и UI-элементов

Ключи должны отражать тип интерфейсного значения:

  • title — заголовки страниц и блоков
  • label — подписи полей
  • placeholder — плейсхолдеры
  • button или btn — действия
  • error — сообщения ошибок
  • hint — подсказки

Пример:

{
  "profile": {
    "form": {
      "email": {
        "label": "Электронная почта",
        "placeholder": "Введите email"
      },
      "submit": {
        "button": "Сохранить"
      }
    }
  }
}

Такое разделение снижает неоднозначность значений и предотвращает смешивание контекстов.

Соглашения для множественного числа

В i18next используются стандартные суффиксы:

{
  "cart": {
    "item_one": "товар",
    "item_other": "товаров"
  }
}

Использование:

t('cart.item', { count: 3 })

Система автоматически выбирает форму на основе правил языка.

Соглашение: базовый ключ без суффикса (item) используется как логический корень, а формы — как расширения (_one, _few, _other).

Контекстные ключи

Для различий значений в зависимости от контекста применяется суффикс context:

{
  "button": {
    "save": "Сохранить",
    "save_context_admin": "Сохранить изменения (админ)"
  }
}

Либо через встроенный контекст:

t('button.save', { context: 'admin' })

Соглашение: контекст добавляется после основного ключа и не разрывает иерархию.

Избежание избыточной детализации

Антипаттерн — чрезмерно глубокие ключи:

{
  "app": {
    "page": {
      "profile": {
        "section": {
          "form": {
            "input": {
              "email": {
                "label": "Email"
              }
            }
          }
        }
      }
    }
  }
}

Проблема — высокая стоимость рефакторинга и слабая читаемость.

Более устойчивый вариант:

{
  "profile": {
    "email": {
      "label": "Email"
    }
  }
}

Принцип: глубина структуры должна отражать доменную иерархию, а не DOM-дерево.

Согласованность между языковыми файлами

Все языковые ресурсы в i18next обязаны сохранять идентичную структуру ключей.

Пример:

// en
{
  "auth": {
    "login": "Login"
  }
}
// ru
{
  "auth": {
    "login": "Вход"
  }
}

Несоответствие структуры приводит к fallback-ошибкам и непредсказуемому поведению интерфейса.

Префиксы домена и модулей

При использовании микрофронтендов или модульной архитектуры применяются доменные префиксы:

{
  "billing.invoice.create": "Создать счёт"
}

или:

{
  "billing": {
    "invoice": {
      "create": "Создать счёт"
    }
  }
}

Соглашение: верхний уровень всегда соответствует модулю системы.

Генерация ключей и стабильность идентификаторов

Ключи не должны зависеть от текстового значения. Плохой пример:

{
  "login_button_click_here": "Войти"
}

Изменение текста ломает семантику ключа.

Устойчивый вариант:

{
  "auth": {
    "login": {
      "button": "Войти"
    }
  }
}

Ключи представляют идентификаторы смысла, а не текстовую форму.

Переиспользование ключей

Повторное использование допустимо только при совпадении контекста. Общие строки выносятся в common namespace:

{
  "common": {
    "cancel": "Отмена",
    "confirm": "Подтвердить"
  }
}

Использование:

t('common:cancel')

Соглашение: общие элементы интерфейса изолируются от доменных словарей.

Версионирование ключей

При изменении семантики ключа предпочтительнее добавление нового идентификатора, а не изменение существующего:

{
  "auth": {
    "login": "Вход",
    "signIn": "Войти"
  }
}

Удаление старых ключей производится после завершения миграционного периода, чтобы избежать поломок кэшей и старых сборок.

Антипаттерны именования

  • использование описательных фраз вместо идентификаторов:

    { "click_the_button_to_save_changes": "Сохранить" }
  • смешение языков в ключах

  • включение HTML или UI-логики в ключи

  • дублирование структуры без доменной логики

В контексте i18next такие подходы приводят к росту технического долга и усложнению локализации.