В системах интернационализации на базе i18next переводы представляют собой структурированные наборы ключей, распределённых по пространствам имён (namespaces). Основная сложность заключается не в хранении строк, а в поддержании целостности и согласованности между кодовой базой и файлами локализации. Любое несоответствие приводит к деградации пользовательского интерфейса: появляются необработанные ключи, отсутствующие переводы, некорректные формы множественного числа или сломанные интерполяции.
Валидация переводов в i18next охватывает несколько уровней контроля: проверку наличия ключей, корректность структуры JSON, соответствие интерполяционных переменных, поддержку множественных форм, а также согласованность между языками.
Базовый уровень валидации заключается в контроле существования ключей, используемых в коде, в соответствующих ресурсах локализации.
i18next при отсутствии перевода использует стратегию fallback:
Типичная проблема возникает при динамическом использовании ключей:
t(`errors.${errorCode}`)
Без статического анализа такие ключи невозможно проверить заранее, что приводит к появлению «битых» переводов в runtime.
В i18next предусмотрены инструменты для фиксации отсутствующих ключей:
i18next.init({
debug: true,
saveMissing: true,
missingKeyHandler: (lng, ns, key) => {
// логирование отсутствующих ключей
}
})
Параметр saveMissing позволяет автоматически
регистрировать недостающие ключи через backend. Однако этот механизм не
заменяет статическую проверку и используется преимущественно в средах
разработки.
Файлы локализации в формате JSON должны соответствовать строгой структуре. Ошибки на уровне структуры приводят к невозможности загрузки namespace.
Типовые нарушения:
Пример корректной структуры:
{
"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
}
}
Это позволяет выявлять несоответствия на этапе компиляции.
Механизм множественных форм в i18next зависит от языка и правил CLDR.
Пример:
{
"apple": "{{count}} яблоко",
"apple_plural": "{{count}} яблок"
}
или с использованием встроенного синтаксиса:
{
"apple_one": "{{count}} яблоко",
"apple_few": "{{count}} яблока",
"apple_many": "{{count}} яблок"
}
count в интерполяцииi18next использует i18n.services.pluralResolver, который
опирается на язык. Несоответствие структуре языка приводит к выбору
fallback формы и некорректному отображению текста.
Одной из ключевых проблем является дрейф переводов между языками.
Пример ситуации:
en/common.json содержит 120 ключейru/common.json содержит 95 ключейЭто приводит к частичному fallback на английский язык.
Используются методы сравнения структур JSON:
Пример логики:
function diffKeys(base, target) {
const missing = [];
for (const key in base) {
if (!(key in target)) missing.push(key);
}
return missing;
}
Такие проверки часто интегрируются в CI-пайплайны.
Экосистема i18next включает утилиты для анализа переводов на этапе сборки.
Инструмент для извлечения ключей из исходного кода:
t('key')Проблема динамических ключей остаётся:
t(`errors.${type}`)
Такие конструкции требуют ручного описания возможных значений или использования ограничительных схем.
Типизация ресурсов позволяет значительно снизить количество ошибок.
Пример расширенной типизации:
type DefaultNS = 'common';
interface I18nResources {
common: {
title: string;
logout: string;
};
errors: {
not_found: string;
};
}
declare module 'i18next' {
interface CustomTypeOptions {
defaultNS: DefaultNS;
resources: I18nResources;
}
}
Это обеспечивает:
Помимо статических проверок используется runtime-контроль.
i18next.init({
debug: true
})
В этом режиме фиксируются:
Позволяет централизованно обрабатывать ошибки:
missingKeyHandler: (lng, ns, key) => {
console.warn(`[i18n missing] ${lng}:${ns}:${key}`)
}
Архитектура i18next основана на namespaces:
Нарушения структуры возникают при:
Валидация включает:
Дополнительный слой контроля обеспечивают специализированные линтеры.
Они проверяют:
Пример правила:
{
"rule": "no-empty-translation",
"severity": "error"
}
В проектах с расширенным форматированием используются ICU message format:
{
"items": "{count, plural, one {# элемент} few {# элемента} other {# элементов}}"
}
Ошибки:
ICU-парсинг требует отдельной проверки синтаксиса, так как i18next сам по себе не валидирует структуру глубоко.
Переводы часто содержат HTML:
{
"description": "Нажмите <strong>Продолжить</strong>"
}
Валидация включает:
script, iframe)При использовании dangerouslySetInnerHTML в React
контроль переводов становится критическим элементом безопасности.
На уровне CI/CD валидация переводов обычно включает:
Типовой сценарий:
Обратная проблема — неиспользуемые ключи.
Алгоритм:
Мёртвые ключи:
Некоторые ошибки проявляются только в интерфейсе:
Такие проблемы требуют визуального regression testing: