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

@ -2,6 +2,7 @@
import { CSSProperties } from "react";
import { components } from "../../generated/api";
import { useTranslation } from "../../hooks/useTranslation";
type ExchangePriceResponse = components["schemas"]["ExchangePriceResponse"];
@ -94,6 +95,7 @@ export function PriceDisplay({
direction,
agreedPrice,
}: PriceDisplayProps) {
const t = useTranslation("exchange");
const marketPrice = priceData?.price?.market_price ?? 0;
const premiumPercent = priceData?.price?.premium_percentage ?? 5;
const isPriceStale = priceData?.price?.is_stale ?? false;
@ -101,16 +103,16 @@ export function PriceDisplay({
return (
<div style={styles.priceCard}>
{isLoading && !priceData ? (
<div style={styles.priceLoading}>Loading price...</div>
<div style={styles.priceLoading}>{t("priceDisplay.loading")}</div>
) : error && !priceData?.price ? (
<div style={styles.priceError}>{error}</div>
) : (
<>
<div style={styles.priceRow}>
<span style={styles.priceLabel}>Market:</span>
<span style={styles.priceLabel}>{t("priceDisplay.market")}</span>
<span style={styles.priceValue}>{formatPrice(marketPrice)}</span>
<span style={styles.priceDivider}></span>
<span style={styles.priceLabel}>Our price:</span>
<span style={styles.priceLabel}>{t("priceDisplay.ourPrice")}</span>
<span style={styles.priceValue}>{formatPrice(agreedPrice)}</span>
<span style={styles.premiumBadge}>
{direction === "buy" ? "+" : "-"}
@ -119,8 +121,8 @@ export function PriceDisplay({
</div>
{lastUpdate && (
<div style={styles.priceTimestamp}>
Updated {lastUpdate.toLocaleTimeString()}
{isPriceStale && <span style={styles.staleWarning}> (stale)</span>}
{t("priceDisplay.updated")} {lastUpdate.toLocaleTimeString()}
{isPriceStale && <span style={styles.staleWarning}> {t("priceDisplay.stale")}</span>}
</div>
)}
</>