В основе форматирования значений в i18next лежит интерполяция — механизм подстановки динамических данных в строки перевода. Он позволяет вставлять переменные в текстовые шаблоны и управлять их отображением.
Типичная структура перевода:
{
"welcome": "Привет, {{name}}!"
}
Использование:
i18next.t('welcome', { name: 'Алексей' })
Результат:
Привет, Алексей!
Интерполяция поддерживает не только строки, но и числа, булевы значения, даты (после преобразования) и сложные объекты, если они приведены к строковому виду.
По умолчанию i18next экранирует значения для защиты от XSS-атак в веб-среде.
{
"danger": "Hello {{value}}"
}
i18next.t('danger', { value: '<script>alert(1)</script>' })
Результат:
Hello <script>alert(1)</script>
Отключение экранирования:
i18next.init({
interpolation: {
escapeValue: false
}
})
Такой режим используется только в окружениях, где уже обеспечена защита (например, React).
i18next позволяет применять функции прямо в процессе подстановки значений. Это используется для преобразования данных перед выводом.
{
"price": "Цена: {{value, formatPrice}}"
}
Регистрация форматтера:
i18next.init({
interpolation: {
format: (value, format) => {
if (format === 'formatPrice') {
return `${value.toFixed(2)} ₽`
}
return value
}
}
})
Использование:
i18next.t('price', { value: 1250 })
Результат:
Цена: 1250.00 ₽
Механизм format является центральной точкой расширения
форматирования.
Часто требуется локализованное отображение чисел: разделители тысяч, дробные знаки, валюта.
i18next.init({
interpolation: {
format: (value, format, lng) => {
if (format === 'number') {
return new Intl.NumberFormat(lng).format(value)
}
return value
}
}
})
Шаблон:
{
"users": "Пользователей: {{count, number}}"
}
Результат для ru:
Пользователей: 1 234
Результат для en:
Users: 1,234
Использование Intl.NumberFormat обеспечивает корректную
локализацию без ручной обработки.
Для дат применяется Intl.DateTimeFormat или сторонние
библиотеки (moment, dayjs).
Пример встроенного подхода:
i18next.init({
interpolation: {
format: (value, format, lng) => {
if (format === 'date') {
return new Intl.DateTimeFormat(lng).format(new Date(value))
}
return value
}
}
})
Шаблон:
{
"created": "Создано: {{date, date}}"
}
Результат зависит от локали:
Создано: 29.05.2026
или
Created: 5/29/2026
Один и тот же механизм позволяет применять несколько форматов к одному значению.
{
"report": "Отчёт: {{value, number}} шт., {{date, date}}"
}
Функция форматирования:
format: (value, format, lng) => {
if (format === 'number') {
return new Intl.NumberFormat(lng).format(value)
}
if (format === 'date') {
return new Intl.DateTimeFormat(lng).format(new Date(value))
}
return value
}
Множественные формы являются встроенным видом форматирования, зависящим от числового значения.
{
"item": "1 элемент",
"item_other": "{{count}} элементов"
}
Использование:
i18next.t('item', { count: 5 })
Результат:
5 элементов
Pluralization тесно связан с интерполяцией, так как значение
count управляет выбором формы.
Форматирование может строиться как цепочка логики внутри одной функции.
format: (value, format) => {
switch (format) {
case 'upper':
return String(value).toUpperCase()
case 'lower':
return String(value).toLowerCase()
case 'currency':
return `$${Number(value).toFixed(2)}`
default:
return value
}
}
Шаблон:
{
"title": "{{name, upper}}"
}
Функция форматирования получает текущую локаль, что позволяет адаптировать вывод без дополнительной логики.
format: (value, format, lng) => {
if (format === 'currency') {
return new Intl.NumberFormat(lng, {
style: 'currency',
currency: lng === 'ru' ? 'RUB' : 'USD'
}).format(value)
}
return value
}
i18next поддерживает ICU Message Format через дополнительные плагины, расширяя возможности интерполяции.
Пример ICU-строки:
{count, plural, one {# файл} few {# файла} many {# файлов} other {# файлов}}
Такие выражения позволяют описывать сложные языковые правила без ручного кодирования условий.
Порядок обработки значений в i18next:
Форматирование выполняется на финальном этапе, что позволяет безопасно комбинировать несколько уровней трансформации.
Контекстные переводы позволяют менять форматы в зависимости от состояния данных.
{
"message_male": "Он вошёл",
"message_female": "Она вошла"
}
Использование:
i18next.t('message', { context: 'female' })
Форматирование может быть дополнено логикой:
format: (value, format) => {
if (format === 'capitalize') {
return value.charAt(0).toUpperCase() + value.slice(1)
}
return value
}
Массивы требуют преобразования перед выводом.
{
"list": "Элементы: {{items, list}}"
}
format: (value, format, lng) => {
if (format === 'list') {
return Array.isArray(value)
? value.join(', ')
: value
}
return value
}
Функция format вызывается при каждой интерполяции,
поэтому её реализация влияет на производительность.
Оптимизация достигается через:
Intl-объектовПример кэширования:
const numberFormatter = {}
function getNumberFormatter(lng) {
if (!numberFormatter[lng]) {
numberFormatter[lng] = new Intl.NumberFormat(lng)
}
return numberFormatter[lng]
}
Интерполяционное форматирование имеет ряд особенностей:
Эти ограничения компенсируются архитектурой плагинов и использованием стандартных API JavaScript.
i18next часто используется вместе с:
dayjsdate-fnsnumeral.jsIntl APIПример с dayjs:
import dayjs from 'dayjs'
format: (value, format) => {
if (format === 'dayjs') {
return dayjs(value).format('DD.MM.YYYY')
}
return value
}
Форматирование значений является связующим слоем между:
Оно обеспечивает отделение данных от представления, позволяя локализовать не только текст, но и способ его отображения.