Backend плагины

Backend-плагины в i18next отвечают за загрузку и хранение переводов вне клиентского окружения. Они позволяют отделить слой локализации от приложения, обеспечивая гибкость в выборе источника данных: файловая система, HTTP API, базы данных, облачные хранилища или собственные сервисы.

Ключевая идея заключается в том, что i18next не фиксирует способ получения ресурсов. Вместо этого используется контракт (интерфейс backend), который реализуется конкретным плагином.


Роль backend в системе i18next

i18next разделяет ответственность между несколькими уровнями:

  • core — управление переводами и языками
  • backend — получение ресурсов перевода
  • cache (опционально) — ускорение загрузки
  • plugins — расширение функциональности

Backend слой отвечает за два основных процесса:

  1. Загрузка переводов

    • получение JSON-файлов или структурированных данных
    • загрузка по языку и namespace
  2. Сохранение переводов

    • используется реже
    • применяется в системах администрирования переводов

Контракт backend-плагина

Любой backend для i18next должен реализовать методы:

read(language, namespace, callback)

Отвечает за получение перевода.

read(language, namespace, callback) {
  // загрузка данных
}

Параметры:

  • language — код языка (en, ru, de)
  • namespace — пространство имён (common, auth, errors)
  • callback(err, data) — возврат результата

create(languages, namespace, key, fallbackValue)

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

create(languages, namespace, key, fallbackValue) {
  // сохранение перевода
}

init(services, backendOptions, i18nextOptions)

Метод инициализации плагина.

init(services, backendOptions, i18nextOptions) {
  this.services = services;
  this.options = backendOptions;
}

Основные backend-реализации

HTTP backend

Один из самых распространённых вариантов — загрузка переводов через HTTP.

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

import i18next from 'i18next';
import HttpBackend from 'i18next-http-backend';

i18next
  .use(HttpBackend)
  .init({
    lng: 'ru',
    backend: {
      loadPath: '/locales/{{lng}}/{{ns}}.json'
    }
  });

Принцип работы

  • формируется URL на основе шаблона
  • выполняется HTTP GET запрос
  • JSON используется как источник переводов

Шаблонные переменные

  • {{lng}} — язык
  • {{ns}} — namespace

Файловый backend (Node.js)

Используется в серверных приложениях на Node.js.

import Backend from 'i18next-fs-backend';

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

Особенности:

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

Multi-backend стратегия

Некоторые реализации используют комбинацию источников.

import MultiBackend from 'i18next-multiload-backend-adapter';

Логика:

  • основной источник — быстрый (cache, memory)
  • резервный — HTTP или файловая система
  • fallback при ошибках загрузки

Кеширование в backend-плагинах

Кеширование снижает количество запросов к источнику данных.

Виды кеширования:

  • memory cache
  • localStorage (в браузере)
  • Redis (в серверных системах)
  • file cache

Пример memory cache слоя

class MemoryCache {
  constructor() {
    this.store = {};
  }

  get(key) {
    return this.store[key];
  }

  set(key, value) {
    this.store[key] = value;
  }
}

Интеграция кеша в backend

class Backend {
  constructor(services, options) {
    this.cache = new MemoryCache();
    this.options = options;
  }

  read(language, namespace, callback) {
    const key = `${language}-${namespace}`;

    const cached = this.cache.get(key);
    if (cached) return callback(null, cached);

    // загрузка данных
  }
}

Формат данных перевода

Backend возвращает JSON-структуру:

{
  "welcome": "Добро пожаловать",
  "auth": {
    "login": "Войти",
    "logout": "Выйти"
  }
}

i18next обрабатывает:

  • вложенные ключи
  • интерполяцию
  • множественные формы
  • контексты

Namespace и сегментация данных

Namespace позволяет разделять переводы по логическим модулям:

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

Пример структуры файлов

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

Асинхронная загрузка и поведение системы

