Разделение ответственности

Архитектура международализации в i18next строится вокруг строгого отделения текстовых ресурсов от логики приложения, представления интерфейса и бизнес-правил. Такой подход позволяет изолировать изменения переводов от изменения кода, а также минимизировать зависимость компонентов системы друг от друга.

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


Архитектурные слои в i18next

Слой инициализации

Инициализация i18next представляет собой отдельный конфигурационный контур, который определяет:

  • активные языки
  • fallback-язык
  • загрузчики ресурсов
  • стратегии детекции языка
  • форматирование и интерполяцию

Пример конфигурации:

import i18next from "i18next";

i18next.init({
  lng: "en",
  fallbackLng: "en",
  ns: ["common", "auth"],
  defaultNS: "common",
  interpolation: {
    escapeValue: false
  },
  resources: {
    en: {
      common: {
        welcome: "Welcome"
      }
    }
  }
});

Инициализация не должна содержать UI-логики или бизнес-правил. Она определяет только механизмы работы системы переводов.


Слой ресурсов переводов

Ресурсы переводов отделяются в самостоятельные структуры данных. Обычно используется разбиение по namespace:

  • common — общие строки интерфейса
  • auth — авторизация
  • profile — пользовательские данные
  • errors — сообщения ошибок

Структура файлов:

locales/
  en/
    common.json
    auth.json
  ru/
    common.json
    auth.json

Пример auth.json:

{
  "login": "Login",
  "logout": "Logout",
  "errors": {
    "invalidCredentials": "Invalid credentials"
  }
}

Такое разделение обеспечивает независимость доменных модулей и снижает связанность между функциональными частями системы.


Разделение UI и переводов

UI-компоненты не должны содержать строковых литералов, относящихся к пользовательскому языку. Вместо этого они используют ключи переводов.

Пример React-интеграции:

import { useTranslation } from "react-i18next";

function LoginButton() {
  const { t } = useTranslation("auth");

  return <button>{t("login")}</button>;
}

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


Разделение бизнес-логики и локализации

Бизнес-логика не должна зависеть от конкретного языка или строковых значений.

Неправильный подход:

if (error === "Invalid credentials") {
  // логика обработки
}

Правильный подход:

const ERROR_CODES = {
  INVALID_CREDENTIALS: "INVALID_CREDENTIALS"
};

if (errorCode === ERROR_CODES.INVALID_CREDENTIALS) {
  // логика обработки
}

А уже UI-слой отображает локализованное сообщение:

t("errors.invalidCredentials");

Таким образом, бизнес-логика оперирует стабильными идентификаторами, а слой i18n отвечает только за отображение.


Namespace как механизм изоляции ответственности

Namespace в i18next выполняет функцию модульного разделения переводов.

Каждый namespace соответствует определённому домену:

  • auth — аутентификация
  • cart — корзина
  • checkout — оформление заказа

Пример использования:

const { t } = useTranslation("checkout");

t("payment.success");

Это снижает риск коллизий ключей и улучшает масштабируемость проекта.


Интерполяция как отдельный уровень ответственности

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

Пример:

t("welcomeUser", { name: "Alex" });

Ресурс:

{
  "welcomeUser": "Welcome, {{name}}"
}

Недопустимо формировать строки вручную:

"Welcome, " + user.name

Интерполяция централизуется в i18n-слое, что позволяет:

  • единообразно управлять форматированием
  • подключать экранирование
  • расширять функциональность без изменения UI

Плюрализация как часть i18n-слоя

Обработка множественных форм чисел также выносится в систему переводов.

t("items", { count: 5 });
{
  "items_one": "{{count}} item",
  "items_other": "{{count}} items"
}

Бизнес-логика не принимает решений о грамматике языка. Она лишь передаёт числовые значения.


Отделение загрузки ресурсов

Для масштабируемых приложений используется динамическая загрузка переводов.

С использованием backend-плагина:

import Backend from "i18next-http-backend";

i18next.use(Backend).init({
  backend: {
    loadPath: "/locales/{{lng}}/{{ns}}.json"
  }
});

Это переносит ответственность за хранение и доставку переводов на внешний слой инфраструктуры.


Форматирование дат и чисел

Форматирование не должно смешиваться с переводами текста. i18next часто используется совместно с Intl API.

Пример:

const date = new Intl.DateTimeFormat("ru-RU").format(new Date());

Локализация текста и форматирование данных разделяются:

  • i18n — текстовые строки
  • Intl — числа, даты, валюты

Контейнеризация ответственности в приложении

В крупных приложениях формируется слоистая архитектура:

  • Presentation layer — компоненты UI
  • Localization layer — i18next
  • Domain layer — бизнес-правила
  • Infrastructure layer — загрузка ресурсов

Каждый слой взаимодействует только с соседним уровнем, избегая прямых зависимостей.


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

Хардкод строк в компонентах

<button>Submit</button>

Условная логика на основе переведённого текста

if (t("status") === "Success") {}

Формирование текста вне i18n слоя

const message = `Error: ${error.message}`;

Хранение бизнес-логики в переводах

{
  "canDelete": "true"
}

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


Изоляция ключей и устойчивость системы

Использование ключей вместо текстов создаёт стабильный контракт между слоями приложения. Ключ:

  • не зависит от языка
  • не меняется при редактировании перевода
  • может использоваться в аналитике и логике
t("errors.network.timeout");

Такой подход позволяет изменять текст без влияния на поведение системы.


Масштабирование через модульность переводов

При росте приложения структура i18n становится модульной:

features/
  auth/
    i18n/
      en.json
      ru.json
  billing/
    i18n/
      en.json
      ru.json

Каждый модуль владеет собственными переводами, что обеспечивает автономность разработки.


Централизация ответственности как базовый принцип

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