Skip to content

Commit

Permalink
feat+refactor(shell): implement language switcher, refactor header, s…
Browse files Browse the repository at this point in the history
…ome more work on i18n
  • Loading branch information
olegshilov committed Nov 5, 2024
1 parent e6c5330 commit 02999d6
Show file tree
Hide file tree
Showing 27 changed files with 472 additions and 169 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions apps/shell/src/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import { env } from '../../env/client';
import { clashDisplayFont, hkGuiseFont } from '../../lib/fonts';
import { AppProviders } from '../../providers/app-providers';
import { PHProvider } from '../../providers/posthog-provider';
import { ALL_LOCALES, getStaticData, Locale } from '../../tolgee/shared';
import '../global.css';
import { AVAILABLE_LOCALES, getStaticData, Locale } from '../../tolgee/shared';
import './global.css';

export const metadata: Metadata = {
title: {
Expand Down Expand Up @@ -106,7 +106,7 @@ export default async function RootLayout({
});
}

if (!ALL_LOCALES.includes(params.locale as Locale)) {
if (!AVAILABLE_LOCALES.includes(params.locale as Locale)) {
notFound();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';
import { useEffect, useMemo, useState } from 'react';
import { useParams, useRouter } from 'next/navigation';
import { formatUnits } from 'viem';
import {
useAddress,
useIndexerBalanceQuery,
Expand Down
21 changes: 7 additions & 14 deletions apps/shell/src/components/header-desktop.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use client';
import { useMemo } from 'react';
import dynamic from 'next/dynamic';
import { useAccount, useChains } from 'wagmi';
import { haqqTestedge2 } from 'wagmi/chains';
import { Header } from '@haqq/shell-ui-kit';
import { headerLinks } from '../config/header-links';
import { useFilteredLinks } from '../hooks/use-filtered-header-links';
import { useLocaleSwitcher } from '../hooks/use-locale-switcher';

const Web3ConnectButtons = dynamic(async () => {
const { Web3ConnectButtons } = await import(
Expand All @@ -13,29 +13,22 @@ const Web3ConnectButtons = dynamic(async () => {
return { default: Web3ConnectButtons };
});

const HeaderUtilsMenu = dynamic(async () => {
const { HeaderUtilsMenu } = await import('../components/header-utils-menu');
return { default: HeaderUtilsMenu };
});

export function AppHeaderDesktop({ className }: { className?: string }) {
const chains = useChains();
const { chain = chains[0] } = useAccount();
const isTestedge = chain.id === haqqTestedge2.id;

const links = useMemo(() => {
return headerLinks.filter((link) => {
return link.chains.includes(chain.id);
});
}, [chain.id]);
const links = useFilteredLinks(chain);
const { switchLocale, locales, currentLocale } = useLocaleSwitcher();

return (
<Header
links={links}
web3ButtonsSlot={<Web3ConnectButtons />}
utilsSlot={<HeaderUtilsMenu />}
className={className}
isTestedge={isTestedge}
locales={locales}
switchLocale={switchLocale}
currentLocale={currentLocale}
/>
);
}
16 changes: 2 additions & 14 deletions apps/shell/src/components/header-mobile.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
'use client';
import { useMemo } from 'react';
import dynamic from 'next/dynamic';
import { useAccount, useChains } from 'wagmi';
import { haqqTestedge2 } from 'wagmi/chains';
import { HeaderMobile } from '@haqq/shell-ui-kit';
import { headerLinks } from '../config/header-links';
import { useFilteredLinks } from '../hooks/use-filtered-header-links';

const Web3ConnectButtonsMobile = dynamic(async () => {
const { Web3ConnectButtonsMobile } = await import(
Expand All @@ -13,27 +12,16 @@ const Web3ConnectButtonsMobile = dynamic(async () => {
return { default: Web3ConnectButtonsMobile };
});

const HeaderUtilsMenu = dynamic(async () => {
const { HeaderUtilsMenu } = await import('../components/header-utils-menu');
return { default: HeaderUtilsMenu };
});

export function AppHeaderMobile({ className }: { className?: string }) {
const chains = useChains();
const { chain = chains[0] } = useAccount();
const isTestedge = chain.id === haqqTestedge2.id;

const links = useMemo(() => {
return headerLinks.filter((link) => {
return link.chains.includes(chain.id);
});
}, [chain.id]);
const links = useFilteredLinks(chain);

return (
<HeaderMobile
links={links}
web3ButtonsSlot={<Web3ConnectButtonsMobile />}
utilsSlot={<HeaderUtilsMenu />}
className={className}
isTestedge={isTestedge}
/>
Expand Down
53 changes: 0 additions & 53 deletions apps/shell/src/components/header-utils-menu.tsx

This file was deleted.

14 changes: 14 additions & 0 deletions apps/shell/src/components/locale-dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useLocaleSwitcher } from '../hooks/use-locale-switcher';
import { LocaleDropdown } from '@haqq/shell-ui-kit';

export function AppLocaleDropdown() {
const { switchLocale, locales, currentLocale } = useLocaleSwitcher();

return (
<LocaleDropdown
locales={locales}
switchLocale={switchLocale}
currentLocale={currentLocale}
/>
);
}
58 changes: 34 additions & 24 deletions apps/shell/src/config/header-links.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,53 @@
import { haqqMainnet, haqqTestedge2 } from 'wagmi/chains';
import { HeaderLink } from '@haqq/shell-ui-kit';

export const headerLinks: {
href: string;
label: string;
chains: number[];
}[] = [
// {
// href: '/',
// label: 'Home',
// chains: [haqqMainnet.id, haqqTestedge2.id],
// },
export const headerLinks: HeaderLink[] = [
{
href: '/uc-dao',
type: 'link',
label: 'UC DAO',
href: '/uc-dao',
chains: [haqqMainnet.id, haqqTestedge2.id],
},
{
href: '/staking',
type: 'link',
label: 'Staking',
href: '/staking',
chains: [haqqMainnet.id, haqqTestedge2.id],
},
{
href: '/governance',
type: 'link',
label: 'Governance',
href: '/governance',
chains: [haqqMainnet.id, haqqTestedge2.id],
},
{
href: '/authz',
label: 'Authz',
chains: [haqqMainnet.id, haqqTestedge2.id],
type: 'dropdown',
label: 'Tools',
children: [
{
type: 'link',
label: 'Authz',
href: '/authz',
chains: [haqqMainnet.id, haqqTestedge2.id],
},
{
type: 'link',
label: 'Faucet',
href: '/faucet',
chains: [haqqTestedge2.id],
},
],
},
{
href: '/faucet',
label: 'Faucet',
chains: [haqqTestedge2.id],
type: 'dropdown',
label: 'Utils',
children: [
{
type: 'link',
label: 'Address conversion',
href: '/utils/address-conversion',
chains: [haqqMainnet.id, haqqTestedge2.id],
},
],
},
];

export const headerUtilsLinks: {
name: string;
link: string;
}[] = [{ name: 'Address conversion', link: '/utils/address-conversion' }];
10 changes: 10 additions & 0 deletions apps/shell/src/hooks/use-available-locale-links.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { AVAILABLE_LOCALES, LOCALE_LABELS } from '../tolgee/shared';

export function useAvailableLocaleLinks() {
return AVAILABLE_LOCALES.map((locale) => {
return {
id: locale,
label: `${LOCALE_LABELS[locale].emoji} ${LOCALE_LABELS[locale].label}`,
};
});
}
30 changes: 30 additions & 0 deletions apps/shell/src/hooks/use-filtered-header-links.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useMemo } from 'react';
import { Chain } from 'wagmi/chains';
import { HeaderLink } from '@haqq/shell-ui-kit';
import { headerLinks } from '../config/header-links';

export function useFilteredLinks(chain: Chain) {
const links = useMemo(() => {
return headerLinks
.map((link) => {
if (link.type === 'dropdown') {
const filteredChildren = link.children.filter((child) => {
return !child.chains || child.chains.includes(chain.id);
});
if (filteredChildren.length > 0) {
return { ...link, children: filteredChildren };
}
return null;
}

if (link.type === 'link' && link.chains.includes(chain.id)) {
return link;
}

return null;
})
.filter(Boolean) as HeaderLink[];
}, [chain.id]);

return links;
}
32 changes: 32 additions & 0 deletions apps/shell/src/hooks/use-locale-switcher.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use client';
import { useCallback } from 'react';
import { useLocale } from 'next-intl';
import { useRouter, usePathname } from '../i18n/routing';
import { AVAILABLE_LOCALES, LOCALE_LABELS } from '../tolgee/shared';

export function useLocaleSwitcher() {
const router = useRouter();
const pathname = usePathname();
const currentLocale = useLocale();

const switchLocale = useCallback(
(locale: string) => {
router.replace(pathname, { locale });
},
[router, pathname],
);

const locales = AVAILABLE_LOCALES.map((locale) => {
return {
id: locale,
label: LOCALE_LABELS[locale].label,
emoji: LOCALE_LABELS[locale].emoji,
};
});

return {
switchLocale,
locales,
currentLocale,
};
}
15 changes: 11 additions & 4 deletions apps/shell/src/i18n/request.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { getRequestConfig } from 'next-intl/server';
import { routing } from './routing';
import { Locale } from '../tolgee/shared';

export default getRequestConfig(async ({ requestLocale }) => {
// Get locale from request and fallback to default if needed
let locale = await requestLocale;

if (!locale || !routing.locales.includes(locale as Locale)) {
locale = routing.defaultLocale;
}

// The i18n/request.ts is required by next-intl package, we don't actually need it,
// so we are only doing necessary actions to stop next-intl from complaining.
export default getRequestConfig(async ({ locale }) => {
return {
// do this to make next-intl not emmit any warnings
locale,
messages: { locale },
};
});
17 changes: 17 additions & 0 deletions apps/shell/src/i18n/routing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { createNavigation } from 'next-intl/navigation';
import { defineRouting } from 'next-intl/routing';
import { AVAILABLE_LOCALES, DEFAULT_LOCALE } from '../tolgee/shared';

export const routing = defineRouting({
locales: AVAILABLE_LOCALES,
defaultLocale: DEFAULT_LOCALE,
localeCookie: {
// Custom cookie name
name: 'USER_LOCALE',
// Expire in one day
maxAge: 60 * 60 * 24,
},
});

export const { Link, redirect, usePathname, useRouter, permanentRedirect } =
createNavigation(routing);
6 changes: 3 additions & 3 deletions apps/shell/src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import createMiddleware from 'next-intl/middleware';
import { ALL_LOCALES, DEFAULT_LOCALE } from './tolgee/shared';
import { AVAILABLE_LOCALES, DEFAULT_LOCALE } from './tolgee/shared';

export default createMiddleware({
locales: ALL_LOCALES,
locales: AVAILABLE_LOCALES,
defaultLocale: DEFAULT_LOCALE,
localePrefix: 'as-needed',
localePrefix: 'never',
});

export const config = {
Expand Down
5 changes: 0 additions & 5 deletions apps/shell/src/navigation.ts

This file was deleted.

Loading

0 comments on commit 02999d6

Please sign in to comment.