Валидация переводов

В системах интернационализации на базе i18next переводы представляют собой структурированные наборы ключей, распределённых по пространствам имён (namespaces). Основная сложность заключается не в хранении строк, а в поддержании целостности и согласованности между кодовой базой и файлами локализации. Любое несоответствие приводит к деградации пользовательского интерфейса: появляются необработанные ключи, отсутствующие переводы, некорректные формы множественного числа или сломанные интерполяции.

Валидация переводов в i18next охватывает несколько уровней контроля: проверку наличия ключей, корректность структуры JSON, соответствие интерполяционных переменных, поддержку множественных форм, а также согласованность между языками.


Проверка наличия ключей перевода

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

i18next при отсутствии перевода использует стратегию fallback:

  • возврат ключа как строки
  • переход на fallback-язык
  • вызов обработчиков отсутствующих ключей

Типичная проблема возникает при динамическом использовании ключей:

t(`errors.${errorCode}`)

Без статического анализа такие ключи невозможно проверить заранее, что приводит к появлению «битых» переводов в runtime.

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

В i18next предусмотрены инструменты для фиксации отсутствующих ключей:

i18next.init({
  debug: true,
  saveMissing: true,
  missingKeyHandler: (lng, ns, key) => {
    // логирование отсутствующих ключей
  }
})

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


Валидация структуры переводов

Файлы локализации в формате JSON должны соответствовать строгой структуре. Ошибки на уровне структуры приводят к невозможности загрузки namespace.

Типовые нарушения:

  • дублирование ключей
  • невалидный JSON
  • смешение типов значений (строки и объекты)
  • нарушение вложенности

Пример корректной структуры:

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

Некорректный пример:

{
  "auth": "Вход",
  "auth.login": "Вход"
}

Такие конфликты не всегда выявляются runtime, но приводят к непредсказуемому поведению резолвинга ключей.


Проверка интерполяции

i18next активно использует интерполяцию:

t('welcome_user', { name: 'Alex' })

Перевод:

{
  "welcome_user": "Добро пожаловать, {{name}}"
}

Основная задача валидации — проверка совпадения параметров:

  • наличие всех переменных в переводе
  • отсутствие лишних переменных
  • корректность синтаксиса {{ }}

Ошибочные случаи:

{
  "welcome_user": "Добро пожаловать, {{username}}"
}

При передаче name вместо username возникает логическая ошибка без явного исключения.

Статическая проверка интерполяции

Для контроля используется парсинг строк переводов и сопоставление с типами вызовов t().

В TypeScript-проектах применяется типизация ресурсов:

interface Resources {
  common: {
    welcome_user: (params: { name: string }) => string
  }
}

Это позволяет выявлять несоответствия на этапе компиляции.


Валидация множественных форм (pluralization)

Механизм множественных форм в i18next зависит от языка и правил CLDR.

Пример:

{
  "apple": "{{count}} яблоко",
  "apple_plural": "{{count}} яблок"
}

или с использованием встроенного синтаксиса:

{
  "apple_one": "{{count}} яблоко",
  "apple_few": "{{count}} яблока",
  "apple_many": "{{count}} яблок"
}

Типовые ошибки:

  • отсутствие необходимых форм
  • неправильные суффиксы plural rules
  • несовпадение count в интерполяции
  • использование ручных форм вместо стандарта

i18next использует i18n.services.pluralResolver, который опирается на язык. Несоответствие структуре языка приводит к выбору fallback формы и некорректному отображению текста.


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

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

Пример ситуации:

  • en/common.json содержит 120 ключей
  • ru/common.json содержит 95 ключей

Это приводит к частичному fallback на английский язык.

Автоматическая проверка синхронизации

Используются методы сравнения структур JSON:

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

Пример логики:

function diffKeys(base, target) {
  const missing = [];
  for (const key in base) {
    if (!(key in target)) missing.push(key);
  }
  return missing;
}

Такие проверки часто интегрируются в CI-пайплайны.


Инструменты статической валидации

Экосистема i18next включает утилиты для анализа переводов на этапе сборки.

i18next-scanner

Инструмент для извлечения ключей из исходного кода:

  • парсинг AST
  • поиск t('key')
  • генерация JSON шаблонов

Проблема динамических ключей остаётся:

t(`errors.${type}`)

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


TypeScript как механизм валидации

Типизация ресурсов позволяет значительно снизить количество ошибок.

Пример расширенной типизации:

type DefaultNS = 'common';

interface I18nResources {
  common: {
    title: string;
    logout: string;
  };
  errors: {
    not_found: string;
  };
}

declare module 'i18next' {
  interface CustomTypeOptions {
    defaultNS: DefaultNS;
    resources: I18nResources;
  }
}

Это обеспечивает:

  • автодополнение ключей
  • проверку существования namespace
  • контроль параметров интерполяции

Runtime-валидация переводов

Помимо статических проверок используется runtime-контроль.

debug режим i18next

i18next.init({
  debug: true
})

В этом режиме фиксируются:

  • отсутствующие ключи
  • проблемы интерполяции
  • ошибки загрузки namespace

missingKeyHandler

Позволяет централизованно обрабатывать ошибки:

missingKeyHandler: (lng, ns, key) => {
  console.warn(`[i18n missing] ${lng}:${ns}:${key}`)
}

Проверка namespace структуры

Архитектура i18next основана на namespaces:

  • common
  • auth
  • dashboard
  • errors

Нарушения структуры возникают при:

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

Валидация включает:

  • проверку соответствия domain-driven структуре
  • контроль глубины вложенности
  • запрет «плоских» глобальных ключей в больших проектах

Линтеры переводов

Дополнительный слой контроля обеспечивают специализированные линтеры.

Они проверяют:

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

Пример правила:

{
  "rule": "no-empty-translation",
  "severity": "error"
}

Валидация ICU сообщений

В проектах с расширенным форматированием используются ICU message format:

{
  "items": "{count, plural, one {# элемент} few {# элемента} other {# элементов}}"
}

Ошибки:

  • неверные plural категории
  • несбалансированные скобки
  • несовпадение переменных

ICU-парсинг требует отдельной проверки синтаксиса, так как i18next сам по себе не валидирует структуру глубоко.


Проверка HTML и безопасного контента

Переводы часто содержат HTML:

{
  "description": "Нажмите <strong>Продолжить</strong>"
}

Валидация включает:

  • запрет опасных тегов (script, iframe)
  • проверку закрытия тегов
  • контроль вложенности

При использовании dangerouslySetInnerHTML в React контроль переводов становится критическим элементом безопасности.


Контроль изменений переводов в CI

На уровне CI/CD валидация переводов обычно включает:

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

Типовой сценарий:

  1. извлечение ключей из кода
  2. генерация эталонного списка
  3. сравнение с JSON ресурсами
  4. блокировка сборки при несоответствии

Детектирование «мертвых» переводов

Обратная проблема — неиспользуемые ключи.

Алгоритм:

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

Мёртвые ключи:

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

Поведенческая валидация перевода

Некоторые ошибки проявляются только в интерфейсе:

  • слишком длинные строки
  • обрезание текста
  • нарушение layout
  • несоответствие контекста (формальный/неформальный стиль)

Такие проблемы требуют визуального regression testing:

  • snapshot тестирование интерфейсов
  • сравнение скриншотов
  • проверка локалей в разных состояниях приложения