Phase 6: Translate User Pages - exchange, trades, invites, profile

- Expand exchange.json with all exchange page strings (page, steps, detailsStep, bookingStep, confirmationStep, priceDisplay)
- Create trades.json translation files for es, en, ca
- Create invites.json translation files for es, en, ca
- Create profile.json translation files for es, en, ca
- Translate exchange page and all components (ExchangeDetailsStep, BookingStep, ConfirmationStep, StepIndicator, PriceDisplay)
- Translate trades page (titles, sections, buttons, status labels)
- Translate invites page (titles, sections, status badges, copy button)
- Translate profile page (form labels, hints, placeholders, messages)
- Update IntlProvider to load all new namespaces
- All frontend tests passing
This commit is contained in:
counterweight 2025-12-25 22:19:13 +01:00
parent 7dd13292a0
commit 246553c402
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
22 changed files with 559 additions and 115 deletions

View file

@ -5,6 +5,7 @@ import { SatsDisplay } from "../../components/SatsDisplay";
import { formatEur } from "../../utils/exchange";
import { buttonStyles } from "../../styles/shared";
import constants from "../../../../shared/constants.json";
import { useTranslation } from "../../hooks/useTranslation";
const { lightningMaxEur: LIGHTNING_MAX_EUR } = constants.exchange;
@ -225,6 +226,7 @@ export function ExchangeDetailsStep({
hasPrice,
onContinue,
}: ExchangeDetailsStepProps) {
const t = useTranslation("exchange");
const isLightningDisabled = eurAmount > LIGHTNING_MAX_EUR * 100;
const handleAmountChange = (value: number) => {
@ -263,7 +265,7 @@ export function ExchangeDetailsStep({
...(direction === "buy" ? styles.directionBtnBuyActive : {}),
}}
>
Buy BTC
{t("direction.buyShort")}
</button>
<button
onClick={() => onDirectionChange("sell")}
@ -272,14 +274,15 @@ export function ExchangeDetailsStep({
...(direction === "sell" ? styles.directionBtnSellActive : {}),
}}
>
Sell BTC
{t("direction.sellShort")}
</button>
</div>
{/* Payment Method Selector */}
<div style={styles.paymentMethodSection}>
<div style={styles.paymentMethodLabel}>
Payment Method <span style={styles.required}>*</span>
{t("detailsStep.paymentMethod")}{" "}
<span style={styles.required}>{t("detailsStep.required")}</span>
</div>
<div style={styles.paymentMethodRow}>
<button
@ -290,7 +293,7 @@ export function ExchangeDetailsStep({
}}
>
<span style={styles.paymentMethodIcon}>🔗</span>
<span>Onchain</span>
<span>{t("transferMethod.onchain")}</span>
</button>
<button
onClick={() => onBitcoinTransferMethodChange("lightning")}
@ -302,12 +305,12 @@ export function ExchangeDetailsStep({
}}
>
<span style={styles.paymentMethodIcon}></span>
<span>Lightning</span>
<span>{t("transferMethod.lightning")}</span>
</button>
</div>
{isLightningDisabled && (
<div style={styles.thresholdMessage}>
Lightning payments are only available for amounts up to {LIGHTNING_MAX_EUR}
{t("detailsStep.lightningThreshold", { max: LIGHTNING_MAX_EUR })}
</div>
)}
</div>
@ -315,7 +318,7 @@ export function ExchangeDetailsStep({
{/* Amount Section */}
<div style={styles.amountSection}>
<div style={styles.amountHeader}>
<span style={styles.amountLabel}>Amount (EUR)</span>
<span style={styles.amountLabel}>{t("detailsStep.amount")}</span>
<div style={styles.amountInputWrapper}>
<span style={styles.amountCurrency}></span>
<input
@ -345,18 +348,24 @@ export function ExchangeDetailsStep({
<div style={styles.tradeSummary}>
{direction === "buy" ? (
<p style={styles.summaryText}>
You buy{" "}
{t("detailsStep.summaryBuy").split("{sats}")[0].trim()}{" "}
<strong style={styles.satsValue}>
<SatsDisplay sats={satsAmount} />
</strong>
, you sell <strong>{formatEur(eurAmount)}</strong>
{", "}
{t("detailsStep.summaryBuy").split("{sats}")[1]?.split("{eur}")[0]?.trim()}{" "}
<strong>{formatEur(eurAmount)}</strong>
</p>
) : (
<p style={styles.summaryText}>
You buy <strong>{formatEur(eurAmount)}</strong>, you sell{" "}
{t("detailsStep.summarySell").split("{sats}")[0]?.split("{eur}")[0]?.trim()}{" "}
<strong>{formatEur(eurAmount)}</strong>
{", "}
{t("detailsStep.summarySell").split("{sats}")[0]?.split("{eur}")[1]?.trim()}{" "}
<strong style={styles.satsValue}>
<SatsDisplay sats={satsAmount} />
</strong>
{t("detailsStep.summarySell").split("{sats}")[1]?.trim()}
</p>
)}
</div>
@ -370,7 +379,7 @@ export function ExchangeDetailsStep({
...(isPriceStale || !hasPrice ? buttonStyles.buttonDisabled : {}),
}}
>
Continue to Booking
{t("detailsStep.continueToBooking")}
</button>
</div>
);