Как отображать информацию о валюте в React Router v7

Отображение кодов, названий и символов валют

Проблема

Приложения часто нуждаются в отображении информации о валюте без форматированной цены. Например, селектор валют может показывать "USD" или "доллар США", а финансовая панель — только символ "$". Каждый формат служит своей цели, но все они сталкиваются с общими проблемами. Код ISO "USD" точен, но непонятен для нетехнических пользователей. Полное название "доллар США" ясно, но требует перевода для международной аудитории. Символ "$" компактен, но неоднозначен — он может обозначать доллары США, Канады или Австралии в зависимости от контекста. Неправильный выбор формата сбивает пользователей с толку и подрывает доверие к финансовым интерфейсам.

Эта проблема усугубляется при создании многоязычных приложений. Название валюты, подходящее для английского языка, может не переводиться напрямую на другие языки, а использование символов варьируется в зависимости от локали. Жёсткое кодирование этих значений создаёт нагрузку на обслуживание и ограничивает охват вашего приложения.

Решение

Используйте метод formatDisplayName из react-intl для отображения локализованных названий и кодов валют, а также API Intl.NumberFormat браузера для извлечения символов валют. Метод formatDisplayName принимает код валюты и возвращает соответствующее локализованное название на основе локали пользователя, автоматически обрабатывая перевод. Для символов отформатируйте пример числа с валютой и извлеките символ из результата.

Создайте вспомогательные функции или компоненты для каждого формата отображения — полного названия, символа или кода — чтобы выбрать подходящее представление для каждого контекста. Такой подход централизует логику отображения валют и обеспечивает согласованность в вашем приложении, уважая предпочтения локали пользователя.

Шаги

1. Создайте вспомогательную функцию для отображения локализованных названий валют

Используйте метод formatDisplayName с type: 'currency', чтобы преобразовать коды валют ISO в локализованные полные названия.

import { useIntl } from "react-intl";

export function CurrencyName({ code }: { code: string }) {
  const intl = useIntl();
  const name = intl.formatDisplayName(code, { type: "currency" });
  return <span>{name}</span>;
}

Когда локаль установлена на "en", а код равен "CNY", это отображает "Chinese Yuan". Метод автоматически переводит название на основе текущей локали из IntlProvider.

2. Создайте вспомогательную функцию для извлечения и отображения символов валют

Используйте Intl.NumberFormat с formatToParts, чтобы извлечь символ валюты, фильтруя части с type === "currency".

function getCurrencySymbol(locale: string, currency: string): string {
  const parts = new Intl.NumberFormat(locale, {
    style: "currency",
    currency,
    currencyDisplay: "narrowSymbol",
  }).formatToParts(0);

  const currencyPart = parts.find((part) => part.type === "currency");
  return currencyPart?.value || currency;
}

export function CurrencySymbol({ code }: { code: string }) {
  const intl = useIntl();
  const symbol = getCurrencySymbol(intl.locale, code);
  return <span>{symbol}</span>;
}

Опция currencyDisplay управляет формой отображения валюты, где "narrowSymbol" предоставляет наиболее компактное представление. Этот подход автоматически обрабатывает размещение и форматирование символов, специфичных для локали.

3. Создайте компонент, предлагающий несколько вариантов отображения

Создайте гибкий компонент, который принимает пропс режима отображения для переключения между форматами кода, символа и названия.

import { useIntl } from "react-intl";

type CurrencyDisplayMode = "code" | "symbol" | "name";

interface CurrencyInfoProps {
  code: string;
  display?: CurrencyDisplayMode;
}

export function CurrencyInfo({ code, display = "symbol" }: CurrencyInfoProps) {
  const intl = useIntl();

  if (display === "name") {
    const name = intl.formatDisplayName(code, { type: "currency" });
    return <span>{name}</span>;
  }

  if (display === "symbol") {
    const parts = new Intl.NumberFormat(intl.locale, {
      style: "currency",
      currency: code,
      currencyDisplay: "narrowSymbol",
    }).formatToParts(0);
    const symbol =
      parts.find((part) => part.type === "currency")?.value || code;
    return <span>{symbol}</span>;
  }

  return <span>{code}</span>;
}

Этот компонент централизует логику отображения валют и упрощает переключение форматов в зависимости от контекста пользовательского интерфейса. Используйте display="name" для селекторов валют, где важна ясность, display="symbol" для компактного отображения, например, в заголовках таблиц, и display="code" для технических или финансовых отчетов.

4. Используйте компонент в разных контекстах

Применяйте соответствующий режим отображения в зависимости от того, где информация о валюте появляется в вашем интерфейсе.

export default function CurrencyExample() {
  return (
    <div>
      <label htmlFor="currency-select">
        Выберите валюту: <CurrencyInfo code="EUR" display="name" />
      </label>

      <table>
        <thead>
          <tr>
            <th>
              Сумма (<CurrencyInfo code="USD" display="symbol" />)
            </th>
          </tr>
        </thead>
      </table>

      <p>
        Валюта транзакции: <CurrencyInfo code="GBP" display="code" />
      </p>
    </div>
  );
}

Каждый контекст использует формат, который лучше всего соответствует его цели: полные названия для интерфейсов выбора, символы для компактного отображения и коды для точных технических ссылок. Компонент автоматически обрабатывает локализацию на основе локали пользователя из IntlProvider.