Cómo mostrar información de moneda en React Router v7

Muestra códigos, nombres y símbolos de moneda

Problema

Las aplicaciones a menudo necesitan mostrar información de moneda sin mostrar un precio formateado. Un selector de moneda podría mostrar "USD" o "dólar estadounidense", mientras que un panel financiero podría mostrar solo el símbolo "$". Cada formato tiene un propósito diferente, pero todos comparten desafíos comunes. El código ISO "USD" es preciso pero poco familiar para usuarios no técnicos. El nombre completo "dólar estadounidense" es claro pero requiere traducción para audiencias internacionales. El símbolo "$" es compacto pero ambiguo: podría representar dólares estadounidenses, canadienses o australianos según el contexto. Elegir el formato incorrecto confunde a los usuarios y socava la confianza en las interfaces financieras.

El desafío se complica al construir aplicaciones multilingües. Un nombre de moneda que funciona en inglés puede no traducirse directamente a otros idiomas, y las convenciones de símbolos varían según la configuración regional. Codificar estos valores de forma fija crea una carga de mantenimiento y limita el alcance de tu aplicación.

Solución

Usa el método formatDisplayName de react-intl para mostrar nombres y códigos de moneda localizados, y aprovecha la API Intl.NumberFormat del navegador para extraer símbolos de moneda. El método formatDisplayName acepta un código de moneda y devuelve el nombre localizado apropiado según la configuración regional del usuario, manejando la traducción automáticamente. Para los símbolos, formatea un número de muestra con la moneda y extrae la parte del símbolo del resultado.

Crea funciones auxiliares o componentes enfocados para cada formato de visualización (nombre completo, símbolo o código) para que puedas elegir la representación adecuada para cada contexto. Este enfoque mantiene la lógica de visualización de moneda centralizada y garantiza la coherencia en toda tu aplicación mientras respeta las preferencias de configuración regional del usuario.

Pasos

1. Crear un helper para mostrar nombres de monedas localizados

Usa el método formatDisplayName con type: 'currency' para convertir códigos de moneda ISO en nombres completos localizados.

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>;
}

Cuando el locale es "en" y el código es "CNY", esto muestra "Chinese Yuan". El método traduce automáticamente el nombre según el locale actual del IntlProvider.

2. Crear un helper para extraer y mostrar símbolos de monedas

Usa Intl.NumberFormat con formatToParts para extraer el símbolo de moneda filtrando las partes con 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>;
}

La opción currencyDisplay controla la forma de la moneda, siendo "narrowSymbol" la representación más compacta. Este enfoque maneja automáticamente la colocación y el formato del símbolo según el locale.

3. Crear un componente que ofrezca múltiples opciones de visualización

Construye un componente flexible que acepte una prop de modo de visualización para cambiar entre formatos de código, símbolo y nombre.

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>;
}

Este componente centraliza la lógica de visualización de monedas y facilita el cambio de formatos según el contexto de la interfaz. Usa display="name" para selectores de moneda donde la claridad es importante, display="symbol" para visualizaciones compactas como encabezados de tabla, y display="code" para informes técnicos o financieros.

4. Usar el componente en diferentes contextos

Aplica el modo de visualización apropiado según dónde aparezca la información de moneda en tu interfaz.

export default function CurrencyExample() {
  return (
    <div>
      <label htmlFor="currency-select">
        Select currency: <CurrencyInfo code="EUR" display="name" />
      </label>

      <table>
        <thead>
          <tr>
            <th>
              Amount (<CurrencyInfo code="USD" display="symbol" />)
            </th>
          </tr>
        </thead>
      </table>

      <p>
        Transaction currency: <CurrencyInfo code="GBP" display="code" />
      </p>
    </div>
  );
}

Cada contexto usa el formato que mejor sirve a su propósito: nombres completos para interfaces de selección, símbolos para visualizaciones compactas, y códigos para referencias técnicas precisas. El componente maneja la localización automáticamente según el locale del usuario desde el IntlProvider.