Translate admin pages - Create admin.json files and translate all admin pages

- Create admin.json translation files for es, en, ca with all admin strings
- Update IntlProvider to include admin namespace
- Translate admin/invites/page.tsx - all strings now use translations
- Translate admin/trades/page.tsx - all strings now use translations
- Translate admin/price-history/page.tsx - all strings now use translations
- Translate admin/availability/page.tsx - all strings now use translations
- Add 'saving' key to common.json for all languages
- Fix linting errors: add t to useCallback dependencies
- All admin pages now fully multilingual
This commit is contained in:
counterweight 2025-12-26 11:49:50 +01:00
parent b8b3e8b9f6
commit e2376855ce
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
11 changed files with 473 additions and 87 deletions

View file

@ -6,9 +6,11 @@ import { adminApi } from "../../api";
import { sharedStyles } from "../../styles/shared";
import { PageLayout } from "../../components/PageLayout";
import { useRequireAuth } from "../../hooks/useRequireAuth";
import { useTranslation } from "../../hooks/useTranslation";
import { useAsyncData } from "../../hooks/useAsyncData";
export default function AdminPriceHistoryPage() {
const t = useTranslation("admin");
const { user, isLoading, isAuthorized } = useRequireAuth({
requiredPermission: Permission.VIEW_AUDIT,
fallbackRedirect: "/",
@ -61,14 +63,16 @@ export default function AdminPriceHistoryPage() {
>
<div style={styles.tableCard}>
<div style={styles.tableHeader}>
<h2 style={styles.tableTitle}>Bitcoin Price History</h2>
<h2 style={styles.tableTitle}>{t("priceHistory.title")}</h2>
<div style={styles.headerActions}>
<span style={styles.totalCount}>{records?.length ?? 0} records</span>
<span style={styles.totalCount}>
{t("priceHistory.recordsCount", { count: records?.length ?? 0 })}
</span>
<button onClick={fetchRecords} style={styles.refreshBtn} disabled={isLoadingData}>
Refresh
{t("priceHistory.refresh")}
</button>
<button onClick={handleFetchNow} style={styles.fetchBtn} disabled={isFetching}>
{isFetching ? "Fetching..." : "Fetch Now"}
{isFetching ? t("priceHistory.fetching") : t("priceHistory.fetchNow")}
</button>
</div>
</div>
@ -77,10 +81,10 @@ export default function AdminPriceHistoryPage() {
<table style={styles.table}>
<thead>
<tr>
<th style={styles.th}>Source</th>
<th style={styles.th}>Pair</th>
<th style={styles.th}>Price</th>
<th style={styles.th}>Timestamp</th>
<th style={styles.th}>{t("priceHistory.tableHeaders.source")}</th>
<th style={styles.th}>{t("priceHistory.tableHeaders.pair")}</th>
<th style={styles.th}>{t("priceHistory.tableHeaders.price")}</th>
<th style={styles.th}>{t("priceHistory.tableHeaders.timestamp")}</th>
</tr>
</thead>
<tbody>
@ -94,14 +98,14 @@ export default function AdminPriceHistoryPage() {
{!error && isLoadingData && (
<tr>
<td colSpan={4} style={styles.emptyRow}>
Loading...
{t("priceHistory.loading")}
</td>
</tr>
)}
{!error && !isLoadingData && (records?.length ?? 0) === 0 && (
<tr>
<td colSpan={4} style={styles.emptyRow}>
No price records yet. Click &quot;Fetch Now&quot; to get the current price.
{t("priceHistory.emptyState")}
</td>
</tr>
)}