diff --git a/android/capawesome.json b/android/capawesome.json index 848a0552..1b3cad89 100644 --- a/android/capawesome.json +++ b/android/capawesome.json @@ -1,3 +1,3 @@ { - "version": 20 + "version": 21 } \ No newline at end of file diff --git a/web/components/nav/bottom-nav-bar.tsx b/web/components/nav/bottom-nav-bar.tsx index 2568bdd9..d30ad83e 100644 --- a/web/components/nav/bottom-nav-bar.tsx +++ b/web/components/nav/bottom-nav-bar.tsx @@ -2,7 +2,7 @@ import Link from 'next/link' import clsx from 'clsx' import {MenuAlt3Icon} from '@heroicons/react/solid' import {Dialog, Transition} from '@headlessui/react' -import {Fragment, useState, useRef, useEffect} from 'react' +import {Fragment, useEffect, useRef, useState} from 'react' import {useRouter} from 'next/router' import Sidebar from './sidebar' import {Item} from './sidebar-item' @@ -49,7 +49,7 @@ export function BottomNavBar(props: { > {navigationOptions.map((item) => ( + {item.icon && } + {children} + {t(item.key, item.name)} + + if (!item.href) { return ( ) } @@ -176,9 +181,7 @@ function NavBarItem(props: { onTouchStart={() => setTouched(true)} onTouchEnd={() => setTouched(false)} > - {item.icon && } - {children} - {item.name} + {element} ) } @@ -249,9 +252,9 @@ export function MobileSidebar(props: { } const target = document.body - target.addEventListener('pointerdown', onPointerDown, { passive: false }) - target.addEventListener('pointermove', onPointerMove, { passive: false }) - target.addEventListener('pointerup', onPointerUp, { passive: false }) + target.addEventListener('pointerdown', onPointerDown, {passive: false}) + target.addEventListener('pointermove', onPointerMove, {passive: false}) + target.addEventListener('pointerup', onPointerUp, {passive: false}) return () => { diff --git a/web/components/nav/sidebar-item.tsx b/web/components/nav/sidebar-item.tsx index 97ae5287..f858419f 100644 --- a/web/components/nav/sidebar-item.tsx +++ b/web/components/nav/sidebar-item.tsx @@ -1,10 +1,12 @@ import clsx from 'clsx' import Link from 'next/link' -import { track } from 'web/lib/service/analytics' +import {track} from 'web/lib/service/analytics' +import {useT} from "web/lib/locale"; export type Item = { name: string + key: string children?: React.ReactNode trackingEventName?: string href?: string @@ -13,7 +15,9 @@ export type Item = { } export function SidebarItem(props: { item: Item; currentPage?: string }) { - const { item, currentPage } = props + const {item, currentPage} = props + + const t = useT() const currentBasePath = '/' + (currentPage?.split('/')[1] ?? '') const isCurrentPage = @@ -45,7 +49,7 @@ export function SidebarItem(props: { item: Item; currentPage?: string }) { aria-hidden="true" /> )} - {item.children ?? item.name} + {item.children ?? t(item.key, item.name)} ) diff --git a/web/components/nav/sidebar.tsx b/web/components/nav/sidebar.tsx index 6d8e5309..c47b18d7 100644 --- a/web/components/nav/sidebar.tsx +++ b/web/components/nav/sidebar.tsx @@ -12,10 +12,10 @@ import {Button, ColorType, SizeType} from 'web/components/buttons/button' import {signupRedirect} from 'web/lib/util/signup' import {useProfile} from 'web/hooks/use-profile' import Image from 'next/image' -import {ANDROID_APP_URL} from "common/constants"; -import {isAndroidApp} from "web/lib/util/webview"; +import {ANDROID_APP_URL} from "common/constants" +import {isAndroidApp} from "web/lib/util/webview" import {useT} from 'web/lib/locale' -import {LanguagePicker} from "web/components/language/language-picker"; +import {LanguagePicker} from "web/components/language/language-picker" export default function Sidebar(props: { className?: string @@ -32,7 +32,7 @@ export default function Sidebar(props: { const navOptions = props.navigationOptions const t = useT() - const bottomNavOptions = bottomNav(!!user, t) + const bottomNavOptions = bottomNav(!!user) const isAndroid = isAndroidApp() @@ -52,7 +52,7 @@ export default function Sidebar(props: {
{navOptions.map((item) => ( - + ))} {!isAndroid && {user === null && } {bottomNavOptions.map((item) => ( - + ))}
@@ -91,11 +91,10 @@ const logout = async () => { const bottomNav = ( loggedIn: boolean, - t: (k: string, fallback: string) => string, ) => buildArray( - !loggedIn && {name: t('nav.sign_in', 'Sign in'), icon: LoginIcon, href: '/signin'}, - loggedIn && {name: t('nav.sign_out', 'Sign out'), icon: LogoutIcon, onClick: logout} + !loggedIn && {key: 'nav.sign_in', name: 'Sign in', icon: LoginIcon, href: '/signin'}, + loggedIn && {key: 'nav.sign_out', name: 'Sign out', icon: LogoutIcon, onClick: logout} ) export const SignUpButton = (props: { diff --git a/web/components/page-base.tsx b/web/components/page-base.tsx index 8de354ba..7a4da713 100644 --- a/web/components/page-base.tsx +++ b/web/components/page-base.tsx @@ -12,7 +12,7 @@ import clsx from 'clsx' import {User} from 'common/user' import {buildArray} from 'common/util/array' import {useOnline} from 'web/hooks/use-online' -import {ReactNode, useEffect, useState} from 'react' +import {ReactNode, useState} from 'react' import {Toaster} from 'react-hot-toast' import {Col} from 'web/components/layout/col' import {PrivateMessagesIcon} from 'web/components/messaging/messages-icon' @@ -28,7 +28,6 @@ import {NotificationsIcon, SolidNotificationsIcon} from './notifications-icon' import {IS_MAINTENANCE} from "common/constants" import {MdThumbUp} from "react-icons/md" import {FaEnvelope} from "react-icons/fa" -import {useLocale, useT} from 'web/lib/locale' export function PageBase(props: { trackPageView: string | false @@ -50,9 +49,6 @@ export function PageBase(props: { const isMobile = useIsMobile() const profile = useProfile() - const t = useT() - const {locale} = useLocale() - const bottomNavOptions = user ? getBottomNavigation(user, profile) : getBottomSignedOutNavigation() @@ -61,22 +57,6 @@ export function PageBase(props: { const mobileSidebarOptions = getMobileSidebar(user, () => setIsAddFundsModalOpen(true)) - useEffect(() => { - // Add this helper function to translate navigation options - const translateNavOptions = (options: any[]) => { - options.forEach(option => { - const key = `nav.${option.key}`; - option.name = t(key, option.name) - console.log(key) - }) - } - - translateNavOptions(bottomNavOptions) - translateNavOptions(desktopSidebarOptions) - translateNavOptions(mobileSidebarOptions) - - }, [locale, bottomNavOptions, desktopSidebarOptions, mobileSidebarOptions, t]); - // eslint-disable-next-line react-hooks/rules-of-hooks trackPageView && useTracking(`view ${trackPageView}`, trackPageProps) useOnline() @@ -128,20 +108,20 @@ export function PageBase(props: { ) } -const Profiles = {key: 'people', name: 'People', href: '/', icon: UsersIcon} -const Home = {key: 'home', name: 'Home', href: '/', icon: HomeIcon} -const faq = {key: 'faq', name: 'FAQ', href: '/faq', icon: SolidQuestionIcon} -const About = {key: 'about', name: 'About', href: '/about', icon: QuestionMarkCircleIcon} -const Signin = {key: 'signin', name: 'Sign in', href: '/signin', icon: UserCircleIcon} -const Notifs = {key: 'notifs', name: 'Notifs', href: `/notifications`, icon: NotificationsIcon} -const NotifsSolid = {key: 'notifs', name: 'Notifs', href: `/notifications`, icon: SolidNotificationsIcon} -const Messages = {key: 'messages', name: 'Messages', href: '/messages', icon: PrivateMessagesIcon} -const Social = {key: 'social', name: 'Social', href: '/social', icon: LinkIcon} -const Organization = {key: 'organization', name: 'Organization', href: '/organization', icon: GlobeAltIcon} -const Vote = {key: 'vote', name: 'Vote', href: '/vote', icon: MdThumbUp} -const Contact = {key: 'contact', name: 'Contact', href: '/contact', icon: FaEnvelope} -const News = {key: 'news', name: "What's new", href: '/news', icon: NewspaperIcon} -const Settings = {key: 'settings', name: "Settings", href: '/settings', icon: CogIcon} +const Profiles = {key: 'nav.people', name: 'People', href: '/', icon: UsersIcon} +const Home = {key: 'nav.home', name: 'Home', href: '/', icon: HomeIcon} +const faq = {key: 'nav.faq', name: 'FAQ', href: '/faq', icon: SolidQuestionIcon} +const About = {key: 'nav.about', name: 'About', href: '/about', icon: QuestionMarkCircleIcon} +const Signin = {key: 'nav.sign_in', name: 'Sign in', href: '/signin', icon: UserCircleIcon} +const Notifs = {key: 'nav.notifs', name: 'Notifs', href: `/notifications`, icon: NotificationsIcon} +const NotifsSolid = {key: 'nav.notifs', name: 'Notifs', href: `/notifications`, icon: SolidNotificationsIcon} +const Messages = {key: 'nav.messages', name: 'Messages', href: '/messages', icon: PrivateMessagesIcon} +const Social = {key: 'nav.social', name: 'Social', href: '/social', icon: LinkIcon} +const Organization = {key: 'nav.organization', name: 'Organization', href: '/organization', icon: GlobeAltIcon} +const Vote = {key: 'nav.vote', name: 'Vote', href: '/vote', icon: MdThumbUp} +const Contact = {key: 'nav.contact', name: 'Contact', href: '/contact', icon: FaEnvelope} +const News = {key: 'nav.news', name: "What's new", href: '/news', icon: NewspaperIcon} +const Settings = {key: 'nav.settings', name: "Settings", href: '/settings', icon: CogIcon} const base = [ About, @@ -158,13 +138,13 @@ function getBottomNavigation(user: User, profile: Profile | null | undefined) { Profiles, NotifsSolid, { - key: 'profile', + key: 'nav.profile', name: 'Profile', href: profile === null ? '/signup' : `/${user.username}`, icon: SolidHomeIcon, }, { - key: 'messages', + key: 'nav.messages', name: 'Messages', href: '/messages', icon: (props) => ( diff --git a/web/lib/locale.ts b/web/lib/locale.ts index 41645e41..2305d864 100644 --- a/web/lib/locale.ts +++ b/web/lib/locale.ts @@ -24,21 +24,28 @@ export function useLocale() { // return messages[locale]?.[key] ?? english // } +const messageCache: Record> = {} + export function useT() { const {locale} = useLocale() - console.log({locale}) - const [messages, setMessages] = useState>({}) + const [messages, setMessages] = useState>( + messageCache[locale] ?? {} + ) useEffect(() => { if (locale === defaultLocale) return + if (messageCache[locale]) { + setMessages(messageCache[locale]) + return + } import(`web/messages/${locale}.json`) - .then((mod) => setMessages(mod.default)) + .then(mod => { + messageCache[locale] = mod.default + setMessages(mod.default) + }) .catch(() => setMessages({})) }, [locale]) - return (key: string, fallback: string) => { - if (locale === defaultLocale) return fallback - return messages[key] ?? fallback - } + return (key: string, fallback: string) => locale === defaultLocale ? fallback : messages[key] ?? fallback }