Backend всегда работает асинхронно, даже если источник синхронный.

Поток выполнения:

  1. инициализация i18next
  2. вызов backend.read
  3. ожидание callback или Promise
  4. кеширование результата
  5. передача в core

Обработка ошибок

Backend обязан корректно возвращать ошибки:

read(language, namespace, callback) {
  fetch(url)
    .then(res => res.json())
    .then(data => callback(null, data))
    .catch(err => callback(err, false));
}

Поведение i18next:

  • при ошибке используется fallback язык
  • при отсутствии namespace применяется пустой объект
  • при критической ошибке возможен fallback к встроенным строкам

Fallback логика

Backend напрямую влияет на механизм fallback:

  • fallbackLng — резервный язык
  • fallbackNS — резервный namespace
  • loadPath fallback — альтернативный источник

Пример fallback цепочки

ru → en → default
auth → common → default

Оптимизация загрузки ресурсов

Пакетная загрузка

Некоторые backend поддерживают загрузку нескольких namespace за один запрос:

loadUrl: '/locales/{{lng}}/bundle?ns={{ns}}'

Lazy loading

Переводы загружаются по мере необходимости:

  • при рендере компонента
  • при переходе на страницу
  • при вызове t()

Предзагрузка

i18next.loadNamespaces(['common', 'auth']);

Backend получает список namespaces и выполняет групповой запрос.


Создание собственного backend-плагина

Структура минимального backend:

class CustomBackend {
  constructor(services, options = {}) {
    this.services = services;
    this.options = options;
  }

  init() {}

  read(language, namespace, callback) {
    const data = getDataSomehow(language, namespace);
    callback(null, data);
  }

  create(languages, namespace, key, fallbackValue) {
    saveTranslation(languages, namespace, key, fallbackValue);
  }
}

Подключение:

i18next.use(CustomBackend).init({});

Использование Promise вместо callback

Некоторые реализации поддерживают Promise:

read(language, namespace) {
  return fetch(`/api/${language}/${namespace}`)
    .then(res => res.json());
}

Безопасность backend-загрузки

При работе с HTTP backend учитываются:

  • CORS ограничения
  • авторизация (token headers)
  • защита от подмены переводов
  • валидация JSON структуры

Пример добавления заголовков

backend: {
  loadPath: '/locales/{{lng}}/{{ns}}.json',
  requestOptions: {
    headers: {
      Authorization: 'Bearer TOKEN'
    }
  }
}

Интеграция с CDN

Переводы часто размещаются на CDN:

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

Пример:

https://cdn.example.com/locales/ru/common.json

Инвалидация кеша

При изменении переводов требуется обновление:

  • versioning (v1, v2)
  • query params (?hash=abc)
  • TTL кеша

Пример versioned path

/locales/v2/{{lng}}/{{ns}}.json

Расширенные сценарии использования

Backend может поддерживать:

  • динамическую генерацию переводов
  • мультитенантные системы
  • A/B тестирование текстов
  • персонализированные переводы
  • загрузку из GraphQL API

Поведение при частичной загрузке

Если namespace загружен частично:

  • отсутствующие ключи не ломают систему
  • используется fallbackValue
  • происходит merge с существующими данными

Синхронизация переводов в реальном времени

В сложных системах backend может:

  • подписываться на изменения
  • обновлять кеш через WebSocket
  • триггерить reload ресурсов

Модель данных backend слоя

Типовая структура:

BackendResponse {
  language: string,
  namespace: string,
  data: object,
  timestamp: number
}

Совместимость с другими плагинами

Backend часто работает вместе с:

  • languageDetector
  • cache plugin
  • i18next-http-middleware
  • react-i18next (на уровне данных)

Ограничения backend архитектуры

  • нельзя синхронно блокировать поток выполнения
  • требуется строгая структура JSON
  • ошибки должны быть контролируемыми
  • высокая зависимость от сети при HTTP backend