From 5a65fee1d1de98cab645e03205def3260f32f20c Mon Sep 17 00:00:00 2001
From: tresabhi <43380238+tresabhi@users.noreply.github.com>
Date: Tue, 7 Jan 2025 13:50:06 -0600
Subject: [PATCH] feat: translate tank search
---
packages/core/lang/en.json | 81 +++-
.../src/components/Compare/Controls.tsx | 18 +-
.../TankSearch/components/SearchBar.tsx | 4 +-
.../components/TankSearch/components/Sort.tsx | 366 +++++-------------
.../src/components/TankSearch/index.tsx | 24 +-
.../[...locale]/tools/compare/_index.tsx | 52 ++-
.../[...locale]/tools/compare/index.astro | 4 +-
.../stores/tankopediaPersistent/constants.ts | 33 +-
.../src/stores/tankopediaPersistent/index.ts | 4 +-
9 files changed, 231 insertions(+), 355 deletions(-)
diff --git a/packages/core/lang/en.json b/packages/core/lang/en.json
index e3b74f683..6cea62945 100644
--- a/packages/core/lang/en.json
+++ b/packages/core/lang/en.json
@@ -716,6 +716,68 @@
"common": {
"copy_button": {
"copied": "Copied!"
+ },
+
+ "tank_search": {
+ "search_bar_hint": "Search tanks...",
+ "recent": "Recently viewed",
+ "select_all": "Select all",
+ "count_singular": "1 tank",
+ "count_plural": "%s1 tanks",
+ "sorting_by": "Sorting by %s1",
+ "sort": {
+ "meta.none": "none",
+ "survivability.health": "health",
+ "survivability.viewRange": "view range",
+ "survivability.camouflageStill": "camouflage still",
+ "survivability.camouflageMoving": "camouflage moving",
+ "survivability.camouflageShooting": "camouflage shooting",
+ "survivability.volume": "volume",
+ "survivability.length": "length",
+ "fire.dpm": "standard DPM",
+ "fire.dpmPremium": "premium DPM",
+ "fire.reload": "reload",
+ "fire.caliber": "caliber",
+ "fire.standardPenetration": "standard penetration",
+ "fire.premiumPenetration": "premium penetration",
+ "fire.damage": "damage",
+ "fire.moduleDamage": "module damage",
+ "fire.shellVelocity": "shell velocity",
+ "fire.shellRange": "shell range",
+ "fire.shellCapacity": "shell capacity",
+ "fire.aimTime": "aim time",
+ "fire.dispersionStill": "dispersion still",
+ "fire.dispersionMoving": "dispersion moving",
+ "fire.gunDepression": "gun depression",
+ "fire.gunElevation": "gun elevation",
+ "maneuverability.forwardsSpeed": "forwards speed",
+ "maneuverability.backwardsSpeed": "backwards speed",
+ "maneuverability.power": "power",
+ "maneuverability.powerToWeight": "power to weight",
+ "maneuverability.weight": "weight",
+ "maneuverability.traverseSpeed": "traverse speed"
+ },
+ "sort_dropdown": {
+ "label": "Sort",
+ "groups": {
+ "sort": {
+ "no_sort": "No sort",
+ "label": "Sort by",
+ "fire": "Fire",
+ "maneuverability": "Maneuverability",
+ "survivability": "Survivability"
+ },
+ "direction": {
+ "label": "Direction",
+ "ascending": "Ascending",
+ "descending": "Descending"
+ }
+ }
+ }
+ },
+
+ "warnings": {
+ "test": "Tanks in testing are subject to change and may not represent the final product."
}
},
@@ -743,7 +805,24 @@
"name": "Compare",
"button": "Compare tanks",
"description": "Compare tank statistics",
- "seo_description": "Compare tanks statistics and loadouts in World of Tanks Blitz"
+ "seo_description": "Compare tanks statistics and loadouts in World of Tanks Blitz",
+ "actions": {
+ "add": {
+ "button": "Add",
+ "title": "Add tanks",
+ "description": "Select tanks to add to comparison"
+ },
+ "clear": "Clear",
+ "deltas": {
+ "none": "No deltas",
+ "percentage": "Percentage",
+ "absolute": "Absolute"
+ }
+ },
+ "no_tanks": {
+ "title": "No tanks selected",
+ "body": "Press the Add button to get started"
+ }
},
"performance": {
"name": "Performance",
diff --git a/packages/website/src/components/Compare/Controls.tsx b/packages/website/src/components/Compare/Controls.tsx
index 50edd5113..b17f8745e 100644
--- a/packages/website/src/components/Compare/Controls.tsx
+++ b/packages/website/src/components/Compare/Controls.tsx
@@ -2,6 +2,7 @@ import { PlusIcon, TrashIcon } from '@radix-ui/react-icons';
import { Button, Dialog, Flex, SegmentedControl } from '@radix-ui/themes';
import { awaitableProvisionDefinitions } from '../../core/awaitables/provisionDefinitions';
import { tankToCompareMember } from '../../core/blitzkit/tankToCompareMember';
+import { useLocale } from '../../hooks/useLocale';
import { CompareEphemeral } from '../../stores/compareEphemeral';
import {
ComparePersistent,
@@ -23,6 +24,7 @@ export function Controls({
const deltaMode = ComparePersistent.use((state) => state.deltaMode);
const mutateCompareEphemeral = CompareEphemeral.useMutation();
const mutateComparePersistent = ComparePersistent.useMutation();
+ const { strings } = useLocale();
return (
@@ -32,14 +34,16 @@ export function Controls({
>
- Add tanks
+
+ {strings.website.tools.compare.actions.add.title}
+
- Select tanks to add to comparison
+ {strings.website.tools.compare.actions.add.description}
@@ -87,7 +91,7 @@ export function Controls({
});
}}
>
- Clear
+ {strings.website.tools.compare.actions.clear}
- No deltas
+ {strings.website.tools.compare.actions.deltas.none}
- Percentage
+ {strings.website.tools.compare.actions.deltas.percentage}
- Absolute
+ {strings.website.tools.compare.actions.deltas.absolute}
diff --git a/packages/website/src/components/TankSearch/components/SearchBar.tsx b/packages/website/src/components/TankSearch/components/SearchBar.tsx
index d06c0d09f..36b05044a 100644
--- a/packages/website/src/components/TankSearch/components/SearchBar.tsx
+++ b/packages/website/src/components/TankSearch/components/SearchBar.tsx
@@ -4,6 +4,7 @@ import { MagnifyingGlassIcon } from '@radix-ui/react-icons';
import { Flex, Spinner, TextField } from '@radix-ui/themes';
import { debounce } from 'lodash-es';
import { type KeyboardEventHandler, useCallback, useRef } from 'react';
+import { useLocale } from '../../../hooks/useLocale';
import { $tankFilters } from '../../../stores/tankFilters';
import { QuickLink } from './QuickLink';
import { Sort } from './Sort';
@@ -14,6 +15,7 @@ interface SearchBarProps {
}
export function SearchBar({ topResult, onSelect }: SearchBarProps) {
+ const { strings } = useLocale();
const tankFilters = useStore($tankFilters);
const input = useRef(null);
const performSearch = useCallback(
@@ -67,7 +69,7 @@ export function SearchBar({ topResult, onSelect }: SearchBarProps) {
defaultValue={tankFilters.search}
style={{ flex: 1 }}
ref={input}
- placeholder="Search tanks..."
+ placeholder={strings.website.common.tank_search.search_bar_hint}
onChange={handleChange}
onKeyDown={handleKeyDown}
>
diff --git a/packages/website/src/components/TankSearch/components/Sort.tsx b/packages/website/src/components/TankSearch/components/Sort.tsx
index ee2620fc8..7a43836a5 100644
--- a/packages/website/src/components/TankSearch/components/Sort.tsx
+++ b/packages/website/src/components/TankSearch/components/Sort.tsx
@@ -1,308 +1,122 @@
import { useStore } from '@nanostores/react';
import { CaretDownIcon } from '@radix-ui/react-icons';
import { Button, DropdownMenu } from '@radix-ui/themes';
-import type { TankopediaSortDirection } from '../../../stores/tankopediaPersistent';
+import { useLocale } from '../../../hooks/useLocale';
+import type {
+ TankopediaSortBy,
+ TankopediaSortDirection,
+} from '../../../stores/tankopediaPersistent';
import { $tankopediaSort } from '../../../stores/tankopediaSort';
+interface ItemProps {
+ by: TankopediaSortBy;
+}
+
+interface ItemProps {
+ by: TankopediaSortBy;
+}
+
+function Item({ by }: ItemProps) {
+ const { strings } = useLocale();
+ const tankopediaSort = useStore($tankopediaSort);
+
+ return (
+ {
+ $tankopediaSort.setKey('by', by);
+ }}
+ >
+ {strings.website.common.tank_search.sort[by]}
+
+ );
+}
+
export function Sort() {
const tankopediaSort = useStore($tankopediaSort);
+ const { strings } = useLocale();
return (
- {
- // mutateTankopediaSort((draft) => {
- // draft.by = 'meta.none';
- // });
- $tankopediaSort.setKey('by', 'meta.none');
- }}
- >
- No sort
-
+
+ {strings.website.common.tank_search.sort_dropdown.groups.sort.label}
+
- Sort by
+
- Fire
+
+ {strings.website.common.tank_search.sort_dropdown.groups.sort.fire}
+
- {
- // mutateTankopediaSort((draft) => {
- // draft.by = 'fire.dpm';
- // });
- $tankopediaSort.setKey('by', 'fire.dpm');
- }}
- >
- Standard DPM
-
- {
- // mutateTankopediaSort((draft) => {
- // draft.by = 'fire.dpmPremium';
- // });
- $tankopediaSort.setKey('by', 'fire.dpmPremium');
- }}
- >
- Premium DPM
-
- {
- // mutateTankopediaSort((draft) => {
- // draft.by = 'fire.reload';
- // });
- $tankopediaSort.setKey('by', 'fire.reload');
- }}
- >
- Reload
-
- {
- // mutateTankopediaSort((draft) => {
- // draft.by = 'fire.caliber';
- // });
- $tankopediaSort.setKey('by', 'fire.caliber');
- }}
- >
- Caliber
-
- {
- // mutateTankopediaSort((draft) => {
- // draft.by = 'fire.standardPenetration';
- // });
- $tankopediaSort.setKey('by', 'fire.standardPenetration');
- }}
- >
- Standard penetration
-
- {
- // mutateTankopediaSort((draft) => {
- // draft.by = 'fire.premiumPenetration';
- // });
- $tankopediaSort.setKey('by', 'fire.premiumPenetration');
- }}
- >
- Premium penetration
-
- {
- $tankopediaSort.setKey('by', 'fire.damage');
- }}
- >
- Damage
-
- {
- $tankopediaSort.setKey('by', 'fire.moduleDamage');
- }}
- >
- Module damage
-
- {
- $tankopediaSort.setKey('by', 'fire.shellVelocity');
- }}
- >
- Shell velocity
-
- {
- $tankopediaSort.setKey('by', 'fire.shellRange');
- }}
- >
- Shell range
-
- {
- $tankopediaSort.setKey('by', 'fire.shellCapacity');
- }}
- >
- Shell capacity
-
- {
- $tankopediaSort.setKey('by', 'fire.aimTime');
- }}
- >
- Aim time
-
- {
- $tankopediaSort.setKey('by', 'fire.dispersionStill');
- }}
- >
- Dispersion still
-
- {
- $tankopediaSort.setKey('by', 'fire.dispersionMoving');
- }}
- >
- Dispersion moving
-
- {
- $tankopediaSort.setKey('by', 'fire.gunDepression');
- }}
- >
- Gun depression
-
- {
- $tankopediaSort.setKey('by', 'fire.gunElevation');
- }}
- >
- Gun elevation
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- Maneuverability
+
+ {
+ strings.website.common.tank_search.sort_dropdown.groups.sort
+ .maneuverability
+ }
+
- {
- $tankopediaSort.setKey('by', 'maneuverability.forwardsSpeed');
- }}
- >
- Forwards speed
-
- {
- $tankopediaSort.setKey('by', 'maneuverability.backwardsSpeed');
- }}
- >
- Backwards speed
-
- {
- $tankopediaSort.setKey('by', 'maneuverability.power');
- }}
- >
- Power
-
- {
- $tankopediaSort.setKey('by', 'maneuverability.powerToWeight');
- }}
- >
- Power to weight
-
- {
- $tankopediaSort.setKey('by', 'maneuverability.weight');
- }}
- >
- Weight
-
- {
- $tankopediaSort.setKey('by', 'maneuverability.traverseSpeed');
- }}
- >
- Traverse speed
-
+
+
+
+
+
+
- Survivability
+
+ {
+ strings.website.common.tank_search.sort_dropdown.groups.sort
+ .survivability
+ }
+
- {
- $tankopediaSort.setKey('by', 'survivability.health');
- }}
- >
- Health
-
- {
- $tankopediaSort.setKey('by', 'survivability.viewRange');
- }}
- >
- View range
-
- {
- $tankopediaSort.setKey('by', 'survivability.camouflageStill');
- }}
- >
- Camouflage
-
- {
- $tankopediaSort.setKey('by', 'survivability.camouflageMoving');
- }}
- >
- Camouflage moving
-
- {
- $tankopediaSort.setKey(
- 'by',
- 'survivability.camouflageShooting',
- );
- }}
- >
- Camouflage shooting
-
- {
- $tankopediaSort.setKey('by', 'survivability.volume');
- }}
- >
- Volume
-
- {
- $tankopediaSort.setKey('by', 'survivability.length');
- }}
- >
- Length
-
+
+
+
+
+
+
+
- Direction
+
+ {
+ strings.website.common.tank_search.sort_dropdown.groups.direction
+ .label
+ }
+
{
@@ -313,10 +127,16 @@ export function Sort() {
}}
>
- Ascending
+ {
+ strings.website.common.tank_search.sort_dropdown.groups.direction
+ .ascending
+ }
- Descending
+ {
+ strings.website.common.tank_search.sort_dropdown.groups.direction
+ .descending
+ }
diff --git a/packages/website/src/components/TankSearch/index.tsx b/packages/website/src/components/TankSearch/index.tsx
index f3735b4bd..5f8ea8226 100644
--- a/packages/website/src/components/TankSearch/index.tsx
+++ b/packages/website/src/components/TankSearch/index.tsx
@@ -16,12 +16,11 @@ import { awaitableTankDefinitions } from '../../core/awaitables/tankDefinitions'
import { awaitableTankNames } from '../../core/awaitables/tankNames';
import { filterTank } from '../../core/blitzkit/filterTank';
import { resolveReload } from '../../core/blitzkit/resolveReload';
+import { literals } from '../../core/i18n/literals';
+import { useLocale } from '../../hooks/useLocale';
import { $tankFilters } from '../../stores/tankFilters';
import { TankopediaPersistent } from '../../stores/tankopediaPersistent';
-import {
- SORT_NAMES,
- SORT_UNITS,
-} from '../../stores/tankopediaPersistent/constants';
+import { SORT_UNITS } from '../../stores/tankopediaPersistent/constants';
import { $tankopediaSort } from '../../stores/tankopediaSort';
import { ExperimentIcon } from '../ExperimentIcon';
import { TankSearchCard } from './components/Card';
@@ -52,6 +51,7 @@ const [gameDefinitions, modelDefinitions, tankDefinitions, tankNames] =
export const TankSearch = memo(
({ compact, onSelect, onSelectAll, ...props }) => {
+ const { strings, locale } = useLocale();
const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
const awaitedTanksDefinitionsArray = Object.values(tankDefinitions.tanks);
const tankFilters = useStore($tankFilters);
@@ -438,8 +438,11 @@ export const TankSearch = memo(
- {tanksFiltered.length} tank
- {tanksFiltered.length === 1 ? '' : 's'}
+ {tanksFiltered.length === 1
+ ? strings.website.common.tank_search.count_singular
+ : literals(strings.website.common.tank_search.count_plural, [
+ `${tanksFiltered.length.toLocaleString(locale)}`,
+ ])}
{onSelectAll && (
@@ -457,14 +460,16 @@ export const TankSearch = memo(
});
}}
>
- Select all
+ {strings.website.common.tank_search.select_all}
)}
{tankopediaSort.by !== 'meta.none' && (
- Sorting by {SORT_NAMES[tankopediaSort.by]}
+ {literals(strings.website.common.tank_search.sorting_by, [
+ strings.website.common.tank_search.sort[tankopediaSort.by],
+ ])}
{SORT_UNITS[tankopediaSort.by] === undefined
? ''
: ` (${SORT_UNITS[tankopediaSort.by]})`}
@@ -480,8 +485,7 @@ export const TankSearch = memo(
- Tanks in testing are subject to change and may not represent the
- final product.
+ {strings.website.common.warnings.test}
diff --git a/packages/website/src/pages/[...locale]/tools/compare/_index.tsx b/packages/website/src/pages/[...locale]/tools/compare/_index.tsx
index a8d74a7cd..59d3106a8 100644
--- a/packages/website/src/pages/[...locale]/tools/compare/_index.tsx
+++ b/packages/website/src/pages/[...locale]/tools/compare/_index.tsx
@@ -1,5 +1,4 @@
import { createDefaultSkills } from '@blitzkit/core';
-import { PlusIcon } from '@radix-ui/react-icons';
import { Flex, Heading, Text } from '@radix-ui/themes';
import { useEffect, useMemo, useState } from 'react';
import { CompareTable } from '../../../../components/Compare/CompareTable';
@@ -13,6 +12,11 @@ import { awaitableSkillDefinitions } from '../../../../core/awaitables/skillDefi
import { awaitableTankDefinitions } from '../../../../core/awaitables/tankDefinitions';
import { tankCharacteristics } from '../../../../core/blitzkit/tankCharacteristics';
import { tankToCompareMember } from '../../../../core/blitzkit/tankToCompareMember';
+import {
+ LocaleProvider,
+ useLocale,
+ type LocaleAcceptorProps,
+} from '../../../../hooks/useLocale';
import { App } from '../../../../stores/app';
import { CompareEphemeral } from '../../../../stores/compareEphemeral';
import { ComparePersistent } from '../../../../stores/comparePersistent';
@@ -32,19 +36,21 @@ const [
awaitableTankDefinitions,
]);
-export function Page() {
+export function Page({ locale }: LocaleAcceptorProps) {
return (
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
);
}
@@ -52,6 +58,7 @@ function Content() {
const members = CompareEphemeral.use((state) => state.members);
const [addTankDialogOpen, setAddTankDialogOpen] = useState(false);
const crewSkills = CompareEphemeral.use((state) => state.crewSkills);
+ const { strings } = useLocale();
const stats = useMemo[]>(
() =>
members.map((thisMember) =>
@@ -136,19 +143,6 @@ function Content() {
{members.length > 0 && (
-
- {/* setAddTankDialogOpen(true)}
- >
-
- */}
)}
@@ -159,9 +153,11 @@ function Content() {
direction="column"
style={{ flex: 1 }}
>
- No tanks selected
+
+ {strings.website.tools.compare.no_tanks.title}
+
- Press the Add button to get started
+ {strings.website.tools.compare.no_tanks.body}
)}
diff --git a/packages/website/src/pages/[...locale]/tools/compare/index.astro b/packages/website/src/pages/[...locale]/tools/compare/index.astro
index 8c28f897f..6cf98cffd 100644
--- a/packages/website/src/pages/[...locale]/tools/compare/index.astro
+++ b/packages/website/src/pages/[...locale]/tools/compare/index.astro
@@ -5,10 +5,12 @@ import BaseLayout from '../../../../layouts/BaseLayout.astro';
import { Page } from './_index';
export { getStaticPaths } from '../../index.astro';
+
+const { locale } = Astro.params;
---
-
+
diff --git a/packages/website/src/stores/tankopediaPersistent/constants.ts b/packages/website/src/stores/tankopediaPersistent/constants.ts
index f06f1d624..49bc4bda1 100644
--- a/packages/website/src/stores/tankopediaPersistent/constants.ts
+++ b/packages/website/src/stores/tankopediaPersistent/constants.ts
@@ -32,38 +32,7 @@ export const SORT_UNITS: Record = {
'survivability.viewRange': 'm',
'survivability.volume': 'm^3',
};
-export const SORT_NAMES = {
- 'meta.none': 'none',
- 'survivability.health': 'health',
- 'survivability.viewRange': 'view range',
- 'survivability.camouflageStill': 'camouflage still',
- 'survivability.camouflageMoving': 'camouflage moving',
- 'survivability.camouflageShooting': 'camouflage shooting',
- 'survivability.volume': 'volume',
- 'survivability.length': 'length',
- 'fire.dpm': 'standard DPM',
- 'fire.dpmPremium': 'premium DPM',
- 'fire.reload': 'reload',
- 'fire.caliber': 'caliber',
- 'fire.standardPenetration': 'standard penetration',
- 'fire.premiumPenetration': 'premium penetration',
- 'fire.damage': 'damage',
- 'fire.moduleDamage': 'module damage',
- 'fire.shellVelocity': 'shell velocity',
- 'fire.shellRange': 'shell range',
- 'fire.shellCapacity': 'shell capacity',
- 'fire.aimTime': 'aim time',
- 'fire.dispersionStill': 'dispersion still',
- 'fire.dispersionMoving': 'dispersion moving',
- 'fire.gunDepression': 'gun depression',
- 'fire.gunElevation': 'gun elevation',
- 'maneuverability.forwardsSpeed': 'forwards speed',
- 'maneuverability.backwardsSpeed': 'backwards speed',
- 'maneuverability.power': 'power',
- 'maneuverability.powerToWeight': 'power to weight',
- 'maneuverability.weight': 'weight',
- 'maneuverability.traverseSpeed': 'traverse speed',
-} as const;
+
export enum TankopediaDisplay {
Model,
DynamicArmor,
diff --git a/packages/website/src/stores/tankopediaPersistent/index.ts b/packages/website/src/stores/tankopediaPersistent/index.ts
index 26807b389..06ed651be 100644
--- a/packages/website/src/stores/tankopediaPersistent/index.ts
+++ b/packages/website/src/stores/tankopediaPersistent/index.ts
@@ -1,10 +1,10 @@
+import type en from '@blitzkit/core/lang/en.json';
import * as lodash from 'lodash-es';
import { create } from 'zustand';
import { persist, subscribeWithSelector } from 'zustand/middleware';
import { createContextualStore } from '../../core/zustand/createContextualStore';
-import { SORT_NAMES } from './constants';
-export type TankopediaSortBy = keyof typeof SORT_NAMES;
+export type TankopediaSortBy = keyof typeof en.website.common.tank_search.sort;
export type TankopediaSortDirection = 'ascending' | 'descending';
export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only';