Конфигурация saveMissing

Назначение механизма сохранения отсутствующих ключей

saveMissing управляет автоматической отправкой отсутствующих переводов в backend. При активации этого режима библиотека фиксирует обращение к несуществующему ключу и инициирует запрос на сохранение строки перевода в хранилище.

Основная цель — автоматизация наполнения словаря переводов во время разработки или при динамическом расширении интерфейса. Вместо ручного поиска всех отсутствующих ключей система фиксирует их в момент использования.

Базовая активация функциональности

Конфигурация задаётся при инициализации i18next:

import i18next from 'i18next';

i18next.init({
  lng: 'ru',
  fallbackLng: 'en',
  saveMissing: true
});

При включении saveMissing любое обращение к отсутствующему ключу активирует механизм отправки данных в backend.

Поведение при отсутствии перевода

При запросе строки:

i18next.t('header.title');

если ключ header.title отсутствует:

  1. Возвращается fallback-значение (если настроено fallbackLng)
  2. Формируется событие missing key
  3. Выполняется отправка данных в backend (при наличии поддерживающего модуля)

Передаваемая информация обычно включает:

  • ключ перевода
  • namespace
  • язык
  • значение по умолчанию (если есть)
  • контекст выполнения

Роль backend-адаптера

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

Пример с HTTP-backend:

import Backend from 'i18next-http-backend';

i18next.init({
  lng: 'ru',
  saveMissing: true,
  backend: {
    loadPath: '/locales/{{lng}}/{{ns}}.json',
    addPath: '/locales/add/{{lng}}/{{ns}}'
  }
});

Параметр addPath определяет endpoint, куда будут отправляться отсутствующие ключи.

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

При активации saveMissing формируется POST-запрос:

{
  "lng": "ru",
  "ns": "translation",
  "key": "header.title",
  "defaultValue": "Заголовок"
}

Структура может изменяться в зависимости от backend-реализации.

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

Если ключ вызывается с дефолтным значением:

i18next.t('header.title', { defaultValue: 'Заголовок' });

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

Контроль namespace

В многоуровневых приложениях перевод делится на пространства имён:

i18next.t('common:button.save');

При saveMissing backend получает информацию о namespace common, что позволяет точно распределять переводы по файлам или коллекциям.

Опция saveMissingTo

Позволяет переопределить язык, в который отправляются отсутствующие ключи:

i18next.init({
  saveMissing: true,
  saveMissingTo: 'all'
});

Возможные значения:

  • текущий язык
  • fallback язык
  • all — отправка для всех языков одновременно

Бэкенд-функция missingKeyHandler

Некоторые реализации используют перехват вместо HTTP-запросов:

i18next.init({
  saveMissing: true,
  missingKeyHandler: (lng, ns, key, fallbackValue) => {
    console.log(lng, ns, key, fallbackValue);
  }
});

Это позволяет полностью контролировать процесс сохранения.

Сценарии применения

Автоматическое наполнение словаря

Во время разработки интерфейса все новые ключи фиксируются и сохраняются без ручного редактирования JSON-файлов.

Сбор переводов в production

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

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

В связке с системами управления контентом saveMissing превращается в инструмент динамического расширения локализации.

Влияние на производительность

Каждое отсутствие ключа инициирует дополнительный вызов backend. При высокой частоте обращений это может создавать нагрузку.

Для оптимизации применяются:

  • батчинг запросов
  • debounce отправки
  • кэширование отсутствующих ключей
  • отключение в production

Ограничение повторных отправок

Без дополнительной логики один и тот же ключ может отправляться многократно. Обычно реализуется локальный фильтр:

const sentKeys = new Set();

missingKeyHandler: (lng, ns, key) => {
  const id = `${lng}:${ns}:${key}`;
  if (sentKeys.has(id)) return;
  sentKeys.add(id);
}

Взаимодействие с интерполяцией

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

i18next.t('user.greeting', { name: 'Ivan' });

возможны два варианта поведения:

  • сохранение ключа без интерполированных значений
  • сохранение шаблона с плейсхолдерами

Чаще сохраняется шаблон:

{
  "user.greeting": "Привет, {{name}}"
}

Работа с множественными формами

При наличии plural rules:

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

backend может получить отдельные ключи:

  • cart.item
  • cart.item_plural

saveMissing фиксирует конкретную форму, в зависимости от вызова.

Безопасность и контроль данных

Так как механизм отправляет ключи в backend, важно учитывать:

  • невозможность утечки чувствительных данных через ключи
  • фильтрацию пользовательского ввода в defaultValue
  • контроль разрешённых namespace

Некорректная конфигурация может привести к записи лишних или мусорных ключей в систему переводов.

Использование с server-side рендерингом

При SSR каждый рендер может генерировать missing events. Чтобы избежать дублирования:

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

Интеграция с i18next-fs-backend

При работе в Node.js:

import Backend from 'i18next-fs-backend';

i18next.use(Backend).init({
  saveMissing: true,
  backend: {
    addPath: './locales/{{lng}}/{{ns}}.missing.json'
  }
});

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

Поведение при отключённом backend

Если backend не поддерживает метод сохранения, saveMissing не вызывает ошибок, но фактически становится неактивным. В таком случае отсутствующие ключи только возвращаются через fallback систему без сохранения.

Типичные ошибки конфигурации

  • включение saveMissing без addPath
  • отсутствие защиты от повторных запросов
  • использование в production без контроля нагрузки
  • сохранение недетерминированных значений из runtime-контекста

Комбинация с debug-режимом

При активации debug: true можно наблюдать процесс генерации missing key событий:

i18next.init({
  debug: true,
  saveMissing: true
});

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

Поведение при lazy loading переводов

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