mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-30 14:09:51 +01:00
feat: strings
This commit is contained in:
1 parent
a2f1593a0e
commit
179ce62a55
17 files changed
+400
-35
No files matched your search
@@ -1,4 +1,11 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"include": ["src/**/*", "../core/src/blitzkit/supportedLocales.ts", "../i18n/src/unwrapper.ts"]
|
"include": [
|
||||||
|
"src/**/*",
|
||||||
|
"../core/src/blitzkit/supportedLocales.ts",
|
||||||
|
"../i18n/src/unwrapper.ts"
|
||||||
|
],
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "../../"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -46,4 +46,5 @@ export * from './gallery';
|
|||||||
export * from './metaSortTank';
|
export * from './metaSortTank';
|
||||||
export * from './popularTanks';
|
export * from './popularTanks';
|
||||||
export * from './romanize';
|
export * from './romanize';
|
||||||
|
export * from './slugify';
|
||||||
export * from './youtubers';
|
export * from './youtubers';
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { deburr } from 'lodash-es';
|
||||||
|
|
||||||
|
const nonAlphanumericRegex = /[^a-z0-9]/g;
|
||||||
|
const multipleDashesRegex = /--+/g;
|
||||||
|
const trailingDashRegex = /-$/g;
|
||||||
|
const leadingDashRegex = /^-/g;
|
||||||
|
|
||||||
|
export function slugify(name: string) {
|
||||||
|
let slug = deburr(name).toLowerCase();
|
||||||
|
slug = slug.replaceAll(nonAlphanumericRegex, '-');
|
||||||
|
slug = slug.replaceAll(multipleDashesRegex, '-');
|
||||||
|
slug = slug.replaceAll(trailingDashRegex, '');
|
||||||
|
slug = slug.replaceAll(leadingDashRegex, '');
|
||||||
|
|
||||||
|
return slug;
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"include": ["src/**/*", "../i18n/src/strings.ts"]
|
"include": ["src/**/*", "../i18n/src/strings.ts"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "../../"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
ResearchCost,
|
ResearchCost,
|
||||||
ShellType,
|
ShellType,
|
||||||
SkillDefinitions,
|
SkillDefinitions,
|
||||||
|
slugify,
|
||||||
TankClass,
|
TankClass,
|
||||||
TankDefinitions,
|
TankDefinitions,
|
||||||
TankPrice,
|
TankPrice,
|
||||||
@@ -37,7 +38,6 @@ import {
|
|||||||
SUPPORTED_LOCALES,
|
SUPPORTED_LOCALES,
|
||||||
} from '@blitzkit/i18n';
|
} from '@blitzkit/i18n';
|
||||||
import { readdir } from 'fs/promises';
|
import { readdir } from 'fs/promises';
|
||||||
import { deburr } from 'lodash-es';
|
|
||||||
import { parse as parsePath } from 'path';
|
import { parse as parsePath } from 'path';
|
||||||
import { Vector3Tuple } from 'three';
|
import { Vector3Tuple } from 'three';
|
||||||
import { parse as parseYaml } from 'yaml';
|
import { parse as parseYaml } from 'yaml';
|
||||||
@@ -49,11 +49,6 @@ import { DATA } from './constants';
|
|||||||
import { Avatar } from './skillIcons';
|
import { Avatar } from './skillIcons';
|
||||||
import { TankParameters } from './tankIcons';
|
import { TankParameters } from './tankIcons';
|
||||||
|
|
||||||
const nonAlphanumericRegex = /[^a-z0-9]/g;
|
|
||||||
const multipleDashesRegex = /--+/g;
|
|
||||||
const trailingDashRegex = /-$/g;
|
|
||||||
const leadingDashRegex = /^-/g;
|
|
||||||
|
|
||||||
const nationSlugDiscriminators = {
|
const nationSlugDiscriminators = {
|
||||||
china: 'cn',
|
china: 'cn',
|
||||||
european: 'eu',
|
european: 'eu',
|
||||||
@@ -740,12 +735,7 @@ export async function definitions() {
|
|||||||
? getString(tank.shortUserString)
|
? getString(tank.shortUserString)
|
||||||
: undefined) ?? getString(tank.userString)
|
: undefined) ?? getString(tank.userString)
|
||||||
).locales.en;
|
).locales.en;
|
||||||
|
const slug = slugify(name);
|
||||||
let slug = deburr(name).toLowerCase();
|
|
||||||
slug = slug.replaceAll(nonAlphanumericRegex, '-');
|
|
||||||
slug = slug.replaceAll(multipleDashesRegex, '-');
|
|
||||||
slug = slug.replaceAll(trailingDashRegex, '');
|
|
||||||
slug = slug.replaceAll(leadingDashRegex, '');
|
|
||||||
|
|
||||||
idToNation[tankId] = nation;
|
idToNation[tankId] = nation;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"include": ["src/**/*"]
|
"include": ["src/**/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "../../"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,29 @@
|
|||||||
import { TankClass } from '@blitzkit/core';
|
import { TankClass as TankClass_dava } from '@blitzkit/core';
|
||||||
|
import { TankClass } from '@protos/blitz_static_tank_component';
|
||||||
|
import { QuestionMarkIcon } from '@radix-ui/react-icons';
|
||||||
import type { ComponentProps, ReactNode } from 'react';
|
import type { ComponentProps, ReactNode } from 'react';
|
||||||
import { ClassHeavy } from './components/ClassHeavy';
|
import { ClassHeavy } from './components/ClassHeavy';
|
||||||
import { ClassLight } from './components/ClassLight';
|
import { ClassLight } from './components/ClassLight';
|
||||||
import { ClassMedium } from './components/ClassMedium';
|
import { ClassMedium } from './components/ClassMedium';
|
||||||
import { ClassTankDestroyer } from './components/ClassTankDestroyer';
|
import { ClassTankDestroyer } from './components/ClassTankDestroyer';
|
||||||
|
|
||||||
export const classIcons: Record<
|
export const classIcons_ue: Record<
|
||||||
TankClass,
|
TankClass,
|
||||||
|
((props: ComponentProps<'svg'>) => ReactNode) | typeof QuestionMarkIcon
|
||||||
|
> = {
|
||||||
|
[TankClass.TANK_CLASS_UNSPECIFIED]: QuestionMarkIcon,
|
||||||
|
[TankClass.TANK_CLASS_TANK_DESTROYER]: ClassTankDestroyer,
|
||||||
|
[TankClass.TANK_CLASS_HEAVY]: ClassHeavy,
|
||||||
|
[TankClass.TANK_CLASS_LIGHT]: ClassLight,
|
||||||
|
[TankClass.TANK_CLASS_MEDIUM]: ClassMedium,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const classIcons: Record<
|
||||||
|
TankClass_dava,
|
||||||
(props: ComponentProps<'svg'>) => ReactNode
|
(props: ComponentProps<'svg'>) => ReactNode
|
||||||
> = {
|
> = {
|
||||||
[TankClass.TANK_DESTROYER]: ClassTankDestroyer,
|
[TankClass_dava.TANK_CLASS_TANK_DESTROYER]: ClassTankDestroyer,
|
||||||
[TankClass.HEAVY]: ClassHeavy,
|
[TankClass_dava.TANK_CLASS_HEAVY]: ClassHeavy,
|
||||||
[TankClass.LIGHT]: ClassLight,
|
[TankClass_dava.TANK_CLASS_LIGHT]: ClassLight,
|
||||||
[TankClass.MEDIUM]: ClassMedium,
|
[TankClass_dava.TANK_CLASS_MEDIUM]: ClassMedium,
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
import {
|
||||||
|
Nation,
|
||||||
|
TankClass,
|
||||||
|
TankType,
|
||||||
|
Tier,
|
||||||
|
} from '@protos/blitz_static_tank_component';
|
||||||
|
import { Box, Code, Flex } from '@radix-ui/themes';
|
||||||
|
import { asset } from 'packages/core/src';
|
||||||
|
import { Var } from '../../core/radix/var';
|
||||||
|
import { useLocale } from '../../hooks/useLocale';
|
||||||
|
import { App } from '../../stores/app';
|
||||||
|
import { TankopediaEphemeral_ue } from '../../stores/tankopediaEphemeral_ue';
|
||||||
|
import { classIcons_ue } from '../ClassIcon';
|
||||||
|
import { Listing } from '../Tankopedia/MetaSection/components/Listing';
|
||||||
|
|
||||||
|
const NATIONAL_BANNER_POSITION_OVERRIDES: Record<string, string> = {
|
||||||
|
germany: '50% 35%',
|
||||||
|
france: '50% 35%',
|
||||||
|
other: '50% 35%',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function MetaSection() {
|
||||||
|
const developerMode = App.useDeferred((state) => state.developerMode, false);
|
||||||
|
const tank = TankopediaEphemeral_ue.use((state) => state.tank);
|
||||||
|
const ClassIcon = classIcons_ue[tank.tank_class];
|
||||||
|
const { locale, strings } = useLocale();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex justify="center" mt="-9">
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
background: `url(/assets/images/national-wallpapers/${tank.nation}.jpg)`,
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundSize: 'cover',
|
||||||
|
backgroundPosition:
|
||||||
|
NATIONAL_BANNER_POSITION_OVERRIDES[tank.nation] ?? 'center',
|
||||||
|
}}
|
||||||
|
flexGrow="1"
|
||||||
|
maxWidth="120rem"
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
background: `url(${asset(`flags/scratched/${tank.nation}.webp`)})`,
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundSize: 'min(53rem, 80vw)',
|
||||||
|
backgroundPosition: '-8rem 50%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
justify="center"
|
||||||
|
align="center"
|
||||||
|
py="6rem"
|
||||||
|
style={{
|
||||||
|
background: `linear-gradient(${Var('black-a8')}, ${Var('black-a8')}, ${Var('gray-1')})`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex direction="column" align="center" gap="6">
|
||||||
|
<Flex
|
||||||
|
gap={{ initial: '2', sm: '8' }}
|
||||||
|
direction={{ initial: 'column', sm: 'row' }}
|
||||||
|
>
|
||||||
|
<Flex direction="column" width="100%" gap="2">
|
||||||
|
<Listing label={strings.website.tools.tankopedia.meta.nation}>
|
||||||
|
<Flex align="center" gap="1">
|
||||||
|
<img
|
||||||
|
style={{ width: '1em', height: '1em' }}
|
||||||
|
alt={Nation[tank.nation]}
|
||||||
|
src={asset(`flags/circle/${tank.nation}.webp`)}
|
||||||
|
/>
|
||||||
|
{Nation[tank.nation]}
|
||||||
|
</Flex>
|
||||||
|
</Listing>
|
||||||
|
<Listing label={strings.website.tools.tankopedia.meta.class}>
|
||||||
|
<Flex align="center" gap="1">
|
||||||
|
<ClassIcon width="1em" height="1em" />
|
||||||
|
{TankClass[tank.tank_class]}
|
||||||
|
</Flex>
|
||||||
|
</Listing>
|
||||||
|
<Listing label={strings.website.tools.tankopedia.meta.tier}>
|
||||||
|
{Tier[tank.tier]}
|
||||||
|
</Listing>
|
||||||
|
<Listing
|
||||||
|
label={strings.website.tools.tankopedia.meta.type}
|
||||||
|
color={
|
||||||
|
tank.tank_type === TankType.TANK_TYPE_COLLECTIBLE
|
||||||
|
? 'blue'
|
||||||
|
: tank.tank_type === TankType.TANK_TYPE_PREMIUM
|
||||||
|
? 'amber'
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{TankType[tank.tank_type]}
|
||||||
|
</Listing>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex direction="column" width="100%" gap="2">
|
||||||
|
{developerMode && (
|
||||||
|
<Listing
|
||||||
|
label={strings.website.tools.tankopedia.meta.dev_id}
|
||||||
|
>
|
||||||
|
<Code>TANK_ID</Code>
|
||||||
|
</Listing>
|
||||||
|
)}
|
||||||
|
{tank.tank_type === TankType.TANK_TYPE_PREMIUM && (
|
||||||
|
<Listing
|
||||||
|
label={strings.website.tools.tankopedia.meta.purchase}
|
||||||
|
>
|
||||||
|
<Flex align="center" gap="1">
|
||||||
|
{tank.price.value / 400}
|
||||||
|
<img
|
||||||
|
style={{ width: '1em', height: '1em' }}
|
||||||
|
alt="gold"
|
||||||
|
src={asset('icons/currencies/gold.webp')}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Listing>
|
||||||
|
)}
|
||||||
|
<Listing
|
||||||
|
label={
|
||||||
|
protagonist.type === TankType.RESEARCHABLE
|
||||||
|
? strings.website.tools.tankopedia.meta.purchase
|
||||||
|
: strings.website.tools.tankopedia.meta.restoration
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Flex align="center" gap="1">
|
||||||
|
{protagonist.price.value.toLocaleString(locale)}
|
||||||
|
<img
|
||||||
|
style={{ width: '1em', height: '1em' }}
|
||||||
|
alt={TankPriceType[protagonist.price.type]}
|
||||||
|
src={asset(
|
||||||
|
`icons/currencies/${
|
||||||
|
protagonist.price.type === TankPriceType.GOLD
|
||||||
|
? 'gold'
|
||||||
|
: 'silver'
|
||||||
|
}.webp`,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Listing>
|
||||||
|
<Listing label={strings.website.tools.tankopedia.meta.sale}>
|
||||||
|
<Flex align="center" gap="1">
|
||||||
|
{(protagonist.price.value / 2).toLocaleString(locale)}
|
||||||
|
<img
|
||||||
|
style={{ width: '1em', height: '1em' }}
|
||||||
|
alt={TankPriceType[protagonist.price.type]}
|
||||||
|
src={asset(
|
||||||
|
`icons/currencies/${
|
||||||
|
protagonist.price.type === TankPriceType.GOLD
|
||||||
|
? 'gold'
|
||||||
|
: 'silver'
|
||||||
|
}.webp`,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Listing>
|
||||||
|
{protagonist.research_cost && (
|
||||||
|
<Listing
|
||||||
|
label={strings.website.tools.tankopedia.meta.research}
|
||||||
|
>
|
||||||
|
<Flex align="center" gap="1">
|
||||||
|
{(
|
||||||
|
protagonist.research_cost.research_cost_type!
|
||||||
|
.value as number
|
||||||
|
).toLocaleString(locale)}
|
||||||
|
<img
|
||||||
|
style={{ width: '1em', height: '1em' }}
|
||||||
|
alt="xp"
|
||||||
|
src={asset('icons/currencies/xp.webp')}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Listing>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { DEFAULT_LOCALE, STRINGS, type SupportedLocale } from '@blitzkit/i18n';
|
import { STRINGS, type SupportedLocale } from '@blitzkit/i18n';
|
||||||
|
|
||||||
export function getStrings(locale: string = DEFAULT_LOCALE) {
|
export function getStrings(locale: string) {
|
||||||
if (locale in STRINGS) return STRINGS[locale as SupportedLocale];
|
if (locale in STRINGS) return STRINGS[locale as SupportedLocale];
|
||||||
throw new Error(`Unsupported locale: ${locale}`);
|
throw new Error(`Unsupported locale: ${locale}`);
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
import { AstroSeo } from '@astrolib/seo';
|
import { AstroSeo } from '@astrolib/seo';
|
||||||
import { assertSecret } from '@blitzkit/core';
|
import { assertSecret } from '@blitzkit/core';
|
||||||
import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from '@blitzkit/i18n';
|
import { DEFAULT_LOCALE } from '@blitzkit/i18n';
|
||||||
|
import locales from '@blitzkit/i18n/locales.json';
|
||||||
import { literals } from '@blitzkit/i18n/src/literals';
|
import { literals } from '@blitzkit/i18n/src/literals';
|
||||||
import { Box, Flex, Heading, Link } from '@radix-ui/themes';
|
import { Box, Flex, Heading, Link } from '@radix-ui/themes';
|
||||||
import type { GetStaticPaths } from 'astro';
|
import type { GetStaticPaths } from 'astro';
|
||||||
@@ -25,15 +26,20 @@ import BaseLayout from '../../layouts/BaseLayout.astro';
|
|||||||
|
|
||||||
const PUBLIC_ASSET_BRANCH = assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH);
|
const PUBLIC_ASSET_BRANCH = assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH);
|
||||||
const locale = Astro.params.locale ?? DEFAULT_LOCALE;
|
const locale = Astro.params.locale ?? DEFAULT_LOCALE;
|
||||||
const strings = getStrings(Astro.params.locale);
|
const strings = getStrings(Astro.props.locale);
|
||||||
|
|
||||||
export const getStaticPaths = (() => {
|
export const getStaticPaths = (() => {
|
||||||
return [
|
// return [
|
||||||
...SUPPORTED_LOCALES.filter((locale) => locale !== DEFAULT_LOCALE).map(
|
// ...SUPPORTED_LOCALES.filter((locale) => locale !== DEFAULT_LOCALE).map(
|
||||||
(locale) => ({ params: { locale } }),
|
// (locale) => ({ params: { locale } }),
|
||||||
),
|
// ),
|
||||||
{ params: { locale: undefined } },
|
// { params: { locale: undefined } },
|
||||||
];
|
// ];
|
||||||
|
|
||||||
|
return locales.supported.map(({ locale, blitz }) => ({
|
||||||
|
params: { locale: locale === locales.default ? undefined : locale },
|
||||||
|
props: { locale, blitzLocale: blitz ?? locale },
|
||||||
|
}));
|
||||||
}) satisfies GetStaticPaths;
|
}) satisfies GetStaticPaths;
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -79,7 +85,9 @@ export const getStaticPaths = (() => {
|
|||||||
>
|
>
|
||||||
{literals(strings.website.home.help_translate, [
|
{literals(strings.website.home.help_translate, [
|
||||||
'BlitzKit',
|
'BlitzKit',
|
||||||
strings.common.locales[locale],
|
strings.common.locales[
|
||||||
|
locale as keyof typeof strings.common.locales
|
||||||
|
],
|
||||||
])}
|
])}
|
||||||
</Link>
|
</Link>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import type { CompensationComponent } from '@protos/blitz_static_compensation_component';
|
||||||
|
import { type TankCatalogComponent } from '@protos/blitz_static_tank_component';
|
||||||
|
import { PageWrapper } from 'packages/website/src/components/PageWrapper';
|
||||||
|
import { MetaSection } from 'packages/website/src/components/Tankopedia_ue/MetaSection';
|
||||||
|
import {
|
||||||
|
LocaleProvider,
|
||||||
|
type LocaleAcceptorProps,
|
||||||
|
} from 'packages/website/src/hooks/useLocale';
|
||||||
|
import { App } from 'packages/website/src/stores/app';
|
||||||
|
import { TankopediaEphemeral_ue } from 'packages/website/src/stores/tankopediaEphemeral_ue';
|
||||||
|
|
||||||
|
interface PageProps extends LocaleAcceptorProps {
|
||||||
|
tank: TankCatalogComponent;
|
||||||
|
compensation: CompensationComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Page({ tank, compensation, locale }: PageProps) {
|
||||||
|
return (
|
||||||
|
<LocaleProvider locale={locale}>
|
||||||
|
<App.Provider>
|
||||||
|
<TankopediaEphemeral_ue.Provider data={{ tank, compensation }}>
|
||||||
|
<PageWrapper p="0" maxWidth="unset" color="purple" gap="9" pb="9">
|
||||||
|
<MetaSection />
|
||||||
|
</PageWrapper>
|
||||||
|
</TankopediaEphemeral_ue.Provider>
|
||||||
|
</App.Provider>
|
||||||
|
</LocaleProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
import type {
|
||||||
|
CatalogItemsComponent,
|
||||||
|
TankCatalogComponent,
|
||||||
|
} from '@blitzkit/closed/src/unreal/protos';
|
||||||
|
import type { GetStaticPaths } from 'astro';
|
||||||
|
import { metadata } from '../../../../core/blitz/metadata';
|
||||||
|
import BaseLayout from '../../../../layouts/BaseLayout.astro';
|
||||||
|
import { getStaticPaths as parentGetStaticPaths } from '../index.astro';
|
||||||
|
import { Page } from './_index';
|
||||||
|
|
||||||
|
export const getStaticPaths = (async () => {
|
||||||
|
const tanks = await metadata
|
||||||
|
.get('CatalogItemsGroupEntity.all_tanks')
|
||||||
|
.then((components) =>
|
||||||
|
components.get<CatalogItemsComponent>('catalogItemsGroupComponent'),
|
||||||
|
);
|
||||||
|
const parentPaths = parentGetStaticPaths();
|
||||||
|
|
||||||
|
return tanks.catalog_items
|
||||||
|
.map((item) => {
|
||||||
|
const id = item.replace('TankEntity.', '');
|
||||||
|
|
||||||
|
return parentPaths.map((parent) => ({
|
||||||
|
params: { ...parent.params, id },
|
||||||
|
props: { item },
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
.flat();
|
||||||
|
}) satisfies GetStaticPaths;
|
||||||
|
|
||||||
|
const { id, locale } = Astro.params;
|
||||||
|
const { item } = Astro.props;
|
||||||
|
const tank = await metadata
|
||||||
|
.get(item)
|
||||||
|
.then((components) =>
|
||||||
|
components.get<TankCatalogComponent>('tankCatalogComponent'),
|
||||||
|
);
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout>
|
||||||
|
<Page client:load {locale} {tank} />
|
||||||
|
</BaseLayout>
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
import { slugify } from '@blitzkit/core';
|
||||||
|
import locales from '@blitzkit/i18n/locales.json';
|
||||||
|
import type { CatalogItemsComponent } from '@protos/blitz_static_catalog_items_group_component';
|
||||||
|
import { TankCatalogComponent } from '@protos/blitz_static_tank_component';
|
||||||
|
import { metadata } from '../../../core/blitz/metadata';
|
||||||
|
|
||||||
|
export { getStaticPaths } from '../index.astro';
|
||||||
|
|
||||||
|
const { blitzLocale } = Astro.props;
|
||||||
|
const allTanks = await metadata
|
||||||
|
.get('CatalogItemsGroupEntity.all_tanks')
|
||||||
|
.then((components) =>
|
||||||
|
components.get<CatalogItemsComponent>('catalogItemsGroupComponent'),
|
||||||
|
);
|
||||||
|
const gameStrings = await metadata
|
||||||
|
.strings(blitzLocale)
|
||||||
|
.then((strings) => strings.subset(['TankEntity']));
|
||||||
|
const gameStringsDefault = await metadata
|
||||||
|
.strings(locales.default)
|
||||||
|
.then((strings) => strings.subset(['TankEntity']));
|
||||||
|
const tanks: { tank: TankCatalogComponent; slug: string; id: string }[] = [];
|
||||||
|
|
||||||
|
for (const tankComponentId of allTanks.catalog_items) {
|
||||||
|
const tank = await metadata.get(tankComponentId).then((components) => {
|
||||||
|
return components.get<TankCatalogComponent>('tankCatalogComponent');
|
||||||
|
});
|
||||||
|
const nameEn = gameStringsDefault[tank.name!.value];
|
||||||
|
const slug = slugify(nameEn);
|
||||||
|
|
||||||
|
tanks.push({ tank, slug, id: tankComponentId });
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
{
|
||||||
|
tanks.map(({ tank, slug, id }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<a href={`/tanks-ue/${slug}`}>
|
||||||
|
{gameStrings[tank.name!.value] ?? `MISSING NAME (${id})`}
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import type { CompensationComponent } from '@protos/blitz_static_compensation_component';
|
||||||
|
import type { TankCatalogComponent } from '@protos/blitz_static_tank_component';
|
||||||
|
import { create } from 'zustand';
|
||||||
|
import { subscribeWithSelector } from 'zustand/middleware';
|
||||||
|
import { createContextualStore } from '../core/zustand/createContextualStore';
|
||||||
|
|
||||||
|
interface TankopediaEphemeral_ue {
|
||||||
|
tank: TankCatalogComponent;
|
||||||
|
compensation: CompensationComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TankopediaEphemeral_ue = createContextualStore(
|
||||||
|
(data: TankopediaEphemeral_ue) => {
|
||||||
|
return create<TankopediaEphemeral_ue>()(
|
||||||
|
subscribeWithSelector<TankopediaEphemeral_ue>(() => data),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"jsxImportSource": "react",
|
"jsxImportSource": "react",
|
||||||
"types": ["vite/client"]
|
"types": ["vite/client"],
|
||||||
|
"baseUrl": "../../"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Submodule submodules/blitzkit-closed updated: 6ee56809b8...25f8838ba5.
+7
-1
@@ -14,11 +14,17 @@
|
|||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
|
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "next"
|
"name": "next"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@protos/*": ["submodules/blitzkit-closed/src/unreal/protos/*"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules/**/*", "dist", ".next"]
|
"exclude": ["node_modules/**/*", "dist", ".next"]
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user