feat: some more localized links

This commit is contained in:
tresabhi committed 2024-12-27 14:01:59 -06:00
1 parent 8203db3dc2
commit e0daf85561
19 files changed
+182 -81

No files matched your search

@@ -1,8 +1,10 @@
import { assertSecret, idToRegion } from '@blitzkit/core';
import { Button, Flex, Heading, Link, Text } from '@radix-ui/themes';
import { Button, Flex, Heading, Text } from '@radix-ui/themes';
import { useEffect, useState } from 'react';
import { useLocale } from '../../hooks/useLocale';
import { App } from '../../stores/app';
import { CURRENT_POLICIES_AGREEMENT_INDEX } from '../../stores/app/constants';
import { LinkI18n } from '../LinkI18n';
import './index.css';
type Extension =
@@ -30,6 +32,7 @@ export function Checks() {
* Wargaming: 14 (refresh: 7)
*/
function Content() {
const { locale } = useLocale();
const logins = App.use((state) => state.logins);
const mutateApp = App.useMutation();
const appStore = App.useStore();
@@ -118,9 +121,14 @@ function Content() {
<Text>
This website utilizes cookies to perform analytics and personalize
your experience. You can learn more through{' '}
<Link href="/docs/legal/privacy-policy">our privacy policy</Link>.
By using BlitzKit, you also agree to our{' '}
<Link href="/docs/legal/terms-of-service">terms of service</Link>.
<LinkI18n locale={locale} href="/docs/legal/privacy-policy">
our privacy policy
</LinkI18n>
. By using BlitzKit, you also agree to our{' '}
<LinkI18n locale={locale} href="/docs/legal/terms-of-service">
terms of service
</LinkI18n>
.
</Text>
</Flex>
@@ -1,9 +1,11 @@
import { ExternalLinkIcon, LoopIcon, TrashIcon } from '@radix-ui/react-icons';
import { Dialog, Flex, IconButton, Link } from '@radix-ui/themes';
import { Dialog, Flex, IconButton } from '@radix-ui/themes';
import { useState } from 'react';
import { awaitableProvisionDefinitions } from '../../core/awaitables/provisionDefinitions';
import { tankToCompareMember } from '../../core/blitzkit/tankToCompareMember';
import { useLocale } from '../../hooks/useLocale';
import { CompareEphemeral } from '../../stores/compareEphemeral';
import { LinkI18n } from '../LinkI18n';
import { TankSearch } from '../TankSearch';
interface TankControlProps {
@@ -14,6 +16,7 @@ interface TankControlProps {
const provisionDefinitions = await awaitableProvisionDefinitions;
export function TankControl({ index, id }: TankControlProps) {
const { locale } = useLocale();
const [switchTankDialogOpen, setSwitchTankDialogOpen] = useState(false);
const mutateCompareEphemeral = CompareEphemeral.useMutation();
@@ -69,11 +72,15 @@ export function TankControl({ index, id }: TankControlProps) {
</Dialog.Content>
</Dialog.Root>
<Link href={`/tools/tankopedia/${id}`} target="_blank">
<LinkI18n
locale={locale}
href={`/tools/tankopedia/${id}`}
target="_blank"
>
<IconButton variant="ghost">
<ExternalLinkIcon />
</IconButton>
</Link>
</LinkI18n>
</Flex>
);
}
@@ -3,6 +3,7 @@ import { EyeOpenIcon } from '@radix-ui/react-icons';
import { Box, Flex, Heading, Text } from '@radix-ui/themes';
import { google } from 'googleapis';
import { awaitableTankDefinitions } from '../core/awaitables/tankDefinitions';
import { LocaleProvider } from '../hooks/useLocale';
import { TankopediaPersistent } from '../stores/tankopediaPersistent';
import { TankCard } from './TankCard';
@@ -63,11 +64,17 @@ const hotTanks = report.data.rows
views,
}));
export function HomePageHotTanks() {
interface HomePageHotTanksProps {
locale: string | undefined;
}
export function HomePageHotTanks({ locale }: HomePageHotTanksProps) {
return (
<TankopediaPersistent.Provider>
<Content />
</TankopediaPersistent.Provider>
<LocaleProvider locale={locale}>
<TankopediaPersistent.Provider>
<Content />
</TankopediaPersistent.Provider>
</LocaleProvider>
);
}
+1 -4
View File
@@ -11,9 +11,6 @@ export function LinkI18n({ locale, href, ...props }: LinkI18nProps) {
const prefix = resolvedLocale === undefined ? '' : `/${resolvedLocale}`;
return (
<Link
href={href === undefined ? undefined : `${prefix}${href}`}
{...props}
/>
<Link href={href?.startsWith('/') ? `${prefix}${href}` : href} {...props} />
);
}
+14 -8
View File
@@ -20,11 +20,13 @@ import {
import { resolveBranchName } from '../core/blitzkit/branches';
import { homeTool, TOOLS } from '../constants/tools';
import { NavbarAccount } from './NavbarAccount';
import { LinkI18n } from './LinkI18n';
const toolsFiltered = TOOLS.filter((tool) => !('href' in tool));
const tools = [homeTool, ...toolsFiltered];
const branchName = resolveBranchName();
const isBranchNamed = branchName !== undefined;
const { locale } = Astro.params;
---
<style>
@@ -108,7 +110,8 @@ const isBranchNamed = branchName !== undefined;
<Flex className="expander" data-expanded="false" direction="column" gap="2">
<Flex justify="center">
<Flex flexGrow="1" maxWidth="1024px" p="3" align="center">
<Link
<LinkI18n
{locale}
color="gray"
highContrast
href="/"
@@ -125,7 +128,7 @@ const isBranchNamed = branchName !== undefined;
)
}
</Flex>
</Link>
</LinkI18n>
<Box flexGrow="1" />
@@ -145,7 +148,8 @@ const isBranchNamed = branchName !== undefined;
return (
<Fragment key={tool.title}>
{index > 0 && <Separator orientation="vertical" size="1" />}
<Link
<LinkI18n
{locale}
color="gray"
highContrast={selected}
size="2"
@@ -153,7 +157,7 @@ const isBranchNamed = branchName !== undefined;
underline={selected ? 'always' : 'hover'}
>
{tool.title}
</Link>
</LinkI18n>
</Fragment>
);
})
@@ -173,14 +177,15 @@ const isBranchNamed = branchName !== undefined;
<DiscordLogoIcon />
</Link>
<Link
<LinkI18n
{locale}
style={{ display: 'flex', alignContent: 'center' }}
color="gray"
href="/settings"
underline="none"
>
<GearIcon />
</Link>
</LinkI18n>
<NavbarAccount client:idle />
@@ -226,7 +231,8 @@ const isBranchNamed = branchName !== undefined;
aspectRatio: '2 / 1',
}}
>
<Link
<LinkI18n
{locale}
href={tool.id.length === 0 ? '/' : `/tools/${tool.id}`}
style={{
display: 'flex',
@@ -261,7 +267,7 @@ const isBranchNamed = branchName !== undefined;
>
<Text>{tool.title}</Text>
</Flex>
</Link>
</LinkI18n>
</Flex>
);
})
@@ -1,9 +1,11 @@
import { asset, TankType, type TankDefinition } from '@blitzkit/core';
import { Flex, Link, Text, type TextProps } from '@radix-ui/themes';
import { Flex, Text, type TextProps } from '@radix-ui/themes';
import { uniq } from 'lodash-es';
import { forwardRef, type ReactNode } from 'react';
import { useLocale } from '../../hooks/useLocale';
import { TankopediaPersistent } from '../../stores/tankopediaPersistent';
import { classIcons } from '../ClassIcon';
import { LinkI18n } from '../LinkI18n';
import { MAX_RECENTLY_VIEWED } from '../TankSearch/constants';
import './index.css';
@@ -26,6 +28,7 @@ export const TankCard = forwardRef<HTMLSpanElement, TankCardProps>(
}: TankCardProps,
ref,
) => {
const { locale } = useLocale();
const provideLink = !noLink && onSelect === undefined;
const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
const Icon = classIcons[tank.class];
@@ -60,7 +63,8 @@ export const TankCard = forwardRef<HTMLSpanElement, TankCardProps>(
}}
{...props}
>
<Link
<LinkI18n
locale={locale}
className="link"
underline="hover"
href={provideLink ? `/tools/tankopedia/${tank.id}` : '#'}
@@ -102,7 +106,7 @@ export const TankCard = forwardRef<HTMLSpanElement, TankCardProps>(
{discriminator}
</Text>
)}
</Link>
</LinkI18n>
</Text>
);
},
@@ -1,7 +1,8 @@
import { type TankDefinition, tankIcon, TankType } from '@blitzkit/core';
import { Link } from '@radix-ui/themes';
import { useLocale } from '../hooks/useLocale';
import { classIcons } from './ClassIcon';
import { ExperimentIcon } from './ExperimentIcon';
import { LinkI18n } from './LinkI18n';
import { StickyRowHeaderCell } from './StickyRowHeaderCell';
interface TankRowHeaderCellProps {
@@ -9,6 +10,7 @@ interface TankRowHeaderCellProps {
}
export function TankRowHeaderCell({ tank }: TankRowHeaderCellProps) {
const { locale } = useLocale();
const Icon = classIcons[tank.class];
return (
@@ -16,7 +18,11 @@ export function TankRowHeaderCell({ tank }: TankRowHeaderCellProps) {
width={{ initial: '144px', sm: '240px' }}
style={{ overflow: 'hidden' }}
>
<Link href={`/tools/tankopedia/${tank.id}`} tabIndex={-1}>
<LinkI18n
locale={locale}
href={`/tools/tankopedia/${tank.id}`}
tabIndex={-1}
>
<img
alt={tank.name}
draggable={false}
@@ -28,9 +34,10 @@ export function TankRowHeaderCell({ tank }: TankRowHeaderCellProps) {
objectFit: 'cover',
}}
/>
</Link>
</LinkI18n>
<Link
<LinkI18n
locale={locale}
color={
tank.type === TankType.COLLECTOR
? 'blue'
@@ -64,7 +71,7 @@ export function TankRowHeaderCell({ tank }: TankRowHeaderCellProps) {
)}
{tank.name}
</Link>
</LinkI18n>
</StickyRowHeaderCell>
);
}
@@ -1,8 +1,10 @@
import { type TankDefinition } from '@blitzkit/core';
import { useStore } from '@nanostores/react';
import { CaretRightIcon } from '@radix-ui/react-icons';
import { Button, Link, TextField } from '@radix-ui/themes';
import { Button, TextField } from '@radix-ui/themes';
import { useLocale } from '../../../hooks/useLocale';
import { $tankFilters } from '../../../stores/tankFilters';
import { LinkI18n } from '../../LinkI18n';
interface QuickLinkProps {
topResult?: TankDefinition;
@@ -10,16 +12,17 @@ interface QuickLinkProps {
export function QuickLink({ topResult }: QuickLinkProps) {
const tankFilters = useStore($tankFilters);
const { locale } = useLocale();
if (!tankFilters.search || !topResult || tankFilters.searching) return null;
return (
<TextField.Slot>
<Link href={`/tools/tankopedia/${topResult.id}`}>
<LinkI18n locale={locale} href={`/tools/tankopedia/${topResult.id}`}>
<Button variant="ghost">
{topResult.name} <CaretRightIcon />
</Button>
</Link>
</LinkI18n>
</TextField.Slot>
);
}
@@ -17,11 +17,12 @@ import {
Flex,
Heading,
IconButton,
Link,
Text,
} from '@radix-ui/themes';
import { awaitableTankDefinitions } from '../../../../core/awaitables/tankDefinitions';
import { useLocale } from '../../../../hooks/useLocale';
import { Duel } from '../../../../stores/duel';
import { LinkI18n } from '../../../LinkI18n';
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
type ModuleDefinition =
@@ -63,6 +64,8 @@ function ModuleButton({
onClick: () => void;
}) {
const isTank = unlock.type === ModuleType.VEHICLE;
const { locale } = useLocale();
const button = (
<IconButton
size="4"
@@ -132,7 +135,9 @@ function ModuleButton({
);
return isTank ? (
<Link href={`/tools/tankopedia/${unlock.id}`}>{button}</Link>
<LinkI18n locale={locale} href={`/tools/tankopedia/${unlock.id}`}>
{button}
</LinkI18n>
) : (
button
);
@@ -12,10 +12,12 @@ import { useState } from 'react';
import { awaitableModelDefinitions } from '../../../core/awaitables/modelDefinitions';
import { awaitableProvisionDefinitions } from '../../../core/awaitables/provisionDefinitions';
import { tankToDuelMember } from '../../../core/blitzkit/tankToDuelMember';
import { useLocale } from '../../../hooks/useLocale';
import { App } from '../../../stores/app';
import { Duel } from '../../../stores/duel';
import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral';
import { classIcons } from '../../ClassIcon';
import { LinkI18n } from '../../LinkI18n';
import { ScienceIcon } from '../../ScienceIcon';
import { TankSearch } from '../../TankSearch';
import { Listing } from './components/Listing';
@@ -37,24 +39,28 @@ export function MetaSection() {
const mutateDuel = Duel.useMutation();
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
const [showSwapDialog, setShowSwapDialog] = useState(false);
const { locale } = useLocale();
return (
<Flex justify="center" align="center">
<Flex direction="column" align="center" gap="6">
<Flex gap="2" wrap="wrap" justify="center" align="center">
<Link href="/tools/tankopedia">
<LinkI18n locale={locale} href="/tools/tankopedia">
<Button variant="outline">
<ChevronLeftIcon />
Back
</Button>
</Link>
</LinkI18n>
<Link href={`/tools/compare?tanks=${compareTanks.join('%2C')}`}>
<LinkI18n
locale={locale}
href={`/tools/compare?tanks=${compareTanks.join('%2C')}`}
>
<Button variant="outline">
<MixIcon />
Compare
</Button>
</Link>
</LinkI18n>
{assertSecret(import.meta.env.PUBLIC_PROMOTE_OPENTEST) === 'true' && (
<Link
@@ -1,9 +1,11 @@
import { asset, formatCompact, TIER_ROMAN_NUMERALS } from '@blitzkit/core';
import { Box, Flex, Link, Skeleton, Text } from '@radix-ui/themes';
import { Box, Flex, Skeleton, Text } from '@radix-ui/themes';
import { awaitableAverageDefinitions } from '../../../../core/awaitables/averageDefinitions';
import { awaitableTankDefinitions } from '../../../../core/awaitables/tankDefinitions';
import { useLocale } from '../../../../hooks/useLocale';
import { TankopediaEphemeral } from '../../../../stores/tankopediaEphemeral';
import type { MaybeSkeletonComponentProps } from '../../../../types/maybeSkeletonComponentProps';
import { LinkI18n } from '../../../LinkI18n';
type NodeProps = MaybeSkeletonComponentProps & {
id: number;
@@ -17,6 +19,7 @@ const [tankDefinitions, averageDefinitions] = await Promise.all([
]);
export function Node({ id, highlight, nextIds, skeleton }: NodeProps) {
const { locale } = useLocale();
const xpMultiplier = TankopediaEphemeral.use((state) => state.xpMultiplier);
const tank = tankDefinitions.tanks[id];
const nextTanks = nextIds?.map((id) => tankDefinitions.tanks[id]);
@@ -40,7 +43,8 @@ export function Node({ id, highlight, nextIds, skeleton }: NodeProps) {
averages && nextTanks ? Math.round(nextTanksXp! / averageXp!) : undefined;
return (
<Link
<LinkI18n
locale={locale}
href={`/tools/tankopedia/${id}`}
key={id}
style={{
@@ -135,6 +139,6 @@ export function Node({ id, highlight, nextIds, skeleton }: NodeProps) {
</Flex>
</Flex>
</Box>
</Link>
</LinkI18n>
);
}
@@ -1,8 +1,9 @@
---
import { assertSecret, imgur, ImgurSize } from '@blitzkit/core';
import { CaretRightIcon } from '@radix-ui/react-icons';
import { Box, Button, Code, Flex, Heading, Link, Text } from '@radix-ui/themes';
import { Box, Button, Code, Flex, Heading, Text } from '@radix-ui/themes';
import type { Tool } from '../constants/tools';
import { LinkI18n } from './LinkI18n';
interface Props {
tool: Tool;
@@ -12,6 +13,7 @@ const { tool } = Astro.props;
const disabled = tool.branches?.every(
(branch) => branch !== assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH),
);
const { locale } = Astro.params;
---
<style>
@@ -54,7 +56,8 @@ const disabled = tool.branches?.every(
flexGrow={tool.significant ? undefined : '1'}
flexBasis={tool.significant ? undefined : { initial: undefined, sm: '0' }}
>
<Link
<LinkI18n
{locale}
className="link"
underline="none"
href={disabled ? '#' : (tool.href ?? `/tools/${tool.id}`)}
@@ -135,5 +138,5 @@ const disabled = tool.branches?.every(
)
}
</Flex>
</Link>
</LinkI18n>
</Flex>
+28
View File
@@ -0,0 +1,28 @@
import { createContext, useContext, type ReactNode } from 'react';
const LocaleContext = createContext<{ locale: string | undefined } | null>(
null,
);
interface LocaleProviderProps {
locale: string | undefined;
children: ReactNode;
}
export function LocaleProvider({ locale, children }: LocaleProviderProps) {
return (
<LocaleContext.Provider value={{ locale }}>
{children}
</LocaleContext.Provider>
);
}
export function useLocale() {
const context = useContext(LocaleContext);
if (!context) {
throw new Error('useLocale must be used within a LocaleProvider');
}
return { locale: context.locale };
}
+5 -2
View File
@@ -1,8 +1,11 @@
---
import { DiscordLogoIcon, HomeIcon } from '@radix-ui/react-icons';
import { Button, Flex, Heading, Link, Text } from '@radix-ui/themes';
import { LinkI18n } from '../components/LinkI18n';
import { PageWrapper } from '../components/PageWrapper';
import BaseLayout from '../layouts/BaseLayout.astro';
const { locale } = Astro.params;
---
<BaseLayout>
@@ -12,11 +15,11 @@ import BaseLayout from '../layouts/BaseLayout.astro';
<Text color="gray">Where would you like to go?</Text>
<Flex mt="4" gap="2">
<Link href="/">
<LinkI18n {locale} href="/">
<Button>
<HomeIcon /> Home
</Button>
</Link>
</LinkI18n>
<Link href="https://discord.gg/nDt7AjGJQH">
<Button variant="outline">
<DiscordLogoIcon /> Discord
@@ -1,7 +1,8 @@
---
import { MagicWandIcon, StarFilledIcon } from '@radix-ui/react-icons';
import { Flex, Heading, Link } from '@radix-ui/themes';
import { Flex, Heading } from '@radix-ui/themes';
import { compareVersions } from 'compare-versions';
import { LinkI18n } from '../../../../components/LinkI18n';
import { PageWrapper } from '../../../../components/PageWrapper';
import BaseLayout from '../../../../layouts/BaseLayout.astro';
@@ -16,6 +17,7 @@ const versions = Object.keys(
.map((file) => file.replace(ROOT, '').replace('.md', ''))
.sort(compareVersions)
.reverse();
const { locale } = Astro.params;
---
<title>BlitzKit Patches</title>
@@ -31,7 +33,8 @@ const versions = Object.keys(
const isMajor = split[2] === 0;
return (
<Link
<LinkI18n
{locale}
size="5"
href={`/docs/changelogs/${version}`}
mb={isMajor ? '6' : '0'}
@@ -41,7 +44,7 @@ const versions = Object.keys(
{isMajor && <StarFilledIcon />}
{version}
</Flex>
</Link>
</LinkI18n>
);
})
}
@@ -21,6 +21,7 @@ import {
import BaseLayout from '../../layouts/BaseLayout.astro';
const branch = assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH);
const { locale } = Astro.params;
export const getStaticPaths = (() => {
return [
@@ -47,7 +48,7 @@ export const getStaticPaths = (() => {
<Flex maxWidth="64rem" flexGrow="1" gap="4" direction="column">
<ToolCard tool={tankopediaTool} />
<HomePageHotTanks />
<HomePageHotTanks {locale} />
<Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
{/* <ToolCard tool={playerStatsTool} /> */}
@@ -2,12 +2,14 @@ import { imgur, ImgurSize } from '@blitzkit/core';
import { Box, Flex, Link, Text } from '@radix-ui/themes';
import { capitalize } from 'lodash-es';
import { PreviewWrapper } from '../../../../components/Embeds/PreviewWrapper';
import { LinkI18n } from '../../../../components/LinkI18n';
import { PageWrapper } from '../../../../components/PageWrapper';
import {
embedConfigurations,
extractEmbedConfigDefaults,
} from '../../../../constants/embeds';
import { Var } from '../../../../core/radix/var';
import { useLocale } from '../../../../hooks/useLocale';
import { App } from '../../../../stores/app';
import { EmbedState } from '../../../../stores/embedState';
@@ -26,6 +28,8 @@ function Content() {
// expires: 0,
// });
const { locale } = useLocale();
return (
<PageWrapper color="red">
{/* {!wargaming && (
@@ -61,7 +65,8 @@ function Content() {
key={embed}
data={extractEmbedConfigDefaults(config)}
>
<Link
<LinkI18n
locale={locale}
href={`/tools/embed/${embed}`}
color="gray"
highContrast
@@ -101,7 +106,7 @@ function Content() {
/>
</Box>
</Flex>
</Link>
</LinkI18n>
</EmbedState.Provider>
))}
</Flex>
@@ -12,6 +12,7 @@ import { VideoSection } from '../../../../../components/Tankopedia/VideoSection'
import { awaitableModelDefinitions } from '../../../../../core/awaitables/modelDefinitions';
import { awaitableProvisionDefinitions } from '../../../../../core/awaitables/provisionDefinitions';
import { awaitableTankDefinitions } from '../../../../../core/awaitables/tankDefinitions';
import { LocaleProvider } from '../../../../../hooks/useLocale';
import { App } from '../../../../../stores/app';
import { Duel } from '../../../../../stores/duel';
import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral';
@@ -20,6 +21,7 @@ import type { MaybeSkeletonComponentProps } from '../../../../../types/maybeSkel
type PageProps = MaybeSkeletonComponentProps & {
id: number;
locale: string | undefined;
};
const [tankDefinitions, provisionDefinitions, modelDefinitions] =
@@ -29,33 +31,35 @@ const [tankDefinitions, provisionDefinitions, modelDefinitions] =
awaitableModelDefinitions,
]);
export function Page({ id, skeleton }: PageProps) {
export function Page({ id, skeleton, locale }: PageProps) {
const tank = tankDefinitions.tanks[id];
const model = modelDefinitions.models[id];
return (
<TankopediaEphemeral.Provider data={model}>
<App.Provider>
<TankopediaPersistent.Provider>
<Duel.Provider
data={{ tank, provisionDefinitions: provisionDefinitions }}
>
<PageWrapper p="0" maxWidth="unset" color="purple" gap="9" pb="9">
<HeroSection skeleton={skeleton} />
<CalloutsSection />
<MetaSection />
{tank.type === TankType.RESEARCHABLE && !tank.deprecated && (
<TechTreeSection skeleton={skeleton} />
)}
<CharacteristicsSection />
<GameModeSection />
<TankopediaCharts />
<VideoSection skeleton={skeleton} />
<HistorySection />
</PageWrapper>
</Duel.Provider>
</TankopediaPersistent.Provider>
</App.Provider>
</TankopediaEphemeral.Provider>
<LocaleProvider locale={locale}>
<TankopediaEphemeral.Provider data={model}>
<App.Provider>
<TankopediaPersistent.Provider>
<Duel.Provider
data={{ tank, provisionDefinitions: provisionDefinitions }}
>
<PageWrapper p="0" maxWidth="unset" color="purple" gap="9" pb="9">
<HeroSection skeleton={skeleton} />
<CalloutsSection />
<MetaSection />
{tank.type === TankType.RESEARCHABLE && !tank.deprecated && (
<TechTreeSection skeleton={skeleton} />
)}
<CharacteristicsSection />
<GameModeSection />
<TankopediaCharts />
<VideoSection skeleton={skeleton} />
<HistorySection />
</PageWrapper>
</Duel.Provider>
</TankopediaPersistent.Provider>
</App.Provider>
</TankopediaEphemeral.Provider>
</LocaleProvider>
);
}
@@ -31,7 +31,7 @@ export const getStaticPaths = (async () => {
.flat();
}) satisfies GetStaticPaths;
const { id } = Astro.params;
const { id, locale } = Astro.params;
const tankDefinitions = await fetchTankDefinitions();
const skillDefinitions = await fetchSkillDefinitions();
@@ -96,7 +96,7 @@ const description = `${
<meta name="twitter:image:src" content={icon} />
<BaseLayout>
<Page id={id} client:only="react">
<Page id={id} skeleton slot="fallback" />
<Page {locale} id={id} client:only="react">
<Page {locale} id={id} skeleton slot="fallback" />
</Page>
</BaseLayout>