From 0b796440f1672d7c4e48572f849bcf0b983456f3 Mon Sep 17 00:00:00 2001
From: SkateSpots
Date: Fri, 2 Oct 2026 10:11:06 +0700
Subject: [PATCH] =?UTF-8?q?feat(i18n):=20Spanish=20batch=202=20=E2=80=94?=
=?UTF-8?q?=20nav/chrome,=20events/shops/tours,=20crews/DMs,=20settings/au?=
=?UTF-8?q?th,=20wallet/stash/newsletter/stats?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
~3,470 new keys (5,770 total, EN=ES), ~115 more files wired.
- nav + chromeUi: header, More menu, burger menu, footer, map toolbar widgets
(sort/trust/weather), spot-type label helper.
- placesUi: events, shops, tours, food. socialUi: crews, DMs, notifications,
collectives, crew chat/coordinator. settingsUi: settings, auth/signup,
onboarding, profile edit, legal. walletUi: wallet/Cashu, stash, mints,
app shop, newsletter, community stats, leaderboards, profile.
- Fixed 738 usages where an agent dropped the socialUi. prefix (caught by check:i18n).
---
AGENTS.md | 25 +-
src/components/AddToCalendar.tsx | 8 +-
src/components/AddToCollectionDialog.tsx | 52 +-
src/components/AdminReviewCard.tsx | 8 +-
src/components/AmberApprovalHint.tsx | 15 +-
src/components/AttendeeList.tsx | 19 +-
src/components/BetaDisclaimerDialog.tsx | 25 +-
src/components/CollectiveJoinRequestCard.tsx | 30 +-
src/components/CollectiveMembers.tsx | 34 +-
src/components/ConfirmMembershipCard.tsx | 27 +-
src/components/CoordinatorSettingsCard.tsx | 112 +-
src/components/CrewAgentPanel.tsx | 49 +-
src/components/CrewBadge.tsx | 14 +-
src/components/CrewChat.tsx | 62 +-
src/components/CrewForm.tsx | 291 +-
src/components/CrewInviteCard.tsx | 24 +-
src/components/CrewInviteDialog.tsx | 58 +-
src/components/CrewLinkField.tsx | 13 +-
src/components/CrewLookingFor.tsx | 6 +-
src/components/CrewNip05Badge.tsx | 6 +-
src/components/CrewRequestToJoin.tsx | 22 +-
src/components/CrewTreasuryCard.tsx | 22 +-
src/components/DestinationSearch.tsx | 19 +-
src/components/EditProfileForm.tsx | 159 +-
src/components/ErrorState.tsx | 15 +-
src/components/EventCard.tsx | 25 +-
src/components/EventCountdown.tsx | 20 +-
src/components/EventSponsors.tsx | 4 +-
src/components/EventUpdates.tsx | 42 +-
src/components/EventsCalendar.tsx | 63 +-
src/components/FeaturedEventUpgrade.tsx | 35 +-
src/components/FollowListManager.tsx | 38 +-
src/components/GrantProCard.tsx | 28 +-
src/components/JoinRequestCard.tsx | 45 +-
src/components/Layout.tsx | 103 +-
src/components/MemberVisibilityControl.tsx | 16 +-
src/components/MyDataTab.tsx | 118 +-
src/components/NewMessageDialog.tsx | 34 +-
src/components/NewsletterBackfillPanel.tsx | 22 +-
src/components/NewsletterComposer.tsx | 35 +-
src/components/NewsletterIssueView.tsx | 8 +-
src/components/NewsletterOverlay.tsx | 17 +-
src/components/NewsletterSubscribeButton.tsx | 24 +-
src/components/Nip05Required.tsx | 20 +-
src/components/NotificationBell.tsx | 69 +-
src/components/NotificationSettingsCard.tsx | 62 +-
src/components/RegionBackfillCard.tsx | 40 +-
src/components/RelatrSettings.tsx | 72 +-
src/components/RelayListManager.tsx | 73 +-
src/components/RequestToJoinCollective.tsx | 27 +-
src/components/RsvpButtons.tsx | 38 +-
src/components/SecuritySettings.tsx | 130 +-
src/components/ShareProfileDialog.tsx | 14 +-
src/components/ShopBountyCard.tsx | 28 +-
src/components/SkateNip05Input.tsx | 14 +-
src/components/SortDropdown.tsx | 28 +-
src/components/SpotMap.tsx | 7 +-
src/components/TourCard.tsx | 63 +-
src/components/TrustBadge.tsx | 16 +-
src/components/TrustFilter.tsx | 34 +-
src/components/UserStatusIndicator.tsx | 6 +-
src/components/VouchCard.tsx | 35 +-
src/components/WalletModal.tsx | 84 +-
src/components/WeatherToggle.tsx | 6 +-
src/components/ZapBadgesCard.tsx | 30 +-
src/components/ZapButton.tsx | 6 +-
src/components/ZapCrewDialog.tsx | 50 +-
src/components/ZapDialog.tsx | 107 +-
src/components/auth/AccountSwitcher.tsx | 10 +-
src/components/auth/AmberCallbackHandler.tsx | 54 +-
src/components/auth/LoginArea.tsx | 10 +-
src/components/auth/LoginDialog.tsx | 131 +-
src/components/auth/MnemonicSignupDialog.tsx | 106 +-
src/components/auth/SignupDialog.tsx | 177 +-
src/components/auth/SignupMethodDialog.tsx | 42 +-
src/components/crew/CrewCoordinatorCard.tsx | 48 +-
src/components/crew/CrewHero.tsx | 8 +-
src/components/crew/CrewLeadership.tsx | 17 +-
src/components/crew/CrewSponsorBanner.tsx | 6 +-
src/components/crew/CrewSponsorPicker.tsx | 14 +-
src/components/crew/CrewVideoSection.tsx | 18 +-
src/components/onboarding/RelayEducation.tsx | 80 +-
src/components/wallet/CashuWalletCard.tsx | 181 +-
src/components/wallet/EscrowKeyCard.tsx | 19 +-
.../wallet/LightningPrivacyTips.tsx | 65 +-
src/components/wallet/MintPrivacyManager.tsx | 104 +-
src/components/wallet/NwcWalletCard.tsx | 46 +-
src/components/wallet/QRScannerModal.tsx | 20 +-
.../wallet/RecoveryPhraseDialog.tsx | 23 +-
.../wallet/WalletComparisonGuide.tsx | 55 +-
src/hooks/useNavPreferences.ts | 14 +-
src/i18n/en.ts | 3720 +++++++++++++++-
src/i18n/es.ts | 3722 ++++++++++++++++-
src/lib/spotTypeLabel.ts | 31 +
src/pages/AboutPage.tsx | 109 +-
src/pages/AdminReviewPage.tsx | 84 +-
src/pages/AppShopPage.tsx | 113 +-
src/pages/BountyLeaderboardPage.tsx | 83 +-
src/pages/CollectionDetailPage.tsx | 50 +-
src/pages/CommunityStatsPage.tsx | 179 +-
src/pages/ContactsPage.tsx | 53 +-
src/pages/ConversationPage.tsx | 80 +-
src/pages/CreateCrewPage.tsx | 16 +-
src/pages/CreateEventPage.tsx | 132 +-
src/pages/CreateShopPage.tsx | 106 +-
src/pages/CreateTourPage.tsx | 467 ++-
src/pages/CrewDetailPage.tsx | 78 +-
src/pages/CrewsPage.tsx | 86 +-
src/pages/DirectMessagesPage.tsx | 68 +-
src/pages/EditCrewPage.tsx | 16 +-
src/pages/EditEventPage.tsx | 132 +-
src/pages/EditShopPage.tsx | 112 +-
src/pages/EditTourPage.tsx | 10 +-
src/pages/EventDetailPage.tsx | 73 +-
src/pages/EventsPage.tsx | 146 +-
src/pages/FAQPage.tsx | 93 +-
src/pages/FoodPage.tsx | 50 +-
src/pages/GlossaryPage.tsx | 31 +-
src/pages/GroupConversationPage.tsx | 30 +-
src/pages/Index.tsx | 26 +-
src/pages/LicensePage.tsx | 28 +-
src/pages/MapPage.tsx | 5 +-
src/pages/MintsPage.tsx | 107 +-
src/pages/NIP19Page.tsx | 84 +-
src/pages/NewsletterPage.tsx | 101 +-
src/pages/NotFound.tsx | 10 +-
src/pages/OnboardingPage.tsx | 219 +-
src/pages/PrivacyPage.tsx | 139 +-
src/pages/SettingsPage.tsx | 218 +-
src/pages/ShopDetailPage.tsx | 68 +-
src/pages/SignersPage.tsx | 105 +-
src/pages/StashPage.tsx | 122 +-
src/pages/SupportersPage.tsx | 71 +-
src/pages/TourDetailPage.tsx | 84 +-
src/pages/WalletPage.tsx | 42 +-
src/pages/ZapLeaderboardPage.tsx | 31 +-
136 files changed, 11615 insertions(+), 3814 deletions(-)
create mode 100644 src/lib/spotTypeLabel.ts
diff --git a/AGENTS.md b/AGENTS.md
index 51dc0ff..7d3cfcc 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1642,14 +1642,23 @@ similar are internal endpoints/hook names, not credits — leave them.)
chain) fails the build if any literal `t('…')` key is missing from `en` OR `es`,
or if `en`/`es` drift. Dynamic template keys (`t(\`ns.${x}\`)`) are NOT checked —
keep those few in sync by hand.
-- **Coverage (2026-10-01, batch 1 done):** ~1,680 new keys (2,297 total) and ~65
- files wired — **Map (`mapUi`)**, **spots (`spotUi`)** incl. detail/create/edit/
- chat, **Marketplace/trades/offers/escrow/shipping (`marketUi`)**, and **Lab/
- `/become/*`/coaches/skaters (`labUi`)**. **Still to do (batch 2+):** Settings,
- auth (LoginArea/dialogs), Onboarding, Events, Shops, Tours, Crews, DMs/group,
- Stash, Newsletter, Community Stats, legal (About/FAQ/Privacy/License/Glossary),
- Wallet/Mints, App Shop, Food, Bounties/leaderboards, Admin review. Untranslated
- text falls back to English, so partial coverage degrades gracefully.
+- **Coverage (2026-10-02, batches 1–2 done):** **~5,770 keys** (EN=ES) and ~180
+ files wired. Namespaces: batch 1 — `mapUi`, `spotUi`, `marketUi`, `labUi`;
+ batch 2 — `nav` (header/More/burger labels) + `chromeUi` (footer, toolbar
+ widgets, spot-type labels), `placesUi` (events/shops/tours/food), `socialUi`
+ (crews/DMs/notifications/collectives), `settingsUi` (settings/auth/signup/
+ onboarding/profile/legal), `walletUi` (wallet/Cashu, stash, mints, app shop,
+ newsletter, community stats, leaderboards, profile page).
+- **Still to translate (batch 3):** `RouteDialog`/`StopDepartures`/`TripItineraryCard`
+ (routing UI), the Sasquatch panel/dialogs (`SasquatchGuide`, `SasquatchProDialog`,
+ `SasquatchActionCard`, `SasquatchAiStatusCard`), `AddToCollectionDialog` edge
+ copy, `SplashScreen`/`LazyMount`, and **shared data-module labels** that live
+ outside components (`SPOT_TYPE_LABELS`/`SPOT_CATEGORIES` in `src/lib/types.ts`,
+ `src/lib/skateTags.ts`, `src/lib/spotStatus.ts`, `src/lib/sortOptions.ts`).
+ **Dates & relative times** are still English (no localized date layer yet).
+- ⚠️ A batch-2 agent dropped the `socialUi.` namespace prefix in ~36 files — the
+ `check:i18n` guard caught all 738 usages. **Always run `node scripts/check-i18n.mjs`
+ (it's in `npm test`) after wiring a file.**
- ⚠️ **When wiring a file, keep `en.ts`/`es.ts` key-for-key in sync** and run
`node scripts/check-i18n.mjs` before committing.
diff --git a/src/components/AddToCalendar.tsx b/src/components/AddToCalendar.tsx
index fc52a6f..1eaf391 100644
--- a/src/components/AddToCalendar.tsx
+++ b/src/components/AddToCalendar.tsx
@@ -12,6 +12,7 @@ import {
type CalendarEventInput,
} from '@/lib/calendar';
import { cn } from '@/lib/utils';
+import { useTranslation } from '@/contexts/language';
interface AddToCalendarProps {
event: CalendarEventInput;
@@ -25,6 +26,7 @@ interface AddToCalendarProps {
* Offers a native .ics download (Apple/Outlook) and a Google Calendar link.
*/
export function AddToCalendar({ event, color = '#06b6d4', className }: AddToCalendarProps) {
+ const { t } = useTranslation();
return (
@@ -35,7 +37,7 @@ export function AddToCalendar({ event, color = '#06b6d4', className }: AddToCale
style={{ borderColor: `${color}55`, color }}
>
- Add to Calendar
+ {t('placesUi.addToCalendar.add')}
@@ -44,7 +46,7 @@ export function AddToCalendar({ event, color = '#06b6d4', className }: AddToCale
className="cursor-pointer"
>
- Apple / Outlook (.ics)
+ {t('placesUi.addToCalendar.appleOutlook')}
- Google Calendar
+ {t('placesUi.addToCalendar.google')}
diff --git a/src/components/AddToCollectionDialog.tsx b/src/components/AddToCollectionDialog.tsx
index 4570b9d..aec4644 100644
--- a/src/components/AddToCollectionDialog.tsx
+++ b/src/components/AddToCollectionDialog.tsx
@@ -12,6 +12,7 @@ import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { Skeleton } from '@/components/ui/skeleton';
import { useToast } from '@/hooks/useToast';
+import { useTranslation } from '@/contexts/language';
import { useCurrentUser } from '@/hooks/useCurrentUser';
import {
useMySpotCollections,
@@ -29,6 +30,7 @@ interface AddToCollectionDialogProps {
}
export function AddToCollectionDialog({ open, onOpenChange, spot }: AddToCollectionDialogProps) {
+ const { t } = useTranslation();
const { user } = useCurrentUser();
const { data: collections, isLoading } = useMySpotCollections();
const { createCollection, isPending: isCreating } = useCreateSpotCollection();
@@ -45,8 +47,8 @@ export function AddToCollectionDialog({ open, onOpenChange, spot }: AddToCollect
const handleAddToCollection = async (collection: SpotCollection) => {
if (collection.spotRefs.includes(spotRef)) {
toast({
- title: 'Already saved',
- description: `"${spot.title}" is already in "${collection.title}"`,
+ title: t('walletUi.addToCollection.alreadySaved'),
+ description: t('walletUi.addToCollection.alreadySavedDesc', { spot: spot.title, collection: collection.title }),
});
return;
}
@@ -59,14 +61,14 @@ export function AddToCollectionDialog({ open, onOpenChange, spot }: AddToCollect
spotIdentifier: spot.identifier,
});
toast({
- title: 'Spot saved!',
- description: `Added "${spot.title}" to "${collection.title}"`,
+ title: t('walletUi.addToCollection.saved'),
+ description: t('walletUi.addToCollection.savedDesc', { spot: spot.title, collection: collection.title }),
});
onOpenChange(false);
} catch (error) {
toast({
- title: 'Failed to save',
- description: error instanceof Error ? error.message : 'Something went wrong',
+ title: t('walletUi.addToCollection.saveFailed'),
+ description: error instanceof Error ? error.message : t('walletUi.addToCollection.somethingWrong'),
variant: 'destructive',
});
} finally {
@@ -85,8 +87,8 @@ export function AddToCollectionDialog({ open, onOpenChange, spot }: AddToCollect
spotRefs: [spotRef], // Add the current spot to the new collection
});
toast({
- title: 'Collection created!',
- description: `"${spot.title}" added to your new collection "${newTitle}"`,
+ title: t('walletUi.addToCollection.created'),
+ description: t('walletUi.addToCollection.createdDesc', { spot: spot.title, collection: newTitle }),
});
setNewTitle('');
setNewDescription('');
@@ -94,8 +96,8 @@ export function AddToCollectionDialog({ open, onOpenChange, spot }: AddToCollect
onOpenChange(false);
} catch (error) {
toast({
- title: 'Failed to create collection',
- description: error instanceof Error ? error.message : 'Something went wrong',
+ title: t('walletUi.addToCollection.createFailed'),
+ description: error instanceof Error ? error.message : t('walletUi.addToCollection.somethingWrong'),
variant: 'destructive',
});
}
@@ -108,11 +110,11 @@ export function AddToCollectionDialog({ open, onOpenChange, spot }: AddToCollect
- Save to Collection
+ {t('walletUi.addToCollection.title')}
-
Please log in to save spots to collections
+
{t('walletUi.addToCollection.loginRequired')}
@@ -125,10 +127,10 @@ export function AddToCollectionDialog({ open, onOpenChange, spot }: AddToCollect
- Save to Collection
+ {t('walletUi.addToCollection.title')}
- Save "{spot.title}" to one of your collections
+ {t('walletUi.addToCollection.desc', { spot: spot.title })}
@@ -179,8 +181,8 @@ export function AddToCollectionDialog({ open, onOpenChange, spot }: AddToCollect
- {collection.spotRefs.length} spot{collection.spotRefs.length !== 1 ? 's' : ''}
- {isInCollection && ' · Already saved'}
+ {t('walletUi.addToCollection.spotCount', { count: collection.spotRefs.length })}
+ {isInCollection && ` · ${t('walletUi.addToCollection.alreadySavedTag')}`}
@@ -190,8 +192,8 @@ export function AddToCollectionDialog({ open, onOpenChange, spot }: AddToCollect
) : !showNewForm ? (
-
You don't have any collections yet
-
Create your first one below!
+
{t('walletUi.addToCollection.noCollections')}
+
{t('walletUi.addToCollection.createFirst')}
) : null}
@@ -199,7 +201,7 @@ export function AddToCollectionDialog({ open, onOpenChange, spot }: AddToCollect
{showNewForm ? (