Как форматировать суммы в валюте в 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>Премиум-план</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={`Оплатить ${formatCurrency(total, "USD")}`}>Оформить заказ</button>
);
}
Помощник возвращает обычную строку, подходящую для любого контекста, где нельзя использовать JSX-компоненты.