Как форматировать суммы в валюте в TanStack Start v1
Отображение цен с валютными символами и разделителями
Проблема
Цены — это сразу две задачи локализации: отображение валюты и форматирование чисел. Одна и та же сумма выглядит как $1,200.50 в США и 1 200,50 € в Германии. Местоположение символа валюты, разделители целых и дробных частей, а также пробелы — всё меняется.
Эти правила — не просто предпочтения, а ожидания пользователей. Если цена показана в непривычном формате, человек начинает сомневаться, правильно ли он понял сумму. Например, «1200.50 EUR» для пользователя из Германии или «1.200,50$» для пользователя из США вызывает недоверие и мешает восприятию.
Решение
Форматируйте денежные значения с учётом и валюты, и локали пользователя. Это сочетает правильное расположение символа валюты с локальными правилами форматирования чисел, чтобы цена выглядела так, как ожидают в конкретном регионе.
Используйте метод formatNumber из react-intl с опцией style: 'currency', чтобы применить и код валюты, и форматирование по локали пользователя. Браузерный API Intl.NumberFormat автоматически расставляет символы, выбирает разделители и пробелы.
Шаги
1. Создайте компонент для форматирования валюты
Сделайте переиспользуемый компонент, который принимает число и код валюты, а затем форматирует цену по локали пользователя.
import { useIntl } from "react-intl";
interface PriceProps {
value: number;
currency: string;
}
export function Price({ value, currency }: PriceProps) {
const intl = useIntl();
const formattedPrice = intl.formatNumber(value, {
style: "currency",
currency: currency,
});
return <span>{formattedPrice}</span>;
}
Хук useIntl даёт доступ к API форматирования. Метод formatNumber с style: 'currency' применяет и символ валюты, и форматирование чисел по локали.
2. Используйте компонент с разными валютами
Показывайте цены в приложении, передавая числовое значение и код валюты.
export default function ProductCard() {
return (
<div>
<h2>Premium Plan</h2>
<Price value={1200.5} currency="USD" />
</div>
);
}
Компонент автоматически форматирует цену в соответствии с локалью пользователя. Например, пользователь из США увидит "$1,200.50", а пользователь из Германии — "1.200,50 $".
3. Форматируйте цены с нужным количеством знаков после запятой
Управляйте количеством отображаемых знаков после запятой с помощью опций minimumFractionDigits и maximumFractionDigits.
export function PriceWithPrecision({ value, currency }: PriceProps) {
const intl = useIntl();
const formattedPrice = intl.formatNumber(value, {
style: "currency",
currency: currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
return <span>{formattedPrice}</span>;
}
Это обеспечивает одинаковое отображение дробной части для всех цен, даже если значение целое, например 100.
4. Создайте хелпер для форматирования на лету
Если обёртка-компонент не нужна, создайте вспомогательную функцию для форматирования.
import { useIntl } from "react-intl";
export function useFormatCurrency() {
const intl = useIntl();
return (value: number, currency: string) => {
return intl.formatNumber(value, {
style: "currency",
currency: currency,
});
};
}
Используйте этот хук, когда нужны отформатированные цены в атрибутах, вычисляемых значениях или других не-JSX контекстах.
export function CheckoutSummary({ total }: { total: number }) {
const formatCurrency = useFormatCurrency();
return (
<button aria-label={`Pay ${formatCurrency(total, "USD")}`}>Checkout</button>
);
}
Хелпер возвращает обычную строку, подходящую для любого случая, где нельзя использовать JSX-компоненты.