如何在 React Router v7 中显示货币信息
显示货币代码、名称和符号
问题
应用程序通常需要显示货币信息,但不一定需要显示格式化的价格。例如,货币选择器可能显示 "USD" 或 "美元",而财务仪表板可能仅显示 "$" 符号。每种格式都有不同的用途,但它们都面临共同的挑战。ISO 代码 "USD" 精确但对非技术用户不够直观;全称 "美元" 清晰但需要为国际用户进行翻译;符号 "$" 简洁但含义模糊——根据上下文,它可能代表美元、加元或澳元。选择错误的格式会让用户感到困惑,并削弱对金融界面的信任。
在构建多语言应用程序时,这一挑战更加复杂。适用于英语的货币名称可能无法直接翻译成其他语言,而符号的使用习惯因地区而异。硬编码这些值会增加维护负担,并限制应用程序的覆盖范围。
解决方案
使用 react-intl 的 formatDisplayName 方法显示本地化的货币名称和代码,并利用浏览器的 Intl.NumberFormat API 提取货币符号。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>;
}
此组件集中管理货币显示逻辑,并使其易于根据 UI 上下文切换格式。在需要清晰度的货币选择器中使用 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 的用户区域设置自动处理本地化。