feat(i18n): extract strings from navigation, dialogs, onboarding, settings, and login
- Add useTranslation() to TopNav, BottomTabBar, FabMenu, UserMenu - Internationalize ConfirmDialog, AuthPromptModal, ExternalLinkDialog - Extract all onboarding flow strings (Welcome, HobbyPicker, ItemBrowser, Review, Done) - Internationalize settings page (weight unit, currency, API keys, import/export) - Internationalize login page and root error boundary - All dialogs in __root.tsx use t() for UI chrome Phase 34, Plan 02 (core navigation and global UI)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Link, useMatchRoute } from "@tanstack/react-router";
|
||||
import { motion } from "framer-motion";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAuth } from "../hooks/useAuth";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
import { useUIStore } from "../stores/uiStore";
|
||||
@@ -26,6 +27,7 @@ function TabItemWrapper({ icon, label, isActive }: TabItemProps) {
|
||||
}
|
||||
|
||||
export function BottomTabBar() {
|
||||
const { t } = useTranslation();
|
||||
const { data: auth } = useAuth();
|
||||
const isAuthenticated = !!auth?.user;
|
||||
const openCatalogSearch = useUIStore((s) => s.openCatalogSearch);
|
||||
@@ -46,7 +48,7 @@ export function BottomTabBar() {
|
||||
<div className="flex justify-around">
|
||||
{/* Home tab — always a Link */}
|
||||
<Link to="/">
|
||||
<TabItemWrapper icon="house" label="Home" isActive={isHome} />
|
||||
<TabItemWrapper icon="house" label={t("nav.home")} isActive={isHome} />
|
||||
</Link>
|
||||
|
||||
{/* Collection tab — Link if authenticated, button if anonymous */}
|
||||
@@ -54,7 +56,7 @@ export function BottomTabBar() {
|
||||
<Link to="/collection">
|
||||
<TabItemWrapper
|
||||
icon="package"
|
||||
label="Collection"
|
||||
label={t("nav.collection")}
|
||||
isActive={isCollection}
|
||||
/>
|
||||
</Link>
|
||||
@@ -62,7 +64,7 @@ export function BottomTabBar() {
|
||||
<button type="button" onClick={openAuthPrompt}>
|
||||
<TabItemWrapper
|
||||
icon="package"
|
||||
label="Collection"
|
||||
label={t("nav.collection")}
|
||||
isActive={isCollection}
|
||||
/>
|
||||
</button>
|
||||
@@ -71,17 +73,17 @@ export function BottomTabBar() {
|
||||
{/* Setups tab — Link if authenticated, button if anonymous */}
|
||||
{isAuthenticated ? (
|
||||
<Link to="/setups">
|
||||
<TabItemWrapper icon="layers" label="Setups" isActive={isSetups} />
|
||||
<TabItemWrapper icon="layers" label={t("nav.setups")} isActive={isSetups} />
|
||||
</Link>
|
||||
) : (
|
||||
<button type="button" onClick={openAuthPrompt}>
|
||||
<TabItemWrapper icon="layers" label="Setups" isActive={isSetups} />
|
||||
<TabItemWrapper icon="layers" label={t("nav.setups")} isActive={isSetups} />
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Search tab — always a button, opens CatalogSearchOverlay */}
|
||||
<button type="button" onClick={() => openCatalogSearch("collection")}>
|
||||
<TabItemWrapper icon="search" label="Search" isActive={false} />
|
||||
<TabItemWrapper icon="search" label={t("nav.search")} isActive={false} />
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
Reference in New Issue
Block a user