Перейти к содержимому

format —— интерполяция текстов

Всего: {total}, {n} звёзд, Шаг {index} из {total} — шаблоны текстов в языковом пакете требуют подстановки чисел времени выполнения. Раньше эта возможность интерполяции жила в синглтоне locales, но когда её стали использовать core-компоненты (звёзды rate, страницы pagination), это заставило core обратно зависеть от побочных эффектов модульного синглтона locales. Очистив её до чистой строковой функции, мы добились того, что интерполяция текстов в core-компонентах больше не зависит ни от какого синглтона.

// из общего ядра (рекомендуется)
import { formatMessage } from '@lh-ui/share/core/shared/format'
// или из входа locales (поверхность экспорта неизменна)
import { formatMessage } from '@lh-ui/share/locales'
Функция Сигнатура Назначение
formatMessage (template: string, params?: Record<string, unknown>) => string заменяет плейсхолдеры '{key}' значениями из params
formatMessage('Всего: {total}', { total: 42 }) // 'Всего: 42'
formatMessage('{n} звёзд', { n: 5 }) // '5 звёзд'
formatMessage('Нет плейсхолдеров') // 'Нет плейсхолдеров'
formatMessage('Неизвестный плейсхолдер {missing}') // 'Неизвестный плейсхолдер {missing}'

Три правила:

  1. Неизвестные плейсхолдеры остаются как есть. Никаких ошибок и пустых строк — вызывающая сторона обычно уже получила шаблон с плейсхолдерами из языкового пакета, и если плейсхолдеру не соответствует параметр, значит, upstream забыл его передать; сохранение как есть делает проблему видимой в UI (а не тихо проглатывает её).
  2. Значения единообразно проходят String(...): числа и логические значения можно интерполировать.
  3. params по умолчанию {}: без параметров шаблон проходит насквозь без изменений.

lhlocale.t(path, params) внутри себя делает именно «найти в языковом пакете → получить шаблон → вызвать formatMessage»:

// внутренняя реализация locales (упрощённо)
t(path, fallbackOrParams) {
const template = resolve(path) ?? fallback
return typeof fallbackOrParams === 'object'
? formatMessage(template, fallbackOrParams)
: template
}

Переэкспорт formatMessage из @lh-ui/share/locales сделан намеренно — он был в старой поверхности экспорта, а после понижения до core путь импорта сохранился неизменным, и downstream не понадобилось никаких правок.

Случай Использовать?
Интерполяция текстов внутри core-компонентов ✅ использовать formatMessage напрямую (не подключая синглтон locales)
Интерполяция текстов в бизнес-коде ✅ безопаснее, чем str.replace (неизвестные плейсхолдеры сохраняются)
Нужно обратиться к языковому пакету + интерполяция ❌ использовать lhlocale.t(path, params) — одним вызовом
В шаблоне нужны условия / множественное число ❌ эта функция делает только простую замену; условные тексты разбиваются на несколько ключей в языковом пакете
// внутри компонента
const totalText = computed(() =>
formatMessage(lhlocale.t('pagination.total'), { total: props.total }),
)
// языковой пакет: 'Всего: {total}' → 'Всего: 42'
const ariaLabel = formatMessage(lhlocale.t('rate.stars'), { n: currentValue.value })
// языковой пакет: '{n} звёзд' → '3 звёзд'
// чистая интерполяция, не затрагивающая языковой пакет
formatMessage('Шаг {index} из {total}', { index: 2, total: 5 })
// 'Шаг 2 из 5'
  • Синтаксис плейсхолдера — {key} (одинарные фигурные скобки), а не ${key} и не {{key}}.
  • Вложенные шаблоны не поддерживаются: значения в params проходят String() один раз, рекурсивного разбора нет.
  • Производительность: один вызов — это цикл String.replace; не вызывайте его многократно для одного шаблона в высокочастотном цикле — достаточно закэшировать в computed на уровне UI-слоя.
@lh-ui/share/core/format → formatMessage( )
返回值
(填好参数后点运行)

Copyright © 2024-2026 FengMo WenXue