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