В системе i18next постпроцессоры представляют собой дополнительный этап обработки уже интерполированной строки перевода. Они применяются после выполнения интерполяции и позволяют модифицировать итоговый текст: форматировать его, преобразовывать регистр, обрабатывать диапазоны значений, а также реализовывать специализированные сценарии отображения.
Постпроцессоры подключаются как часть цепочки обработки перевода и могут комбинироваться между собой. Их выполнение происходит строго после всех стандартных операций интерполяции, но до возврата строки в вызывающий код.
Постпроцессор получает на вход уже сформированную строку перевода и контекст вызова. Его задача — вернуть преобразованный результат или оставить строку без изменений.
Общая схема обработки выглядит следующим образом:
Постпроцессоры активируются через параметр postProcess в
вызове t.
i18next.t('key', {
postProcess: 'processorName'
});
Также возможно передавать параметры, которые будут доступны внутри постпроцессора:
i18next.t('key', {
postProcess: 'processorName',
someOption: true
});
Одним из немногих встроенных постпроцессоров является
interval. Он используется для обработки числовых диапазонов
и выбора текста в зависимости от значения.
Этот механизм позволяет реализовывать конструкции вида «от X до Y» или различные текстовые формы для диапазонов.
В ресурсе перевода задаётся строка с диапазонной логикой:
{
"key": "Сообщений: {{count}}",
"key_interval": "нет сообщений | одно сообщение | несколько сообщений | много сообщений"
}
При использовании:
i18next.t('key_interval', {
postProcess: 'interval',
count: 0
});
Постпроцессор анализирует значение count и выбирает
соответствующий сегмент строки. Разделителем обычно выступает символ
|.
Логика может включать диапазоны:
0
1
2-4
5+
Пример более явной формы:
{
"messages_interval": "0 сообщений | 1 сообщение | 2-4 сообщения | 5+ сообщений"
}
Хотя встроенных постпроцессоров немного, архитектура i18next предполагает активное использование пользовательских.
Постпроцессор представляет собой объект с методом
process:
const uppercasePostProcessor = {
type: 'postProcessor',
name: 'uppercase',
process(value) {
return value.toUpperCase();
}
};
Регистрация:
i18next.use(uppercasePostProcessor).init({
resources: {
en: {
translation: {
key: 'hello world'
}
}
}
});
Использование:
i18next.t('key', {
postProcess: 'uppercase'
});
Результат:
HELLO WORLD
i18next поддерживает последовательное применение нескольких постпроцессоров. Они выполняются в порядке перечисления:
i18next.t('key', {
postProcess: 'uppercase, customTrim'
});
Каждый постпроцессор получает результат предыдущего, что позволяет строить сложные конвейеры обработки строки.
Пример:
i18next.t('key', {
postProcess: 'uppercase, reverse'
});
Если исходная строка:
hello
После обработки:
OLLEH
Постпроцессор получает полный набор опций, переданных в
t.
const debugPostProcessor = {
type: 'postProcessor',
name: 'debug',
process(value, key, options) {
if (options.debug) {
return `[DEBUG] ${value}`;
}
return value;
}
};
Использование:
i18next.t('key', {
postProcess: 'debug',
debug: true
});
Постпроцессоры вызываются после интерполяции, поэтому доступ к уже подставленным значениям сохраняется.
i18next.t('greeting', {
name: 'Ivan',
postProcess: 'uppercase'
});
Ресурс:
{
"greeting": "Привет, {{name}}"
}
Этапы обработки:
Привет, IvanПРИВЕТ, IVANПостпроцессоры не влияют на механизм подстановки переменных. Интерполяция всегда выполняется раньше.
Это означает:
Встроенный набор постпроцессоров минимален и рассчитан на базовые сценарии:
interval)Большинство реальных сценариев решается через:
Постпроцессоры можно отключать, не указывая параметр
postProcess:
i18next.t('key');
Также возможно динамическое управление через условия:
i18next.t('key', {
postProcess: condition ? 'uppercase' : undefined
});
Постпроцессоры находятся в конце цепочки обработки и взаимодействуют с другими механизмами следующим образом:
Это делает постпроцессоры финальным уровнем трансформации текста перед выводом.
При работе с числовыми диапазонами interval может
использоваться совместно с динамическими значениями:
i18next.t('notifications_interval', {
count: unreadMessages
});
Ресурс:
{
"notifications_interval": "нет уведомлений | 1 уведомление | {{count}} уведомления | {{count}} уведомлений"
}
Здесь интерполяция и постобработка работают совместно: сначала
подставляется count, затем выбирается корректная форма.
Если несколько постпроцессоров изменяют одну и ту же строку, итоговый результат зависит от порядка их объявления:
postProcess: 'trim, uppercase'
или
postProcess: 'uppercase, trim'
В первом случае сначала убираются пробелы, затем выполняется преобразование регистра. Во втором — наоборот, что может привести к различным результатам при наличии пробелов.