How to display currency information in TanStack Start v1
Show currency codes, names, and symbols
Problem
Applications often need to display currency information without showing a formatted price. A currency selector might list available currencies, an article about exchange rates might reference specific currencies by symbol, or a financial dashboard might show currency codes. However, each representation has limitations. ISO codes like "USD" are precise but cryptic to non-technical users. Full names like "US Dollar" are clear but require translation for international audiences. Symbols like "$" are familiar but ambiguous—the same symbol represents US, Canadian, and Australian dollars. Choosing the wrong format for the context reduces clarity and can confuse users.
The challenge is compounded by localization. A currency name that works in English may not exist or may be incorrect in another language. Symbols that are standard in one region may be unfamiliar in another. Without a consistent, locale-aware approach, applications either hard-code currency representations in a single language or maintain large translation tables that quickly become outdated.
Solution
Use the browser's built-in internationalization APIs to display currency information in the format that matches both the user's locale and the context. The Intl.DisplayNames API provides localized full currency names, while Intl.NumberFormat with the currencyDisplay option can extract currency symbols or codes. By selecting the appropriate API and format option based on context, you ensure currency references are both clear and properly localized without maintaining translation data.
Create small, reusable components or helper functions that accept a currency code and locale, then return the appropriate representation. This approach keeps currency display logic centralized and makes it easy to show the same currency in different formats across your application.
Steps
1. Create a helper to get localized currency names
The Intl.DisplayNames API with type: "currency" returns localized full currency names for any ISO 4217 currency code.
export function getCurrencyName(currencyCode: string, locale: string): string {
const displayNames = new Intl.DisplayNames([locale], { type: "currency" });
return displayNames.of(currencyCode) || currencyCode;
}
This helper accepts a three-letter ISO currency code and returns the full name in the user's language. Use this for currency selectors or explanatory text where clarity is more important than brevity.
2. Create a helper to extract currency symbols
The currencyDisplay option in Intl.NumberFormat controls how currency appears, with values "code", "symbol", "narrowSymbol", and "name".
export function getCurrencySymbol(
currencyCode: string,
locale: string,
narrow: boolean = false,
): string {
const formatter = new Intl.NumberFormat(locale, {
style: "currency",
currency: currencyCode,
currencyDisplay: narrow ? "narrowSymbol" : "symbol",
});
const parts = formatter.formatToParts(0);
const currencyPart = parts.find((part) => part.type === "currency");
return currencyPart?.value || currencyCode;
}
This helper formats a zero value and extracts only the currency symbol. The narrow parameter controls whether to use a compact symbol like "$" or a disambiguated one like "US$". Use symbols in compact UI elements like tables or charts.
3. Create a component for displaying currency information
Build a flexible component that can render currency information in any format based on a display prop.
interface CurrencyDisplayProps {
code: string;
locale: string;
display: "name" | "symbol" | "narrowSymbol" | "code";
}
export function CurrencyDisplay({
code,
locale,
display,
}: CurrencyDisplayProps) {
let content: string;
if (display === "name") {
content = getCurrencyName(code, locale);
} else if (display === "code") {
content = code.toUpperCase();
} else {
content = getCurrencySymbol(code, locale, display === "narrowSymbol");
}
return <span>{content}</span>;
}
This component centralizes currency display logic and makes it easy to switch formats. Use "name" for dropdowns and explanatory text, "symbol" or "narrowSymbol" for compact displays, and "code" when precision is required.
4. Use the component in a TanStack Start route
Import and use the component in any route component, passing the user's locale from your i18n context or route loader.
import { createFileRoute } from "@tanstack/react-router";
import { CurrencyDisplay } from "~/components/CurrencyDisplay";
export const Route = createFileRoute("/currencies")({
component: CurrenciesPage,
});
function CurrenciesPage() {
const locale = "en-US";
return (
<div>
<h1>Currency Information</h1>
<p>
Full name: <CurrencyDisplay code="USD" locale={locale} display="name" />
</p>
<p>
Symbol: <CurrencyDisplay code="USD" locale={locale} display="symbol" />
</p>
<p>
Code: <CurrencyDisplay code="USD" locale={locale} display="code" />
</p>
</div>
);
}
The component renders the same currency in different formats. In a real application, retrieve the locale from your i18n provider or route context to ensure all currency displays respect the user's language preference.