В i18next постпроцессоры представляют собой слой преобразования уже
полученного перевода перед его возвратом из t() или
аналогичных методов. Этот механизм встроен в цепочку интерполяции и
форматирования, позволяя изменять итоговую строку без модификации
ресурсов переводов.
Постпроцессоры выполняются после:
И до финального возврата строки потребителю.
Кастомный постпроцессор в i18next реализуется через регистрацию объекта с определённым интерфейсом:
name — уникальное имя постпроцессораtype — тип регистрации (обычно не требуется явно
задавать)process — функция преобразования строкиСигнатура функции обработки:
process(value, key, options, translator)
Где:
value — строка перевода после интерполяцииkey — ключ переводаoptions — параметры вызова t()translator — экземпляр i18next TranslatorМеханизм регистрации осуществляется через
addPostProcessor:
import i18next from "i18next";
const reversePostProcessor = {
name: "reverse",
process(value) {
return value.split("").reverse().join("");
}
};
i18next.addPostProcessor(reversePostProcessor);
После регистрации постпроцессор становится доступным в цепочке
postProcess.
Использование постпроцессора задаётся через опцию
postProcess:
i18next.t("welcome_message", {
postProcess: "reverse"
});
Поддерживается указание массива, что формирует цепочку обработки:
i18next.t("welcome_message", {
postProcess: ["trim", "uppercase"]
});
Порядок выполнения соответствует порядку элементов массива.
При наличии нескольких зарегистрированных постпроцессоров i18next последовательно прогоняет значение через каждый из них.
Модель обработки:
raw translation
→ interpolation
→ postProcessor[0]
→ postProcessor[1]
→ ...
→ result
Каждый следующий этап получает результат предыдущего.
Типовой пример постпроцессора — приведение строки к верхнему регистру:
const upperCasePostProcessor = {
name: "uppercase",
process(value) {
return typeof value === "string"
? value.toUpperCase()
: value;
}
};
i18next.addPostProcessor(upperCasePostProcessor);
Использование:
i18next.t("status_ready", {
postProcess: "uppercase"
});
Постпроцессоры часто используются для постобработки пробелов и символов переноса:
const trimPostProcessor = {
name: "trim",
process(value) {
return value.replace(/\s+/g, " ").trim();
}
};
i18next.addPostProcessor(trimPostProcessor);
Такая обработка полезна при:
Постпроцессоры часто применяются для управления HTML-вставками и экранирования.
const escapeHtmlPostProcessor = {
name: "escapeHtml",
process(value) {
return value
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
};
i18next.addPostProcessor(escapeHtmlPostProcessor);
Такой слой применяется в приложениях, где переводы могут содержать пользовательский ввод.
Постпроцессор получает options, что позволяет
адаптировать поведение под контекст вызова.
const genderPostProcessor = {
name: "gender",
process(value, key, options) {
if (options.gender === "female") {
return value.replace("{actor}", "она");
}
if (options.gender === "male") {
return value.replace("{actor}", "он");
}
return value.replace("{actor}", "они");
}
};
i18next.addPostProcessor(genderPostProcessor);
Использование:
i18next.t("actor_message", {
postProcess: "gender",
gender: "female"
});
Постпроцессоры могут заменять собой внешние форматтеры для сложных случаев, например числовых или временных преобразований.
const numberFormatPostProcessor = {
name: "numberFormat",
process(value, key, options) {
const number = Number(value);
if (Number.isNaN(number)) return value;
return new Intl.NumberFormat(options.locale || "ru-RU").format(number);
}
};
i18next.addPostProcessor(numberFormatPostProcessor);
Постпроцессоры выполняются после интерполяции, что позволяет работать уже с финальной строкой:
i18next.t("balance", {
amount: 1500,
postProcess: "numberFormat"
});
При этом интерполяция:
"balance": "Баланс: {{amount}}"
Превращается в промежуточную строку, которая затем модифицируется постпроцессором.
Постпроцессор может динамически отключать собственное применение:
const conditionalPostProcessor = {
name: "conditional",
process(value, key, options) {
if (options.skipPostProcess) {
return value;
}
return `[processed] ${value}`;
}
};
i18next.addPostProcessor(conditionalPostProcessor);
Постпроцессоры применяются уже после выбора языка и fallback-цепочки. Это означает, что:
Такая последовательность исключает влияние постпроцессора на выбор перевода.
Постпроцессоры выполняются синхронно в основном потоке обработки перевода. Это накладывает ограничения:
Типичный постпроцессор должен оставаться чистой функцией относительно входных данных.
В экосистеме i18next существуют параллельные механизмы форматирования:
interpolation.format)postProcess)Постпроцессоры применяются позже и обладают более широким доступом к итоговой строке, тогда как форматтеры работают на уровне отдельных значений.
Полный pipeline обработки перевода:
Любое вмешательство постпроцессора происходит на последнем этапе логической обработки строки.
Кастомные постпроцессоры часто применяются для:
import { marked } from "marked";
const markdownPostProcessor = {
name: "markdown",
process(value) {
return marked.parse(value);
}
};
i18next.addPostProcessor(markdownPostProcessor);
Такая схема позволяет хранить переводы в markdown-формате и рендерить их в HTML на финальном этапе.
Система позволяет строить переиспользуемые блоки обработки:
i18next.t("text", {
postProcess: ["trim", "escapeHtml", "uppercase"]
});
Каждый модуль выполняет строго одну функцию, формируя предсказуемую цепочку трансформаций.
При возникновении ошибки внутри process поведение
зависит от реализации конкретной версии i18next, но в типовой
модели:
Поэтому постпроцессоры проектируются с защитой от исключений:
process(value) {
try {
return customTransform(value);
} catch (e) {
return value;
}
}