Автоматизация workflow

Автоматизация workflow в i18next представляет собой совокупность практик и инструментов, позволяющих минимизировать ручную работу с переводами, снизить вероятность рассинхронизации ключей и обеспечить стабильную доставку локализаций на всех этапах разработки — от написания кода до продакшена.


Типовой workflow строится вокруг нескольких уровней:

  • извлечение ключей переводов из кода
  • синхронизация ресурсов с внешними системами локализации
  • генерация и валидация файлов переводов
  • интеграция с CI/CD
  • runtime-оптимизация загрузки переводов

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


Автоматическое извлечение ключей

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

Чаще всего применяется инструмент i18next-parser, который сканирует JavaScript/TypeScript/JSX файлы и формирует JSON-структуры ресурсов.

Пример конфигурации i18next-parser

module.exports = {
  input: ['src/**/*.{js,jsx,ts,tsx}'],
  output: './locales/$LOCALE/$NAMESPACE.json',
  options: {
    func: {
      list: ['t', 'i18next.t', 'i18n.t']
    },
    lngs: ['en', 'ru', 'de'],
    defaultLng: 'en',
    defaultNs: 'common',
    resource: {
      loadPath: './locales/{{lng}}/{{ns}}.json',
      savePath: './locales/{{lng}}/{{ns}}.json'
    }
  }
};

Результат работы парсера

{
  "button.save": "",
  "form.title": "",
  "errors.required": ""
}

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


Синхронизация ключей между окружениями

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

Автоматизация решает это через:

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

Скрипт синхронизации ресурсов

const fs = require('fs');

function mergeLocales(base, target) {
  return {
    ...base,
    ...Object.fromEntries(
      Object.keys(base).map(key => [
        key,
        target[key] || ''
      ])
    )
  };
}

Интеграция с системой перевода (TMS)

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

  • Crowdin
  • Lokalise
  • Phrase

Автоматический экспорт и импорт

Типовой pipeline:

  1. извлечение ключей
  2. генерация source.json
  3. загрузка в TMS
  4. получение переводов
  5. синхронизация в репозиторий

CLI-интеграция (пример)

i18next-parser
crowdin upload sources
crowdin download translations

Автоматизация через CI/CD

CI/CD пайплайн позволяет проверять корректность переводов до попадания кода в main-ветку.

Проверка отсутствующих ключей

function validateTranslations(locales) {
  const base = locales.en;

  return Object.keys(base).filter(key => {
    return !Object.values(locales).every(lang => lang[key]);
  });
}

Если список непустой — сборка может завершаться ошибкой.


Pre-commit хуки для локализаций

Husky и lint-staged позволяют предотвращать попадание неконсистентных переводов в репозиторий.

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

{
  "lint-staged": {
    "src/**/*.{js,ts,tsx}": [
      "i18next-parser",
      "node scripts/validate-i18n.js"
    ]
  }
}

Такой подход обеспечивает актуальность ключей в момент коммита, а не после деплоя.


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

При использовании TypeScript важным элементом становится типизация ключей переводов.

Генерация типов из JSON

export interface I18nKeys {
  "button.save": string;
  "form.title": string;
  "errors.required": string;
}

Более продвинутый вариант — автогенерация через CLI:

i18next-types-generator --input ./locales --output ./types/i18n.d.ts

Это позволяет исключить ошибки обращения к несуществующим ключам на этапе компиляции.


Lazy-loading переводов

Автоматизация загрузки переводов уменьшает размер бандла и ускоряет старт приложения.

Динамическая подгрузка namespace

i18next
  .use(Backend)
  .init({
    ns: ['common', 'auth'],
    defaultNS: 'common',
    backend: {
      loadPath: '/locales/{{lng}}/{{ns}}.json'
    }
  });

Разделение по чанкам

В Webpack или Vite перевод может загружаться вместе с компонентом:

import('locales/ru/auth.json');

Автоматическая проверка отсутствующих переводов в runtime

В продакшене часто требуется fallback-механизм и логирование отсутствующих ключей.

Хук отсутствующих переводов

i18next.on('missingKey', function(lng, ns, key) {
  console.warn(`Missing translation: ${key}`);
});

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


Псевдолокализация как часть pipeline

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

Пример трансформации:

  • SaveŜȧṽḗ
  • Profile settings[!!! Pŕôƒīļë śëţţīñğś !!!]

Генератор псевдотекста

function pseudoLocalize(str) {
  return str
    .replace(/a/g, 'á')
    .replace(/e/g, 'ë')
    .replace(/i/g, 'ï')
    .replace(/o/g, 'ô')
    .replace(/u/g, 'ü');
}

Автоматизация namespace-структуры

Разделение переводов на namespaces снижает нагрузку и упрощает поддержку.

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

locales/
  en/
    common.json
    auth.json
    dashboard.json

Автоматическое распределение ключей

Скрипт может анализировать префиксы:

  • auth.login.titleauth.json
  • dashboard.header.titledashboard.json

Генерация отчётов качества локализации

Автоматизация включает метрики:

  • процент переведённых ключей
  • количество missing keys
  • устаревшие ключи
  • дубликаты

Пример отчётного скрипта

function generateReport(locales) {
  const keys = Object.keys(locales.en);

  const stats = keys.map(key => ({
    key,
    missing: Object.values(locales).some(lng => !lng[key])
  }));

  return {
    total: keys.length,
    missing: stats.filter(s => s.missing).length
  };
}

Интеграция с bundler-экосистемой

В современных приложениях i18next тесно связан с системой сборки.

Webpack

module.exports = {
  module: {
    rules: [
      {
        test: /locales\/.*\.json$/,
        type: 'javascript/auto',
        use: 'json-loader'
      }
    ]
  }
};

Vite

export default {
  optimizeDeps: {
    include: ['i18next']
  }
};

Автоматизация тестирования локализации

Тесты позволяют гарантировать целостность переводов.

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

test('all keys exist in all locales', () => {
  const keys = Object.keys(locales.en);

  localesList.forEach(locale => {
    keys.forEach(key => {
      expect(locales[locale][key]).toBeDefined();
    });
  });
});

Автоматическое обновление переводов при изменении кода

Скрипты watch-режима позволяют поддерживать актуальность ресурсов в реальном времени.

i18next-parser --watch

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


Версионирование переводов

Переводы часто требуют версионирования отдельно от кода.

Стратегии:

  • versioning через Git теги
  • хранение hash ключей
  • semantic versioning для локалей

Пример hash-ключей

{
  "a8f4c2_login_title": "Вход"
}

Оптимизация runtime через кэширование

i18next поддерживает плагины кэширования:

  • localStorage backend
  • HTTP cache headers
  • service worker caching

Пример кэширования

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

Полный автоматизированный цикл

Современный production workflow обычно включает:

  1. разработка с использованием t('key')
  2. автоматическое извлечение ключей
  3. генерация JSON ресурсов
  4. синхронизация с TMS
  5. перевод
  6. CI-валидация
  7. сборка с lazy-loading
  8. runtime-кэширование и fallback-логика