style: translate all units, currencies, and scale symbols into Persian across entire app
This commit is contained in:
parent
984d44a18b
commit
23898868ec
|
|
@ -512,9 +512,9 @@ export function LmeView() {
|
|||
<div className="flex items-center justify-between border-b border-border/50 pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<DollarSign className="w-4 h-4 text-primary" />
|
||||
<h3 className="text-sm font-semibold text-foreground">نرخهای برابری ارز (Exchange Rates)</h3>
|
||||
<h3 className="text-sm font-semibold text-foreground">نرخهای برابری ارز</h3>
|
||||
</div>
|
||||
<span className="text-[11px] text-muted-foreground font-mono">EUR / USD</span>
|
||||
<span className="text-[11px] text-muted-foreground">یورو / دلار</span>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3 pt-1">
|
||||
|
|
|
|||
|
|
@ -163,3 +163,64 @@ export function commodityLabel(symbol: string, fallback: string): string {
|
|||
export function commodityGroup(symbol: string): CommodityGroup {
|
||||
return COMMODITIES[symbol]?.group ?? "metals";
|
||||
}
|
||||
|
||||
export const COMMODITY_UNITS: Record<string, string> = {
|
||||
"CL=F": "دلار / بشکه",
|
||||
"BZ=F": "دلار / بشکه",
|
||||
"NG=F": "دلار / MMBtu",
|
||||
"RB=F": "دلار / گالن",
|
||||
"HO=F": "دلار / گالن",
|
||||
"GC=F": "دلار / اونس",
|
||||
"SI=F": "دلار / اونس",
|
||||
"HG=F": "دلار / پوند",
|
||||
"PL=F": "دلار / اونس",
|
||||
"PA=F": "دلار / اونس",
|
||||
"ALI=F": "دلار / تن",
|
||||
"NI=F": "دلار / تن",
|
||||
"ZC=F": "سنت / بوشل",
|
||||
"ZW=F": "سنت / بوشل",
|
||||
"ZS=F": "سنت / بوشل",
|
||||
"KC=F": "سنت / پوند",
|
||||
"CT=F": "سنت / پوند",
|
||||
"CC=F": "دلار / تن",
|
||||
"SB=F": "سنت / پوند",
|
||||
"OJ=F": "سنت / پوند",
|
||||
};
|
||||
|
||||
export function faUnit(u: string | null | undefined): string {
|
||||
if (!u) return "";
|
||||
const clean = u.trim();
|
||||
const map: Record<string, string> = {
|
||||
"USD": "دلار",
|
||||
"$": "دلار",
|
||||
"USc": "سنت",
|
||||
"cents": "سنت",
|
||||
"IRR": "ریال",
|
||||
"Rial": "ریال",
|
||||
"EUR": "یورو",
|
||||
"GBP": "پوند",
|
||||
"RMB": "یوان",
|
||||
"CNY": "یوان",
|
||||
"JPY": "ین",
|
||||
"CAD": "دلار کانادا",
|
||||
"AUD": "دلار استرالیا",
|
||||
"TRY": "لیر",
|
||||
"INR": "روپیه",
|
||||
"BRL": "رئال",
|
||||
"USD/mt": "دلار / تن",
|
||||
"USD/dmt": "دلار / تن خشک",
|
||||
"RMB/mt": "یوان / تن",
|
||||
"USD/bbl": "دلار / بشکه",
|
||||
"USD/oz": "دلار / اونس",
|
||||
"USD/t.oz": "دلار / اونس",
|
||||
"USD/lb": "دلار / پوند",
|
||||
"c/lb": "سنت / پوند",
|
||||
"USD/bu": "دلار / بوشل",
|
||||
"c/bu": "سنت / بوشل",
|
||||
"T$": "تریلیون دلار",
|
||||
"B$": "میلیارد دلار",
|
||||
"M$": "میلیون دلار",
|
||||
"bps": "نقطه پایه",
|
||||
};
|
||||
return map[clean] ?? clean;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ import {
|
|||
commodityGroup,
|
||||
COMMODITY_GROUP_LABELS,
|
||||
COMMODITY_GROUP_ORDER,
|
||||
COMMODITY_UNITS,
|
||||
faUnit,
|
||||
} from "@/lib/labels";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { API_BASE } from "@/lib/api";
|
||||
|
|
@ -1203,7 +1205,7 @@ function CommodityView() {
|
|||
return chosen.map((r) => ({
|
||||
label: commodityLabel(r.symbol, r.name),
|
||||
value: r.price,
|
||||
unit: r.currency,
|
||||
unit: COMMODITY_UNITS[r.symbol] || faUnit(r.currency),
|
||||
pct: r.pct,
|
||||
dir: (r.up ? "up" : "down") as "up" | "down",
|
||||
series: series[r.symbol],
|
||||
|
|
@ -1295,7 +1297,7 @@ function CommodityCard({
|
|||
value={row.price}
|
||||
format={(n) => faDigits(n.toLocaleString("en-US", { maximumFractionDigits: 2 }))}
|
||||
/>
|
||||
<span className="mr-1 text-[10px] font-normal text-muted-foreground">{row.currency}</span>
|
||||
<span className="mr-1 text-[10px] font-normal text-muted-foreground">{COMMODITY_UNITS[row.symbol] || faUnit(row.currency)}</span>
|
||||
</div>
|
||||
{series && series.length > 1 ? (
|
||||
<div className="-mx-4 mt-2">
|
||||
|
|
@ -1444,17 +1446,18 @@ function SteelStocksView() {
|
|||
const kpis: KpiItem[] = rows.slice(0, 3).map((r) => ({
|
||||
label: r.name,
|
||||
value: r.price || 0,
|
||||
unit: "$",
|
||||
unit: "دلار",
|
||||
pct: r.today_pct ?? undefined,
|
||||
dir: r.dir,
|
||||
series: series[r.code],
|
||||
decimals: 2,
|
||||
}));
|
||||
|
||||
const capStr = (v: number | null) =>
|
||||
v == null
|
||||
? "—"
|
||||
: faDigits("$" + (v >= 1000 ? (v / 1000).toFixed(2) + "T" : v.toFixed(2) + "B"));
|
||||
const capStr = (v: number | null) => {
|
||||
if (v == null) return "—";
|
||||
if (v >= 1000) return `${faDigits((v / 1000).toFixed(2))} تریلیون دلار`;
|
||||
return `${faDigits(v.toFixed(2))} میلیارد دلار`;
|
||||
};
|
||||
const pctText = (r: SteelRow) =>
|
||||
r.today_pct != null
|
||||
? faDigits(
|
||||
|
|
@ -1475,11 +1478,11 @@ function SteelStocksView() {
|
|||
<ViewHeader
|
||||
live={rows.length > 0}
|
||||
title="قیمت سهام شرکتها"
|
||||
subtitle={faDigits(
|
||||
`${rows.length} شرکت فولادی · مجموع ارزش بازار ${
|
||||
totalCap >= 1000 ? (totalCap / 1000).toFixed(2) + "T$" : totalCap.toFixed(0) + "B$"
|
||||
}`,
|
||||
)}
|
||||
subtitle={
|
||||
`${faDigits(rows.length)} شرکت فولادی · مجموع ارزش بازار ${
|
||||
totalCap >= 1000 ? faDigits((totalCap / 1000).toFixed(2)) + " تریلیون دلار" : faDigits(totalCap.toFixed(0)) + " میلیارد دلار"
|
||||
}`
|
||||
}
|
||||
lastUpdate={lastUpdate}
|
||||
/>
|
||||
|
||||
|
|
@ -1550,7 +1553,7 @@ function SteelStocksView() {
|
|||
<div className="flex flex-col">
|
||||
<span className="text-[10px] text-muted-foreground">قیمت</span>
|
||||
<span className="font-mono text-sm font-bold tabular-nums text-foreground">
|
||||
{r.price != null ? "$" + usd(r.price) : "—"}
|
||||
{r.price != null ? usd(r.price) + " دلار" : "—"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
|
|
@ -1585,7 +1588,7 @@ function SteelStocksView() {
|
|||
{capStr(r.market_cap)}
|
||||
</div>
|
||||
<div className="col-span-2 text-left font-mono tabular-nums text-foreground whitespace-nowrap">
|
||||
{r.price != null ? "$" + usd(r.price) : "—"}
|
||||
{r.price != null ? usd(r.price) + " دلار" : "—"}
|
||||
</div>
|
||||
<div className="col-span-2 flex items-center justify-center gap-2">
|
||||
<SteelBar pct={r.today_pct} dir={r.dir} />
|
||||
|
|
@ -2404,21 +2407,17 @@ type CryptoPayload = {
|
|||
const cryptoPrice = (p: number | null) => {
|
||||
if (p == null || !Number.isFinite(p)) return "—";
|
||||
if (p >= 1)
|
||||
return faDigits(
|
||||
"$" + p.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }),
|
||||
);
|
||||
return faDigits(p.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })) + " دلار";
|
||||
if (p >= 0.01)
|
||||
return faDigits(
|
||||
"$" + p.toLocaleString("en-US", { minimumFractionDigits: 4, maximumFractionDigits: 4 }),
|
||||
);
|
||||
return faDigits("$" + p.toLocaleString("en-US", { maximumFractionDigits: 8 }));
|
||||
return faDigits(p.toLocaleString("en-US", { minimumFractionDigits: 4, maximumFractionDigits: 4 })) + " دلار";
|
||||
return faDigits(p.toLocaleString("en-US", { maximumFractionDigits: 8 })) + " دلار";
|
||||
};
|
||||
const usdAbbr = (n: number | null) => {
|
||||
if (n == null || !Number.isFinite(n)) return "—";
|
||||
if (n >= 1e12) return faDigits("$" + (n / 1e12).toFixed(2) + "T");
|
||||
if (n >= 1e9) return faDigits("$" + (n / 1e9).toFixed(2) + "B");
|
||||
if (n >= 1e6) return faDigits("$" + (n / 1e6).toFixed(2) + "M");
|
||||
return faDigits("$" + n.toLocaleString("en-US", { maximumFractionDigits: 0 }));
|
||||
if (n >= 1e12) return faDigits((n / 1e12).toFixed(2)) + " تریلیون دلار";
|
||||
if (n >= 1e9) return faDigits((n / 1e9).toFixed(2)) + " میلیارد دلار";
|
||||
if (n >= 1e6) return faDigits((n / 1e6).toFixed(2)) + " میلیون دلار";
|
||||
return faDigits(n.toLocaleString("en-US", { maximumFractionDigits: 0 })) + " دلار";
|
||||
};
|
||||
const pctClass = (p: number | null) =>
|
||||
p == null ? "text-muted-foreground" : p >= 0 ? "text-emerald-700" : "text-red-600";
|
||||
|
|
@ -2751,7 +2750,7 @@ function WorldEconomyView() {
|
|||
|
||||
const fmtCell = (col: (typeof WE_COLS)[number], val: number | null) => {
|
||||
if (val == null) return "—";
|
||||
if (col.gdp) return faDigits((val / 1000).toFixed(2) + " T$");
|
||||
if (col.gdp) return faDigits((val / 1000).toFixed(2) + " تریلیون دلار");
|
||||
return faDigits(formatNumber(val) + (col.suffix || ""));
|
||||
};
|
||||
|
||||
|
|
@ -2860,7 +2859,7 @@ function WorldEconomyView() {
|
|||
{us10y && <DeltaPill pct={us10y.change} dir={us10y.change >= 0 ? "up" : "down"} />}
|
||||
</div>
|
||||
<div className="mt-1 text-[11px] text-muted-foreground font-mono">
|
||||
تغییر: {us10y ? faDigits((us10y.change_abs >= 0 ? "+" : "") + (us10y.change_abs * 100).toFixed(1) + " bps") : "—"}
|
||||
تغییر: {us10y ? faDigits((us10y.change_abs >= 0 ? "+" : "") + (us10y.change_abs * 100).toFixed(1) + " نقطه پایه") : "—"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -2876,7 +2875,7 @@ function WorldEconomyView() {
|
|||
{de10y && <DeltaPill pct={de10y.change} dir={de10y.change >= 0 ? "up" : "down"} />}
|
||||
</div>
|
||||
<div className="mt-1 text-[11px] text-muted-foreground font-mono">
|
||||
تغییر: {de10y ? faDigits((de10y.change_abs >= 0 ? "+" : "") + (de10y.change_abs * 100).toFixed(1) + " bps") : "—"}
|
||||
تغییر: {de10y ? faDigits((de10y.change_abs >= 0 ? "+" : "") + (de10y.change_abs * 100).toFixed(1) + " نقطه پایه") : "—"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -2892,7 +2891,7 @@ function WorldEconomyView() {
|
|||
{gb10y && <DeltaPill pct={gb10y.change} dir={gb10y.change >= 0 ? "up" : "down"} />}
|
||||
</div>
|
||||
<div className="mt-1 text-[11px] text-muted-foreground font-mono">
|
||||
تغییر: {gb10y ? faDigits((gb10y.change_abs >= 0 ? "+" : "") + (gb10y.change_abs * 100).toFixed(1) + " bps") : "—"}
|
||||
تغییر: {gb10y ? faDigits((gb10y.change_abs >= 0 ? "+" : "") + (gb10y.change_abs * 100).toFixed(1) + " نقطه پایه") : "—"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -2903,7 +2902,7 @@ function WorldEconomyView() {
|
|||
</div>
|
||||
<div className="mt-2 flex items-baseline justify-between">
|
||||
<span className={cn("text-2xl font-bold font-mono tabular-nums", (spread10_2 ?? 0) >= 0 ? "text-emerald-700" : "text-red-600")}>
|
||||
{spread10_2 != null ? faDigits((spread10_2 >= 0 ? "+" : "") + (spread10_2 * 100).toFixed(1) + " bps") : "—"}
|
||||
{spread10_2 != null ? faDigits((spread10_2 >= 0 ? "+" : "") + (spread10_2 * 100).toFixed(1) + " نقطه پایه") : "—"}
|
||||
</span>
|
||||
<span className="text-[11px] px-2 py-0.5 rounded-full font-mono font-medium bg-muted text-muted-foreground">
|
||||
{(spread10_2 ?? 0) >= 0 ? "نرمال" : "وارونه (Inverted)"}
|
||||
|
|
@ -2924,7 +2923,7 @@ function WorldEconomyView() {
|
|||
<th className="p-3 font-semibold text-center">سررسید</th>
|
||||
<th className="p-3 font-semibold text-center">نرخ بازدهی (Yield)</th>
|
||||
<th className="p-3 font-semibold text-center">تغییر روزانه</th>
|
||||
<th className="p-3 font-semibold text-center">تغییر پایه (bps)</th>
|
||||
<th className="p-3 font-semibold text-center">تغییر (نقطه پایه)</th>
|
||||
<th className="p-3 font-semibold text-center">کف / سقف امروز</th>
|
||||
<th className="p-3 font-semibold text-center">بازدهی هفتگی</th>
|
||||
<th className="p-3 font-semibold text-center">بازدهی ۱ ماهه</th>
|
||||
|
|
|
|||
Loading…
Reference in New Issue