Постобработка в i18next представляет собой этап преобразования уже сформированного перевода после выполнения интерполяции, выбора языка, применения фолбэков и обработки контекста. На этом уровне строка перевода уже считается «готовой», однако может требовать дополнительной модификации перед тем, как попасть в интерфейс приложения.
Постобработчики (post processors) подключаются как расширения и формируют цепочку трансформаций, применяемых к итоговому тексту.
Процесс получения строки в i18next включает несколько этапов:
Постобработка выполняется после того, как строка уже полностью собрана. Это означает, что любые переменные уже подставлены, а языковые правила применены.
PostProcessor в i18next — это функция или модуль, который принимает готовую строку и возвращает её изменённую версию.
Базовая сигнатура постпроцессора:
const myPostProcessor = {
type: 'postProcessor',
name: 'customProcessor',
process(value, key, options, translator) {
return value;
}
};
value — итоговая строка переводаkey — ключ переводаoptions — параметры перевода (interpolation, context и
др.)translator — доступ к API i18next внутри процессаРегистрация выполняется через use:
import i18next from 'i18next';
const uppercaseProcessor = {
type: 'postProcessor',
name: 'uppercase',
process(value) {
return value.toUpperCase();
}
};
i18next
.use(uppercaseProcessor)
.init({
resources: {
en: {
translation: {
hello: 'Hello {{name}}'
}
}
},
postProcess: ['uppercase']
});
i18next.t('hello', { name: 'John' });
Результат:
HELLO JOHN
i18next поддерживает применение нескольких постпроцессоров последовательно.
postProcess: ['trim', 'uppercase', 'markdown']
Каждый следующий процесс получает результат предыдущего.
Постобработка может использоваться для стилизации результата:
const trimProcessor = {
type: 'postProcessor',
name: 'trim',
process(value) {
return value.trim();
}
};
Постпроцессоры часто применяются для очистки текста:
const sanitizeProcessor = {
type: 'postProcessor',
name: 'sanitize',
process(value) {
return value.replace(/<script.*?>.*?<\/script>/gi, '');
}
};
В контексте i18next важно учитывать, что интерполяция может содержать HTML, поэтому постобработка становится дополнительным уровнем защиты.
Постобработка используется для преобразования разметки:
const markdownProcessor = {
type: 'postProcessor',
name: 'markdown',
process(value) {
return value
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>');
}
};
Пример перевода:
"welcome": "Hello **{{name}}**"
Результат:
Hello <strong>John</strong>
Хотя базовая интерполяция в i18next может форматировать числа, постпроцессор позволяет централизованно обрабатывать единицы измерения.
const unitProcessor = {
type: 'postProcessor',
name: 'units',
process(value, key, options) {
if (options.unit === 'km') {
return `${value} km`;
}
if (options.unit === 'mi') {
return `${value} miles`;
}
return value;
}
};
Постпроцессоры получают доступ к параметрам перевода, что позволяет реализовывать сложную логику.
const contextProcessor = {
type: 'postProcessor',
name: 'contextAware',
process(value, key, options) {
if (options.context === 'error') {
return `⚠ ${value}`;
}
return value;
}
};
Вызов:
i18next.t('message', { context: 'error' });
В i18next интерполяция выполняется до постобработки. Это означает, что постпроцессор получает уже «развёрнутую» строку.
{
"greeting": "Hello {{name}}"
}
После интерполяции:
Hello John
Постобработчик работает уже с финальным результатом.
Постпроцессоры в i18next выполняются синхронно. Это накладывает ограничения:
Для подобных задач требуется предварительная подготовка данных до
вызова t().
Если задано несколько постпроцессоров:
postProcess: ['trim', 'uppercase', 'suffix']
Порядок строго последовательный:
Каждый этап получает модифицированный результат предыдущего.
Параметр translator позволяет постпроцессору обращаться
к внутренним методам i18next:
process(value, key, options, translator) {
const fallback = translator.t(key, { lng: 'en' });
return value || fallback;
}
Это позволяет реализовать сложные fallback-стратегии на уровне постобработки.
Кэширование в i18next может влиять на постпроцессоры:
Это особенно важно при динамических трансформациях текста.
Постпроцессоры должны быть устойчивыми к ошибкам. Любое исключение может прервать цепочку обработки.
process(value) {
try {
return value.toUpperCase();
} catch (e) {
return value;
}
}
В архитектуре i18next предпочтительно возвращать исходное значение при сбоях.
При использовании ICU-подобных конструкций или сложной интерполяции постобработка применяется уже к финальному тексту:
Постпроцессор не участвует в логике выбора формы, а только модифицирует результат.
Постобработка позволяет строить конвейеры преобразований:
const pipeline = [
{ type: 'postProcessor', name: 'trim' },
{ type: 'postProcessor', name: 'sanitize' },
{ type: 'postProcessor', name: 'emojiReplace' }
];
В i18next существуют ограничения:
Это делает постобработку строго финальным этапом трансформации.