mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf04fe21b3 | ||
|
|
84eb3c2da3 | ||
|
|
22bf2dc1d8 | ||
|
|
b9c339daa7 | ||
|
|
ef3006cac1 | ||
|
|
e482fd40c1 | ||
|
|
cc4569966e | ||
|
|
3708a3ced7 | ||
|
|
0ae59c2fd7 | ||
|
|
7027f63236 | ||
|
|
6725e79021 | ||
|
|
5ca3cee9da | ||
|
|
602a5a1e99 | ||
|
|
bfbf3bdc39 | ||
|
|
644686582e | ||
|
|
1c00bc81f8 | ||
|
|
ac3b69bec5 | ||
|
|
3e14c943b6 | ||
|
|
d33633be2c | ||
|
|
4bf70d02d0 | ||
|
|
377bcf0e38 | ||
|
|
884b6d4318 | ||
|
|
ee94d762d0 | ||
|
|
bcde319ac1 | ||
|
|
a4828774ca | ||
|
|
e59725d763 | ||
|
|
a62179a853 | ||
|
|
38ba940a98 | ||
|
|
a07d6c775e | ||
|
|
f9f7468544 | ||
|
|
98724df711 | ||
|
|
5499cb5cca | ||
|
|
122b3f6478 | ||
|
|
d2b24fc953 | ||
|
|
bb557a7dd7 | ||
|
|
f1612e8fe3 | ||
|
|
d12f4fb00e | ||
|
|
ad555ece9a | ||
|
|
9aee8feaf4 | ||
|
|
baa16840df | ||
|
|
4e80490fd4 | ||
|
|
6233c16b88 | ||
|
|
c4f1d9f3b0 | ||
|
|
2c365cdea0 | ||
|
|
18afa4cd28 | ||
|
|
ef9778ea96 | ||
|
|
d8459d373c | ||
|
|
7900c61a9b | ||
|
|
ceb7842d49 | ||
|
|
e0c897025e | ||
|
|
ade6ec8af1 | ||
|
|
06cbe1e733 | ||
|
|
cb3e759f75 | ||
|
|
e4558d978c | ||
|
|
260d819c77 | ||
|
|
ffe58de179 | ||
|
|
6fbe1d6339 | ||
|
|
835d03d12c | ||
|
|
2b208fa6a0 | ||
|
|
66d63d5c60 | ||
|
|
6ccffa0458 | ||
|
|
4c0c10e39e | ||
|
|
3d41c56c73 | ||
|
|
e0dda567f4 | ||
|
|
91b367cd70 | ||
|
|
5a65fee1d1 | ||
|
|
c7856364ad | ||
|
|
65899a06c4 | ||
|
|
571ae81306 | ||
|
|
6b2dda0f9d | ||
|
|
9de41529d1 | ||
|
|
7dfdf4c11b | ||
|
|
db4132f666 | ||
|
|
d9688f6051 | ||
|
|
12e89a6b65 | ||
|
|
2d524cd273 | ||
|
|
1d44ecab18 | ||
|
|
bf9addf589 | ||
|
|
4deee2d709 | ||
|
|
309fda1ed1 | ||
|
|
d6e7f35214 | ||
|
|
7cd9131b60 | ||
|
|
599b81934e | ||
|
|
3f595d0d8a | ||
|
|
9afed23bb8 | ||
|
|
fc869f8b45 | ||
|
|
cf7ba1c6b5 | ||
|
|
07ca41e82a | ||
|
|
c487d9af61 | ||
|
|
9be6725043 | ||
|
|
e0daf85561 | ||
|
|
8203db3dc2 | ||
|
|
eb5527706e | ||
|
|
1f577c2317 | ||
|
|
68362c22b1 | ||
|
|
844965bcb0 | ||
|
|
1843eb3bcf | ||
|
|
60ab845326 | ||
|
|
3bbc083b2a | ||
|
|
8df159b182 | ||
|
|
c7238b0342 | ||
|
|
ba6006a320 | ||
|
|
43b9252f21 | ||
|
|
d727ceaaf6 | ||
|
|
eb95230a5f | ||
|
|
b6fd5eaa66 | ||
|
|
117f9892d6 | ||
|
|
c20caf45a2 | ||
|
|
670b678348 | ||
|
|
b1f0d4d844 | ||
|
|
e9d1c82a60 | ||
|
|
cc4345f1a3 | ||
|
|
6d8326861b | ||
|
|
8517ecfdb6 | ||
|
|
a38b5d7ddd | ||
|
|
f726793819 | ||
|
|
19531aa9ae |
No files matched your search
@@ -39,6 +39,17 @@ env:
|
||||
PUBLIC_WARGAMING_APPLICATION_ID: ${{ secrets.PUBLIC_WARGAMING_APPLICATION_ID }}
|
||||
PUBLIC_ASSET_REPO: ${{ secrets.PUBLIC_ASSET_REPO }}
|
||||
PUBLIC_ASSET_BRANCH: ${{ github.event.inputs.cdn_branch || secrets.PUBLIC_ASSET_BRANCH }}
|
||||
WOTB_GLOSSARY_DOMAIN: ${{ secrets.WOTB_GLOSSARY_DOMAIN }}
|
||||
WOTB_GLOSSARY_PATH: ${{ secrets.WOTB_GLOSSARY_PATH }}
|
||||
PUBLIC_PROMOTE_OPENTEST: ${{ secrets.PUBLIC_PROMOTE_OPENTEST }}
|
||||
ALLOW_ROBOTS: true
|
||||
PUBLIC_GOOGLE_TAG_MANAGER_ID: ${{ secrets.PUBLIC_GOOGLE_TAG_MANAGER_ID }}
|
||||
PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ${{ secrets.PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID }}
|
||||
PUBLIC_PATREON_CLIENT_ID: ${{ secrets.PUBLIC_PATREON_CLIENT_ID }}
|
||||
PUBLIC_PATREON_REDIRECT_URI: ${{ secrets.PUBLIC_PATREON_REDIRECT_URI }}
|
||||
PATREON_CLIENT_SECRET: ${{ secrets.PATREON_CLIENT_SECRET }}
|
||||
PUBLIC_NITROPAY_ID: ${{ secrets.PUBLIC_NITROPAY_ID }}
|
||||
PUBLIC_DEBUG_MISSING_I18N: false
|
||||
|
||||
jobs:
|
||||
download_client:
|
||||
@@ -106,6 +117,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
@@ -113,11 +127,23 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
|
||||
- name: Lint
|
||||
run: bun run lint:website
|
||||
|
||||
- name: Download depots
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: depots
|
||||
path: depots
|
||||
|
||||
- name: Build assets
|
||||
run: bun run build:assets --all-targets --depot --production
|
||||
- name: AppArmor hack
|
||||
run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns
|
||||
|
||||
- name: Start server and build assets
|
||||
run: |
|
||||
bun dev:website --verbosepa &
|
||||
SERVER_PID=$!
|
||||
|
||||
bun run build:assets --all-targets --depot --production
|
||||
|
||||
kill $SERVER_PID || true
|
||||
@@ -26,6 +26,8 @@ env:
|
||||
PUBLIC_GOOGLE_TAG_MANAGER_ID: ${{ secrets.PUBLIC_GOOGLE_TAG_MANAGER_ID }}
|
||||
PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ${{ secrets.PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID }}
|
||||
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
|
||||
WOTB_GLOSSARY_DOMAIN: ${{ secrets.WOTB_GLOSSARY_DOMAIN }}
|
||||
WOTB_GLOSSARY_PATH: ${{ secrets.WOTB_GLOSSARY_PATH }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -52,8 +54,7 @@ jobs:
|
||||
path: dist/website
|
||||
|
||||
deploy-github-pages:
|
||||
if: github.ref == 'refs/heads/main'
|
||||
|
||||
if: ${{ github.ref == 'refs/heads/main' }}
|
||||
name: Deploy to GitHub Pages
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
@@ -65,27 +66,3 @@ jobs:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
deploy-vercel:
|
||||
name: Deploy to Vercel
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: Preview
|
||||
|
||||
steps:
|
||||
# vercel begs for the .git dir so here it is my guy
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ./dist/website
|
||||
|
||||
- uses: amondnet/vercel-action@v25
|
||||
with:
|
||||
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
vercel-org-id: ${{ secrets.VERCEL_ORG_ID}}
|
||||
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
|
||||
working-directory: ./dist/website
|
||||
Vendored
+1
@@ -189,6 +189,7 @@
|
||||
"unpickled",
|
||||
"Unregistering",
|
||||
"unrotate",
|
||||
"unwrapper",
|
||||
"vercel",
|
||||
"vickers",
|
||||
"vitepress",
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
## Visit the website
|
||||
## BlitzKit
|
||||
|
||||
Your premier source for all things Blitz.
|
||||
|
||||
### https://blitzkit.app/
|
||||
|
||||

|
||||
|
||||
# BlitzKit
|
||||
|
||||
[](https://codeium.com)
|
||||
|
||||
Tools for everything World of Tanks Blitz
|
||||

|
||||
|
||||
## Invite the bot
|
||||
|
||||
Go to [application directory for BlitzKit](https://discord.com/application-directory/1097673957865443370) and click "Add to Server." Voila! You're ready to go.
|
||||
|
||||

|
||||
|
||||
## Visit the documentation website
|
||||
|
||||
### https://tresabhi.github.io/blitzkit/
|
||||
|
||||

|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
files:
|
||||
- source: /packages/core/lang/en-US.json
|
||||
- source: /packages/i18n/strings/en.json
|
||||
translation: /%original_path%/%locale%.json
|
||||
@@ -5,6 +5,7 @@ BlitzKit is a one man band **TrèsAbhi** but I am far from solo.
|
||||
| Role | People |
|
||||
| ------------------------------ | ------------------------------ |
|
||||
| Bot verification | S0AP |
|
||||
| General testing | Prince_NA |
|
||||
| Bot advertisement platform | S0AP |
|
||||
| Bot rendering pipeline | Vovko |
|
||||
| Game asset decompression | Maddox |
|
||||
@@ -12,7 +13,7 @@ BlitzKit is a one man band **TrèsAbhi** but I am far from solo.
|
||||
| Game file layout | Aeson |
|
||||
| 3-caliber rule edge cases | Minitelrose, ChickenMan7777 |
|
||||
| Embed UX | \_34, HisRoyalFatness, Synx |
|
||||
| Tankopedia pre-release testing | [OPTML], Aeson, \_34 |
|
||||
| Tankopedia pre-release testing | [OPTML], Aeson, \_34, xkdkw |
|
||||
| Website advertisement platform | Aeson |
|
||||
| Compare pre-release testing | [OPTML] |
|
||||
| Redacted | GonnaHetzMe |
|
||||
@@ -0,0 +1,15 @@
|
||||
# BlitzKit 1.26.6
|
||||
|
||||
This update only affects the website.
|
||||
|
||||
## Features
|
||||
|
||||
- Added an option to hide the tank model beneath the armor
|
||||
|
||||
## Fixes
|
||||
|
||||
- 3RC is now only display when it is used to avoid a ricochet in the advanced armor highlighting mode
|
||||
- Fixed the excessively sharp lighting in static mode
|
||||
- Brightness for non-PBR tanks is a bit better now
|
||||
- Decimal places are now properly rounded in BlitzKit link embeds
|
||||
- The titles in the Tankopedia pages aren't too massive now
|
||||
@@ -0,0 +1,14 @@
|
||||
# BlitzKit 1.27.0
|
||||
|
||||
PLEASE HELP TRANSLATE BLITZKIT: https://crowdin.com/project/blitzkrieg
|
||||
|
||||
This update will be the last major update before the release of World of Tanks Blitz Unreal Engine.
|
||||
|
||||
## Features
|
||||
|
||||
- Added support for English, Spanish, French, Japanese, Polish, Portuguese, Russian, Ukrainian, and Chinese to the website and bot
|
||||
- You can switch languages through the home page, the footer of any page, or the settings page
|
||||
|
||||
## Fixes
|
||||
|
||||
- Fixed the units for shell capacity
|
||||
@@ -0,0 +1,7 @@
|
||||
# BlitzKit 1.27.1
|
||||
|
||||
## Fixes
|
||||
|
||||
- Fixed a crash that occurs if tanks are deleted in Blitz and were once available in BlitzKit
|
||||
- All tank icons are now back
|
||||
- The tank search once again returns results
|
||||
+3
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "blitzkit",
|
||||
"private": true,
|
||||
"version": "1.26.5",
|
||||
"version": "1.27.1",
|
||||
"description": "🎉 Tools for everything World of Tanks Blitz",
|
||||
"type": "module",
|
||||
"types": "./types.d.ts",
|
||||
@@ -35,7 +35,8 @@
|
||||
"build:protos": "bun packages/scripts/src/protos.ts",
|
||||
"preview:website": "cd packages/website && bun run preview",
|
||||
"build:reviews": "cd packages/scripts && bun build:reviews",
|
||||
"build:ids": "cd packages/scripts && bun build:ids"
|
||||
"build:ids": "cd packages/scripts && bun build:ids",
|
||||
"prunestrings": "cd packages/scripts && bun prunestrings"
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"types": "src/types.d.ts",
|
||||
"dependencies": {
|
||||
"@blitzkit/core": "workspace:*",
|
||||
"@blitzkit/i18n": "workspace:*",
|
||||
"satori": "^0.10.14",
|
||||
"@resvg/resvg-js": "^2.6.2",
|
||||
"discord.js": "^14.16.3",
|
||||
|
||||
@@ -28,10 +28,10 @@ export const aboutCommand = new Promise<CommandRegistry>(async (resolve) => {
|
||||
|
||||
async handler(interaction) {
|
||||
const subcommand = interaction.options.getSubcommand();
|
||||
const { t } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
|
||||
if (subcommand === 'commands') {
|
||||
return t`bot.commands.about.subcommands.commands.body${(
|
||||
return `${strings.bot.commands.about.subcommands.commands.body}${(
|
||||
await Promise.all(COMMANDS_RAW)
|
||||
)
|
||||
.sort((a, b) =>
|
||||
|
||||
@@ -3,17 +3,18 @@ import {
|
||||
Region,
|
||||
regionToRegionSubdomain,
|
||||
} from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { tankDefinitions } from '../core/blitzkit/nonBlockingPromises';
|
||||
import { chunkLines } from '../core/discord/chunkLines';
|
||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||
import { translator } from '../core/localization/translator';
|
||||
import { CommandRegistry } from '../events/interactionCreate';
|
||||
|
||||
interface Auction {
|
||||
type Auction = null | {
|
||||
count: number;
|
||||
has_next: boolean;
|
||||
results: Result[];
|
||||
}
|
||||
};
|
||||
|
||||
type Result =
|
||||
| {
|
||||
@@ -75,7 +76,7 @@ export const auctionCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
command: createLocalizedCommand('auction'),
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const awaitedTankDefinitions = await tankDefinitions;
|
||||
const region: Region = 'com';
|
||||
const pageSize = 80;
|
||||
@@ -87,16 +88,16 @@ export const auctionCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
pageSize
|
||||
}&type[]=vehicle&saleable=${saleable}`,
|
||||
).then((response) => response.json() as Promise<Auction>);
|
||||
const saleableTanks = data.results.filter((result) => result.available);
|
||||
|
||||
if (saleableTanks.length === 0) {
|
||||
return t`bot.commands.auction.errors.no_auction`;
|
||||
if (data === null) {
|
||||
return strings.bot.commands.auction.errors.no_auction;
|
||||
}
|
||||
|
||||
const saleableTanks = data.results.filter((result) => result.available);
|
||||
const nextPricesTimestamp = saleableTanks[0].next_price_timestamp;
|
||||
|
||||
const title = `# ${t`bot.commands.auction.body.title`}`;
|
||||
const subtitle = `${translate('bot.commands.auction.body.subtitle', [
|
||||
const title = `# ${strings.bot.commands.auction.body.title}`;
|
||||
const subtitle = `${literals(strings.bot.commands.auction.body.subtitle, [
|
||||
`${saleableTanks.length} / ${data.results.length}`,
|
||||
`<t:${nextPricesTimestamp}:R>`,
|
||||
'<https://wotblitz.com/auction/>',
|
||||
@@ -112,15 +113,18 @@ export const auctionCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
const next =
|
||||
data.next_price === null
|
||||
? ''
|
||||
: `\n-# ${translate('bot.commands.auction.body.next', [
|
||||
: `\n-# ${literals(strings.bot.commands.auction.body.next, [
|
||||
`<:gold:1317173197082333244> ${data.next_price.value.toLocaleString(
|
||||
interaction.locale,
|
||||
)}`,
|
||||
])}`;
|
||||
const available = translate('bot.commands.auction.body.available', [
|
||||
data.current_count.toLocaleString(interaction.locale),
|
||||
data.initial_count.toLocaleString(interaction.locale),
|
||||
]);
|
||||
const available = literals(
|
||||
strings.bot.commands.auction.body.available,
|
||||
[
|
||||
data.current_count.toLocaleString(interaction.locale),
|
||||
data.initial_count.toLocaleString(interaction.locale),
|
||||
],
|
||||
);
|
||||
const isOut = data.current_count === 0;
|
||||
const outString = isOut ? '~~' : '';
|
||||
const isLow = data.current_count <= WARNING_COUNT;
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
getWN8Percentile,
|
||||
TankDefinition,
|
||||
} from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { Locale } from 'discord.js';
|
||||
import { chunk } from 'lodash-es';
|
||||
import * as Breakdown from '../../components/Breakdown';
|
||||
@@ -32,7 +33,7 @@ export async function renderBreakdown(
|
||||
filters: StatFilters,
|
||||
locale: Locale,
|
||||
) {
|
||||
const { t, translate } = translator(locale);
|
||||
const { strings, unwrap } = translator(locale);
|
||||
const awaitedTankDefinitions = await tankDefinitions;
|
||||
const awaitedTankAverages = await blitzStarsTankAverages;
|
||||
const statsInPeriod = await getStatsInPeriod(region, id, start, end, locale);
|
||||
@@ -48,7 +49,7 @@ export async function renderBreakdown(
|
||||
const orderedCareerWN8Full: (number | undefined)[] = [];
|
||||
|
||||
if (tankStats === null) {
|
||||
throw new UserError(t`bot.common.errors.no_tank_stats`);
|
||||
throw new UserError(strings.bot.common.errors.no_tank_stats);
|
||||
}
|
||||
|
||||
filteredOrder.forEach((id) => {
|
||||
@@ -136,21 +137,21 @@ export async function renderBreakdown(
|
||||
<Breakdown.Row
|
||||
key={id}
|
||||
displayType="summary"
|
||||
title={t`bot.commands.breakdown.body.total`}
|
||||
title={strings.bot.commands.breakdown.body.total}
|
||||
stats={[
|
||||
{
|
||||
title: t`bot.commands.breakdown.body.battles`,
|
||||
title: strings.bot.commands.breakdown.body.battles,
|
||||
current: currentBattles,
|
||||
career: careerBattles,
|
||||
},
|
||||
{
|
||||
title: t`bot.commands.breakdown.body.winrate`,
|
||||
title: strings.bot.commands.breakdown.body.winrate,
|
||||
current: `${(100 * currentWinrate).toFixed(2)}%`,
|
||||
career: `${(100 * careerWinrate).toFixed(2)}%`,
|
||||
delta: currentWinrate - careerWinrate,
|
||||
},
|
||||
{
|
||||
title: t`bot.commands.breakdown.body.wn8`,
|
||||
title: strings.bot.commands.breakdown.body.wn8,
|
||||
current:
|
||||
currentWN8 === undefined
|
||||
? undefined
|
||||
@@ -165,7 +166,7 @@ export async function renderBreakdown(
|
||||
: getWN8Percentile(currentWN8),
|
||||
},
|
||||
{
|
||||
title: t`bot.commands.breakdown.body.damage`,
|
||||
title: strings.bot.commands.breakdown.body.damage,
|
||||
current: Math.round(currentDamage).toLocaleString(),
|
||||
career: Math.round(careerDamage).toLocaleString(),
|
||||
delta: currentDamage - careerDamage,
|
||||
@@ -190,17 +191,20 @@ export async function renderBreakdown(
|
||||
class={tankDefinition?.class}
|
||||
type={tankDefinition?.type}
|
||||
title={
|
||||
tankDefinition?.name ??
|
||||
translate('bot.commands.breakdown.body.unknown_tank', [`${id}`])
|
||||
tankDefinition
|
||||
? unwrap(tankDefinition.name)
|
||||
: literals(strings.bot.commands.breakdown.body.unknown_tank, [
|
||||
`${id}`,
|
||||
])
|
||||
}
|
||||
stats={[
|
||||
{
|
||||
title: t`bot.commands.breakdown.body.battles`,
|
||||
title: strings.bot.commands.breakdown.body.battles,
|
||||
current: current.battles.toLocaleString(),
|
||||
career: career.battles.toLocaleString(),
|
||||
},
|
||||
{
|
||||
title: t`bot.commands.breakdown.body.winrate`,
|
||||
title: strings.bot.commands.breakdown.body.winrate,
|
||||
current: `${(100 * (current.wins / current.battles)).toFixed(
|
||||
2,
|
||||
)}%`,
|
||||
@@ -209,7 +213,7 @@ export async function renderBreakdown(
|
||||
current.wins / current.battles - career.wins / career.battles,
|
||||
},
|
||||
{
|
||||
title: t`bot.commands.breakdown.body.wn8`,
|
||||
title: strings.bot.commands.breakdown.body.wn8,
|
||||
current:
|
||||
currentWN8 === undefined
|
||||
? undefined
|
||||
@@ -224,7 +228,7 @@ export async function renderBreakdown(
|
||||
: getWN8Percentile(currentWN8),
|
||||
},
|
||||
{
|
||||
title: t`bot.commands.breakdown.body.damage`,
|
||||
title: strings.bot.commands.breakdown.body.damage,
|
||||
current: Math.round(
|
||||
current.damage_dealt / current.battles,
|
||||
).toLocaleString(),
|
||||
|
||||
@@ -11,17 +11,17 @@ export const debugCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
command: createLocalizedCommand('debug'),
|
||||
|
||||
async handler(interaction) {
|
||||
const { t } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const currentTime = new Date().getTime();
|
||||
const uptime = currentTime - executionStart;
|
||||
const list = [
|
||||
[t`bot.commands.debug.body.version`, packageJSON.version],
|
||||
[strings.bot.commands.debug.body.version, packageJSON.version],
|
||||
[
|
||||
t`bot.commands.debug.body.shard`,
|
||||
client.shard?.ids[0] ?? t`bot.commands.debug.body.shard.default`,
|
||||
strings.bot.commands.debug.body.shard,
|
||||
client.shard?.ids[0] ?? strings.bot.commands.debug.body.shard.default,
|
||||
],
|
||||
[
|
||||
t`bot.commands.debug.body.uptime`,
|
||||
strings.bot.commands.debug.body.uptime,
|
||||
`${Math.floor((uptime / 1000 / 60 / 60) % 24)}h ${Math.floor(
|
||||
(uptime / 1000 / 60) % 60,
|
||||
)}m ${Math.floor((uptime / 1000) % 60)}s ${Math.floor(
|
||||
@@ -29,7 +29,7 @@ export const debugCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
)}ms`,
|
||||
],
|
||||
];
|
||||
return t`bot.commands.debug.body.title${list
|
||||
return `${strings.bot.commands.debug.body.title}${list
|
||||
.map(([key, value]) => `- ${key}: ${value}`)
|
||||
.join('\n')}`;
|
||||
},
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getAccountInfo, getClanInfo } from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { Locale } from 'discord.js';
|
||||
import { CommandWrapper } from '../components/CommandWrapper';
|
||||
import { GenericStats } from '../components/GenericStats';
|
||||
@@ -19,30 +20,31 @@ export const inactiveCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
command: createLocalizedCommand('inactive')
|
||||
.addStringOption(addClanChoices)
|
||||
.addNumberOption((option) => {
|
||||
const { translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
return option
|
||||
.setName('threshold')
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.inactive.options.threshold',
|
||||
(strings) => strings.bot.commands.inactive.options.threshold.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
translate('bot.commands.inactive.options.threshold.description'),
|
||||
strings.bot.commands.inactive.options.threshold.description,
|
||||
)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.inactive.options.threshold.description',
|
||||
(strings) =>
|
||||
strings.bot.commands.inactive.options.threshold.description,
|
||||
),
|
||||
)
|
||||
.setMinValue(0);
|
||||
}),
|
||||
|
||||
async handler(interaction) {
|
||||
const { translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const { region, id } = await resolveClanFromCommand(interaction);
|
||||
const threshold =
|
||||
interaction.options.getNumber('threshold')! ?? DEFAULT_THRESHOLD;
|
||||
@@ -63,7 +65,7 @@ export const inactiveCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
([name, days]) =>
|
||||
[
|
||||
name,
|
||||
translate('bot.commands.inactive.body.listing', [
|
||||
literals(strings.bot.commands.inactive.body.listing, [
|
||||
days.toFixed(0),
|
||||
]),
|
||||
] as [string, string],
|
||||
@@ -75,9 +77,10 @@ export const inactiveCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
<TitleBar
|
||||
title={clanInfo.name}
|
||||
image={`https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clanInfo.emblem_set_id}.png`}
|
||||
description={`${translate('bot.commands.inactive.body.subtitle', [
|
||||
`${threshold}`,
|
||||
])} • ${new Date().toLocaleDateString(interaction.locale)}`}
|
||||
description={`${literals(
|
||||
strings.bot.commands.inactive.body.subtitle,
|
||||
[`${threshold}`],
|
||||
)} • ${new Date().toLocaleDateString(interaction.locale)}`}
|
||||
/>
|
||||
|
||||
{!hasInactiveMembers && (
|
||||
|
||||
@@ -22,7 +22,7 @@ export const verifyCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
),
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const { id, region } = await resolvePlayerFromCommand(interaction);
|
||||
const discordId = BigInt(interaction.user.id);
|
||||
const accountInfo = await getAccountInfo(region, id);
|
||||
@@ -120,9 +120,9 @@ export const verifyCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
height: 16,
|
||||
}}
|
||||
/>
|
||||
<span
|
||||
style={{ fontSize: 16 }}
|
||||
>{t`bot.commands.link.body.accounts_linked`}</span>
|
||||
<span style={{ fontSize: 16 }}>
|
||||
{strings.bot.commands.link.body.accounts_linked}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -174,7 +174,7 @@ export const verifyCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
{clanAccountInfo?.clan
|
||||
? `[${clanAccountInfo?.clan?.tag}] • `
|
||||
: ''}
|
||||
{translate(`common.regions.normal.${region}`)}
|
||||
{strings.common.regions.normal[region]}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -185,8 +185,8 @@ export const verifyCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
</CommandWrapper>,
|
||||
|
||||
embedInfo(
|
||||
t`bot.commands.link.embed.title`,
|
||||
t`bot.commands.link.embed.description`,
|
||||
strings.bot.commands.link.embed.title,
|
||||
strings.bot.commands.link.embed.description,
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
getAccountInfo,
|
||||
getTankStats,
|
||||
} from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import markdownEscape from 'markdown-escape';
|
||||
import {
|
||||
gameDefinitions,
|
||||
@@ -27,14 +28,14 @@ export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
.addStringOption(addUsernameChoices),
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const { strings, unwrap } = translator(interaction.locale);
|
||||
const tier = Number(interaction.options.getString('tier'));
|
||||
const { id, region } = await resolvePlayerFromCommand(interaction);
|
||||
const accountInfo = await getAccountInfo(region, id);
|
||||
const tankStats = await getTankStats(region, id);
|
||||
|
||||
if (tankStats === null) {
|
||||
return t`bot.common.errors.no_tank_stats`;
|
||||
return strings.bot.common.errors.no_tank_stats;
|
||||
}
|
||||
|
||||
const filteredTanks = (
|
||||
@@ -59,7 +60,7 @@ export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
|
||||
const awaitedTankDefinitions = await tankDefinitions;
|
||||
const awaitedGameDefinitions = await gameDefinitions;
|
||||
const title = translate('bot.commands.owned_tanks.body.title', [
|
||||
const title = literals(strings.bot.commands.owned_tanks.body.title, [
|
||||
markdownEscape(accountInfo.nickname),
|
||||
TIER_ROMAN_NUMERALS[tier],
|
||||
]);
|
||||
@@ -77,7 +78,7 @@ export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
)
|
||||
.map(
|
||||
(tank) =>
|
||||
`[${flags[tank.nation]} ${markdownEscape(tank.name)}](<https://blitzkit.app/tools/tankopedia/${tank.id}>)`,
|
||||
`[${flags[tank.nation]} ${markdownEscape(unwrap(tank.name))}](<https://blitzkit.app/tools/tankopedia/${tank.id}>)`,
|
||||
);
|
||||
const lines = [title, ...tankList];
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||
import { translator } from '../core/localization/translator';
|
||||
import { CommandRegistry } from '../events/interactionCreate';
|
||||
@@ -7,26 +8,26 @@ export const permissionsCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
command: createLocalizedCommand('permissions'),
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
// friday the 13th permissions easter egg
|
||||
const isFridayThe13th =
|
||||
new Date().getDay() === 5 && new Date().getDate() === 13;
|
||||
const permissions = [
|
||||
[
|
||||
interaction.appPermissions?.has('ViewChannel'),
|
||||
t`bot.commands.permissions.body.view_channels`,
|
||||
strings.bot.commands.permissions.body.view_channels,
|
||||
],
|
||||
[
|
||||
interaction.appPermissions?.has('ReadMessageHistory'),
|
||||
t`bot.commands.permissions.body.read_message_history`,
|
||||
strings.bot.commands.permissions.body.read_message_history,
|
||||
],
|
||||
[
|
||||
interaction.appPermissions?.has('AttachFiles'),
|
||||
t`bot.commands.permissions.body.attach_files`,
|
||||
strings.bot.commands.permissions.body.attach_files,
|
||||
],
|
||||
[
|
||||
interaction.appPermissions?.has('UseExternalEmojis'),
|
||||
t`bot.commands.permissions.body.external_emojis`,
|
||||
strings.bot.commands.permissions.body.external_emojis,
|
||||
],
|
||||
];
|
||||
const body = permissions
|
||||
@@ -39,7 +40,7 @@ export const permissionsCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return translate('bot.commands.permissions.body.title', [body]);
|
||||
return literals(strings.bot.commands.permissions.body.title, [body]);
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||
import { translator } from '../core/localization/translator';
|
||||
import { CommandRegistry } from '../events/interactionCreate';
|
||||
@@ -12,19 +13,19 @@ export const pingCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
]),
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const subcommand = interaction.options.getSubcommand();
|
||||
const executionStart = Date.now();
|
||||
|
||||
if (subcommand === 'blitzkit') {
|
||||
await interaction.editReply(t`bot.commands.ping.body.pong`);
|
||||
await interaction.editReply(strings.bot.commands.ping.body.pong);
|
||||
} else {
|
||||
await fetch('https://api.wotblitz.com/');
|
||||
}
|
||||
|
||||
const executionTime = Date.now() - executionStart;
|
||||
interaction.editReply(
|
||||
translate('bot.commands.ping.body.pong_with_time', [
|
||||
literals(strings.bot.commands.ping.body.pong_with_time, [
|
||||
`${Math.round(executionTime)}`,
|
||||
]),
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getAccountInfo } from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import markdownEscape from 'markdown-escape';
|
||||
import { addUsernameChoices } from '../core/discord/addUsernameChoices';
|
||||
import { autocompleteUsername } from '../core/discord/autocompleteUsername';
|
||||
@@ -15,27 +16,27 @@ export const playerInfoCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
createLocalizedCommand('player-info').addStringOption(addUsernameChoices),
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const account = await resolvePlayerFromCommand(interaction);
|
||||
const { id, region: region } = account;
|
||||
const accountInfo = await getAccountInfo(region, id);
|
||||
|
||||
return embedInfo(
|
||||
translate('bot.commands.player_info.body.title', [
|
||||
literals(strings.bot.commands.player_info.body.title, [
|
||||
markdownEscape(accountInfo.nickname),
|
||||
]),
|
||||
|
||||
markdownTable([
|
||||
[
|
||||
t`bot.commands.player_info.body.nickname`,
|
||||
strings.bot.commands.player_info.body.nickname,
|
||||
`${accountInfo.nickname}`,
|
||||
],
|
||||
[
|
||||
t`bot.commands.player_info.body.battles`,
|
||||
strings.bot.commands.player_info.body.battles,
|
||||
`${accountInfo.statistics.all.battles}`,
|
||||
],
|
||||
[
|
||||
t`bot.commands.player_info.body.winrate`,
|
||||
strings.bot.commands.player_info.body.winrate,
|
||||
`${(
|
||||
100 *
|
||||
(accountInfo.statistics.all.wins /
|
||||
@@ -44,17 +45,17 @@ export const playerInfoCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
],
|
||||
[],
|
||||
[
|
||||
t`bot.commands.player_info.body.account_id`,
|
||||
strings.bot.commands.player_info.body.account_id,
|
||||
`${accountInfo.account_id}`,
|
||||
],
|
||||
[
|
||||
t`bot.commands.player_info.body.created`,
|
||||
strings.bot.commands.player_info.body.created,
|
||||
new Date(accountInfo.created_at * 1000).toLocaleDateString(
|
||||
interaction.locale,
|
||||
),
|
||||
],
|
||||
[
|
||||
t`bot.commands.player_info.body.last_battle`,
|
||||
strings.bot.commands.player_info.body.last_battle,
|
||||
new Date(accountInfo.last_battle_time * 1000).toLocaleDateString(
|
||||
interaction.locale,
|
||||
),
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
getRatingNeighbors,
|
||||
imgur,
|
||||
} from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { SlashCommandSubcommandBuilder } from 'discord.js';
|
||||
import markdownEscape from 'markdown-escape';
|
||||
import { Glow } from '../components/AllStatsOverview/components/HeroStat/components/Glow';
|
||||
@@ -53,7 +54,7 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
const subcommand = interaction.options.getSubcommand(true) as
|
||||
| 'season'
|
||||
| 'today';
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const { id, region } = await resolvePlayerFromCommand(interaction);
|
||||
const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan;
|
||||
const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined;
|
||||
@@ -89,7 +90,7 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
const statsB2Array = (await getRatingNeighbors(region, id, 0)).neighbors;
|
||||
|
||||
if (statsB2Array === undefined) {
|
||||
return translate('bot.commands.rating.errors.no_participation', [
|
||||
return literals(strings.bot.commands.rating.errors.no_participation, [
|
||||
markdownEscape(accountInfo.nickname),
|
||||
]);
|
||||
}
|
||||
@@ -98,10 +99,10 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
const league = getLeagueFromScore(statsB2.score);
|
||||
|
||||
if (!statsA) {
|
||||
return t`bot.commands.rating.errors.unrecorded_stats`;
|
||||
return strings.bot.commands.rating.errors.unrecorded_stats;
|
||||
}
|
||||
if (!statsB1) {
|
||||
return translate('bot.commands.rating.errors.no_participation', [
|
||||
return literals(strings.bot.commands.rating.errors.no_participation, [
|
||||
markdownEscape(accountInfo.nickname),
|
||||
]);
|
||||
}
|
||||
@@ -139,9 +140,9 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
<TitleBar
|
||||
title={accountInfo.nickname}
|
||||
image={clanImage}
|
||||
description={`${translate(
|
||||
`bot.commands.rating.body.subtitle.${subcommand}`,
|
||||
)} • ${new Date().toLocaleDateString(interaction.locale)}`}
|
||||
description={`${
|
||||
strings.bot.commands.rating.body.subtitle[subcommand]
|
||||
} • ${new Date().toLocaleDateString(interaction.locale)}`}
|
||||
/>
|
||||
|
||||
<div
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
RatingLeaderboard,
|
||||
Region,
|
||||
} from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import {
|
||||
APIApplicationCommandOptionChoice,
|
||||
Locale,
|
||||
@@ -54,28 +55,32 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
);
|
||||
|
||||
function addOptions(option: SlashCommandSubcommandBuilder) {
|
||||
const { t, translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
return option
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName(t`bot.commands.rating_leaderboard.options.limit`)
|
||||
.setName(strings.bot.commands.rating_leaderboard.options.limit.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.rating_leaderboard.options.limit',
|
||||
(strings) =>
|
||||
strings.bot.commands.rating_leaderboard.options.limit.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
translate(
|
||||
'bot.commands.rating_leaderboard.options.limit.description',
|
||||
literals(
|
||||
strings.bot.commands.rating_leaderboard.options.limit
|
||||
.description,
|
||||
[`${DEFAULT_LIMIT}`],
|
||||
),
|
||||
)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.rating_leaderboard.options.limit.description',
|
||||
(strings) =>
|
||||
strings.bot.commands.rating_leaderboard.options.limit
|
||||
.description,
|
||||
[`${DEFAULT_LIMIT}`],
|
||||
),
|
||||
)
|
||||
@@ -85,22 +90,26 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName(t`bot.commands.rating_leaderboard.options.season`)
|
||||
.setName(
|
||||
strings.bot.commands.rating_leaderboard.options.season.name,
|
||||
)
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.rating_leaderboard.options.season',
|
||||
(strings) =>
|
||||
strings.bot.commands.rating_leaderboard.options.season.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
translate(
|
||||
'bot.commands.rating_leaderboard.options.season.description',
|
||||
),
|
||||
strings.bot.commands.rating_leaderboard.options.season
|
||||
.description,
|
||||
)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.rating_leaderboard.options.season.description',
|
||||
(strings) =>
|
||||
strings.bot.commands.rating_leaderboard.options.season
|
||||
.description,
|
||||
),
|
||||
)
|
||||
.setRequired(false)
|
||||
@@ -112,15 +121,18 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
|
||||
return {
|
||||
name: current
|
||||
? translate(
|
||||
'bot.commands.rating_leaderboard.options.season.choices.current',
|
||||
? literals(
|
||||
strings.bot.commands.rating_leaderboard.options.season
|
||||
.choices.current,
|
||||
[`${number}`],
|
||||
)
|
||||
: `${number}`,
|
||||
value: `${number}`,
|
||||
name_localizations: current
|
||||
? localizationObject(
|
||||
'bot.commands.rating_leaderboard.options.season.choices.current',
|
||||
(strings) =>
|
||||
strings.bot.commands.rating_leaderboard.options
|
||||
.season.choices.current,
|
||||
[`${number}`],
|
||||
)
|
||||
: undefined,
|
||||
@@ -145,35 +157,45 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
modify(option: SlashCommandSubcommandBuilder) {
|
||||
option
|
||||
.addStringOption((option) => {
|
||||
const { t, translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
return option
|
||||
.setName(t`bot.commands.rating_leaderboard.options.league`)
|
||||
.setName(
|
||||
strings.bot.commands.rating_leaderboard.options.league.name,
|
||||
)
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.rating_leaderboard.options.league',
|
||||
(strings) =>
|
||||
strings.bot.commands.rating_leaderboard.options.league
|
||||
.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
translate(
|
||||
'bot.commands.rating_leaderboard.options.league.description',
|
||||
),
|
||||
strings.bot.commands.rating_leaderboard.options.league
|
||||
.description,
|
||||
)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.rating_leaderboard.options.league.description',
|
||||
(strings) =>
|
||||
strings.bot.commands.rating_leaderboard.options.league
|
||||
.description,
|
||||
),
|
||||
)
|
||||
.addChoices(
|
||||
...LEAGUES.map(
|
||||
({ name }, value) =>
|
||||
({
|
||||
name: translate(`common.leagues.${name}`),
|
||||
name: (
|
||||
strings.common.leagues as Record<string, string>
|
||||
)[name],
|
||||
value: `${value}`,
|
||||
name_localizations: localizationObject(
|
||||
`common.leagues.${name}`,
|
||||
(strings) =>
|
||||
(
|
||||
strings.common.leagues as Record<string, string>
|
||||
)[name],
|
||||
),
|
||||
}) satisfies APIApplicationCommandOptionChoice<string>,
|
||||
),
|
||||
@@ -189,7 +211,7 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
// BIG TODO: title seems to be in english
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const subcommand = interaction.options.getSubcommand(true) as
|
||||
| 'league'
|
||||
| 'neighbors';
|
||||
@@ -223,7 +245,8 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
regionRatingInfo !== null &&
|
||||
regionRatingInfo.detail !== undefined
|
||||
) {
|
||||
return t`bot.commands.rating_leaderboard.body.no_ongoing_season`;
|
||||
return strings.bot.commands.rating_leaderboard.body
|
||||
.no_ongoing_season;
|
||||
}
|
||||
|
||||
const result = isCurrentSeason
|
||||
@@ -268,8 +291,9 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
clan: clanData[player.id]?.clan?.tag,
|
||||
nickname:
|
||||
clanData[index]?.account_name ??
|
||||
translate(
|
||||
'bot.commands.rating_leaderboard.body.deleted_player',
|
||||
literals(
|
||||
strings.bot.commands.rating_leaderboard.body
|
||||
.deleted_player,
|
||||
[`${player.id}`],
|
||||
),
|
||||
}) satisfies SimplifiedPlayer,
|
||||
@@ -289,12 +313,14 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
: regionRatingInfo.count) - result[result.length - 1].position;
|
||||
titleName = `${
|
||||
leagueInfo
|
||||
? translate(`common.leagues.${LEAGUES[leagueInfo.index].name}`)
|
||||
? (strings.common.leagues as Record<string, string>)[
|
||||
LEAGUES[leagueInfo.index].name
|
||||
]
|
||||
: ''
|
||||
} - ${translate(`common.regions.short.${region}`)}`;
|
||||
} - ${strings.common.regions.short[region]}`;
|
||||
titleImage = imgur(leagueInfo.icon);
|
||||
titleDescription = translate(
|
||||
'bot.commands.rating_leaderboard.body.top_players',
|
||||
titleDescription = literals(
|
||||
strings.bot.commands.rating_leaderboard.body.top_players,
|
||||
[`${limit}`],
|
||||
);
|
||||
} else {
|
||||
@@ -307,7 +333,8 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
regionRatingInfo !== null &&
|
||||
regionRatingInfo.detail !== undefined
|
||||
) {
|
||||
return t`bot.commands.rating_leaderboard.body.no_ongoing_season`;
|
||||
return strings.bot.commands.rating_leaderboard.body
|
||||
.no_ongoing_season;
|
||||
}
|
||||
|
||||
const accountInfo = await getAccountInfo(region, id);
|
||||
@@ -334,8 +361,9 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
|
||||
if (playerIndex === -1) {
|
||||
throw new UserError(
|
||||
translate(
|
||||
'bot.commands.rating_leaderboard.body.no_participation',
|
||||
literals(
|
||||
strings.bot.commands.rating_leaderboard.body
|
||||
.no_participation,
|
||||
[markdownEscape(accountInfo.nickname), `${season}`],
|
||||
),
|
||||
);
|
||||
@@ -373,7 +401,8 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clan.emblem_set_id}.png`
|
||||
: undefined;
|
||||
titleName = neighbors ? accountInfo.nickname : '';
|
||||
titleDescription = t`bot.commands.rating_leaderboard.body.neighbors`;
|
||||
titleDescription =
|
||||
strings.bot.commands.rating_leaderboard.body.neighbors;
|
||||
playersAfter =
|
||||
(regionRatingInfo === null
|
||||
? archivedLeaderboard.version!.value.entries.length
|
||||
@@ -422,8 +451,8 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
|
||||
{items}
|
||||
{playersAfter > 0 && (
|
||||
<Leaderboard.Gap
|
||||
message={translate(
|
||||
'bot.commands.rating_leaderboard.body.more',
|
||||
message={literals(
|
||||
strings.bot.commands.rating_leaderboard.body.more,
|
||||
[`${playersAfter.toLocaleString(interaction.locale)}`],
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
tankIcon,
|
||||
TIER_ROMAN_NUMERALS,
|
||||
} from '@blitzkit/core';
|
||||
import { Locale } from 'discord.js';
|
||||
import { clamp } from 'lodash-es';
|
||||
import { CommandWrapper } from '../components/CommandWrapper';
|
||||
import { TitleBar } from '../components/TitleBar';
|
||||
@@ -18,6 +19,7 @@ import { RenderConfiguration } from '../core/blitzkit/renderConfiguration';
|
||||
import { blitzStarsTankAverages } from '../core/blitzstars/tankAverages';
|
||||
import { buttonLink } from '../core/discord/buttonLink';
|
||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||
import { translator } from '../core/localization/translator';
|
||||
import { CommandRegistry } from '../events/interactionCreate';
|
||||
import { theme } from '../stitches.config';
|
||||
|
||||
@@ -218,11 +220,13 @@ function stat(value: string | number, flex = 2) {
|
||||
}
|
||||
|
||||
async function playerListing(
|
||||
locale: Locale,
|
||||
player: WotInspectorReplayPlayerData,
|
||||
protagonistTeam: boolean,
|
||||
winningTeam: number,
|
||||
recordingPlayer = false,
|
||||
) {
|
||||
const { unwrap } = translator(locale);
|
||||
const awaitedTankAverages = await blitzStarsTankAverages;
|
||||
const awaitedTankDefinitions = await tankDefinitions;
|
||||
const tank = awaitedTankDefinitions.tanks[player.vehicle_descr];
|
||||
@@ -275,7 +279,7 @@ async function playerListing(
|
||||
}}
|
||||
>
|
||||
<img
|
||||
alt={tank.name}
|
||||
alt={unwrap(tank.name)}
|
||||
src={await iconPng(tankIcon(tank.id))}
|
||||
style={{
|
||||
width: 32,
|
||||
@@ -312,7 +316,7 @@ async function playerListing(
|
||||
fontSize: 16,
|
||||
}}
|
||||
>
|
||||
{tank.name}
|
||||
{unwrap(tank.name)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -530,6 +534,7 @@ export const replayCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
)
|
||||
.map((player) =>
|
||||
playerListing(
|
||||
interaction.locale,
|
||||
player,
|
||||
true,
|
||||
replayData.winner_team,
|
||||
@@ -553,7 +558,12 @@ export const replayCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
players
|
||||
.filter((player) => player.team === antagonistTeamId)
|
||||
.map((player) =>
|
||||
playerListing(player, false, replayData.winner_team),
|
||||
playerListing(
|
||||
interaction.locale,
|
||||
player,
|
||||
false,
|
||||
replayData.winner_team,
|
||||
),
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
TankType,
|
||||
TIER_ROMAN_NUMERALS,
|
||||
} from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { escapeMarkdown, Locale } from 'discord.js';
|
||||
import { CommandWrapper } from '../components/CommandWrapper';
|
||||
import { TitleBar } from '../components/TitleBar';
|
||||
@@ -28,26 +29,28 @@ import { CommandRegistry } from '../events/interactionCreate';
|
||||
import { theme } from '../stitches.config';
|
||||
|
||||
export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
const { t } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
resolve({
|
||||
command: createLocalizedCommand('research')
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName(t`bot.commands.research.options.target_tank`)
|
||||
.setName(strings.bot.commands.research.options.target_tank.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.research.options.target_tank',
|
||||
(strings) =>
|
||||
strings.bot.commands.research.options.target_tank.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
t`bot.commands.research.options.target_tank.description`,
|
||||
strings.bot.commands.research.options.target_tank.description,
|
||||
)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.research.options.target_tank.description',
|
||||
(strings) =>
|
||||
strings.bot.commands.research.options.target_tank.description,
|
||||
),
|
||||
)
|
||||
.setAutocomplete(true)
|
||||
@@ -55,20 +58,22 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName(t`bot.commands.research.options.starting_tank`)
|
||||
.setName(strings.bot.commands.research.options.starting_tank.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.research.options.starting_tank',
|
||||
(strings) =>
|
||||
strings.bot.commands.research.options.starting_tank.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
t`bot.commands.research.options.starting_tank.description`,
|
||||
strings.bot.commands.research.options.starting_tank.description,
|
||||
)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.research.options.starting_tank.description',
|
||||
(strings) =>
|
||||
strings.bot.commands.research.options.starting_tank.description,
|
||||
),
|
||||
)
|
||||
.setAutocomplete(true)
|
||||
@@ -77,7 +82,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
.addStringOption(addUsernameChoices),
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const { strings, unwrap } = translator(interaction.locale);
|
||||
const awaitedTankDefinitions = await tankDefinitions;
|
||||
const targetTankId = await resolveTankId(
|
||||
interaction.options.getString('target-tank', true),
|
||||
@@ -98,50 +103,55 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
);
|
||||
|
||||
if (targetTankId === startingTankId) {
|
||||
return translate('bot.commands.research.errors.start_end_equal', [
|
||||
escapeMarkdown(targetTank.name),
|
||||
]);
|
||||
return literals(
|
||||
strings.bot.commands.research.errors.start_end_equal,
|
||||
[escapeMarkdown(unwrap(targetTank.name))],
|
||||
);
|
||||
}
|
||||
|
||||
const startingTank = awaitedTankDefinitions.tanks[startingTankId];
|
||||
|
||||
if (startingTank.tier > targetTank.tier) {
|
||||
return translate('bot.commands.research.errors.unordered', [
|
||||
escapeMarkdown(startingTank.name),
|
||||
escapeMarkdown(targetTank.name),
|
||||
escapeMarkdown(targetTank.name),
|
||||
return literals(strings.bot.commands.research.errors.unordered, [
|
||||
escapeMarkdown(unwrap(startingTank.name)),
|
||||
escapeMarkdown(unwrap(targetTank.name)),
|
||||
escapeMarkdown(unwrap(targetTank.name)),
|
||||
]);
|
||||
}
|
||||
|
||||
if (!targetTankAncestry.includes(startingTankId)) {
|
||||
return translate('bot.commands.research.errors.tanks_not_on_line', [
|
||||
escapeMarkdown(targetTank.name),
|
||||
escapeMarkdown(startingTank.name),
|
||||
]);
|
||||
return literals(
|
||||
strings.bot.commands.research.errors.tanks_not_on_line,
|
||||
[
|
||||
escapeMarkdown(unwrap(targetTank.name)),
|
||||
escapeMarkdown(unwrap(startingTank.name)),
|
||||
],
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (targetTank.type !== TankType.RESEARCHABLE) {
|
||||
return translate('bot.commands.research.errors.non_tech_tree', [
|
||||
escapeMarkdown(targetTank.name),
|
||||
return literals(strings.bot.commands.research.errors.non_tech_tree, [
|
||||
escapeMarkdown(unwrap(targetTank.name)),
|
||||
]);
|
||||
}
|
||||
|
||||
if (targetTank.tier === 1) {
|
||||
return translate('bot.commands.research.errors.tier_1', [
|
||||
escapeMarkdown(targetTank.name),
|
||||
return literals(strings.bot.commands.research.errors.tier_1, [
|
||||
escapeMarkdown(unwrap(targetTank.name)),
|
||||
]);
|
||||
}
|
||||
|
||||
const tankStats = await getTankStats(region, id);
|
||||
|
||||
if (tankStats === null) {
|
||||
return t`bot.common.errors.no_tank_stats`;
|
||||
return strings.bot.common.errors.no_tank_stats;
|
||||
}
|
||||
|
||||
if (tankStats.some(({ tank_id }) => tank_id === targetTankId)) {
|
||||
return translate('bot.commands.research.errors.already_researched', [
|
||||
escapeMarkdown(targetTank.name),
|
||||
]);
|
||||
return literals(
|
||||
strings.bot.commands.research.errors.already_researched,
|
||||
[escapeMarkdown(unwrap(targetTank.name))],
|
||||
);
|
||||
}
|
||||
|
||||
const foundAncestor = targetTankAncestry.find(
|
||||
@@ -255,7 +265,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
<TitleBar
|
||||
title={nickname}
|
||||
image={clanImage}
|
||||
description={`${t`bot.commands.research.body.subtitle`} • ${
|
||||
description={`${strings.bot.commands.research.body.subtitle} • ${
|
||||
targetTank.name
|
||||
}`}
|
||||
/>
|
||||
@@ -292,7 +302,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
color: theme.colors.textHighContrast,
|
||||
}}
|
||||
>
|
||||
{t`bot.commands.research.body.total`}
|
||||
{strings.bot.commands.research.body.total}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -452,7 +462,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
}}
|
||||
>
|
||||
<img
|
||||
alt={tank.name}
|
||||
alt={unwrap(tank.name)}
|
||||
src={TANK_ICONS[tank.class]}
|
||||
width={16}
|
||||
height={16}
|
||||
@@ -463,7 +473,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
color: theme.colors.textHighContrast,
|
||||
}}
|
||||
>
|
||||
{tank.name}
|
||||
{unwrap(tank.name)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -497,11 +507,14 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
color: theme.colors.textHighContrast,
|
||||
}}
|
||||
>
|
||||
{translate('bot.commands.research.body.research', [
|
||||
`${costs[index].research?.toLocaleString(
|
||||
interaction.locale,
|
||||
)}`,
|
||||
])}
|
||||
{literals(
|
||||
strings.bot.commands.research.body.research,
|
||||
[
|
||||
`${costs[index].research?.toLocaleString(
|
||||
interaction.locale,
|
||||
)}`,
|
||||
],
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -527,9 +540,10 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
color: theme.colors.textHighContrast,
|
||||
}}
|
||||
>
|
||||
{translate('bot.commands.research.body.upgrades', [
|
||||
costs[index].upgrades.toLocaleString(),
|
||||
])}
|
||||
{literals(
|
||||
strings.bot.commands.research.body.upgrades,
|
||||
[costs[index].upgrades.toLocaleString()],
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -555,11 +569,14 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
color: theme.colors.textHighContrast,
|
||||
}}
|
||||
>
|
||||
{translate('bot.commands.research.body.purchase', [
|
||||
costs[index].purchase.toLocaleString(
|
||||
interaction.locale,
|
||||
),
|
||||
])}
|
||||
{literals(
|
||||
strings.bot.commands.research.body.purchase,
|
||||
[
|
||||
costs[index].purchase.toLocaleString(
|
||||
interaction.locale,
|
||||
),
|
||||
],
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -584,11 +601,14 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
color: theme.colors.textHighContrast,
|
||||
}}
|
||||
>
|
||||
{translate('bot.commands.research.body.equipment', [
|
||||
costs[index].equipment.toLocaleString(
|
||||
interaction.locale,
|
||||
),
|
||||
])}
|
||||
{literals(
|
||||
strings.bot.commands.research.body.equipment,
|
||||
[
|
||||
costs[index].equipment.toLocaleString(
|
||||
interaction.locale,
|
||||
),
|
||||
],
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -602,7 +622,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
|
||||
return startingTankRaw
|
||||
? image
|
||||
: [t`bot.commands.research.body.estimation`, image];
|
||||
: [strings.bot.commands.research.body.estimation, image];
|
||||
},
|
||||
|
||||
autocomplete(interaction) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ClanList, fetchBlitz, Region } from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { Locale } from 'discord.js';
|
||||
import markdownEscape from 'markdown-escape';
|
||||
import { addClanChoices } from '../core/discord/addClanChoices';
|
||||
@@ -19,25 +20,27 @@ export const searchClansCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
addClanChoices(option).setAutocomplete(false),
|
||||
)
|
||||
.addIntegerOption((option) => {
|
||||
const { t, translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
return option
|
||||
.setName(t`bot.commands.search_clans.options.limit`)
|
||||
.setName(strings.bot.commands.search_clans.options.limit.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.search_clans.options.limit',
|
||||
(strings) => strings.bot.commands.search_clans.options.limit.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
translate('bot.commands.search_clans.options.limit.description', [
|
||||
`${DEFAULT_LIMIT}`,
|
||||
]),
|
||||
literals(
|
||||
strings.bot.commands.search_clans.options.limit.description,
|
||||
[`${DEFAULT_LIMIT}`],
|
||||
),
|
||||
)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.search_clans.options.limit.description',
|
||||
(strings) =>
|
||||
strings.bot.commands.search_clans.options.limit.description,
|
||||
[`${DEFAULT_LIMIT}`],
|
||||
),
|
||||
)
|
||||
@@ -46,7 +49,7 @@ export const searchClansCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
}),
|
||||
|
||||
async handler(interaction) {
|
||||
const { translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const region = interaction.options.getString('region') as Region;
|
||||
const clan = interaction.options.getString('clan')!;
|
||||
const limit = interaction.options.getInteger('limit') ?? DEFAULT_LIMIT;
|
||||
@@ -56,12 +59,12 @@ export const searchClansCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
});
|
||||
|
||||
return embedInfo(
|
||||
translate('bot.commands.search_clans.body.title', [
|
||||
literals(strings.bot.commands.search_clans.body.title, [
|
||||
markdownEscape(clan),
|
||||
translate(`common.regions.normal.${region}`),
|
||||
strings.common.regions.normal[region],
|
||||
]),
|
||||
clanList.length === 0
|
||||
? translate('bot.commands.search_clans.body.no_results')
|
||||
? strings.bot.commands.search_clans.body.no_results
|
||||
: `\`\`\`\n${clanList
|
||||
.map((clan) => `${clan.name} [${clan.tag}]`)
|
||||
.join('\n')}\n\`\`\``,
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
Region,
|
||||
usernamePattern,
|
||||
} from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { Locale } from 'discord.js';
|
||||
import markdownEscape from 'markdown-escape';
|
||||
import { addRegionChoices } from '../core/discord/addRegionChoices';
|
||||
@@ -17,7 +18,7 @@ import { CommandRegistry } from '../events/interactionCreate';
|
||||
const DEFAULT_LIMIT = 25;
|
||||
|
||||
export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
const { t, translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
resolve({
|
||||
command: createLocalizedCommand('search-players')
|
||||
@@ -27,22 +28,25 @@ export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName(t`bot.commands.search_players.options.limit`)
|
||||
.setName(strings.bot.commands.search_players.options.limit.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.search_players.options.limit',
|
||||
(strings) =>
|
||||
strings.bot.commands.search_players.options.limit.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
translate('bot.commands.search_players.options.limit.description', [
|
||||
`${DEFAULT_LIMIT}`,
|
||||
]),
|
||||
literals(
|
||||
strings.bot.commands.search_players.options.limit.description,
|
||||
[`${DEFAULT_LIMIT}`],
|
||||
),
|
||||
)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject(
|
||||
'bot.commands.search_players.options.limit.description',
|
||||
(strings) =>
|
||||
strings.bot.commands.search_players.options.limit.description,
|
||||
[`${DEFAULT_LIMIT}`],
|
||||
),
|
||||
)
|
||||
@@ -51,7 +55,7 @@ export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
),
|
||||
|
||||
async handler(interaction) {
|
||||
const { translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const region = interaction.options.getString('region') as Region;
|
||||
const name = interaction.options.getString('username')!;
|
||||
const limit = interaction.options.getInteger('limit') ?? 25;
|
||||
@@ -64,13 +68,13 @@ export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
: [];
|
||||
|
||||
return embedInfo(
|
||||
translate('bot.commands.search_players.body.title', [
|
||||
literals(strings.bot.commands.search_players.body.title, [
|
||||
markdownEscape(trimmedSearch),
|
||||
translate(`common.regions.normal.${region}`),
|
||||
strings.common.regions.normal[region],
|
||||
]),
|
||||
`\`\`\`${
|
||||
players.length === 0
|
||||
? translate('bot.commands.search_players.body.no_results')
|
||||
? strings.bot.commands.search_players.body.no_results
|
||||
: players.map((player) => player.nickname).join('\n')
|
||||
}\`\`\``,
|
||||
);
|
||||
|
||||
@@ -32,7 +32,7 @@ export function AllStatsOverview({
|
||||
locale,
|
||||
supplementaryStats,
|
||||
}: AllStatsOverviewProps) {
|
||||
const { t, translate } = translator(locale);
|
||||
const { strings } = translator(locale);
|
||||
const percentile =
|
||||
typeof supplementaryStats.WN8 === 'number'
|
||||
? getWN8Percentile(supplementaryStats.WN8)
|
||||
@@ -63,18 +63,18 @@ export function AllStatsOverview({
|
||||
}}
|
||||
>
|
||||
<WN8SurroundingStat
|
||||
label={t`bot.common.hero_stats.battles`}
|
||||
label={strings.bot.common.hero_stats.battles}
|
||||
value={stats.battles.toLocaleString()}
|
||||
align={WN8SurroundingStatAlign.Right}
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label={t`bot.common.hero_stats.winrate`}
|
||||
label={strings.bot.common.hero_stats.winrate}
|
||||
value={`${(100 * (stats.wins / stats.battles)).toFixed(2)}%`}
|
||||
align={WN8SurroundingStatAlign.Right}
|
||||
padded
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label={t`bot.common.hero_stats.damage`}
|
||||
label={strings.bot.common.hero_stats.damage}
|
||||
value={Math.round(
|
||||
stats.damage_dealt / stats.battles,
|
||||
).toLocaleString()}
|
||||
@@ -82,7 +82,7 @@ export function AllStatsOverview({
|
||||
padded
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label={t`bot.common.hero_stats.damage_ratio`}
|
||||
label={strings.bot.common.hero_stats.damage_ratio}
|
||||
value={(stats.damage_dealt / stats.damage_received).toFixed(2)}
|
||||
align={WN8SurroundingStatAlign.Right}
|
||||
/>
|
||||
@@ -90,7 +90,7 @@ export function AllStatsOverview({
|
||||
|
||||
<HeroStat
|
||||
value={heroStat}
|
||||
subtitle={translate(`common.wn8_percentile.${percentile}`)}
|
||||
subtitle={strings.common.wn8_percentile[percentile]}
|
||||
color={color}
|
||||
/>
|
||||
|
||||
@@ -103,25 +103,25 @@ export function AllStatsOverview({
|
||||
}}
|
||||
>
|
||||
<WN8SurroundingStat
|
||||
label={t`bot.common.hero_stats.tier`}
|
||||
label={strings.bot.common.hero_stats.tier}
|
||||
value={
|
||||
supplementaryStats.tier ? supplementaryStats.tier.toFixed(2) : '--'
|
||||
}
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label={t`bot.common.hero_stats.survival`}
|
||||
label={strings.bot.common.hero_stats.survival}
|
||||
value={`${(100 * (stats.survived_battles / stats.battles)).toFixed(
|
||||
2,
|
||||
)}%`}
|
||||
padded
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label={t`bot.common.hero_stats.accuracy`}
|
||||
label={strings.bot.common.hero_stats.accuracy}
|
||||
value={`${(100 * (stats.hits / stats.shots)).toFixed(2)}%`}
|
||||
padded
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label={t`bot.common.hero_stats.kills`}
|
||||
label={strings.bot.common.hero_stats.kills}
|
||||
value={(stats.frags / stats.battles).toFixed(2)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@ export function GenericAllStats({
|
||||
supplementaryStats,
|
||||
locale,
|
||||
}: GenericAllStatsProps) {
|
||||
const { t } = translator(locale);
|
||||
const { strings } = translator(locale);
|
||||
const damageRatio = stats.damage_dealt / stats.damage_received;
|
||||
const killsToDeathRatio =
|
||||
stats.frags / (stats.battles - stats.survived_battles);
|
||||
@@ -30,27 +30,28 @@ export function GenericAllStats({
|
||||
<Root>
|
||||
<Row>
|
||||
<Card
|
||||
title={t`bot.commands.full_stats.body.cards.games`}
|
||||
title={strings.bot.commands.full_stats.body.cards.games.title}
|
||||
items={[
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.games.winrate`,
|
||||
label: strings.bot.commands.full_stats.body.cards.games.winrate,
|
||||
value: `${(100 * (stats.wins / stats.battles)).toFixed(2)}%`,
|
||||
},
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.games.battles`,
|
||||
label: strings.bot.commands.full_stats.body.cards.games.battles,
|
||||
value: stats.battles,
|
||||
},
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.games.wins_losses`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.games.wins_losses,
|
||||
value: `${stats.wins} / ${stats.losses}`,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Card
|
||||
title={t`bot.commands.full_stats.body.cards.efficiency`}
|
||||
title={strings.bot.commands.full_stats.body.cards.efficiency.title}
|
||||
items={[
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.efficiency.wn8`,
|
||||
label: strings.bot.commands.full_stats.body.cards.efficiency.wn8,
|
||||
value:
|
||||
supplementaryStats && isNumber(supplementaryStats.WN8)
|
||||
? supplementaryStats.WN8!.toFixed(0)
|
||||
@@ -60,14 +61,16 @@ export function GenericAllStats({
|
||||
: undefined,
|
||||
},
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.efficiency.survival`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.efficiency.survival,
|
||||
value: `${(
|
||||
100 *
|
||||
(stats.survived_battles / stats.battles)
|
||||
).toFixed(2)}%`,
|
||||
},
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.efficiency.accuracy`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.efficiency.accuracy,
|
||||
value: `${((stats.hits / stats.shots) * 100).toFixed(2)}%`,
|
||||
},
|
||||
]}
|
||||
@@ -75,14 +78,18 @@ export function GenericAllStats({
|
||||
</Row>
|
||||
<Row>
|
||||
<Card
|
||||
title={t`bot.commands.full_stats.body.cards.lethality`}
|
||||
title={strings.bot.commands.full_stats.body.cards.lethality.title}
|
||||
items={[
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.lethality.average_damage`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.lethality
|
||||
.average_damage,
|
||||
value: (stats.damage_dealt / stats.battles).toFixed(0),
|
||||
},
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.lethality.damage_per_tier`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.lethality
|
||||
.damage_per_tier,
|
||||
value: supplementaryStats?.tier
|
||||
? (
|
||||
stats.damage_dealt /
|
||||
@@ -92,32 +99,44 @@ export function GenericAllStats({
|
||||
: undefined,
|
||||
},
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.lethality.damage_ratio`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.lethality
|
||||
.damage_ratio,
|
||||
value: isFinite(damageRatio) ? damageRatio.toFixed(2) : undefined,
|
||||
},
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.lethality.average_kills`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.lethality
|
||||
.average_kills,
|
||||
value: (stats.frags / stats.battles).toFixed(0),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Card
|
||||
title={t`bot.commands.full_stats.body.cards.miscellaneous`}
|
||||
title={strings.bot.commands.full_stats.body.cards.miscellaneous.title}
|
||||
items={[
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.miscellaneous.average_tier`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.miscellaneous
|
||||
.average_tier,
|
||||
value: supplementaryStats?.tier?.toFixed(2),
|
||||
},
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.miscellaneous.average_spots`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.miscellaneous
|
||||
.average_spots,
|
||||
value: (stats.spotted / stats.battles).toFixed(2),
|
||||
},
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.miscellaneous.average_xp`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.miscellaneous
|
||||
.average_xp,
|
||||
value: (stats.xp / stats.battles).toFixed(0),
|
||||
},
|
||||
{
|
||||
label: t`bot.commands.full_stats.body.cards.miscellaneous.kills_to_death_ratio`,
|
||||
label:
|
||||
strings.bot.commands.full_stats.body.cards.miscellaneous
|
||||
.kills_to_death_ratio,
|
||||
value: isFinite(killsToDeathRatio)
|
||||
? killsToDeathRatio.toFixed(2)
|
||||
: undefined,
|
||||
|
||||
@@ -12,7 +12,7 @@ interface NoDataProps {
|
||||
}
|
||||
|
||||
export function NoData({ type, locale }: NoDataProps) {
|
||||
const { translate } = translator(locale);
|
||||
const { strings } = translator(locale);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -23,7 +23,7 @@ export function NoData({ type, locale }: NoDataProps) {
|
||||
}}
|
||||
>
|
||||
<span style={{ fontSize: 16, color: theme.colors.textLowContrast }}>
|
||||
{translate(`bot.common.no_data.${type}`)}
|
||||
{strings.bot.common.no_data[type]}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { SEARCH_KEYS } from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { Locale } from 'discord.js';
|
||||
import { go } from 'fuzzysort';
|
||||
import markdownEscape from 'markdown-escape';
|
||||
@@ -11,22 +13,19 @@ export async function resolveTankId(
|
||||
locale: Locale,
|
||||
techTreeOnly = false,
|
||||
) {
|
||||
const { translate } = translator(locale);
|
||||
const { strings } = translator(locale);
|
||||
const number = typeof tank === 'string' ? Number(tank) : tank;
|
||||
|
||||
if (Number.isNaN(number)) {
|
||||
const searchResult = go(
|
||||
`${tank}`,
|
||||
await (techTreeOnly ? tankNamesTechTreeOnly : tankNames),
|
||||
{
|
||||
keys: ['searchableName', 'searchableNameDeburr', 'camouflages'],
|
||||
limit: 1,
|
||||
},
|
||||
{ keys: SEARCH_KEYS, limit: 1 },
|
||||
);
|
||||
|
||||
if (searchResult.length === 0) {
|
||||
throw new UserError(
|
||||
translate('bot.common.errors.tank_name_not_found', [
|
||||
literals(strings.bot.common.errors.tank_name_not_found, [
|
||||
markdownEscape(`${tank}`),
|
||||
]),
|
||||
);
|
||||
@@ -40,7 +39,7 @@ export async function resolveTankId(
|
||||
return number;
|
||||
} else {
|
||||
throw new UserError(
|
||||
translate('bot.common.errors.tank_id_not_found', [`${number}`]),
|
||||
literals(strings.bot.common.errors.tank_id_not_found, [`${number}`]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,15 @@ export async function searchClansAcrossRegionsBotWrapper(
|
||||
locale: Locale,
|
||||
limit?: number,
|
||||
) {
|
||||
const { t } = translator(locale);
|
||||
const { strings } = translator(locale);
|
||||
const trimmed = search.trim();
|
||||
|
||||
if (trimmed.length < 3) {
|
||||
throw new UserError(t`bot.common.errors.query_too_small`);
|
||||
throw new UserError(strings.bot.common.errors.query_too_small);
|
||||
}
|
||||
|
||||
if (trimmed.length > 100) {
|
||||
throw new UserError(t`bot.common.errors.query_too_long`);
|
||||
throw new UserError(strings.bot.common.errors.query_too_long);
|
||||
}
|
||||
|
||||
return await searchClansAcrossRegions(trimmed, limit);
|
||||
|
||||
@@ -8,15 +8,15 @@ export async function searchPlayersAcrossRegionsBotWrapper(
|
||||
locale: Locale,
|
||||
limit?: number,
|
||||
) {
|
||||
const { t } = translator(locale);
|
||||
const { strings } = translator(locale);
|
||||
const trimmed = search.trim();
|
||||
|
||||
if (trimmed.length < 3) {
|
||||
throw new UserError(t`bot.common.errors.query_too_small`);
|
||||
throw new UserError(strings.bot.common.errors.query_too_small);
|
||||
}
|
||||
|
||||
if (trimmed.length > 100) {
|
||||
throw new UserError(t`bot.common.errors.query_too_long`);
|
||||
throw new UserError(strings.bot.common.errors.query_too_long);
|
||||
}
|
||||
|
||||
return await searchPlayersAcrossRegions(trimmed, limit);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { fetchTankDefinitions, TIER_ROMAN_NUMERALS } from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { Locale } from 'discord.js';
|
||||
import { StatFilters } from '../blitzstars/filterStats';
|
||||
import { translator } from '../localization/translator';
|
||||
@@ -7,22 +8,21 @@ export async function filtersToDescription(
|
||||
{ nation, tier, type, class: tankClass, tank }: StatFilters,
|
||||
locale: Locale,
|
||||
) {
|
||||
const { translate } = translator(locale);
|
||||
const { strings } = translator(locale);
|
||||
const awaitedTankDefinitions = await fetchTankDefinitions();
|
||||
const info: string[] = [];
|
||||
|
||||
// TODO: somehow localize tank names?
|
||||
if (tank) return awaitedTankDefinitions.tanks[tank].name;
|
||||
if (nation) info.push(translate(`common.nations.${nation}`));
|
||||
if (nation)
|
||||
info.push((strings.common.nations as Record<string, string>)[nation]);
|
||||
if (tier) {
|
||||
info.push(
|
||||
translate('bot.common.filters.tier', [TIER_ROMAN_NUMERALS[tier]]),
|
||||
literals(strings.bot.common.filters.tier, [TIER_ROMAN_NUMERALS[tier]]),
|
||||
);
|
||||
}
|
||||
if (tankClass) info.push(translate(`common.tank_class_short.${tankClass}`));
|
||||
if (type) info.push(translate(`common.tree_type.${type}`));
|
||||
if (tankClass) info.push(strings.common.tank_class_short[tankClass]);
|
||||
if (type) info.push(strings.common.tree_type[type]);
|
||||
|
||||
return info.length === 0
|
||||
? translate('bot.common.filters.none')
|
||||
: info.join(', ');
|
||||
return info.length === 0 ? strings.bot.common.filters.none : info.join(', ');
|
||||
}
|
||||
@@ -38,7 +38,7 @@ export async function getTankHistories(
|
||||
locale: Locale,
|
||||
options?: Partial<GetTankHistoriesOptions>,
|
||||
) {
|
||||
const { t } = translator(locale);
|
||||
const { strings } = translator(locale);
|
||||
const mergedOptions = { ...getTankHistoriesDefaultOptions, ...options };
|
||||
const tankHistoriesResponse = await fetch(
|
||||
`https://www.blitzstars.com/api/tankhistories/for/${id}/`,
|
||||
@@ -82,7 +82,7 @@ export async function getTankHistories(
|
||||
const tankStats = await getTankStats(server, id);
|
||||
|
||||
if (tankStats === null) {
|
||||
throw new UserError(t`bot.common.errors.no_tank_stats`);
|
||||
throw new UserError(strings.bot.common.errors.no_tank_stats);
|
||||
}
|
||||
|
||||
tankStats.forEach((tankHistory) => {
|
||||
|
||||
@@ -3,16 +3,22 @@ import { translator } from '../localization/translator';
|
||||
import { localizationObject } from './localizationObject';
|
||||
|
||||
export function addClanChoices(option: SlashCommandStringOption) {
|
||||
const { translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
return option
|
||||
.setName('clan')
|
||||
.setNameLocalizations(
|
||||
localizationObject('bot.common.options.clan', undefined, true),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.clan.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(translate('bot.common.options.clan.description'))
|
||||
.setDescription(strings.bot.common.options.clan.description)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject('bot.common.options.clan.description'),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.clan.description,
|
||||
),
|
||||
)
|
||||
.setAutocomplete(true)
|
||||
.setMinLength(2)
|
||||
|
||||
@@ -17,34 +17,40 @@ import { localizationObject } from './localizationObject';
|
||||
export function addFilterOptions<
|
||||
Option extends SlashCommandBuilder | SlashCommandSubcommandBuilder,
|
||||
>(option: Option, nations: string[]) {
|
||||
const { translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
return (
|
||||
option
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName(translate('bot.common.options.filters.nation'))
|
||||
.setName(strings.bot.common.options.filters.nation.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.common.options.filters.nation',
|
||||
(strings) => strings.bot.common.options.filters.nation.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
translate('bot.common.options.filters.nation.description'),
|
||||
)
|
||||
.setDescription(strings.bot.common.options.filters.nation.description)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject('bot.common.options.filters.nation.description'),
|
||||
localizationObject(
|
||||
(strings) =>
|
||||
strings.bot.common.options.filters.nation.description,
|
||||
),
|
||||
)
|
||||
.addChoices(
|
||||
...nations.map(
|
||||
(nation) =>
|
||||
({
|
||||
value: nation,
|
||||
name: translate(`common.nations.${nation}`),
|
||||
name: (strings.common.nations as Record<string, string>)[
|
||||
nation
|
||||
],
|
||||
name_localizations: localizationObject(
|
||||
`common.nations.${nation}`,
|
||||
(strings) =>
|
||||
(strings.common.nations as Record<string, string>)[
|
||||
nation
|
||||
],
|
||||
),
|
||||
}) satisfies APIApplicationCommandOptionChoice,
|
||||
),
|
||||
@@ -54,28 +60,28 @@ export function addFilterOptions<
|
||||
.addStringOption((option) => addTierChoices(option).setRequired(false))
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName(translate('bot.common.options.filters.class'))
|
||||
.setName(strings.bot.common.options.filters.class.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.common.options.filters.class',
|
||||
(strings) => strings.bot.common.options.filters.class.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
translate('bot.common.options.filters.class.description'),
|
||||
)
|
||||
.setDescription(strings.bot.common.options.filters.class.description)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject('bot.common.options.filters.class.description'),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.filters.class.description,
|
||||
),
|
||||
)
|
||||
.addChoices(
|
||||
...TANK_CLASSES.map(
|
||||
(tankType) =>
|
||||
({
|
||||
value: `${tankType}`,
|
||||
name: translate(`common.tank_class_short.${tankType}`),
|
||||
name: strings.common.tank_class_short[tankType],
|
||||
name_localizations: localizationObject(
|
||||
`common.tank_class_short.${tankType}`,
|
||||
(strings) => strings.common.tank_class_short[tankType],
|
||||
),
|
||||
}) satisfies APIApplicationCommandOptionChoice,
|
||||
),
|
||||
@@ -84,28 +90,28 @@ export function addFilterOptions<
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName(translate('bot.common.options.filters.type'))
|
||||
.setName(strings.bot.common.options.filters.type.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject(
|
||||
'bot.common.options.filters.type',
|
||||
(strings) => strings.bot.common.options.filters.type.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(
|
||||
translate('bot.common.options.filters.type.description'),
|
||||
)
|
||||
.setDescription(strings.bot.common.options.filters.type.description)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject('bot.common.options.filters.type.description'),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.filters.type.description,
|
||||
),
|
||||
)
|
||||
.addChoices(
|
||||
...TANK_TYPES.map(
|
||||
(treeType) =>
|
||||
({
|
||||
value: TANK_TYPE_COMMAND_NAMES[treeType],
|
||||
name: translate(`common.tree_type.${treeType}`),
|
||||
name: strings.common.tree_type[treeType],
|
||||
name_localizations: localizationObject(
|
||||
`common.tree_type.${treeType}`,
|
||||
(strings) => strings.common.tree_type[treeType],
|
||||
),
|
||||
}) satisfies APIApplicationCommandOptionChoice,
|
||||
),
|
||||
|
||||
@@ -16,39 +16,67 @@ export function addPeriodSubCommands(
|
||||
option: SlashCommandSubcommandBuilder,
|
||||
) => SlashCommandSubcommandBuilder = (option) => option,
|
||||
) {
|
||||
const { translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
const subcommandNameLocalizations = {
|
||||
today: localizationObject('bot.common.subcommands.today', undefined, true),
|
||||
30: localizationObject('bot.common.subcommands.30', undefined, true),
|
||||
60: localizationObject('bot.common.subcommands.60', undefined, true),
|
||||
90: localizationObject('bot.common.subcommands.90', undefined, true),
|
||||
today: localizationObject(
|
||||
(strings) => strings.bot.common.subcommands.today.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
30: localizationObject(
|
||||
(strings) => strings.bot.common.subcommands[30].name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
60: localizationObject(
|
||||
(strings) => strings.bot.common.subcommands[60].name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
90: localizationObject(
|
||||
(strings) => strings.bot.common.subcommands[90].name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
career: localizationObject(
|
||||
'bot.common.subcommands.career',
|
||||
(strings) => strings.bot.common.subcommands.career.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
custom: localizationObject(
|
||||
'bot.common.subcommands.custom',
|
||||
(strings) => strings.bot.common.subcommands.custom.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
};
|
||||
const subcommandDescriptionLocalizations = {
|
||||
today: localizationObject('bot.common.subcommands.today.description'),
|
||||
30: localizationObject('bot.common.subcommands.30.description'),
|
||||
60: localizationObject('bot.common.subcommands.60.description'),
|
||||
90: localizationObject('bot.common.subcommands.90.description'),
|
||||
career: localizationObject('bot.common.subcommands.career.description'),
|
||||
custom: localizationObject('bot.common.subcommands.custom.description'),
|
||||
today: localizationObject(
|
||||
(strings) => strings.bot.common.subcommands.today.description,
|
||||
),
|
||||
30: localizationObject(
|
||||
(strings) => strings.bot.common.subcommands[30].description,
|
||||
),
|
||||
60: localizationObject(
|
||||
(strings) => strings.bot.common.subcommands[60].description,
|
||||
),
|
||||
90: localizationObject(
|
||||
(strings) => strings.bot.common.subcommands[90].description,
|
||||
),
|
||||
career: localizationObject(
|
||||
(strings) => strings.bot.common.subcommands.career.description,
|
||||
),
|
||||
custom: localizationObject(
|
||||
(strings) => strings.bot.common.subcommands.custom.description,
|
||||
),
|
||||
};
|
||||
|
||||
option
|
||||
.addSubcommand((option) =>
|
||||
extra(
|
||||
option
|
||||
.setName(translate('bot.common.subcommands.today'))
|
||||
.setName(strings.bot.common.subcommands.today.name)
|
||||
.setNameLocalizations(subcommandNameLocalizations.today)
|
||||
.setDescription(translate('bot.common.subcommands.today.description'))
|
||||
.setDescription(strings.bot.common.subcommands.today.description)
|
||||
.setDescriptionLocalizations(
|
||||
subcommandDescriptionLocalizations.today,
|
||||
),
|
||||
@@ -57,38 +85,36 @@ export function addPeriodSubCommands(
|
||||
.addSubcommand((option) =>
|
||||
extra(
|
||||
option
|
||||
.setName(translate('bot.common.subcommands.30'))
|
||||
.setName(strings.bot.common.subcommands[30].name)
|
||||
.setNameLocalizations(subcommandNameLocalizations[30])
|
||||
.setDescription(translate('bot.common.subcommands.30.description'))
|
||||
.setDescription(strings.bot.common.subcommands[30].description)
|
||||
.setDescriptionLocalizations(subcommandDescriptionLocalizations[30]),
|
||||
),
|
||||
)
|
||||
.addSubcommand((option) =>
|
||||
extra(
|
||||
option
|
||||
.setName(translate('bot.common.subcommands.60'))
|
||||
.setName(strings.bot.common.subcommands[60].name)
|
||||
.setNameLocalizations(subcommandNameLocalizations[60])
|
||||
.setDescription(translate('bot.common.subcommands.60.description'))
|
||||
.setDescription(strings.bot.common.subcommands[60].description)
|
||||
.setDescriptionLocalizations(subcommandDescriptionLocalizations[60]),
|
||||
),
|
||||
)
|
||||
.addSubcommand((option) =>
|
||||
extra(
|
||||
option
|
||||
.setName(translate('bot.common.subcommands.90'))
|
||||
.setName(strings.bot.common.subcommands[90].name)
|
||||
.setNameLocalizations(subcommandNameLocalizations[90])
|
||||
.setDescription(translate('bot.common.subcommands.90.description'))
|
||||
.setDescription(strings.bot.common.subcommands[90].description)
|
||||
.setDescriptionLocalizations(subcommandDescriptionLocalizations[90]),
|
||||
),
|
||||
)
|
||||
.addSubcommand((option) =>
|
||||
extra(
|
||||
option
|
||||
.setName(translate('bot.common.subcommands.career'))
|
||||
.setName(strings.bot.common.subcommands.career.name)
|
||||
.setNameLocalizations(subcommandNameLocalizations.career)
|
||||
.setDescription(
|
||||
translate('bot.common.subcommands.career.description'),
|
||||
)
|
||||
.setDescription(strings.bot.common.subcommands.career.description)
|
||||
.setDescriptionLocalizations(
|
||||
subcommandDescriptionLocalizations.career,
|
||||
),
|
||||
@@ -97,31 +123,25 @@ export function addPeriodSubCommands(
|
||||
.addSubcommand((option) =>
|
||||
extra(
|
||||
option
|
||||
.setName(translate('bot.common.subcommands.custom'))
|
||||
.setName(strings.bot.common.subcommands.custom.name)
|
||||
.setNameLocalizations(subcommandNameLocalizations.custom)
|
||||
.setDescription(
|
||||
translate('bot.common.subcommands.custom.description'),
|
||||
)
|
||||
.setDescription(strings.bot.common.subcommands.custom.description)
|
||||
.setDescriptionLocalizations(
|
||||
subcommandDescriptionLocalizations.custom,
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName(translate('bot.common.subcommands.custom.options.start'))
|
||||
.setName(strings.bot.common.subcommands.custom.options.start.name)
|
||||
.setDescription(
|
||||
translate(
|
||||
'bot.common.subcommands.custom.options.start.description',
|
||||
),
|
||||
strings.bot.common.subcommands.custom.options.start.description,
|
||||
)
|
||||
.setRequired(true),
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName(translate('bot.common.subcommands.custom.options.end'))
|
||||
.setName(strings.bot.common.subcommands.custom.options.end.name)
|
||||
.setDescription(
|
||||
translate(
|
||||
'bot.common.subcommands.custom.options.end.description',
|
||||
),
|
||||
strings.bot.common.subcommands.custom.options.end.description,
|
||||
)
|
||||
.setRequired(true),
|
||||
),
|
||||
|
||||
@@ -8,25 +8,31 @@ import { translator } from '../localization/translator';
|
||||
import { localizationObject } from './localizationObject';
|
||||
|
||||
export function addRegionChoices(option: SlashCommandStringOption) {
|
||||
const { t, translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
return option
|
||||
.setName(t`bot.common.options.region`)
|
||||
.setName(strings.bot.common.options.region.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject('bot.common.options.region', undefined, true),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.region.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(t`bot.common.options.region.description`)
|
||||
.setDescription(strings.bot.common.options.region.description)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject('bot.common.options.region.description'),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.region.description,
|
||||
),
|
||||
)
|
||||
.addChoices(
|
||||
...REGIONS.map(
|
||||
(region) =>
|
||||
({
|
||||
value: region,
|
||||
name: translate(`common.regions.normal.${region}`),
|
||||
name: strings.common.regions.normal[region],
|
||||
name_localizations: localizationObject(
|
||||
`common.regions.normal.${region}`,
|
||||
(strings) => strings.common.regions.normal[region],
|
||||
),
|
||||
}) satisfies APIApplicationCommandOptionChoice,
|
||||
),
|
||||
|
||||
@@ -3,16 +3,22 @@ import { translator } from '../localization/translator';
|
||||
import { localizationObject } from './localizationObject';
|
||||
|
||||
export function addTankChoices(option: SlashCommandStringOption) {
|
||||
const { translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
return option
|
||||
.setName(translate('bot.common.options.tank'))
|
||||
.setName(strings.bot.common.options.tank.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject('bot.common.options.tank', undefined, true),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.tank.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(translate('bot.common.options.tank.description'))
|
||||
.setDescription(strings.bot.common.options.tank.description)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject('bot.common.options.tank.description'),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.tank.description,
|
||||
),
|
||||
)
|
||||
.setAutocomplete(true)
|
||||
.setRequired(true);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { numberToRomanNumeral } from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import {
|
||||
APIApplicationCommandOptionChoice,
|
||||
Locale,
|
||||
@@ -9,28 +10,34 @@ import { translator } from '../localization/translator';
|
||||
import { localizationObject } from './localizationObject';
|
||||
|
||||
export function addTierChoices(option: SlashCommandStringOption) {
|
||||
const { t, translate } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
return option
|
||||
.setName(t`bot.common.options.tier`)
|
||||
.setName(strings.bot.common.options.tier.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject('bot.common.options.tier', undefined, true),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.tier.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(t`bot.common.options.tier.description`)
|
||||
.setDescription(strings.bot.common.options.tier.description)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject('bot.common.options.tier.description'),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.tier.description,
|
||||
),
|
||||
)
|
||||
.setChoices(
|
||||
...range(10, 0).map(
|
||||
(tier) =>
|
||||
({
|
||||
name: translate('bot.common.options.tier.choices.tier', [
|
||||
name: literals(strings.bot.common.options.tier.choices.tier, [
|
||||
`${tier}`,
|
||||
numberToRomanNumeral(tier),
|
||||
]),
|
||||
value: `${tier}`,
|
||||
name_localizations: localizationObject(
|
||||
'bot.common.options.tier.choices.tier',
|
||||
(strings) => strings.bot.common.options.tier.choices.tier,
|
||||
[`${tier}`, numberToRomanNumeral(tier)],
|
||||
),
|
||||
}) satisfies APIApplicationCommandOptionChoice,
|
||||
|
||||
@@ -3,16 +3,22 @@ import { translator } from '../localization/translator';
|
||||
import { localizationObject } from './localizationObject';
|
||||
|
||||
export function addUsernameChoices(option: SlashCommandStringOption) {
|
||||
const { t } = translator(Locale.EnglishUS);
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
|
||||
return option
|
||||
.setName(t`bot.common.options.username`)
|
||||
.setName(strings.bot.common.options.username.name)
|
||||
.setNameLocalizations(
|
||||
localizationObject('bot.common.options.username', undefined, true),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.username.name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(t`bot.common.options.username.description`)
|
||||
.setDescription(strings.bot.common.options.username.description)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject('bot.common.options.username.description'),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.common.options.username.description,
|
||||
),
|
||||
)
|
||||
.setAutocomplete(true);
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import { DISCORD_CHOICES_MAX_NAME_SIZE, OVERFLOW_SUFFIX } from './constants';
|
||||
export async function autocompleteClan(
|
||||
interaction: AutocompleteInteraction<CacheType>,
|
||||
) {
|
||||
const { translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const focusedOption = interaction.options.getFocused(true);
|
||||
if (focusedOption.name !== 'clan') return;
|
||||
if (focusedOption.value.length < 2) return interaction.respond([]);
|
||||
@@ -19,9 +19,7 @@ export async function autocompleteClan(
|
||||
await interaction.respond(
|
||||
clans
|
||||
? clans.map((clan) => {
|
||||
let name = `${clan.name} (${translate(
|
||||
`common.regions.short.${clan.region}`,
|
||||
)})`;
|
||||
let name = `${clan.name} (${strings.common.regions.short[clan.region]})`;
|
||||
|
||||
if (name.length > DISCORD_CHOICES_MAX_NAME_SIZE) {
|
||||
const overSize = name.length - DISCORD_CHOICES_MAX_NAME_SIZE;
|
||||
@@ -29,9 +27,7 @@ export async function autocompleteClan(
|
||||
name = `${clan.name.slice(
|
||||
0,
|
||||
clan.name.length - overSize - OVERFLOW_SUFFIX.length,
|
||||
)}${OVERFLOW_SUFFIX} (${translate(
|
||||
`common.regions.short.${clan.region}`,
|
||||
)})`;
|
||||
)}${OVERFLOW_SUFFIX} (${strings.common.regions.short[clan.region]})`;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { fetchTankNames, TankType } from '@blitzkit/core';
|
||||
import { fetchTankNames, SEARCH_KEYS, TankType } from '@blitzkit/core';
|
||||
import {
|
||||
ApplicationCommandOptionChoiceData,
|
||||
AutocompleteInteraction,
|
||||
CacheType,
|
||||
} from 'discord.js';
|
||||
import { go } from 'fuzzysort';
|
||||
import { tankNames } from '../blitzkit/nonBlockingPromises';
|
||||
import { translator } from '../localization/translator';
|
||||
import {
|
||||
DISCORD_CHOICES_MAX_NAME_SIZE,
|
||||
OVERFLOW_SUFFIX,
|
||||
} from './autocompleteClan/constants';
|
||||
import { tankNames } from '../blitzkit/nonBlockingPromises';
|
||||
|
||||
export const tankNamesTechTreeOnly = fetchTankNames().then((names) =>
|
||||
names.filter((tank) => tank.treeType === TankType.RESEARCHABLE),
|
||||
@@ -20,6 +21,7 @@ export async function autocompleteTanks(
|
||||
techTreeOnly = false,
|
||||
fields = ['tank'],
|
||||
) {
|
||||
const { unwrap } = translator(interaction.locale);
|
||||
const focusedOption = interaction.options.getFocused(true);
|
||||
if (!fields.includes(focusedOption.name)) return;
|
||||
|
||||
@@ -29,19 +31,16 @@ export async function autocompleteTanks(
|
||||
go(
|
||||
focusedOption.value,
|
||||
await (techTreeOnly ? tankNamesTechTreeOnly : tankNames),
|
||||
{
|
||||
keys: ['searchableName', 'searchableNameDeburr', 'camouflages'],
|
||||
limit: 10,
|
||||
},
|
||||
{ keys: SEARCH_KEYS, limit: 10 },
|
||||
).map(async (item) => {
|
||||
let name = item.obj.searchableName;
|
||||
let name = unwrap(item.obj.searchableName);
|
||||
|
||||
if (name.length > DISCORD_CHOICES_MAX_NAME_SIZE) {
|
||||
const overSize = name.length - DISCORD_CHOICES_MAX_NAME_SIZE;
|
||||
|
||||
name = `${item.obj.searchableName.slice(
|
||||
name = `${unwrap(item.obj.searchableName).slice(
|
||||
0,
|
||||
item.obj.searchableName.length -
|
||||
unwrap(item.obj.searchableName).length -
|
||||
overSize -
|
||||
OVERFLOW_SUFFIX.length,
|
||||
)}${OVERFLOW_SUFFIX}`;
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
export async function autocompleteUsername(
|
||||
interaction: AutocompleteInteraction<CacheType>,
|
||||
) {
|
||||
const { translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const focusedOption = interaction.options.getFocused(true);
|
||||
if (focusedOption.name !== 'username') return;
|
||||
const players = await searchPlayersAcrossRegions(focusedOption.value);
|
||||
@@ -22,9 +22,9 @@ export async function autocompleteUsername(
|
||||
await interaction.respond(
|
||||
players
|
||||
? players.map((player) => {
|
||||
let name = `${player.nickname} (${translate(
|
||||
`common.regions.short.${player.region}`,
|
||||
)})`;
|
||||
let name = `${player.nickname} (${
|
||||
strings.common.regions.short[player.region]
|
||||
})`;
|
||||
|
||||
if (name.length > DISCORD_CHOICES_MAX_NAME_SIZE) {
|
||||
const overSize = name.length - DISCORD_CHOICES_MAX_NAME_SIZE;
|
||||
@@ -32,9 +32,9 @@ export async function autocompleteUsername(
|
||||
name = `${player.nickname.slice(
|
||||
0,
|
||||
player.nickname.length - overSize - OVERFLOW_SUFFIX.length,
|
||||
)}${OVERFLOW_SUFFIX} (${translate(
|
||||
`common.regions.short.${player.region}`,
|
||||
)})`;
|
||||
)}${OVERFLOW_SUFFIX} (${
|
||||
strings.common.regions.short[player.region]
|
||||
})`;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -6,13 +6,13 @@ export function buttonRefresh(
|
||||
interaction: ChatInputCommandInteraction,
|
||||
path: string,
|
||||
) {
|
||||
const { t } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
|
||||
if (
|
||||
interaction.appPermissions?.has('ReadMessageHistory') &&
|
||||
interaction.appPermissions?.has('ViewChannel')
|
||||
) {
|
||||
return buttonPrimary(path, t`bot.common.buttons.refresh`);
|
||||
return buttonPrimary(path, strings.bot.common.buttons.refresh);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { BlitzKitStrings } from '@blitzkit/i18n';
|
||||
import {
|
||||
Locale,
|
||||
SlashCommandBuilder,
|
||||
@@ -23,28 +24,47 @@ export function createLocalizedCommand(
|
||||
| CreateLocalizedCommandSubcommand[]
|
||||
| CreateLocalizedCommandSubcommandGroup[],
|
||||
) {
|
||||
const commandPathItem = command.replaceAll('-', '_');
|
||||
const { translate } = translator(Locale.EnglishUS);
|
||||
const commandPathItem = command.replaceAll(
|
||||
'-',
|
||||
'_',
|
||||
) as keyof BlitzKitStrings['bot']['commands'];
|
||||
const { strings } = translator(Locale.EnglishUS);
|
||||
const slashCommand = new SlashCommandBuilder()
|
||||
.setName(command)
|
||||
.setNameLocalizations(
|
||||
localizationObject(`bot.commands.${commandPathItem}`, undefined, true),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.commands[commandPathItem].name,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.setDescription(translate(`bot.commands.${commandPathItem}.description`))
|
||||
.setDescription(strings.bot.commands[commandPathItem].description)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject(`bot.commands.${commandPathItem}.description`),
|
||||
localizationObject(
|
||||
(strings) => strings.bot.commands[commandPathItem].description,
|
||||
),
|
||||
);
|
||||
|
||||
if (sub) {
|
||||
sub.map((subItem) => {
|
||||
if ('subcommand' in subItem) {
|
||||
const subcommandNameLocalizations = localizationObject(
|
||||
`bot.commands.${commandPathItem}.subcommands.${subItem.subcommand}`,
|
||||
(strings) =>
|
||||
(
|
||||
strings.bot.commands[commandPathItem] as unknown as {
|
||||
subcommands: Record<string, { name: string }>;
|
||||
}
|
||||
).subcommands[subItem.subcommand].name,
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
const subcommandDescriptionLocalizations = localizationObject(
|
||||
`bot.commands.${commandPathItem}.subcommands.${subItem.subcommand}.description`,
|
||||
(strings) =>
|
||||
(
|
||||
strings.bot.commands[commandPathItem] as unknown as {
|
||||
subcommands: Record<string, { description: string }>;
|
||||
}
|
||||
).subcommands[subItem.subcommand].description,
|
||||
);
|
||||
|
||||
slashCommand.addSubcommand((option) => {
|
||||
@@ -54,20 +74,32 @@ export function createLocalizedCommand(
|
||||
.setName(subItem.subcommand)
|
||||
.setNameLocalizations(subcommandNameLocalizations)
|
||||
.setDescription(
|
||||
translate(
|
||||
`bot.commands.${commandPathItem}.subcommands.${subItem.subcommand}.description`,
|
||||
),
|
||||
(
|
||||
strings.bot.commands[commandPathItem] as unknown as {
|
||||
subcommands: Record<string, { description: string }>;
|
||||
}
|
||||
).subcommands[subItem.subcommand].description,
|
||||
)
|
||||
.setDescriptionLocalizations(subcommandDescriptionLocalizations);
|
||||
});
|
||||
} else {
|
||||
const subcommandNameLocalizations = localizationObject(
|
||||
`bot.commands.${commandPathItem}.groups.${subItem.group}`,
|
||||
(strings) =>
|
||||
(
|
||||
strings.bot.commands[commandPathItem] as unknown as {
|
||||
groups: Record<string, { name: string }>;
|
||||
}
|
||||
).groups[subItem.group].name,
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
const subcommandDescriptionLocalizations = localizationObject(
|
||||
`bot.commands.${commandPathItem}.groups.${subItem.group}.description`,
|
||||
(strings) =>
|
||||
(
|
||||
strings.bot.commands[commandPathItem] as unknown as {
|
||||
groups: Record<string, { description: string }>;
|
||||
}
|
||||
).groups[subItem.group].description,
|
||||
);
|
||||
|
||||
slashCommand.addSubcommandGroup((option) => {
|
||||
@@ -77,9 +109,11 @@ export function createLocalizedCommand(
|
||||
.setName(subItem.group)
|
||||
.setNameLocalizations(subcommandNameLocalizations)
|
||||
.setDescription(
|
||||
translate(
|
||||
`bot.commands.${commandPathItem}.groups.${subItem.group}.description`,
|
||||
),
|
||||
(
|
||||
strings.bot.commands[commandPathItem] as unknown as {
|
||||
groups: Record<string, { description: string }>;
|
||||
}
|
||||
).groups[subItem.group].description,
|
||||
)
|
||||
.setDescriptionLocalizations(subcommandDescriptionLocalizations);
|
||||
});
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { Locale } from 'discord.js';
|
||||
import { translator } from '../localization/translator';
|
||||
import { PeriodSize } from './addPeriodSubCommands';
|
||||
|
||||
export function getPeriodOptionName(period: PeriodSize, locale: Locale) {
|
||||
const { translate } = translator(locale);
|
||||
if (period === 'career') return translate('bot.common.periods.career');
|
||||
if (period === 'today') return translate('bot.common.periods.today');
|
||||
return translate('bot.common.periods.days', [period]);
|
||||
const { strings } = translator(locale);
|
||||
if (period === 'career') return strings.bot.common.periods.career;
|
||||
if (period === 'today') return strings.bot.common.periods.today;
|
||||
return literals(strings.bot.common.periods.days, [period]);
|
||||
}
|
||||
@@ -1,18 +1,19 @@
|
||||
import { BlitzKitStrings, literals as literalsFunc } from '@blitzkit/i18n';
|
||||
import { Locale } from 'discord.js';
|
||||
import { SUPPORTED_LOCALES } from '../localization/strings/constants';
|
||||
import { SUPPORTED_LOCALES_DISCORD } from '../localization/strings/constants';
|
||||
import { translator } from '../localization/translator';
|
||||
|
||||
const validNameRegex = /^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$/u;
|
||||
|
||||
export function localizationObject(
|
||||
path: string,
|
||||
literals?: string[],
|
||||
path: (strings: BlitzKitStrings) => string,
|
||||
literals: string[] = [],
|
||||
strict = false,
|
||||
) {
|
||||
return SUPPORTED_LOCALES.reduce<Partial<Record<Locale, string>>>(
|
||||
return SUPPORTED_LOCALES_DISCORD.reduce<Partial<Record<Locale, string>>>(
|
||||
(localizations, locale) => {
|
||||
const { translate } = translator(locale);
|
||||
const translation = translate(path, literals);
|
||||
const { strings } = translator(locale);
|
||||
const translation = literalsFunc(path(strings), literals);
|
||||
const isValid = !strict || validNameRegex.test(translation);
|
||||
|
||||
if (!isValid) {
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import { assertSecret } from '@blitzkit/core';
|
||||
import { ShardingManager } from 'discord.js';
|
||||
|
||||
export const manager = new ShardingManager('dist/bot/workers/bot.js', {
|
||||
token: assertSecret(import.meta.env.DISCORD_TOKEN),
|
||||
});
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Region } from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { ChatInputCommandInteraction } from 'discord.js';
|
||||
import markdownEscape from 'markdown-escape';
|
||||
import { searchClansAcrossRegionsBotWrapper } from '../blitz/searchClansAcrossRegionsBotWrapper';
|
||||
@@ -10,7 +11,7 @@ export const serverAndIdPattern = /(com|eu|asia)\/[0-9]+/;
|
||||
export async function resolveClanFromCommand(
|
||||
interaction: ChatInputCommandInteraction,
|
||||
) {
|
||||
const { translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const clan = interaction.options.getString('clan', true);
|
||||
|
||||
if (serverAndIdPattern.test(clan)) {
|
||||
@@ -26,7 +27,9 @@ export async function resolveClanFromCommand(
|
||||
return { region: accounts[0].region, id: accounts[0].clan_id };
|
||||
} else {
|
||||
throw new UserError(
|
||||
translate('bot.common.errors.clan_not_found', [markdownEscape(clan)]),
|
||||
literals(strings.bot.common.errors.clan_not_found, [
|
||||
markdownEscape(clan),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getTimeDaysAgo, Region } from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { CacheType, ChatInputCommandInteraction } from 'discord.js';
|
||||
import { getPeriodNow } from '../blitzkit/getPeriodNow';
|
||||
import { getPeriodStart } from '../blitzkit/getPeriodStart';
|
||||
@@ -17,7 +18,7 @@ export function resolvePeriodFromCommand(
|
||||
interaction: ChatInputCommandInteraction<CacheType>,
|
||||
forcedPeriod?: PeriodType,
|
||||
) {
|
||||
const { translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
let name: string;
|
||||
let start: number;
|
||||
let end: number;
|
||||
@@ -31,7 +32,7 @@ export function resolvePeriodFromCommand(
|
||||
const startDaysAgoMin = Math.min(startOption, endOption);
|
||||
const endDaysAgoMax = Math.max(startOption, endOption);
|
||||
|
||||
name = translate('bot.common.periods.custom', [
|
||||
name = literals(strings.bot.common.periods.custom, [
|
||||
`${startDaysAgoMin}`,
|
||||
`${endDaysAgoMax}`,
|
||||
]);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { idToRegion, Region } from '@blitzkit/core';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { CacheType, ChatInputCommandInteraction } from 'discord.js';
|
||||
import markdownEscape from 'markdown-escape';
|
||||
import { searchPlayersAcrossRegionsBotWrapper } from '../../blitz/searchPlayersAcrossRegionsBotWrapper';
|
||||
@@ -14,7 +15,7 @@ export interface ResolvedPlayer {
|
||||
export async function resolvePlayerFromCommand(
|
||||
interaction: ChatInputCommandInteraction<CacheType>,
|
||||
) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
const commandUsername = interaction.options.getString('username');
|
||||
|
||||
if (commandUsername !== null) {
|
||||
@@ -36,7 +37,7 @@ export async function resolvePlayerFromCommand(
|
||||
} satisfies ResolvedPlayer;
|
||||
} else {
|
||||
throw new UserError(
|
||||
translate('bot.common.errors.player_not_found', [
|
||||
literals(strings.bot.common.errors.player_not_found, [
|
||||
markdownEscape(commandUsername),
|
||||
]),
|
||||
);
|
||||
@@ -47,6 +48,6 @@ export async function resolvePlayerFromCommand(
|
||||
|
||||
if (account) return account;
|
||||
|
||||
throw new UserError(t`bot.common.errors.player_not_linked`);
|
||||
throw new UserError(strings.bot.common.errors.player_not_linked);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
import { DEFAULT_LOCALE, SupportedLocale } from '@blitzkit/i18n';
|
||||
import { Locale } from 'discord.js';
|
||||
|
||||
export const SUPPORTED_LOCALES: Locale[] = [
|
||||
Locale.EnglishUS,
|
||||
Locale.SpanishES,
|
||||
Locale.Croatian,
|
||||
Locale.Russian,
|
||||
Locale.Ukrainian,
|
||||
Locale.ChineseCN,
|
||||
];
|
||||
const SUPPORTED_LOCALES_DISCORD_MAP: Record<SupportedLocale, Locale> = {
|
||||
en: Locale.EnglishUS,
|
||||
es: Locale.SpanishES,
|
||||
pt: Locale.PortugueseBR,
|
||||
ru: Locale.Russian,
|
||||
uk: Locale.Ukrainian,
|
||||
zh: Locale.ChineseCN,
|
||||
fr: Locale.French,
|
||||
ja: Locale.Japanese,
|
||||
pl: Locale.Polish,
|
||||
};
|
||||
|
||||
export const SUPPORTED_LOCALES_DISCORD_MAP_INVERSE = Object.fromEntries(
|
||||
Object.entries(SUPPORTED_LOCALES_DISCORD_MAP).map(([k, v]) => [v, k]),
|
||||
) as Record<Locale, SupportedLocale>;
|
||||
|
||||
export const SUPPORTED_LOCALES_DISCORD = Object.values(
|
||||
SUPPORTED_LOCALES_DISCORD_MAP,
|
||||
);
|
||||
|
||||
export const DEFAULT_LOCALE_DISCORD =
|
||||
SUPPORTED_LOCALES_DISCORD_MAP[DEFAULT_LOCALE];
|
||||
@@ -1,19 +0,0 @@
|
||||
import { Locale } from 'discord.js';
|
||||
import { SUPPORTED_LOCALES } from './constants';
|
||||
|
||||
export type TranslationFragmentTree = {
|
||||
[key: string]: TranslationFragment;
|
||||
} & {
|
||||
$?: string;
|
||||
};
|
||||
export type TranslationFragment = string | TranslationFragmentTree;
|
||||
|
||||
export const translations = SUPPORTED_LOCALES.reduce<
|
||||
Partial<Record<Locale, TranslationFragment>>
|
||||
>(
|
||||
(table, locale) => ({
|
||||
...table,
|
||||
[locale]: require(`../../../../../core/lang/${locale}.json`),
|
||||
}),
|
||||
{},
|
||||
);
|
||||
@@ -1,74 +1,19 @@
|
||||
import { STRINGS, unwrapper } from '@blitzkit/i18n';
|
||||
import { Locale } from 'discord.js';
|
||||
import { translations } from './strings';
|
||||
import { SUPPORTED_LOCALES } from './strings/constants';
|
||||
import {
|
||||
DEFAULT_LOCALE_DISCORD,
|
||||
SUPPORTED_LOCALES_DISCORD,
|
||||
SUPPORTED_LOCALES_DISCORD_MAP_INVERSE,
|
||||
} from './strings/constants';
|
||||
|
||||
export function translator(localeRaw: Locale) {
|
||||
const locale =
|
||||
localeRaw !== Locale.EnglishUS && SUPPORTED_LOCALES.includes(localeRaw)
|
||||
localeRaw !== DEFAULT_LOCALE_DISCORD &&
|
||||
SUPPORTED_LOCALES_DISCORD.includes(localeRaw)
|
||||
? localeRaw
|
||||
: Locale.EnglishUS;
|
||||
const strings = translations[locale]!;
|
||||
: DEFAULT_LOCALE_DISCORD;
|
||||
const strings = STRINGS[SUPPORTED_LOCALES_DISCORD_MAP_INVERSE[locale]];
|
||||
const unwrap = unwrapper(SUPPORTED_LOCALES_DISCORD_MAP_INVERSE[locale]);
|
||||
|
||||
function translate(path: string, literals?: string[]): string {
|
||||
const pathArray = path.split('.');
|
||||
let fragment = strings;
|
||||
let resolvedString: string;
|
||||
|
||||
for (const pathItem of pathArray) {
|
||||
if (typeof fragment === 'string') {
|
||||
throw new SyntaxError(
|
||||
`Attempted to access string with key "${pathItem}" in "${path}" from within a string instead of an object in locale "${locale}"`,
|
||||
);
|
||||
} else {
|
||||
fragment = fragment[pathItem];
|
||||
|
||||
if (typeof fragment === 'undefined') {
|
||||
const message = `Undefined translation at "${pathItem}" in "${path}" for locale "${locale}"`;
|
||||
|
||||
if (locale === Locale.EnglishUS) {
|
||||
throw new Error(message);
|
||||
} else {
|
||||
console.warn(`${message} falling back to en-US`);
|
||||
return translator(Locale.EnglishUS).translate(path, literals);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof fragment === 'string') {
|
||||
resolvedString = fragment;
|
||||
} else if (fragment.$) {
|
||||
resolvedString = fragment.$!;
|
||||
} else {
|
||||
throw new Error(
|
||||
`Unresolved tree ending for "${path}" in locale "${locale}"`,
|
||||
);
|
||||
}
|
||||
|
||||
if (literals) {
|
||||
const chunks = resolvedString.split('%s');
|
||||
let embeddedString = '';
|
||||
|
||||
chunks.forEach((chunk, index) => {
|
||||
if (index !== 0) embeddedString += literals[index - 1];
|
||||
embeddedString += chunk;
|
||||
});
|
||||
|
||||
return embeddedString;
|
||||
}
|
||||
|
||||
return resolvedString;
|
||||
}
|
||||
|
||||
function t(paths: TemplateStringsArray, ...embeds: string[]) {
|
||||
return paths
|
||||
.map((path, index) =>
|
||||
path.length === 0
|
||||
? ''
|
||||
: `${translate(path)}${index === embeds.length ? '' : embeds[index]}`,
|
||||
)
|
||||
.join('');
|
||||
}
|
||||
|
||||
return { locale, translate, t };
|
||||
return { locale, strings, unwrap };
|
||||
}
|
||||
@@ -8,13 +8,13 @@ import {
|
||||
InteractionReplyOptions,
|
||||
} from 'discord.js';
|
||||
import { InteractionRawReturnable, commands } from '..';
|
||||
import { UserError } from '../../../core/blitzkit/userError';
|
||||
import { buttonLink } from '../../../core/discord/buttonLink';
|
||||
import { embedWarning } from '../../../core/discord/embedWarning';
|
||||
import { normalizeInteractionReturnable } from '../../../core/discord/normalizeInteractionReturnable';
|
||||
import { psa } from '../../../core/discord/psa';
|
||||
import { translator } from '../../../core/localization/translator';
|
||||
import { Writeable } from '../../../types/writable';
|
||||
import { UserError } from '../../../core/blitzkit/userError';
|
||||
|
||||
export async function handleChatInputCommand(
|
||||
interaction: ChatInputCommandInteraction<CacheType>,
|
||||
@@ -126,16 +126,16 @@ export async function handleChatInputCommand(
|
||||
index++;
|
||||
}
|
||||
} catch (error) {
|
||||
const { t } = translator(interaction.locale);
|
||||
const { strings } = translator(interaction.locale);
|
||||
|
||||
const components = [
|
||||
new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel(t`bot.common.errors.get_help`)
|
||||
.setLabel(strings.bot.common.errors.get_help)
|
||||
.setURL('https://discord.gg/nDt7AjGJQH')
|
||||
.setStyle(ButtonStyle.Link),
|
||||
),
|
||||
];
|
||||
|
||||
if (error instanceof UserError) {
|
||||
interaction.editReply({
|
||||
content: error.message,
|
||||
@@ -143,9 +143,8 @@ export async function handleChatInputCommand(
|
||||
});
|
||||
} else {
|
||||
console.error(interaction.commandName, error);
|
||||
|
||||
interaction.editReply({
|
||||
content: t`bot.common.errors.uncaught_error`,
|
||||
content: strings.bot.common.errors.uncaught_error,
|
||||
components,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -64,16 +64,19 @@ interface CommandRegistryBase {
|
||||
autocomplete?: (interaction: AutocompleteInteraction<CacheType>) => void;
|
||||
button?: (interaction: ButtonInteraction<CacheType>) => InteractionReturnable;
|
||||
}
|
||||
|
||||
interface CommandRegistryImplicit extends CommandRegistryBase {
|
||||
handlesInteraction: true;
|
||||
handler: (interaction: ChatInputCommandInteraction<CacheType>) => void;
|
||||
}
|
||||
|
||||
interface CommandRegistryExplicit extends CommandRegistryBase {
|
||||
handlesInteraction?: false;
|
||||
handler: (
|
||||
interaction: ChatInputCommandInteraction<CacheType>,
|
||||
) => InteractionReturnable;
|
||||
}
|
||||
|
||||
export type CommandRegistry = CommandRegistryImplicit | CommandRegistryExplicit;
|
||||
|
||||
export const COMMANDS_RAW: Promise<CommandRegistry>[] = [
|
||||
@@ -107,10 +110,8 @@ export const commands = Promise.allSettled(COMMANDS_RAW).then((rawCommands) => {
|
||||
`Command ${index} failed to load; skipping...`,
|
||||
registry.reason,
|
||||
);
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
return { ...commands, [registry.value.command.name]: registry.value };
|
||||
},
|
||||
{},
|
||||
|
||||
+30
-62
@@ -1,77 +1,50 @@
|
||||
import { ActivityType } from 'discord.js';
|
||||
import { assertSecret } from '@blitzkit/core';
|
||||
import { ActivityType, ShardingManager } from 'discord.js';
|
||||
import {
|
||||
discoveredIdsDefinitions,
|
||||
tankDefinitions,
|
||||
} from './core/blitzkit/nonBlockingPromises';
|
||||
import { manager } from './core/discord/manager';
|
||||
|
||||
async function setupShardManager() {
|
||||
console.log('Pre-manager setup starting...');
|
||||
let iteration = 0;
|
||||
const interval = setInterval(async () => {
|
||||
iteration++;
|
||||
|
||||
const readyShards = new Set();
|
||||
const totalShards = manager.totalShards;
|
||||
console.log(`Attempting launch on iteration ${iteration}`);
|
||||
|
||||
const allShardsReady = new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
reject(new Error('Shard initialization timed out after 60 seconds'));
|
||||
}, 60000);
|
||||
|
||||
manager.on('shardCreate', (shard) => {
|
||||
console.log(`🟡 Launching shard ${shard.id}`);
|
||||
|
||||
shard.on('ready', () => {
|
||||
console.log(`🟢 Launched shard ${shard.id}`);
|
||||
readyShards.add(shard.id);
|
||||
|
||||
if (readyShards.size === totalShards) {
|
||||
clearTimeout(timeout);
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
|
||||
shard.on('error', (error) => {
|
||||
console.error(`❌ Shard ${shard.id} encountered an error:`, error);
|
||||
});
|
||||
|
||||
shard.on('disconnect', () => {
|
||||
console.warn(`⚠️ Shard ${shard.id} disconnected`);
|
||||
});
|
||||
});
|
||||
const manager = new ShardingManager('dist/bot/workers/bot.js', {
|
||||
token: assertSecret(import.meta.env.DISCORD_TOKEN),
|
||||
});
|
||||
|
||||
const shards = await manager
|
||||
.on('shardCreate', (shard) => {
|
||||
clearInterval(interval);
|
||||
console.log(`🟡 Launching shard ${shard.id}`);
|
||||
shard.on('ready', () => console.log(`🟢 Launched shard ${shard.id}`));
|
||||
})
|
||||
.spawn();
|
||||
|
||||
try {
|
||||
console.log('Spawning shards...');
|
||||
const shards = await manager.spawn();
|
||||
console.log('Shards spawned, waiting for ready state...');
|
||||
|
||||
await allShardsReady;
|
||||
console.log('All shards ready, setting up presence...');
|
||||
|
||||
let servers = 0;
|
||||
let channels = 0;
|
||||
let users = 0;
|
||||
|
||||
for (const [, shard] of shards) {
|
||||
try {
|
||||
const guilds = (await shard.fetchClientValue('guilds.cache')) as any;
|
||||
servers += guilds.length;
|
||||
const guilds = (await shard.fetchClientValue('guilds.cache')) as any;
|
||||
|
||||
for (const guild of guilds) {
|
||||
channels += guild.channels.length;
|
||||
users += guild.memberCount;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch statistics from shard:`, error);
|
||||
servers += guilds.length;
|
||||
|
||||
for (const guild of guilds) {
|
||||
channels += guild.channels.length;
|
||||
users += guild.memberCount;
|
||||
}
|
||||
}
|
||||
|
||||
const [awaitedTankDefinitions, awaitedDiscoveredIdsDefinitions] =
|
||||
await Promise.all([tankDefinitions, discoveredIdsDefinitions]);
|
||||
|
||||
const awaitedTankDefinitions = await tankDefinitions;
|
||||
const tanks = Object.values(awaitedTankDefinitions.tanks).length;
|
||||
const awaitedDiscoveredIdsDefinitions = await discoveredIdsDefinitions;
|
||||
const usernames = awaitedDiscoveredIdsDefinitions.count;
|
||||
|
||||
await manager.broadcastEval(
|
||||
manager.broadcastEval(
|
||||
(client, { servers, users, channels, tanks, usernames }) => {
|
||||
const bios = [
|
||||
`Living in ${servers.toLocaleString()} servers`,
|
||||
@@ -92,15 +65,10 @@ async function setupShardManager() {
|
||||
},
|
||||
{ context: { servers, channels, users, tanks, usernames } },
|
||||
);
|
||||
|
||||
console.log('Bot startup complete!');
|
||||
} catch (error) {
|
||||
console.error('Critical error during startup:', error);
|
||||
throw error;
|
||||
console.warn(
|
||||
'An error occurred when setting up presence, ignoring to keep the process alive',
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
setupShardManager().catch((error) => {
|
||||
console.error('Failed to start the bot:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
}, 5000);
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": ["src/**/*"]
|
||||
"include": ["src/**/*", "../core/src/blitzkit/supportedLocales.ts", "../i18n/src/unwrapper.ts"]
|
||||
}
|
||||
@@ -1,683 +0,0 @@
|
||||
{
|
||||
"common": {
|
||||
"wn8_percentile": {
|
||||
"0": "Very bad",
|
||||
"1": "Bad",
|
||||
"2": "Below average",
|
||||
"3": "Average",
|
||||
"4": "Above average",
|
||||
"5": "Good",
|
||||
"6": "Very good",
|
||||
"7": "Great",
|
||||
"8": "Unicum",
|
||||
"9": "Super unicum"
|
||||
},
|
||||
|
||||
"bkni_percentile": {
|
||||
"0": "Super malum",
|
||||
"1": "Malum",
|
||||
"2": "Very bad",
|
||||
"3": "Bad",
|
||||
"4": "Below average",
|
||||
"5": "Average",
|
||||
"6": "Above average",
|
||||
"7": "Good",
|
||||
"8": "Very good",
|
||||
"9": "Unicum",
|
||||
"10": "Super unicum"
|
||||
},
|
||||
|
||||
"nations": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "Germany",
|
||||
"usa": "U.S.A.",
|
||||
"china": "China",
|
||||
"uk": "U.K.",
|
||||
"france": "France",
|
||||
"japan": "Japan",
|
||||
"european": "European Nation",
|
||||
"other": "Hybrid Nation"
|
||||
},
|
||||
|
||||
"nations_adjectives": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "German",
|
||||
"usa": "U.S.A.",
|
||||
"china": "Chinese",
|
||||
"uk": "U.K.",
|
||||
"france": "French",
|
||||
"japan": "Japanese",
|
||||
"european": "European",
|
||||
"other": "Hybrid"
|
||||
},
|
||||
|
||||
"tank_class_short": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "TD"
|
||||
},
|
||||
|
||||
"tank_class_short_plural_lowercase": {
|
||||
"0": "lights",
|
||||
"1": "mediums",
|
||||
"2": "heavies",
|
||||
"3": "TDs"
|
||||
},
|
||||
|
||||
"tank_class_medium": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "Tank destroyer"
|
||||
},
|
||||
|
||||
"tree_type": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Tech tree",
|
||||
"1": "Premium",
|
||||
"2": "Collector"
|
||||
},
|
||||
|
||||
"regions": {
|
||||
"normal": {
|
||||
"com": "North America",
|
||||
"eu": "Europe",
|
||||
"asia": "Asia-Pacific"
|
||||
},
|
||||
"short": {
|
||||
"com": "NA",
|
||||
"eu": "EU",
|
||||
"asia": "APAC"
|
||||
}
|
||||
},
|
||||
|
||||
"leagues": {
|
||||
"diamond": "Diamond",
|
||||
"platinum": "Platinum",
|
||||
"gold": "Gold",
|
||||
"silver": "Silver",
|
||||
"bronze": "Bronze"
|
||||
},
|
||||
|
||||
"composite_stats": {
|
||||
"normalized_damage_dealt": "Damage",
|
||||
"normalized_damage_received": "Damage received",
|
||||
"normalized_deaths": "Deathrate",
|
||||
"normalized_frags": "Kills",
|
||||
"normalized_hits": "Hits",
|
||||
"normalized_losses": "Lossrate",
|
||||
"normalized_misses": "Misses",
|
||||
"normalized_shots": "Shots",
|
||||
"normalized_spotted": "Spots",
|
||||
"normalized_survived_battles": "Survival rate",
|
||||
"normalized_win_and_survived": "Winning and surviving rate",
|
||||
"normalized_wins": "Winrate",
|
||||
"normalized_xp": "XP",
|
||||
"normalized_battle_life_time": "Battle time",
|
||||
|
||||
"cumulative_accuracy": "Accuracy",
|
||||
"cumulative_battles": "Battles",
|
||||
"cumulative_capture_points": "Total capture points",
|
||||
"cumulative_damage_dealt": "Total damage",
|
||||
"cumulative_damage_ratio": "Damage ratio",
|
||||
"cumulative_damage_received": "Total damage received",
|
||||
"cumulative_deaths": "Total deaths",
|
||||
"cumulative_dropped_capture_points": "Total dropped capture points",
|
||||
"cumulative_frags": "Total kills",
|
||||
"cumulative_hits": "Total hits",
|
||||
"cumulative_inaccuracy": "Inaccuracy",
|
||||
"cumulative_kills_to_death_ratio": "Kills to death ratio",
|
||||
"cumulative_losses": "Losses",
|
||||
"cumulative_misses": "Total misses",
|
||||
"cumulative_shots": "Total shots",
|
||||
"cumulative_spotted": "Total spots",
|
||||
"cumulative_survived_battles": "Survived battles",
|
||||
"cumulative_win_and_survived": "Won and survived battles",
|
||||
"cumulative_wins": "Wins",
|
||||
"cumulative_xp": "Total XP",
|
||||
"cumulative_wn8": "WN8",
|
||||
"cumulative_battle_life_time": "Total battle time"
|
||||
}
|
||||
},
|
||||
|
||||
"bot": {
|
||||
"common": {
|
||||
"errors": {
|
||||
"clan_not_found": "# Could not find clan\nCouldn't find \"%s\". Try selecting a clan from the search result.",
|
||||
"player_not_found": "# Could not find user\nI couldn't find user \"%s\". Try picking an user from the search result, typing in a valid username, or using the `/link` command.",
|
||||
"player_not_linked": "# Use `/link` to get started\nI don't know who you are but you can tell me today!",
|
||||
"tank_name_not_found": "# Tank not found\nCould not find tank by the name \"%s\".",
|
||||
"tank_id_not_found": "# Tank not found\nCould not find tank by the ID \"%s\". Try typing the name of the tank instead of a number.",
|
||||
"no_tank_stats": "# No tank stats available\nThis player doesn't have any stats available. This may not be the player you are looking for.",
|
||||
"get_help": "Help Discord server",
|
||||
"uncaught_error": "# BlitzKit ran into an error!\nWe're so sorry about this. Feel free to [join the official Discord server](https://discord.gg/nDt7AjGJQH) to get help.",
|
||||
"preview": "# This command is in preview\n\nYou can only access this command in [the official Discord server](https://discord.gg/nDt7AjGJQH). The command will be generally available soon.",
|
||||
"query_too_small": "# Your search is too short\nYour search must be at least 3 characters long.",
|
||||
"query_too_long": "# Your search is too long\nYour search must be at most 100 characters long."
|
||||
},
|
||||
|
||||
"wn8": {
|
||||
"$": "WN8",
|
||||
"very_bad": "Very bad",
|
||||
"bad": "Bad",
|
||||
"below_average": "Below average",
|
||||
"average": "Average",
|
||||
"above_average": "Above average",
|
||||
"good": "Good",
|
||||
"very_good": "Very good",
|
||||
"great": "Great",
|
||||
"unicum": "Unicum",
|
||||
"super_unicum": "Super unicum"
|
||||
},
|
||||
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today"
|
||||
},
|
||||
"30": {
|
||||
"$": "30",
|
||||
"description": "30 days"
|
||||
},
|
||||
"60": {
|
||||
"$": "60",
|
||||
"description": "60 days"
|
||||
},
|
||||
"90": {
|
||||
"$": "90",
|
||||
"description": "90 days"
|
||||
},
|
||||
"career": {
|
||||
"$": "career",
|
||||
"description": "Career"
|
||||
},
|
||||
"custom": {
|
||||
"$": "custom",
|
||||
"description": "Custom range",
|
||||
|
||||
"options": {
|
||||
"start": {
|
||||
"$": "start",
|
||||
"description": "Start in number of days ago from today"
|
||||
},
|
||||
"end": {
|
||||
"$": "end",
|
||||
"description": "End in number of days ago from today"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"options": {
|
||||
"clan": {
|
||||
"$": "clan",
|
||||
"description": "The clan name or tag"
|
||||
},
|
||||
|
||||
"tank": {
|
||||
"$": "tank",
|
||||
"description": "The tank to get stats for"
|
||||
},
|
||||
|
||||
"username": {
|
||||
"$": "username",
|
||||
"description": "The Blitz username of the player"
|
||||
},
|
||||
|
||||
"filters": {
|
||||
"nation": {
|
||||
"$": "nation",
|
||||
"description": "Nation"
|
||||
},
|
||||
"class": {
|
||||
"$": "class",
|
||||
"description": "Class"
|
||||
},
|
||||
"type": {
|
||||
"$": "type",
|
||||
"description": "Type"
|
||||
}
|
||||
},
|
||||
|
||||
"region": {
|
||||
"$": "region",
|
||||
"description": "Region"
|
||||
},
|
||||
|
||||
"tier": {
|
||||
"$": "tier",
|
||||
"description": "Tier",
|
||||
|
||||
"choices": {
|
||||
"tier": "Tier %s - %s"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"periods": {
|
||||
"career": "Career",
|
||||
"today": "Today",
|
||||
"days": "%s days",
|
||||
"custom": "%s - %s days"
|
||||
},
|
||||
|
||||
"filters": {
|
||||
"none": "No filters",
|
||||
"tier": "Tier %s"
|
||||
},
|
||||
|
||||
"no_data": {
|
||||
"battles_in_period": "No battles played in this period",
|
||||
"battles_in_season": "No battles played in this season",
|
||||
"players_in_period": "No players in this period",
|
||||
"tanks_found": "No tanks found"
|
||||
},
|
||||
|
||||
"buttons": {
|
||||
"refresh": "Refresh"
|
||||
},
|
||||
|
||||
"hero_stats": {
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"tier": "Tier",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy",
|
||||
"kills": "Kills"
|
||||
}
|
||||
},
|
||||
|
||||
"commands": {
|
||||
"auction": {
|
||||
"$": "auction",
|
||||
"description": "Tanks available right now in the auction",
|
||||
|
||||
"body": {
|
||||
"title": "Blitz Auction",
|
||||
"subtitle": "%s available • next prices %s\nBid now: %s",
|
||||
"next": "Next price: %s",
|
||||
"available": "Available: %s / %s"
|
||||
},
|
||||
"errors": {
|
||||
"no_auction": "# No ongoing auction\n\nCurrently, there are no tanks available for purchase in the auction. If you think this is an error, please report this discrepancy in [the official Discord Server](https://discord.gg/nDt7AjGJQH)."
|
||||
},
|
||||
"actions": {
|
||||
"bid": "Bid now"
|
||||
}
|
||||
},
|
||||
|
||||
"replay": {
|
||||
"$": "replay",
|
||||
"description": "Display replay results"
|
||||
},
|
||||
|
||||
"research": {
|
||||
"$": "research",
|
||||
"description": "Lists the expenses in researching a line",
|
||||
|
||||
"options": {
|
||||
"target_tank": {
|
||||
"$": "target-tank",
|
||||
"description": "The final tank to research in the line"
|
||||
},
|
||||
"starting_tank": {
|
||||
"$": "starting-tank",
|
||||
"description": "The starting tank in the line (inferred automatically if not provided)"
|
||||
}
|
||||
},
|
||||
|
||||
"body": {
|
||||
"subtitle": "Research",
|
||||
"total": "Total",
|
||||
"research": "Research: %s",
|
||||
"upgrades": "Upgrades: %s",
|
||||
"purchase": "Purchase: %s",
|
||||
"equipment": "Equipment: %s",
|
||||
"estimation": "# This is an estimation!\n\nThis list may include already researched tanks because of the inaccurate information Wargaming provides. Try providing a `starting-tank` from the line when using the command if you can."
|
||||
},
|
||||
|
||||
"errors": {
|
||||
"non_tech_tree": "# %s is not on the tech tree\n\nYou cannot research a premium/collector tank.",
|
||||
"tier_1": "# %s is a tier I\n\nTier I tanks are always unlocked for free for all players.",
|
||||
"already_researched": "# %s is already researched\n\nTry providing a `starting-tank` when using the command to view the totals for a line you have already researched.",
|
||||
"start_end_equal": "# %s was provided twice\n\nMake sure `starting-tank` and `target-tank` are different.",
|
||||
"tanks_not_on_line": "# %s and %s are not on the same line\n\nMake sure `starting-tank` and `target-tank` are on the same tech-tree line.",
|
||||
"unordered": "# %s higher tiered to %s\n\nMake sure to provide %s as the `starting-tank` instead as it is the lower tiered tank."
|
||||
}
|
||||
},
|
||||
|
||||
"about": {
|
||||
"$": "about",
|
||||
"description": "All the info you need about the bot",
|
||||
"subcommands": {
|
||||
"commands": {
|
||||
"$": "commands",
|
||||
"description": "List of all commands and their descriptions",
|
||||
"body": "# Commands\n\nBlitzKit offers the following commands:\n\n"
|
||||
},
|
||||
"embeds": {
|
||||
"$": "embeds",
|
||||
"description": "How embeds work"
|
||||
},
|
||||
"introduction": {
|
||||
"$": "introduction",
|
||||
"description": "About the bot"
|
||||
},
|
||||
"invite": {
|
||||
"$": "invite",
|
||||
"description": "How to invite the bot"
|
||||
},
|
||||
"timezones": {
|
||||
"$": "timezones",
|
||||
"description": "How BlitzKit infers and uses your timezone"
|
||||
},
|
||||
"credits": {
|
||||
"$": "credits",
|
||||
"description": "People who have helped BlitzKit"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"breakdown": {
|
||||
"$": "breakdown",
|
||||
"description": "A period's breakdown by tanks played",
|
||||
|
||||
"body": {
|
||||
"total": "Total",
|
||||
"battles": "Battles",
|
||||
"wn8": "WN8",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"unknown_tank": "Unknown tank %s"
|
||||
}
|
||||
},
|
||||
|
||||
"debug": {
|
||||
"$": "debug",
|
||||
"description": "Debug information about the bot",
|
||||
|
||||
"body": {
|
||||
"title": "# Debug\n\n",
|
||||
"version": "Version",
|
||||
"shard": {
|
||||
"$": "Shard",
|
||||
"default": "default"
|
||||
},
|
||||
"uptime": "Uptime"
|
||||
}
|
||||
},
|
||||
|
||||
"evolution": {
|
||||
"$": "evolution",
|
||||
"description": "Evolution of statistics",
|
||||
|
||||
"groups": {
|
||||
"player": {
|
||||
"$": "player",
|
||||
"description": "Player statistics"
|
||||
},
|
||||
|
||||
"tank": {
|
||||
"$": "tank",
|
||||
"description": "Tank statistics"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"inactive": {
|
||||
"$": "inactive",
|
||||
"description": "Lists all inactive players in a clan above a threshold",
|
||||
|
||||
"options": {
|
||||
"threshold": {
|
||||
"$": "threshold",
|
||||
"description": "The number of days inactive (default: %s days)"
|
||||
}
|
||||
},
|
||||
|
||||
"body": {
|
||||
"subtitle": "Inactive for %s+ days",
|
||||
"listing": "%s days"
|
||||
}
|
||||
},
|
||||
|
||||
"full_stats": {
|
||||
"$": "full-stats",
|
||||
"description": "Full in-game statistics",
|
||||
|
||||
"body": {
|
||||
"cards": {
|
||||
"games": {
|
||||
"$": "Games",
|
||||
"winrate": "Winrate",
|
||||
"battles": "Battles",
|
||||
"wins_losses": "Wins / losses"
|
||||
},
|
||||
"efficiency": {
|
||||
"$": "Efficiency",
|
||||
"wn8": "WN8",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy"
|
||||
},
|
||||
"lethality": {
|
||||
"$": "Lethality",
|
||||
"average_damage": "Average damage",
|
||||
"damage_per_tier": "Damage per tier",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"average_kills": "Average kills"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"$": "Miscellaneous",
|
||||
"average_tier": "Average tier",
|
||||
"average_spots": "Average spots",
|
||||
"average_xp": "Average XP",
|
||||
"kills_to_death_ratio": "Kills to death ratio"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"link": {
|
||||
"$": "link",
|
||||
"description": "Links your Blitz and Discord account",
|
||||
|
||||
"body": {
|
||||
"accounts_linked": "Accounts linked",
|
||||
"no_role_permissions": {
|
||||
"$": "%s failed to verify",
|
||||
"description": "I don't have the permission to manage roles."
|
||||
}
|
||||
},
|
||||
|
||||
"embed": {
|
||||
"title": "Incorrect account?",
|
||||
"description": "Use the command again and select a username from the search results."
|
||||
}
|
||||
},
|
||||
|
||||
"search_clans": {
|
||||
"$": "search-clans",
|
||||
"description": "Search clans",
|
||||
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "The max number of clan results (default: %s)"
|
||||
}
|
||||
},
|
||||
|
||||
"body": {
|
||||
"title": "Clan search for %s in region %s",
|
||||
"no_results": "No clans found"
|
||||
}
|
||||
},
|
||||
|
||||
"search_players": {
|
||||
"$": "search-players",
|
||||
"description": "Search players",
|
||||
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "The max number of player results (default: %s)"
|
||||
}
|
||||
},
|
||||
|
||||
"body": {
|
||||
"title": "Player search for %s in region %s",
|
||||
"no_results": "No players found"
|
||||
}
|
||||
},
|
||||
|
||||
"rating_leaderboard": {
|
||||
"$": "rating-leaderboard",
|
||||
"description": "Rating battles statistics",
|
||||
|
||||
"subcommands": {
|
||||
"neighbors": {
|
||||
"$": "neighbors",
|
||||
"description": "Neighboring players on the leaderboard"
|
||||
},
|
||||
|
||||
"league": {
|
||||
"$": "league",
|
||||
"description": "Top players of a league"
|
||||
}
|
||||
},
|
||||
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "How many neighbors to display (default: %s)"
|
||||
},
|
||||
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "Season number (default: current)",
|
||||
|
||||
"choices": {
|
||||
"current": "%s (current)"
|
||||
}
|
||||
},
|
||||
|
||||
"league": {
|
||||
"$": "league",
|
||||
"description": "The league to display"
|
||||
}
|
||||
},
|
||||
|
||||
"body": {
|
||||
"top_players": "Top %s players",
|
||||
"no_participation": "# %s didn't play rating in season %s\n\nThis player did not participate in this season or did not get past calibration.",
|
||||
"no_ongoing_season": "# No ongoing season\n\nThere isn't a currently running rating season.",
|
||||
"deleted_player": "Deleted %s",
|
||||
"neighbors": "Rating neighbors",
|
||||
"more": "+ %s more"
|
||||
}
|
||||
},
|
||||
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's played tanks and statistics"
|
||||
},
|
||||
|
||||
"stats": {
|
||||
"$": "stats",
|
||||
"description": "Quick statistics for a period"
|
||||
},
|
||||
|
||||
"owned_tanks": {
|
||||
"$": "owned-tanks",
|
||||
"description": "Shows all own tanks in a tier",
|
||||
|
||||
"body": {
|
||||
"title": "# %s's owned tier %s tanks\n\n"
|
||||
}
|
||||
},
|
||||
|
||||
"permissions": {
|
||||
"$": "permissions",
|
||||
"description": "Checks wether the bot has the required permissions to function",
|
||||
|
||||
"body": {
|
||||
"title": "# Permissions\n\n%s",
|
||||
"view_channels": "View channels: needed to find the message the refresh button was used on",
|
||||
"read_message_history": "Read message history: needed to find the message to refresh",
|
||||
"attach_files": "Attach files: needed to add images to image-based commands",
|
||||
"external_emojis": "External emojis: needed to add national flags and tank class emojis"
|
||||
}
|
||||
},
|
||||
|
||||
"ping": {
|
||||
"$": "ping",
|
||||
"description": "Check wether the bot is alive.",
|
||||
|
||||
"body": {
|
||||
"pong": "Pong 🏓",
|
||||
"pong_with_time": "Pong 🏓 - %sms"
|
||||
},
|
||||
|
||||
"subcommands": {
|
||||
"blitzkit": {
|
||||
"$": "blitzkit",
|
||||
"description": "Ping BlitzKit"
|
||||
},
|
||||
"wotb": {
|
||||
"$": "wotb",
|
||||
"description": "Ping World of Tanks Blitz"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"player_info": {
|
||||
"$": "player-info",
|
||||
"description": "Basic information about a player",
|
||||
|
||||
"body": {
|
||||
"title": "%s's information",
|
||||
"nickname": "Nickname",
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"account_id": "Account ID",
|
||||
"created": "Created",
|
||||
"last_battle": "Last battle"
|
||||
}
|
||||
},
|
||||
|
||||
"rating": {
|
||||
"$": "rating",
|
||||
"description": "Rating player's statistics",
|
||||
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's rating statistics"
|
||||
},
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
|
||||
"body": {
|
||||
"subtitle": {
|
||||
"today": "Today's rating statistics",
|
||||
"season": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
|
||||
"errors": {
|
||||
"no_participation": "# %s hasn't played rating\n\nThis player hasn't participated in the rating gamemode this season.",
|
||||
"unrecorded_stats": "# Statistics currently unavailable\n\nWargaming may be currently be facing server downtime. If there is an on-going season, statistics should be available withing 24 hours."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"website": {}
|
||||
}
|
||||
@@ -1,603 +0,0 @@
|
||||
{
|
||||
"common": {
|
||||
"wn8_percentile": {
|
||||
"0": "Muy malo",
|
||||
"1": "Malo",
|
||||
"2": "Inferior al promedio",
|
||||
"3": "Promedio",
|
||||
"4": "Superior al promedio",
|
||||
"5": "Bueno",
|
||||
"6": "Muy bueno",
|
||||
"7": "Genial",
|
||||
"8": "Unicum",
|
||||
"9": "Super unicum"
|
||||
},
|
||||
"bkni_percentile": {
|
||||
"0": "Super malum",
|
||||
"1": "Malum",
|
||||
"2": "Very bad",
|
||||
"3": "Bad",
|
||||
"4": "Below average",
|
||||
"5": "Average",
|
||||
"6": "Above average",
|
||||
"7": "Good",
|
||||
"8": "Very good",
|
||||
"9": "Unicum",
|
||||
"10": "Super unicum"
|
||||
},
|
||||
"nations": {
|
||||
"ussr": "URSS",
|
||||
"germany": "Alemania",
|
||||
"usa": "EE. UU.",
|
||||
"china": "China",
|
||||
"uk": "Reino Unido",
|
||||
"france": "Francia",
|
||||
"japan": "Japón",
|
||||
"european": "Nación europea",
|
||||
"other": "Nación híbrida"
|
||||
},
|
||||
"nations_adjectives": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "German",
|
||||
"usa": "U.S.A.",
|
||||
"china": "Chinese",
|
||||
"uk": "U.K.",
|
||||
"france": "French",
|
||||
"japan": "Japanese",
|
||||
"european": "European",
|
||||
"other": "Hybrid"
|
||||
},
|
||||
"tank_class_short": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "TD"
|
||||
},
|
||||
"tank_class_short_plural_lowercase": {
|
||||
"0": "lights",
|
||||
"1": "mediums",
|
||||
"2": "heavies",
|
||||
"3": "TDs"
|
||||
},
|
||||
"tank_class_medium": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "Tank destroyer"
|
||||
},
|
||||
"tree_type": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Tech tree",
|
||||
"1": "Premium",
|
||||
"2": "Collector"
|
||||
},
|
||||
"regions": {
|
||||
"normal": {
|
||||
"com": "Norteamérica",
|
||||
"eu": "Europa",
|
||||
"asia": "Asia-Pacífico"
|
||||
},
|
||||
"short": {
|
||||
"com": "NA",
|
||||
"eu": "Europa",
|
||||
"asia": "APAC"
|
||||
}
|
||||
},
|
||||
"leagues": {
|
||||
"diamond": "Diamante",
|
||||
"platinum": "Platino",
|
||||
"gold": "Oro",
|
||||
"silver": "Plata",
|
||||
"bronze": "Bronce"
|
||||
},
|
||||
"composite_stats": {
|
||||
"normalized_damage_dealt": "Damage",
|
||||
"normalized_damage_received": "Damage received",
|
||||
"normalized_deaths": "Deathrate",
|
||||
"normalized_frags": "Kills",
|
||||
"normalized_hits": "Hits",
|
||||
"normalized_losses": "Lossrate",
|
||||
"normalized_misses": "Misses",
|
||||
"normalized_shots": "Shots",
|
||||
"normalized_spotted": "Spots",
|
||||
"normalized_survived_battles": "Survival rate",
|
||||
"normalized_win_and_survived": "Winning and surviving rate",
|
||||
"normalized_wins": "Winrate",
|
||||
"normalized_xp": "XP",
|
||||
"normalized_battle_life_time": "Battle time",
|
||||
"cumulative_accuracy": "Accuracy",
|
||||
"cumulative_battles": "Battles",
|
||||
"cumulative_capture_points": "Total capture points",
|
||||
"cumulative_damage_dealt": "Total damage",
|
||||
"cumulative_damage_ratio": "Damage ratio",
|
||||
"cumulative_damage_received": "Total damage received",
|
||||
"cumulative_deaths": "Total deaths",
|
||||
"cumulative_dropped_capture_points": "Total dropped capture points",
|
||||
"cumulative_frags": "Total kills",
|
||||
"cumulative_hits": "Total hits",
|
||||
"cumulative_inaccuracy": "Inaccuracy",
|
||||
"cumulative_kills_to_death_ratio": "Kills to death ratio",
|
||||
"cumulative_losses": "Losses",
|
||||
"cumulative_misses": "Total misses",
|
||||
"cumulative_shots": "Total shots",
|
||||
"cumulative_spotted": "Total spots",
|
||||
"cumulative_survived_battles": "Survived battles",
|
||||
"cumulative_win_and_survived": "Won and survived battles",
|
||||
"cumulative_wins": "Wins",
|
||||
"cumulative_xp": "Total XP",
|
||||
"cumulative_wn8": "WN8",
|
||||
"cumulative_battle_life_time": "Total battle time"
|
||||
}
|
||||
},
|
||||
"bot": {
|
||||
"common": {
|
||||
"errors": {
|
||||
"clan_not_found": "# No se pudo encontrar el clan\nNo se pudo encontrar \"%s\". Prueba seleccionando un clan de los resultados de búsqueda.",
|
||||
"player_not_found": "# No se pudo encontrar el usuario\nNo pude encontrar al usuario \"%s\". Prueba eligiendo un usuario de los resultados de búsqueda, escribiendo un nombre de usuario aceptable o usando el comando `/vincular`.",
|
||||
"player_not_linked": "# No sé quién eres\nUsa el comando `/vincular` para comenzar.",
|
||||
"tank_name_not_found": "# No se pudo encontrar el tanque\nNo se pudo encontrar el tanque con el nombre \"%s\".",
|
||||
"tank_id_not_found": "# Tanque no encontrado\nNo se pudo encontrar al tanque del ID \"%s\". Prueba escribiendo el nombre del tanque en vez de un número.",
|
||||
"no_tank_stats": "# No hay estadísticas de tanque disponibles\nEste jugador no tiene estadísticas disponibles. Este podría no ser el jugador que estás buscando.",
|
||||
"get_help": "Servidor de ayuda de Discord",
|
||||
"uncaught_error": "# ¡Blitzkrieg sufrió un error!\nLo sentimos mucho. Siéntete libre de [unirte al servidor oficial de Discord](https://discord.gg/nDt7AjGJQH) para obtener ayuda.",
|
||||
"preview": "# Este comando es una vista previa\n\nSolo puedes acceder a este comando en [el servidor oficial de Discord](https://discord.gg/nDt7AjGJQH). Generalmente este comando estará disponible pronto.",
|
||||
"query_too_small": "# Your search is too short\nYour search must be at least 3 characters long.",
|
||||
"query_too_long": "# Your search is too long\nYour search must be at most 100 characters long."
|
||||
},
|
||||
"wn8": {
|
||||
"$": "WN8",
|
||||
"very_bad": "Muy malo",
|
||||
"bad": "Malo",
|
||||
"below_average": "Inferior al promedio",
|
||||
"average": "Promedio",
|
||||
"above_average": "Superior al promedio",
|
||||
"good": "Bueno",
|
||||
"very_good": "Muy bueno",
|
||||
"great": "Genial",
|
||||
"unicum": "Unicum",
|
||||
"super_unicum": "Super unicum"
|
||||
},
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "hoy",
|
||||
"description": "Hoy"
|
||||
},
|
||||
"30": {
|
||||
"$": "30",
|
||||
"description": "30 días"
|
||||
},
|
||||
"60": {
|
||||
"$": "60",
|
||||
"description": "60 días"
|
||||
},
|
||||
"90": {
|
||||
"$": "90",
|
||||
"description": "90 días"
|
||||
},
|
||||
"career": {
|
||||
"$": "carrera",
|
||||
"description": "Carrera"
|
||||
},
|
||||
"custom": {
|
||||
"$": "personalizado",
|
||||
"description": "Rango personalizado",
|
||||
"options": {
|
||||
"start": {
|
||||
"$": "comienzo",
|
||||
"description": "Comenzar en cantidad de días pasados desde hoy"
|
||||
},
|
||||
"end": {
|
||||
"$": "fin",
|
||||
"description": "Terminar en cantidad de días pasados desde hoy"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"clan": {
|
||||
"$": "clan",
|
||||
"description": "El nombre o etiqueta del clan"
|
||||
},
|
||||
"tank": {
|
||||
"$": "tanque",
|
||||
"description": "El tanque al cual conseguirle estadísticas"
|
||||
},
|
||||
"username": {
|
||||
"$": "usuario",
|
||||
"description": "El nombre de usuario de Blitz"
|
||||
},
|
||||
"filters": {
|
||||
"nation": {
|
||||
"$": "nación",
|
||||
"description": "Nación"
|
||||
},
|
||||
"class": {
|
||||
"$": "class",
|
||||
"description": "Class"
|
||||
},
|
||||
"type": {
|
||||
"$": "type",
|
||||
"description": "Type"
|
||||
}
|
||||
},
|
||||
"region": {
|
||||
"$": "región",
|
||||
"description": "Región"
|
||||
},
|
||||
"tier": {
|
||||
"$": "nivel",
|
||||
"description": "Nivel",
|
||||
"choices": {
|
||||
"tier": "Nivel %s - %s"
|
||||
}
|
||||
}
|
||||
},
|
||||
"periods": {
|
||||
"career": "Carrera",
|
||||
"today": "Hoy",
|
||||
"days": "%s días",
|
||||
"custom": "%s - %s días"
|
||||
},
|
||||
"filters": {
|
||||
"none": "Sin filtros",
|
||||
"tier": "Nivel %s"
|
||||
},
|
||||
"no_data": {
|
||||
"battles_in_period": "No hay batallas jugadas en este período",
|
||||
"battles_in_season": "No hay batallas jugadas en esta temporada",
|
||||
"players_in_period": "No hay jugadores en este período",
|
||||
"tanks_found": "No se encontraron tanques"
|
||||
},
|
||||
"buttons": {
|
||||
"refresh": "Actualizar"
|
||||
},
|
||||
"hero_stats": {
|
||||
"battles": "Batallas",
|
||||
"winrate": "Tasa de victorias",
|
||||
"damage": "Daño",
|
||||
"damage_ratio": "Relación de daño",
|
||||
"tier": "Nivel",
|
||||
"survival": "Supervivencia",
|
||||
"accuracy": "Precisión",
|
||||
"kills": "Bajas"
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
"auction": {
|
||||
"$": "auction",
|
||||
"description": "Tanks available right now in the auction",
|
||||
"body": {
|
||||
"title": "Blitz Auction",
|
||||
"subtitle": "%s available • next prices %s\nBid now: %s",
|
||||
"next": "Next price: %s",
|
||||
"available": "Available: %s / %s"
|
||||
},
|
||||
"errors": {
|
||||
"no_auction": "# No ongoing auction\n\nCurrently, there are no tanks available for purchase in the auction. If you think this is an error, please report this discrepancy in [the official Discord Server](https://discord.gg/nDt7AjGJQH)."
|
||||
},
|
||||
"actions": {
|
||||
"bid": "Bid now"
|
||||
}
|
||||
},
|
||||
"replay": {
|
||||
"$": "replay",
|
||||
"description": "Display replay results"
|
||||
},
|
||||
"research": {
|
||||
"$": "investigar",
|
||||
"description": "Enumera los gastos por investigar una línea",
|
||||
"options": {
|
||||
"target_tank": {
|
||||
"$": "tanque-objetivo",
|
||||
"description": "El último tanque a investigar en la línea"
|
||||
},
|
||||
"starting_tank": {
|
||||
"$": "tanque-inicial",
|
||||
"description": "El tanque inicial en la línea (se deduce automáticamente si no se proporciona)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": "Investigar",
|
||||
"total": "Total",
|
||||
"research": "Investigar: %s",
|
||||
"upgrades": "Mejoras: %s",
|
||||
"purchase": "Comprar: %s",
|
||||
"equipment": "Equipamiento: %s",
|
||||
"estimation": "# ¡Esto es una estimación!\n\nEsta lista podría incluir tanques ya investigados debido a la información errónea que proporciona Wargaming. Si puedes, prueba proporcionando un `tanque-inicial` de la línea al usar el comando."
|
||||
},
|
||||
"errors": {
|
||||
"non_tech_tree": "# %s no está en el árbol tecnológico\n\nNo puedes investigar un tanque prémium o coleccionista.",
|
||||
"tier_1": "# %s es un nivel I\n\nLos tanque de nivel I están siempre desbloqueados gratuitamente para todos los jugadores.",
|
||||
"already_researched": "# %s ya está investigado\n\nPrueba proporcionando un `tanque-inicial` al usar el comando para ver los totales para una línea que ya has investigado.",
|
||||
"start_end_equal": "# %s fue proporcionado dos veces\n\nAsegúrate de que `tanque-inicial` y `tanque-objetivo` son diferentes.",
|
||||
"tanks_not_on_line": "# %s y %s no están en la misma línea\n\nAsegúrate de que `tanque-inicial` y `tanque-objetivo` están en la misma línea del árbol tecnológico.",
|
||||
"unordered": "# %s de nivel superior a %s\n\nAsegúrate de proporcionar %s como el `tanque-inicial` en su lugar ya que es el tanque de nivel inferior."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"$": "sobre",
|
||||
"description": "Toda la información que necesitas sobre el bot",
|
||||
"subcommands": {
|
||||
"commands": {
|
||||
"$": "comandos",
|
||||
"description": "Lista de todos los comandos y sus descripciones",
|
||||
"body": "# Comandos\n\nBlitzkrieg ofrece los siguientes comandos:\n\n"
|
||||
},
|
||||
"embeds": {
|
||||
"$": "embeds",
|
||||
"description": "Cómo funcionan los embeds"
|
||||
},
|
||||
"introduction": {
|
||||
"$": "introducción",
|
||||
"description": "Sobre el bot"
|
||||
},
|
||||
"invite": {
|
||||
"$": "invitar",
|
||||
"description": "Cómo invitar al bot"
|
||||
},
|
||||
"timezones": {
|
||||
"$": "zonas-horarias",
|
||||
"description": "Cómo Blitzkrieg infiere y utiliza tu zona horaria"
|
||||
},
|
||||
"credits": {
|
||||
"$": "credits",
|
||||
"description": "People who have helped BlitzKit"
|
||||
}
|
||||
}
|
||||
},
|
||||
"breakdown": {
|
||||
"$": "resumen",
|
||||
"description": "Resumen de un período por tanques jugados",
|
||||
"body": {
|
||||
"total": "Total",
|
||||
"battles": "Batallas",
|
||||
"wn8": "WN8",
|
||||
"winrate": "Tasa de victorias",
|
||||
"damage": "Daño",
|
||||
"unknown_tank": "Tanque desconocido %s"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"$": "depurar",
|
||||
"description": "Muestra más información sobre el bot",
|
||||
"body": {
|
||||
"title": "# Depuración\n\n",
|
||||
"version": "Versión",
|
||||
"shard": {
|
||||
"$": "Partición",
|
||||
"default": "predeterminado"
|
||||
},
|
||||
"uptime": "Tiempo en línea"
|
||||
}
|
||||
},
|
||||
"evolution": {
|
||||
"$": "evolución",
|
||||
"description": "Evolución de estadísticas",
|
||||
"groups": {
|
||||
"player": {
|
||||
"$": "jugador",
|
||||
"description": "Estadísticas del jugador"
|
||||
},
|
||||
"tank": {
|
||||
"$": "tanque",
|
||||
"description": "Estadísticas del tanque"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inactive": {
|
||||
"$": "inactivo",
|
||||
"description": "Enumera a todos los jugadores inactivos en un clan por encima de un umbral",
|
||||
"options": {
|
||||
"threshold": {
|
||||
"$": "umbral",
|
||||
"description": "El número de días inactivo (predeterminado: %s días)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": "Inactivo por %s+ días",
|
||||
"listing": "%s días"
|
||||
}
|
||||
},
|
||||
"full_stats": {
|
||||
"$": "estadísticas-completas",
|
||||
"description": "Estadísticas completas del juego",
|
||||
"body": {
|
||||
"cards": {
|
||||
"games": {
|
||||
"$": "Partidas",
|
||||
"winrate": "Tasa de victorias",
|
||||
"battles": "Batallas",
|
||||
"wins_losses": "Victorias / derrotas"
|
||||
},
|
||||
"efficiency": {
|
||||
"$": "Eficiencia",
|
||||
"wn8": "WN8",
|
||||
"survival": "Supervivencia",
|
||||
"accuracy": "Precisión"
|
||||
},
|
||||
"lethality": {
|
||||
"$": "Letalidad",
|
||||
"average_damage": "Daño promedio",
|
||||
"damage_per_tier": "Daño por nivel",
|
||||
"damage_ratio": "Relación de daño",
|
||||
"average_kills": "Promedio de bajas"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"$": "Misceláneo",
|
||||
"average_tier": "Nivel promedio",
|
||||
"average_spots": "Promedio de detecciones",
|
||||
"average_xp": "Promedio de XP",
|
||||
"kills_to_death_ratio": "Relación bajas-muertes"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"link": {
|
||||
"$": "vincular",
|
||||
"description": "Vincula tu cuenta de Blitz y Discord",
|
||||
"body": {
|
||||
"accounts_linked": "Cuentas vinculadas",
|
||||
"no_role_permissions": {
|
||||
"$": "%s no se pudo verificar",
|
||||
"description": "No tengo permiso para administrar roles."
|
||||
}
|
||||
},
|
||||
"embed": {
|
||||
"title": "¿Cuenta incorrecta?",
|
||||
"description": "Usa el comando de nuevo y selecciona un usuario de los resultados de búsqueda."
|
||||
}
|
||||
},
|
||||
"search_clans": {
|
||||
"$": "buscar-clanes",
|
||||
"description": "Buscar clanes",
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "límite",
|
||||
"description": "El número máximo de resultados de clanes (predeterminado: %s)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"title": "Búsqueda del clan %s en la región %s",
|
||||
"no_results": "No se encontraron clanes"
|
||||
}
|
||||
},
|
||||
"search_players": {
|
||||
"$": "buscar-jugadores",
|
||||
"description": "Buscar jugadores",
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "límite",
|
||||
"description": "El número máximo para resultados de jugador (predeterminado: %s)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"title": "Búsqueda del jugador %s en la región %s",
|
||||
"no_results": "No se encontraron jugadores"
|
||||
}
|
||||
},
|
||||
"rating_leaderboard": {
|
||||
"$": "rating-leaderboard",
|
||||
"description": "Rating battles statistics",
|
||||
"subcommands": {
|
||||
"neighbors": {
|
||||
"$": "vecinos",
|
||||
"description": "Neighboring players on the leaderboard"
|
||||
},
|
||||
"league": {
|
||||
"$": "liga",
|
||||
"description": "Mejores jugadores de una liga"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "límite",
|
||||
"description": "Cuántos vecinos a mostrar (predeterminado: %s)"
|
||||
},
|
||||
"season": {
|
||||
"$": "temporada",
|
||||
"description": "Número de temporada (predeterminado: actual)",
|
||||
"choices": {
|
||||
"current": "%s (actual)"
|
||||
}
|
||||
},
|
||||
"league": {
|
||||
"$": "liga",
|
||||
"description": "La liga a mostrar"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"top_players": "Mejores %s jugadores",
|
||||
"no_participation": "# %s didn't play rating in season %s\n\nThis player did not participate in this season or did not get past calibration.",
|
||||
"no_ongoing_season": "# No ongoing season\n\nThere isn't a currently running rating season.",
|
||||
"deleted_player": "%s eliminado",
|
||||
"neighbors": "Rating neighbors",
|
||||
"more": "+ %s más"
|
||||
}
|
||||
},
|
||||
"today": {
|
||||
"$": "hoy",
|
||||
"description": "Tanques jugados hoy y estadísticas"
|
||||
},
|
||||
"stats": {
|
||||
"$": "estadísticas",
|
||||
"description": "Estadísticas rápidas para un período"
|
||||
},
|
||||
"owned_tanks": {
|
||||
"$": "tanques-propios",
|
||||
"description": "Muestra todos los tanques propios en un nivel",
|
||||
"body": {
|
||||
"title": "# Tanques de %s de nivel %s\n\n"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"$": "permisos",
|
||||
"description": "Comprueba si el bot tiene los permisos requeridos para funcionar",
|
||||
"body": {
|
||||
"title": "# Permisos\n\n%s",
|
||||
"view_channels": "Ver canales: necesario para encontrar el mensaje en el cual el botón \"actualizar\" fue usado",
|
||||
"read_message_history": "Leer historial de mensajes: necesario para encontrar el mensaje a actualizar",
|
||||
"attach_files": "Adjuntar archivos: necesario para añadir imágenes a los comandos basados en estas",
|
||||
"external_emojis": "Emoticonos externos: necesario para añadir emoticonos de banderas nacionales y clases de tanque"
|
||||
}
|
||||
},
|
||||
"ping": {
|
||||
"$": "ping",
|
||||
"description": "Comprueba si el bot está vivo.",
|
||||
"body": {
|
||||
"pong": "Pong 🏓",
|
||||
"pong_with_time": "Pong 🏓 - %sms"
|
||||
},
|
||||
"subcommands": {
|
||||
"blitzkit": {
|
||||
"$": "blitzkit",
|
||||
"description": "Ping BlitzKit"
|
||||
},
|
||||
"wotb": {
|
||||
"$": "wotb",
|
||||
"description": "Hacerle un ping a World of Tanks Blitz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"player_info": {
|
||||
"$": "info-jugador",
|
||||
"description": "Información básica sobre un jugador",
|
||||
"body": {
|
||||
"title": "Información de %s",
|
||||
"nickname": "Apodo",
|
||||
"battles": "Batallas",
|
||||
"winrate": "Tasa de victorias",
|
||||
"account_id": "ID de cuenta",
|
||||
"created": "Creado",
|
||||
"last_battle": "Última batalla"
|
||||
}
|
||||
},
|
||||
"rating": {
|
||||
"$": "rating-session",
|
||||
"description": "Rating player's statistics",
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's rating statistics"
|
||||
},
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": {
|
||||
"today": "Today's rating statistics",
|
||||
"season": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"no_participation": "# %s hasn't played rating\n\nThis player hasn't participated in the rating gamemode this season.",
|
||||
"unrecorded_stats": "# Estadísticas no disponibles actualmente\n\nWargaming podría estar sufriendo una caída del servidor. Si hay alguna temporada en curso, las estadísticas deberían estar disponibles en 24 horas."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"website": {}
|
||||
}
|
||||
@@ -1,603 +0,0 @@
|
||||
{
|
||||
"common": {
|
||||
"wn8_percentile": {
|
||||
"0": "Very bad",
|
||||
"1": "Bad",
|
||||
"2": "Below average",
|
||||
"3": "Average",
|
||||
"4": "Above average",
|
||||
"5": "Good",
|
||||
"6": "Very good",
|
||||
"7": "Great",
|
||||
"8": "Unicum",
|
||||
"9": "Super unicum"
|
||||
},
|
||||
"bkni_percentile": {
|
||||
"0": "Super malum",
|
||||
"1": "Malum",
|
||||
"2": "Very bad",
|
||||
"3": "Bad",
|
||||
"4": "Below average",
|
||||
"5": "Average",
|
||||
"6": "Above average",
|
||||
"7": "Good",
|
||||
"8": "Very good",
|
||||
"9": "Unicum",
|
||||
"10": "Super unicum"
|
||||
},
|
||||
"nations": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "Germany",
|
||||
"usa": "U.S.A.",
|
||||
"china": "China",
|
||||
"uk": "U.K.",
|
||||
"france": "France",
|
||||
"japan": "Japan",
|
||||
"european": "European Nation",
|
||||
"other": "Hybrid Nation"
|
||||
},
|
||||
"nations_adjectives": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "German",
|
||||
"usa": "U.S.A.",
|
||||
"china": "Chinese",
|
||||
"uk": "U.K.",
|
||||
"france": "French",
|
||||
"japan": "Japanese",
|
||||
"european": "European",
|
||||
"other": "Hybrid"
|
||||
},
|
||||
"tank_class_short": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "TD"
|
||||
},
|
||||
"tank_class_short_plural_lowercase": {
|
||||
"0": "lights",
|
||||
"1": "mediums",
|
||||
"2": "heavies",
|
||||
"3": "TDs"
|
||||
},
|
||||
"tank_class_medium": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "Tank destroyer"
|
||||
},
|
||||
"tree_type": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Tech tree",
|
||||
"1": "Premium",
|
||||
"2": "Collector"
|
||||
},
|
||||
"regions": {
|
||||
"normal": {
|
||||
"com": "North America",
|
||||
"eu": "Europe",
|
||||
"asia": "Asia-Pacific"
|
||||
},
|
||||
"short": {
|
||||
"com": "NA",
|
||||
"eu": "EU",
|
||||
"asia": "APAC"
|
||||
}
|
||||
},
|
||||
"leagues": {
|
||||
"diamond": "Diamond",
|
||||
"platinum": "Platinum",
|
||||
"gold": "Gold",
|
||||
"silver": "Silver",
|
||||
"bronze": "Bronze"
|
||||
},
|
||||
"composite_stats": {
|
||||
"normalized_damage_dealt": "Damage",
|
||||
"normalized_damage_received": "Damage received",
|
||||
"normalized_deaths": "Deathrate",
|
||||
"normalized_frags": "Kills",
|
||||
"normalized_hits": "Hits",
|
||||
"normalized_losses": "Lossrate",
|
||||
"normalized_misses": "Misses",
|
||||
"normalized_shots": "Shots",
|
||||
"normalized_spotted": "Spots",
|
||||
"normalized_survived_battles": "Survival rate",
|
||||
"normalized_win_and_survived": "Winning and surviving rate",
|
||||
"normalized_wins": "Winrate",
|
||||
"normalized_xp": "XP",
|
||||
"normalized_battle_life_time": "Battle time",
|
||||
"cumulative_accuracy": "Accuracy",
|
||||
"cumulative_battles": "Battles",
|
||||
"cumulative_capture_points": "Total capture points",
|
||||
"cumulative_damage_dealt": "Total damage",
|
||||
"cumulative_damage_ratio": "Damage ratio",
|
||||
"cumulative_damage_received": "Total damage received",
|
||||
"cumulative_deaths": "Total deaths",
|
||||
"cumulative_dropped_capture_points": "Total dropped capture points",
|
||||
"cumulative_frags": "Total kills",
|
||||
"cumulative_hits": "Total hits",
|
||||
"cumulative_inaccuracy": "Inaccuracy",
|
||||
"cumulative_kills_to_death_ratio": "Kills to death ratio",
|
||||
"cumulative_losses": "Losses",
|
||||
"cumulative_misses": "Total misses",
|
||||
"cumulative_shots": "Total shots",
|
||||
"cumulative_spotted": "Total spots",
|
||||
"cumulative_survived_battles": "Survived battles",
|
||||
"cumulative_win_and_survived": "Won and survived battles",
|
||||
"cumulative_wins": "Wins",
|
||||
"cumulative_xp": "Total XP",
|
||||
"cumulative_wn8": "WN8",
|
||||
"cumulative_battle_life_time": "Total battle time"
|
||||
}
|
||||
},
|
||||
"bot": {
|
||||
"common": {
|
||||
"errors": {
|
||||
"clan_not_found": "# Could not find clan\nCouldn't find \"%s\". Try selecting a clan from the search result.",
|
||||
"player_not_found": "# Could not find user\nI couldn't find user \"%s\". Try picking an user from the search result, typing in a valid username, or using the `/link` command.",
|
||||
"player_not_linked": "# Use `/link` to get started\nI don't know who you are but you can tell me today!",
|
||||
"tank_name_not_found": "# Tank not found\nCould not find tank by the name \"%s\".",
|
||||
"tank_id_not_found": "# Tank not found\nCould not find tank by the ID \"%s\". Try typing the name of the tank instead of a number.",
|
||||
"no_tank_stats": "# No tank stats available\nThis player doesn't have any stats available. This may not be the player you are looking for.",
|
||||
"get_help": "Help Discord server",
|
||||
"uncaught_error": "# BlitzKit ran into an error!\nWe're so sorry about this. Feel free to [join the official Discord server](https://discord.gg/nDt7AjGJQH) to get help.",
|
||||
"preview": "# This command is in preview\n\nYou can only access this command in [the official Discord server](https://discord.gg/nDt7AjGJQH). The command will be generally available soon.",
|
||||
"query_too_small": "# Your search is too short\nYour search must be at least 3 characters long.",
|
||||
"query_too_long": "# Your search is too long\nYour search must be at most 100 characters long."
|
||||
},
|
||||
"wn8": {
|
||||
"$": "WN8",
|
||||
"very_bad": "Very bad",
|
||||
"bad": "Bad",
|
||||
"below_average": "Below average",
|
||||
"average": "Average",
|
||||
"above_average": "Above average",
|
||||
"good": "Good",
|
||||
"very_good": "Very good",
|
||||
"great": "Great",
|
||||
"unicum": "Unicum",
|
||||
"super_unicum": "Super unicum"
|
||||
},
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today"
|
||||
},
|
||||
"30": {
|
||||
"$": "30",
|
||||
"description": "30 days"
|
||||
},
|
||||
"60": {
|
||||
"$": "60",
|
||||
"description": "60 days"
|
||||
},
|
||||
"90": {
|
||||
"$": "90",
|
||||
"description": "90 days"
|
||||
},
|
||||
"career": {
|
||||
"$": "career",
|
||||
"description": "Career"
|
||||
},
|
||||
"custom": {
|
||||
"$": "custom",
|
||||
"description": "Custom range",
|
||||
"options": {
|
||||
"start": {
|
||||
"$": "start",
|
||||
"description": "Start in number of days ago from today"
|
||||
},
|
||||
"end": {
|
||||
"$": "end",
|
||||
"description": "End in number of days ago from today"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"clan": {
|
||||
"$": "clan",
|
||||
"description": "The clan name or tag"
|
||||
},
|
||||
"tank": {
|
||||
"$": "tank",
|
||||
"description": "The tank to get stats for"
|
||||
},
|
||||
"username": {
|
||||
"$": "username",
|
||||
"description": "The Blitz username of the player"
|
||||
},
|
||||
"filters": {
|
||||
"nation": {
|
||||
"$": "nation",
|
||||
"description": "Nation"
|
||||
},
|
||||
"class": {
|
||||
"$": "class",
|
||||
"description": "Class"
|
||||
},
|
||||
"type": {
|
||||
"$": "type",
|
||||
"description": "Type"
|
||||
}
|
||||
},
|
||||
"region": {
|
||||
"$": "region",
|
||||
"description": "Region"
|
||||
},
|
||||
"tier": {
|
||||
"$": "tier",
|
||||
"description": "Tier",
|
||||
"choices": {
|
||||
"tier": "Tier %s - %s"
|
||||
}
|
||||
}
|
||||
},
|
||||
"periods": {
|
||||
"career": "Career",
|
||||
"today": "Today",
|
||||
"days": "%s days",
|
||||
"custom": "%s - %s days"
|
||||
},
|
||||
"filters": {
|
||||
"none": "No filters",
|
||||
"tier": "Tier %s"
|
||||
},
|
||||
"no_data": {
|
||||
"battles_in_period": "No battles played in this period",
|
||||
"battles_in_season": "No battles played in this season",
|
||||
"players_in_period": "No players in this period",
|
||||
"tanks_found": "No tanks found"
|
||||
},
|
||||
"buttons": {
|
||||
"refresh": "Refresh"
|
||||
},
|
||||
"hero_stats": {
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"tier": "Tier",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy",
|
||||
"kills": "Kills"
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
"auction": {
|
||||
"$": "auction",
|
||||
"description": "Tanks available right now in the auction",
|
||||
"body": {
|
||||
"title": "Blitz Auction",
|
||||
"subtitle": "%s available • next prices %s\nBid now: %s",
|
||||
"next": "Next price: %s",
|
||||
"available": "Available: %s / %s"
|
||||
},
|
||||
"errors": {
|
||||
"no_auction": "# No ongoing auction\n\nCurrently, there are no tanks available for purchase in the auction. If you think this is an error, please report this discrepancy in [the official Discord Server](https://discord.gg/nDt7AjGJQH)."
|
||||
},
|
||||
"actions": {
|
||||
"bid": "Bid now"
|
||||
}
|
||||
},
|
||||
"replay": {
|
||||
"$": "replay",
|
||||
"description": "Display replay results"
|
||||
},
|
||||
"research": {
|
||||
"$": "research",
|
||||
"description": "Lists the expenses in researching a line",
|
||||
"options": {
|
||||
"target_tank": {
|
||||
"$": "target-tank",
|
||||
"description": "The final tank to research in the line"
|
||||
},
|
||||
"starting_tank": {
|
||||
"$": "starting-tank",
|
||||
"description": "The starting tank in the line (inferred automatically if not provided)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": "Research",
|
||||
"total": "Total",
|
||||
"research": "Research: %s",
|
||||
"upgrades": "Upgrades: %s",
|
||||
"purchase": "Purchase: %s",
|
||||
"equipment": "Equipment: %s",
|
||||
"estimation": "# This is an estimation!\n\nThis list may include already researched tanks because of the inaccurate information Wargaming provides. Try providing a `starting-tank` from the line when using the command if you can."
|
||||
},
|
||||
"errors": {
|
||||
"non_tech_tree": "# %s is not on the tech tree\n\nYou cannot research a premium/collector tank.",
|
||||
"tier_1": "# %s is a tier I\n\nTier I tanks are always unlocked for free for all players.",
|
||||
"already_researched": "# %s is already researched\n\nTry providing a `starting-tank` when using the command to view the totals for a line you have already researched.",
|
||||
"start_end_equal": "# %s was provided twice\n\nMake sure `starting-tank` and `target-tank` are different.",
|
||||
"tanks_not_on_line": "# %s and %s are not on the same line\n\nMake sure `starting-tank` and `target-tank` are on the same tech-tree line.",
|
||||
"unordered": "# %s higher tiered to %s\n\nMake sure to provide %s as the `starting-tank` instead as it is the lower tiered tank."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"$": "about",
|
||||
"description": "All the info you need about the bot",
|
||||
"subcommands": {
|
||||
"commands": {
|
||||
"$": "commands",
|
||||
"description": "List of all commands and their descriptions",
|
||||
"body": "# Commands\n\nBlitzKit offers the following commands:\n\n"
|
||||
},
|
||||
"embeds": {
|
||||
"$": "embeds",
|
||||
"description": "How embeds work"
|
||||
},
|
||||
"introduction": {
|
||||
"$": "introduction",
|
||||
"description": "About the bot"
|
||||
},
|
||||
"invite": {
|
||||
"$": "invite",
|
||||
"description": "How to invite the bot"
|
||||
},
|
||||
"timezones": {
|
||||
"$": "timezones",
|
||||
"description": "How BlitzKit infers and uses your timezone"
|
||||
},
|
||||
"credits": {
|
||||
"$": "credits",
|
||||
"description": "People who have helped BlitzKit"
|
||||
}
|
||||
}
|
||||
},
|
||||
"breakdown": {
|
||||
"$": "breakdown",
|
||||
"description": "A period's breakdown by tanks played",
|
||||
"body": {
|
||||
"total": "Total",
|
||||
"battles": "Battles",
|
||||
"wn8": "WN8",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"unknown_tank": "Unknown tank %s"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"$": "debug",
|
||||
"description": "Debug information about the bot",
|
||||
"body": {
|
||||
"title": "# Debug\n\n",
|
||||
"version": "Version",
|
||||
"shard": {
|
||||
"$": "Shard",
|
||||
"default": "default"
|
||||
},
|
||||
"uptime": "Uptime"
|
||||
}
|
||||
},
|
||||
"evolution": {
|
||||
"$": "evolution",
|
||||
"description": "Evolution of statistics",
|
||||
"groups": {
|
||||
"player": {
|
||||
"$": "player",
|
||||
"description": "Player statistics"
|
||||
},
|
||||
"tank": {
|
||||
"$": "tank",
|
||||
"description": "Tank statistics"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inactive": {
|
||||
"$": "inactive",
|
||||
"description": "Lists all inactive players in a clan above a threshold",
|
||||
"options": {
|
||||
"threshold": {
|
||||
"$": "threshold",
|
||||
"description": "The number of days inactive (default: %s days)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": "Inactive for %s+ days",
|
||||
"listing": "%s days"
|
||||
}
|
||||
},
|
||||
"full_stats": {
|
||||
"$": "full-stats",
|
||||
"description": "Full in-game statistics",
|
||||
"body": {
|
||||
"cards": {
|
||||
"games": {
|
||||
"$": "Games",
|
||||
"winrate": "Winrate",
|
||||
"battles": "Battles",
|
||||
"wins_losses": "Wins / losses"
|
||||
},
|
||||
"efficiency": {
|
||||
"$": "Efficiency",
|
||||
"wn8": "WN8",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy"
|
||||
},
|
||||
"lethality": {
|
||||
"$": "Lethality",
|
||||
"average_damage": "Average damage",
|
||||
"damage_per_tier": "Damage per tier",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"average_kills": "Average kills"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"$": "Miscellaneous",
|
||||
"average_tier": "Average tier",
|
||||
"average_spots": "Average spots",
|
||||
"average_xp": "Average XP",
|
||||
"kills_to_death_ratio": "Kills to death ratio"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"link": {
|
||||
"$": "link",
|
||||
"description": "Links your Blitz and Discord account",
|
||||
"body": {
|
||||
"accounts_linked": "Accounts linked",
|
||||
"no_role_permissions": {
|
||||
"$": "%s failed to verify",
|
||||
"description": "I don't have the permission to manage roles."
|
||||
}
|
||||
},
|
||||
"embed": {
|
||||
"title": "Incorrect account?",
|
||||
"description": "Use the command again and select a username from the search results."
|
||||
}
|
||||
},
|
||||
"search_clans": {
|
||||
"$": "search-clans",
|
||||
"description": "Search clans",
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "The max number of clan results (default: %s)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"title": "Clan search for %s in region %s",
|
||||
"no_results": "No clans found"
|
||||
}
|
||||
},
|
||||
"search_players": {
|
||||
"$": "search-players",
|
||||
"description": "Search players",
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "The max number of player results (default: %s)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"title": "Player search for %s in region %s",
|
||||
"no_results": "No players found"
|
||||
}
|
||||
},
|
||||
"rating_leaderboard": {
|
||||
"$": "rating-leaderboard",
|
||||
"description": "Rating battles statistics",
|
||||
"subcommands": {
|
||||
"neighbors": {
|
||||
"$": "neighbors",
|
||||
"description": "Neighboring players on the leaderboard"
|
||||
},
|
||||
"league": {
|
||||
"$": "league",
|
||||
"description": "Top players of a league"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "How many neighbors to display (default: %s)"
|
||||
},
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "Season number (default: current)",
|
||||
"choices": {
|
||||
"current": "%s (current)"
|
||||
}
|
||||
},
|
||||
"league": {
|
||||
"$": "league",
|
||||
"description": "The league to display"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"top_players": "Top %s players",
|
||||
"no_participation": "# %s didn't play rating in season %s\n\nThis player did not participate in this season or did not get past calibration.",
|
||||
"no_ongoing_season": "# No ongoing season\n\nThere isn't a currently running rating season.",
|
||||
"deleted_player": "Deleted %s",
|
||||
"neighbors": "Rating neighbors",
|
||||
"more": "+ %s more"
|
||||
}
|
||||
},
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's played tanks and statistics"
|
||||
},
|
||||
"stats": {
|
||||
"$": "stats",
|
||||
"description": "Quick statistics for a period"
|
||||
},
|
||||
"owned_tanks": {
|
||||
"$": "owned-tanks",
|
||||
"description": "Shows all own tanks in a tier",
|
||||
"body": {
|
||||
"title": "# %s's owned tier %s tanks\n\n"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"$": "permissions",
|
||||
"description": "Checks wether the bot has the required permissions to function",
|
||||
"body": {
|
||||
"title": "# Permissions\n\n%s",
|
||||
"view_channels": "View channels: needed to find the message the refresh button was used on",
|
||||
"read_message_history": "Read message history: needed to find the message to refresh",
|
||||
"attach_files": "Attach files: needed to add images to image-based commands",
|
||||
"external_emojis": "External emojis: needed to add national flags and tank class emojis"
|
||||
}
|
||||
},
|
||||
"ping": {
|
||||
"$": "ping",
|
||||
"description": "Check wether the bot is alive.",
|
||||
"body": {
|
||||
"pong": "Pong 🏓",
|
||||
"pong_with_time": "Pong 🏓 - %sms"
|
||||
},
|
||||
"subcommands": {
|
||||
"blitzkit": {
|
||||
"$": "blitzkit",
|
||||
"description": "Ping BlitzKit"
|
||||
},
|
||||
"wotb": {
|
||||
"$": "wotb",
|
||||
"description": "Ping World of Tanks Blitz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"player_info": {
|
||||
"$": "player-info",
|
||||
"description": "Basic information about a player",
|
||||
"body": {
|
||||
"title": "%s's information",
|
||||
"nickname": "Nickname",
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"account_id": "Account ID",
|
||||
"created": "Created",
|
||||
"last_battle": "Last battle"
|
||||
}
|
||||
},
|
||||
"rating": {
|
||||
"$": "rating",
|
||||
"description": "Rating player's statistics",
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's rating statistics"
|
||||
},
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": {
|
||||
"today": "Today's rating statistics",
|
||||
"season": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"no_participation": "# %s hasn't played rating\n\nThis player hasn't participated in the rating gamemode this season.",
|
||||
"unrecorded_stats": "# Statistics currently unavailable\n\nWargaming may be currently be facing server downtime. If there is an on-going season, statistics should be available withing 24 hours."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"website": {}
|
||||
}
|
||||
@@ -1,603 +0,0 @@
|
||||
{
|
||||
"common": {
|
||||
"wn8_percentile": {
|
||||
"0": "Very bad",
|
||||
"1": "Bad",
|
||||
"2": "Below average",
|
||||
"3": "Average",
|
||||
"4": "Above average",
|
||||
"5": "Good",
|
||||
"6": "Very good",
|
||||
"7": "Great",
|
||||
"8": "Unicum",
|
||||
"9": "Super unicum"
|
||||
},
|
||||
"bkni_percentile": {
|
||||
"0": "Super malum",
|
||||
"1": "Malum",
|
||||
"2": "Very bad",
|
||||
"3": "Bad",
|
||||
"4": "Below average",
|
||||
"5": "Average",
|
||||
"6": "Above average",
|
||||
"7": "Good",
|
||||
"8": "Very good",
|
||||
"9": "Unicum",
|
||||
"10": "Super unicum"
|
||||
},
|
||||
"nations": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "Germany",
|
||||
"usa": "U.S.A.",
|
||||
"china": "China",
|
||||
"uk": "U.K.",
|
||||
"france": "France",
|
||||
"japan": "Japan",
|
||||
"european": "European Nation",
|
||||
"other": "Hybrid Nation"
|
||||
},
|
||||
"nations_adjectives": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "German",
|
||||
"usa": "U.S.A.",
|
||||
"china": "Chinese",
|
||||
"uk": "U.K.",
|
||||
"france": "French",
|
||||
"japan": "Japanese",
|
||||
"european": "European",
|
||||
"other": "Hybrid"
|
||||
},
|
||||
"tank_class_short": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "TD"
|
||||
},
|
||||
"tank_class_short_plural_lowercase": {
|
||||
"0": "lights",
|
||||
"1": "mediums",
|
||||
"2": "heavies",
|
||||
"3": "TDs"
|
||||
},
|
||||
"tank_class_medium": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "Tank destroyer"
|
||||
},
|
||||
"tree_type": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Tech tree",
|
||||
"1": "Premium",
|
||||
"2": "Collector"
|
||||
},
|
||||
"regions": {
|
||||
"normal": {
|
||||
"com": "North America",
|
||||
"eu": "Europe",
|
||||
"asia": "Asia-Pacific"
|
||||
},
|
||||
"short": {
|
||||
"com": "NA",
|
||||
"eu": "EU",
|
||||
"asia": "APAC"
|
||||
}
|
||||
},
|
||||
"leagues": {
|
||||
"diamond": "Diamond",
|
||||
"platinum": "Platinum",
|
||||
"gold": "Gold",
|
||||
"silver": "Silver",
|
||||
"bronze": "Bronze"
|
||||
},
|
||||
"composite_stats": {
|
||||
"normalized_damage_dealt": "Damage",
|
||||
"normalized_damage_received": "Damage received",
|
||||
"normalized_deaths": "Deathrate",
|
||||
"normalized_frags": "Kills",
|
||||
"normalized_hits": "Hits",
|
||||
"normalized_losses": "Lossrate",
|
||||
"normalized_misses": "Misses",
|
||||
"normalized_shots": "Shots",
|
||||
"normalized_spotted": "Spots",
|
||||
"normalized_survived_battles": "Survival rate",
|
||||
"normalized_win_and_survived": "Winning and surviving rate",
|
||||
"normalized_wins": "Winrate",
|
||||
"normalized_xp": "XP",
|
||||
"normalized_battle_life_time": "Battle time",
|
||||
"cumulative_accuracy": "Accuracy",
|
||||
"cumulative_battles": "Battles",
|
||||
"cumulative_capture_points": "Total capture points",
|
||||
"cumulative_damage_dealt": "Total damage",
|
||||
"cumulative_damage_ratio": "Damage ratio",
|
||||
"cumulative_damage_received": "Total damage received",
|
||||
"cumulative_deaths": "Total deaths",
|
||||
"cumulative_dropped_capture_points": "Total dropped capture points",
|
||||
"cumulative_frags": "Total kills",
|
||||
"cumulative_hits": "Total hits",
|
||||
"cumulative_inaccuracy": "Inaccuracy",
|
||||
"cumulative_kills_to_death_ratio": "Kills to death ratio",
|
||||
"cumulative_losses": "Losses",
|
||||
"cumulative_misses": "Total misses",
|
||||
"cumulative_shots": "Total shots",
|
||||
"cumulative_spotted": "Total spots",
|
||||
"cumulative_survived_battles": "Survived battles",
|
||||
"cumulative_win_and_survived": "Won and survived battles",
|
||||
"cumulative_wins": "Wins",
|
||||
"cumulative_xp": "Total XP",
|
||||
"cumulative_wn8": "WN8",
|
||||
"cumulative_battle_life_time": "Total battle time"
|
||||
}
|
||||
},
|
||||
"bot": {
|
||||
"common": {
|
||||
"errors": {
|
||||
"clan_not_found": "# Could not find clan\nCouldn't find \"%s\". Try selecting a clan from the search result.",
|
||||
"player_not_found": "# Could not find user\nI couldn't find user \"%s\". Try picking an user from the search result, typing in a valid username, or using the `/link` command.",
|
||||
"player_not_linked": "# Use `/link` to get started\nI don't know who you are but you can tell me today!",
|
||||
"tank_name_not_found": "# Tank not found\nCould not find tank by the name \"%s\".",
|
||||
"tank_id_not_found": "# Tank not found\nCould not find tank by the ID \"%s\". Try typing the name of the tank instead of a number.",
|
||||
"no_tank_stats": "# No tank stats available\nThis player doesn't have any stats available. This may not be the player you are looking for.",
|
||||
"get_help": "Help Discord server",
|
||||
"uncaught_error": "# BlitzKit ran into an error!\nWe're so sorry about this. Feel free to [join the official Discord server](https://discord.gg/nDt7AjGJQH) to get help.",
|
||||
"preview": "# This command is in preview\n\nYou can only access this command in [the official Discord server](https://discord.gg/nDt7AjGJQH). The command will be generally available soon.",
|
||||
"query_too_small": "# Your search is too short\nYour search must be at least 3 characters long.",
|
||||
"query_too_long": "# Your search is too long\nYour search must be at most 100 characters long."
|
||||
},
|
||||
"wn8": {
|
||||
"$": "WN8",
|
||||
"very_bad": "Very bad",
|
||||
"bad": "Bad",
|
||||
"below_average": "Below average",
|
||||
"average": "Average",
|
||||
"above_average": "Above average",
|
||||
"good": "Good",
|
||||
"very_good": "Very good",
|
||||
"great": "Great",
|
||||
"unicum": "Unicum",
|
||||
"super_unicum": "Super unicum"
|
||||
},
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today"
|
||||
},
|
||||
"30": {
|
||||
"$": "30",
|
||||
"description": "30 days"
|
||||
},
|
||||
"60": {
|
||||
"$": "60",
|
||||
"description": "60 days"
|
||||
},
|
||||
"90": {
|
||||
"$": "90",
|
||||
"description": "90 days"
|
||||
},
|
||||
"career": {
|
||||
"$": "career",
|
||||
"description": "Career"
|
||||
},
|
||||
"custom": {
|
||||
"$": "custom",
|
||||
"description": "Custom range",
|
||||
"options": {
|
||||
"start": {
|
||||
"$": "start",
|
||||
"description": "Start in number of days ago from today"
|
||||
},
|
||||
"end": {
|
||||
"$": "end",
|
||||
"description": "End in number of days ago from today"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"clan": {
|
||||
"$": "clan",
|
||||
"description": "The clan name or tag"
|
||||
},
|
||||
"tank": {
|
||||
"$": "tank",
|
||||
"description": "The tank to get stats for"
|
||||
},
|
||||
"username": {
|
||||
"$": "username",
|
||||
"description": "The Blitz username of the player"
|
||||
},
|
||||
"filters": {
|
||||
"nation": {
|
||||
"$": "nation",
|
||||
"description": "Nation"
|
||||
},
|
||||
"class": {
|
||||
"$": "class",
|
||||
"description": "Class"
|
||||
},
|
||||
"type": {
|
||||
"$": "type",
|
||||
"description": "Type"
|
||||
}
|
||||
},
|
||||
"region": {
|
||||
"$": "region",
|
||||
"description": "Region"
|
||||
},
|
||||
"tier": {
|
||||
"$": "tier",
|
||||
"description": "Tier",
|
||||
"choices": {
|
||||
"tier": "Tier %s - %s"
|
||||
}
|
||||
}
|
||||
},
|
||||
"periods": {
|
||||
"career": "Career",
|
||||
"today": "Today",
|
||||
"days": "%s days",
|
||||
"custom": "%s - %s days"
|
||||
},
|
||||
"filters": {
|
||||
"none": "No filters",
|
||||
"tier": "Tier %s"
|
||||
},
|
||||
"no_data": {
|
||||
"battles_in_period": "No battles played in this period",
|
||||
"battles_in_season": "No battles played in this season",
|
||||
"players_in_period": "No players in this period",
|
||||
"tanks_found": "No tanks found"
|
||||
},
|
||||
"buttons": {
|
||||
"refresh": "Refresh"
|
||||
},
|
||||
"hero_stats": {
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"tier": "Tier",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy",
|
||||
"kills": "Kills"
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
"auction": {
|
||||
"$": "auction",
|
||||
"description": "Tanks available right now in the auction",
|
||||
"body": {
|
||||
"title": "Blitz Auction",
|
||||
"subtitle": "%s available • next prices %s\nBid now: %s",
|
||||
"next": "Next price: %s",
|
||||
"available": "Available: %s / %s"
|
||||
},
|
||||
"errors": {
|
||||
"no_auction": "# No ongoing auction\n\nCurrently, there are no tanks available for purchase in the auction. If you think this is an error, please report this discrepancy in [the official Discord Server](https://discord.gg/nDt7AjGJQH)."
|
||||
},
|
||||
"actions": {
|
||||
"bid": "Bid now"
|
||||
}
|
||||
},
|
||||
"replay": {
|
||||
"$": "replay",
|
||||
"description": "Display replay results"
|
||||
},
|
||||
"research": {
|
||||
"$": "research",
|
||||
"description": "Lists the expenses in researching a line",
|
||||
"options": {
|
||||
"target_tank": {
|
||||
"$": "target-tank",
|
||||
"description": "The final tank to research in the line"
|
||||
},
|
||||
"starting_tank": {
|
||||
"$": "starting-tank",
|
||||
"description": "The starting tank in the line (inferred automatically if not provided)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": "Research",
|
||||
"total": "Total",
|
||||
"research": "Research: %s",
|
||||
"upgrades": "Upgrades: %s",
|
||||
"purchase": "Purchase: %s",
|
||||
"equipment": "Equipment: %s",
|
||||
"estimation": "# This is an estimation!\n\nThis list may include already researched tanks because of the inaccurate information Wargaming provides. Try providing a `starting-tank` from the line when using the command if you can."
|
||||
},
|
||||
"errors": {
|
||||
"non_tech_tree": "# %s is not on the tech tree\n\nYou cannot research a premium/collector tank.",
|
||||
"tier_1": "# %s is a tier I\n\nTier I tanks are always unlocked for free for all players.",
|
||||
"already_researched": "# %s is already researched\n\nTry providing a `starting-tank` when using the command to view the totals for a line you have already researched.",
|
||||
"start_end_equal": "# %s was provided twice\n\nMake sure `starting-tank` and `target-tank` are different.",
|
||||
"tanks_not_on_line": "# %s and %s are not on the same line\n\nMake sure `starting-tank` and `target-tank` are on the same tech-tree line.",
|
||||
"unordered": "# %s higher tiered to %s\n\nMake sure to provide %s as the `starting-tank` instead as it is the lower tiered tank."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"$": "about",
|
||||
"description": "All the info you need about the bot",
|
||||
"subcommands": {
|
||||
"commands": {
|
||||
"$": "commands",
|
||||
"description": "List of all commands and their descriptions",
|
||||
"body": "# Commands\n\nBlitzKit offers the following commands:\n\n"
|
||||
},
|
||||
"embeds": {
|
||||
"$": "embeds",
|
||||
"description": "How embeds work"
|
||||
},
|
||||
"introduction": {
|
||||
"$": "introduction",
|
||||
"description": "About the bot"
|
||||
},
|
||||
"invite": {
|
||||
"$": "invite",
|
||||
"description": "How to invite the bot"
|
||||
},
|
||||
"timezones": {
|
||||
"$": "timezones",
|
||||
"description": "How BlitzKit infers and uses your timezone"
|
||||
},
|
||||
"credits": {
|
||||
"$": "credits",
|
||||
"description": "People who have helped BlitzKit"
|
||||
}
|
||||
}
|
||||
},
|
||||
"breakdown": {
|
||||
"$": "breakdown",
|
||||
"description": "A period's breakdown by tanks played",
|
||||
"body": {
|
||||
"total": "Total",
|
||||
"battles": "Battles",
|
||||
"wn8": "WN8",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"unknown_tank": "Unknown tank %s"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"$": "debug",
|
||||
"description": "Debug information about the bot",
|
||||
"body": {
|
||||
"title": "# Debug\n\n",
|
||||
"version": "Version",
|
||||
"shard": {
|
||||
"$": "Shard",
|
||||
"default": "default"
|
||||
},
|
||||
"uptime": "Uptime"
|
||||
}
|
||||
},
|
||||
"evolution": {
|
||||
"$": "evolution",
|
||||
"description": "Evolution of statistics",
|
||||
"groups": {
|
||||
"player": {
|
||||
"$": "player",
|
||||
"description": "Player statistics"
|
||||
},
|
||||
"tank": {
|
||||
"$": "tank",
|
||||
"description": "Tank statistics"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inactive": {
|
||||
"$": "inactive",
|
||||
"description": "Lists all inactive players in a clan above a threshold",
|
||||
"options": {
|
||||
"threshold": {
|
||||
"$": "threshold",
|
||||
"description": "The number of days inactive (default: %s days)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": "Inactive for %s+ days",
|
||||
"listing": "%s days"
|
||||
}
|
||||
},
|
||||
"full_stats": {
|
||||
"$": "full-stats",
|
||||
"description": "Full in-game statistics",
|
||||
"body": {
|
||||
"cards": {
|
||||
"games": {
|
||||
"$": "Games",
|
||||
"winrate": "Winrate",
|
||||
"battles": "Battles",
|
||||
"wins_losses": "Wins / losses"
|
||||
},
|
||||
"efficiency": {
|
||||
"$": "Efficiency",
|
||||
"wn8": "WN8",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy"
|
||||
},
|
||||
"lethality": {
|
||||
"$": "Lethality",
|
||||
"average_damage": "Average damage",
|
||||
"damage_per_tier": "Damage per tier",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"average_kills": "Average kills"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"$": "Miscellaneous",
|
||||
"average_tier": "Average tier",
|
||||
"average_spots": "Average spots",
|
||||
"average_xp": "Average XP",
|
||||
"kills_to_death_ratio": "Kills to death ratio"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"link": {
|
||||
"$": "link",
|
||||
"description": "Links your Blitz and Discord account",
|
||||
"body": {
|
||||
"accounts_linked": "Accounts linked",
|
||||
"no_role_permissions": {
|
||||
"$": "%s failed to verify",
|
||||
"description": "I don't have the permission to manage roles."
|
||||
}
|
||||
},
|
||||
"embed": {
|
||||
"title": "Incorrect account?",
|
||||
"description": "Use the command again and select a username from the search results."
|
||||
}
|
||||
},
|
||||
"search_clans": {
|
||||
"$": "search-clans",
|
||||
"description": "Search clans",
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "The max number of clan results (default: %s)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"title": "Clan search for %s in region %s",
|
||||
"no_results": "No clans found"
|
||||
}
|
||||
},
|
||||
"search_players": {
|
||||
"$": "search-players",
|
||||
"description": "Search players",
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "The max number of player results (default: %s)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"title": "Player search for %s in region %s",
|
||||
"no_results": "No players found"
|
||||
}
|
||||
},
|
||||
"rating_leaderboard": {
|
||||
"$": "rating-leaderboard",
|
||||
"description": "Rating battles statistics",
|
||||
"subcommands": {
|
||||
"neighbors": {
|
||||
"$": "neighbors",
|
||||
"description": "Neighboring players on the leaderboard"
|
||||
},
|
||||
"league": {
|
||||
"$": "league",
|
||||
"description": "Top players of a league"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "How many neighbors to display (default: %s)"
|
||||
},
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "Season number (default: current)",
|
||||
"choices": {
|
||||
"current": "%s (current)"
|
||||
}
|
||||
},
|
||||
"league": {
|
||||
"$": "league",
|
||||
"description": "The league to display"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"top_players": "Top %s players",
|
||||
"no_participation": "# %s didn't play rating in season %s\n\nThis player did not participate in this season or did not get past calibration.",
|
||||
"no_ongoing_season": "# No ongoing season\n\nThere isn't a currently running rating season.",
|
||||
"deleted_player": "Deleted %s",
|
||||
"neighbors": "Rating neighbors",
|
||||
"more": "+ %s more"
|
||||
}
|
||||
},
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's played tanks and statistics"
|
||||
},
|
||||
"stats": {
|
||||
"$": "stats",
|
||||
"description": "Quick statistics for a period"
|
||||
},
|
||||
"owned_tanks": {
|
||||
"$": "owned-tanks",
|
||||
"description": "Shows all own tanks in a tier",
|
||||
"body": {
|
||||
"title": "# %s's owned tier %s tanks\n\n"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"$": "permissions",
|
||||
"description": "Checks wether the bot has the required permissions to function",
|
||||
"body": {
|
||||
"title": "# Permissions\n\n%s",
|
||||
"view_channels": "View channels: needed to find the message the refresh button was used on",
|
||||
"read_message_history": "Read message history: needed to find the message to refresh",
|
||||
"attach_files": "Attach files: needed to add images to image-based commands",
|
||||
"external_emojis": "External emojis: needed to add national flags and tank class emojis"
|
||||
}
|
||||
},
|
||||
"ping": {
|
||||
"$": "ping",
|
||||
"description": "Check wether the bot is alive.",
|
||||
"body": {
|
||||
"pong": "Pong 🏓",
|
||||
"pong_with_time": "Pong 🏓 - %sms"
|
||||
},
|
||||
"subcommands": {
|
||||
"blitzkit": {
|
||||
"$": "blitzkit",
|
||||
"description": "Ping BlitzKit"
|
||||
},
|
||||
"wotb": {
|
||||
"$": "wotb",
|
||||
"description": "Ping World of Tanks Blitz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"player_info": {
|
||||
"$": "player-info",
|
||||
"description": "Basic information about a player",
|
||||
"body": {
|
||||
"title": "%s's information",
|
||||
"nickname": "Nickname",
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"account_id": "Account ID",
|
||||
"created": "Created",
|
||||
"last_battle": "Last battle"
|
||||
}
|
||||
},
|
||||
"rating": {
|
||||
"$": "rating",
|
||||
"description": "Rating player's statistics",
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's rating statistics"
|
||||
},
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": {
|
||||
"today": "Today's rating statistics",
|
||||
"season": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"no_participation": "# %s hasn't played rating\n\nThis player hasn't participated in the rating gamemode this season.",
|
||||
"unrecorded_stats": "# Statistics currently unavailable\n\nWargaming may be currently be facing server downtime. If there is an on-going season, statistics should be available withing 24 hours."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"website": {}
|
||||
}
|
||||
@@ -1,603 +0,0 @@
|
||||
{
|
||||
"common": {
|
||||
"wn8_percentile": {
|
||||
"0": "Very bad",
|
||||
"1": "Bad",
|
||||
"2": "Below average",
|
||||
"3": "Average",
|
||||
"4": "Above average",
|
||||
"5": "Good",
|
||||
"6": "Very good",
|
||||
"7": "Great",
|
||||
"8": "Unicum",
|
||||
"9": "Super unicum"
|
||||
},
|
||||
"bkni_percentile": {
|
||||
"0": "Super malum",
|
||||
"1": "Malum",
|
||||
"2": "Very bad",
|
||||
"3": "Bad",
|
||||
"4": "Below average",
|
||||
"5": "Average",
|
||||
"6": "Above average",
|
||||
"7": "Good",
|
||||
"8": "Very good",
|
||||
"9": "Unicum",
|
||||
"10": "Super unicum"
|
||||
},
|
||||
"nations": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "Germany",
|
||||
"usa": "U.S.A.",
|
||||
"china": "China",
|
||||
"uk": "U.K.",
|
||||
"france": "France",
|
||||
"japan": "Japan",
|
||||
"european": "European Nation",
|
||||
"other": "Hybrid Nation"
|
||||
},
|
||||
"nations_adjectives": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "German",
|
||||
"usa": "U.S.A.",
|
||||
"china": "Chinese",
|
||||
"uk": "U.K.",
|
||||
"france": "French",
|
||||
"japan": "Japanese",
|
||||
"european": "European",
|
||||
"other": "Hybrid"
|
||||
},
|
||||
"tank_class_short": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "TD"
|
||||
},
|
||||
"tank_class_short_plural_lowercase": {
|
||||
"0": "lights",
|
||||
"1": "mediums",
|
||||
"2": "heavies",
|
||||
"3": "TDs"
|
||||
},
|
||||
"tank_class_medium": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "Tank destroyer"
|
||||
},
|
||||
"tree_type": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Tech tree",
|
||||
"1": "Premium",
|
||||
"2": "Collector"
|
||||
},
|
||||
"regions": {
|
||||
"normal": {
|
||||
"com": "North America",
|
||||
"eu": "Europe",
|
||||
"asia": "Asia-Pacific"
|
||||
},
|
||||
"short": {
|
||||
"com": "NA",
|
||||
"eu": "EU",
|
||||
"asia": "APAC"
|
||||
}
|
||||
},
|
||||
"leagues": {
|
||||
"diamond": "Diamond",
|
||||
"platinum": "Platinum",
|
||||
"gold": "Gold",
|
||||
"silver": "Silver",
|
||||
"bronze": "Bronze"
|
||||
},
|
||||
"composite_stats": {
|
||||
"normalized_damage_dealt": "Damage",
|
||||
"normalized_damage_received": "Damage received",
|
||||
"normalized_deaths": "Deathrate",
|
||||
"normalized_frags": "Kills",
|
||||
"normalized_hits": "Hits",
|
||||
"normalized_losses": "Lossrate",
|
||||
"normalized_misses": "Misses",
|
||||
"normalized_shots": "Shots",
|
||||
"normalized_spotted": "Spots",
|
||||
"normalized_survived_battles": "Survival rate",
|
||||
"normalized_win_and_survived": "Winning and surviving rate",
|
||||
"normalized_wins": "Winrate",
|
||||
"normalized_xp": "XP",
|
||||
"normalized_battle_life_time": "Battle time",
|
||||
"cumulative_accuracy": "Accuracy",
|
||||
"cumulative_battles": "Battles",
|
||||
"cumulative_capture_points": "Total capture points",
|
||||
"cumulative_damage_dealt": "Total damage",
|
||||
"cumulative_damage_ratio": "Damage ratio",
|
||||
"cumulative_damage_received": "Total damage received",
|
||||
"cumulative_deaths": "Total deaths",
|
||||
"cumulative_dropped_capture_points": "Total dropped capture points",
|
||||
"cumulative_frags": "Total kills",
|
||||
"cumulative_hits": "Total hits",
|
||||
"cumulative_inaccuracy": "Inaccuracy",
|
||||
"cumulative_kills_to_death_ratio": "Kills to death ratio",
|
||||
"cumulative_losses": "Losses",
|
||||
"cumulative_misses": "Total misses",
|
||||
"cumulative_shots": "Total shots",
|
||||
"cumulative_spotted": "Total spots",
|
||||
"cumulative_survived_battles": "Survived battles",
|
||||
"cumulative_win_and_survived": "Won and survived battles",
|
||||
"cumulative_wins": "Wins",
|
||||
"cumulative_xp": "Total XP",
|
||||
"cumulative_wn8": "WN8",
|
||||
"cumulative_battle_life_time": "Total battle time"
|
||||
}
|
||||
},
|
||||
"bot": {
|
||||
"common": {
|
||||
"errors": {
|
||||
"clan_not_found": "# Could not find clan\nCouldn't find \"%s\". Try selecting a clan from the search result.",
|
||||
"player_not_found": "# Could not find user\nI couldn't find user \"%s\". Try picking an user from the search result, typing in a valid username, or using the `/link` command.",
|
||||
"player_not_linked": "# Use `/link` to get started\nI don't know who you are but you can tell me today!",
|
||||
"tank_name_not_found": "# Tank not found\nCould not find tank by the name \"%s\".",
|
||||
"tank_id_not_found": "# Tank not found\nCould not find tank by the ID \"%s\". Try typing the name of the tank instead of a number.",
|
||||
"no_tank_stats": "# No tank stats available\nThis player doesn't have any stats available. This may not be the player you are looking for.",
|
||||
"get_help": "Help Discord server",
|
||||
"uncaught_error": "# BlitzKit ran into an error!\nWe're so sorry about this. Feel free to [join the official Discord server](https://discord.gg/nDt7AjGJQH) to get help.",
|
||||
"preview": "# This command is in preview\n\nYou can only access this command in [the official Discord server](https://discord.gg/nDt7AjGJQH). The command will be generally available soon.",
|
||||
"query_too_small": "# Your search is too short\nYour search must be at least 3 characters long.",
|
||||
"query_too_long": "# Your search is too long\nYour search must be at most 100 characters long."
|
||||
},
|
||||
"wn8": {
|
||||
"$": "WN8",
|
||||
"very_bad": "Very bad",
|
||||
"bad": "Bad",
|
||||
"below_average": "Below average",
|
||||
"average": "Average",
|
||||
"above_average": "Above average",
|
||||
"good": "Good",
|
||||
"very_good": "Very good",
|
||||
"great": "Great",
|
||||
"unicum": "Unicum",
|
||||
"super_unicum": "Super unicum"
|
||||
},
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today"
|
||||
},
|
||||
"30": {
|
||||
"$": "30",
|
||||
"description": "30 days"
|
||||
},
|
||||
"60": {
|
||||
"$": "60",
|
||||
"description": "60 days"
|
||||
},
|
||||
"90": {
|
||||
"$": "90",
|
||||
"description": "90 days"
|
||||
},
|
||||
"career": {
|
||||
"$": "career",
|
||||
"description": "Career"
|
||||
},
|
||||
"custom": {
|
||||
"$": "custom",
|
||||
"description": "Custom range",
|
||||
"options": {
|
||||
"start": {
|
||||
"$": "start",
|
||||
"description": "Start in number of days ago from today"
|
||||
},
|
||||
"end": {
|
||||
"$": "end",
|
||||
"description": "End in number of days ago from today"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"clan": {
|
||||
"$": "clan",
|
||||
"description": "The clan name or tag"
|
||||
},
|
||||
"tank": {
|
||||
"$": "tank",
|
||||
"description": "The tank to get stats for"
|
||||
},
|
||||
"username": {
|
||||
"$": "username",
|
||||
"description": "The Blitz username of the player"
|
||||
},
|
||||
"filters": {
|
||||
"nation": {
|
||||
"$": "nation",
|
||||
"description": "Nation"
|
||||
},
|
||||
"class": {
|
||||
"$": "class",
|
||||
"description": "Class"
|
||||
},
|
||||
"type": {
|
||||
"$": "type",
|
||||
"description": "Type"
|
||||
}
|
||||
},
|
||||
"region": {
|
||||
"$": "region",
|
||||
"description": "Region"
|
||||
},
|
||||
"tier": {
|
||||
"$": "tier",
|
||||
"description": "Tier",
|
||||
"choices": {
|
||||
"tier": "Tier %s - %s"
|
||||
}
|
||||
}
|
||||
},
|
||||
"periods": {
|
||||
"career": "Career",
|
||||
"today": "Today",
|
||||
"days": "%s days",
|
||||
"custom": "%s - %s days"
|
||||
},
|
||||
"filters": {
|
||||
"none": "No filters",
|
||||
"tier": "Tier %s"
|
||||
},
|
||||
"no_data": {
|
||||
"battles_in_period": "No battles played in this period",
|
||||
"battles_in_season": "No battles played in this season",
|
||||
"players_in_period": "No players in this period",
|
||||
"tanks_found": "No tanks found"
|
||||
},
|
||||
"buttons": {
|
||||
"refresh": "Refresh"
|
||||
},
|
||||
"hero_stats": {
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"tier": "Tier",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy",
|
||||
"kills": "Kills"
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
"auction": {
|
||||
"$": "auction",
|
||||
"description": "Tanks available right now in the auction",
|
||||
"body": {
|
||||
"title": "Blitz Auction",
|
||||
"subtitle": "%s available • next prices %s\nBid now: %s",
|
||||
"next": "Next price: %s",
|
||||
"available": "Available: %s / %s"
|
||||
},
|
||||
"errors": {
|
||||
"no_auction": "# No ongoing auction\n\nCurrently, there are no tanks available for purchase in the auction. If you think this is an error, please report this discrepancy in [the official Discord Server](https://discord.gg/nDt7AjGJQH)."
|
||||
},
|
||||
"actions": {
|
||||
"bid": "Bid now"
|
||||
}
|
||||
},
|
||||
"replay": {
|
||||
"$": "replay",
|
||||
"description": "Display replay results"
|
||||
},
|
||||
"research": {
|
||||
"$": "research",
|
||||
"description": "Lists the expenses in researching a line",
|
||||
"options": {
|
||||
"target_tank": {
|
||||
"$": "target-tank",
|
||||
"description": "The final tank to research in the line"
|
||||
},
|
||||
"starting_tank": {
|
||||
"$": "starting-tank",
|
||||
"description": "The starting tank in the line (inferred automatically if not provided)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": "Research",
|
||||
"total": "Total",
|
||||
"research": "Research: %s",
|
||||
"upgrades": "Upgrades: %s",
|
||||
"purchase": "Purchase: %s",
|
||||
"equipment": "Equipment: %s",
|
||||
"estimation": "# This is an estimation!\n\nThis list may include already researched tanks because of the inaccurate information Wargaming provides. Try providing a `starting-tank` from the line when using the command if you can."
|
||||
},
|
||||
"errors": {
|
||||
"non_tech_tree": "# %s is not on the tech tree\n\nYou cannot research a premium/collector tank.",
|
||||
"tier_1": "# %s is a tier I\n\nTier I tanks are always unlocked for free for all players.",
|
||||
"already_researched": "# %s is already researched\n\nTry providing a `starting-tank` when using the command to view the totals for a line you have already researched.",
|
||||
"start_end_equal": "# %s was provided twice\n\nMake sure `starting-tank` and `target-tank` are different.",
|
||||
"tanks_not_on_line": "# %s and %s are not on the same line\n\nMake sure `starting-tank` and `target-tank` are on the same tech-tree line.",
|
||||
"unordered": "# %s higher tiered to %s\n\nMake sure to provide %s as the `starting-tank` instead as it is the lower tiered tank."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"$": "about",
|
||||
"description": "All the info you need about the bot",
|
||||
"subcommands": {
|
||||
"commands": {
|
||||
"$": "commands",
|
||||
"description": "List of all commands and their descriptions",
|
||||
"body": "# Commands\n\nBlitzKit offers the following commands:\n\n"
|
||||
},
|
||||
"embeds": {
|
||||
"$": "embeds",
|
||||
"description": "How embeds work"
|
||||
},
|
||||
"introduction": {
|
||||
"$": "introduction",
|
||||
"description": "About the bot"
|
||||
},
|
||||
"invite": {
|
||||
"$": "invite",
|
||||
"description": "How to invite the bot"
|
||||
},
|
||||
"timezones": {
|
||||
"$": "timezones",
|
||||
"description": "How BlitzKit infers and uses your timezone"
|
||||
},
|
||||
"credits": {
|
||||
"$": "credits",
|
||||
"description": "People who have helped BlitzKit"
|
||||
}
|
||||
}
|
||||
},
|
||||
"breakdown": {
|
||||
"$": "breakdown",
|
||||
"description": "A period's breakdown by tanks played",
|
||||
"body": {
|
||||
"total": "Total",
|
||||
"battles": "Battles",
|
||||
"wn8": "WN8",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"unknown_tank": "Unknown tank %s"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"$": "debug",
|
||||
"description": "Debug information about the bot",
|
||||
"body": {
|
||||
"title": "# Debug\n\n",
|
||||
"version": "Version",
|
||||
"shard": {
|
||||
"$": "Shard",
|
||||
"default": "default"
|
||||
},
|
||||
"uptime": "Uptime"
|
||||
}
|
||||
},
|
||||
"evolution": {
|
||||
"$": "evolution",
|
||||
"description": "Evolution of statistics",
|
||||
"groups": {
|
||||
"player": {
|
||||
"$": "player",
|
||||
"description": "Player statistics"
|
||||
},
|
||||
"tank": {
|
||||
"$": "tank",
|
||||
"description": "Tank statistics"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inactive": {
|
||||
"$": "inactive",
|
||||
"description": "Lists all inactive players in a clan above a threshold",
|
||||
"options": {
|
||||
"threshold": {
|
||||
"$": "threshold",
|
||||
"description": "The number of days inactive (default: %s days)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": "Inactive for %s+ days",
|
||||
"listing": "%s days"
|
||||
}
|
||||
},
|
||||
"full_stats": {
|
||||
"$": "full-stats",
|
||||
"description": "Full in-game statistics",
|
||||
"body": {
|
||||
"cards": {
|
||||
"games": {
|
||||
"$": "Games",
|
||||
"winrate": "Winrate",
|
||||
"battles": "Battles",
|
||||
"wins_losses": "Wins / losses"
|
||||
},
|
||||
"efficiency": {
|
||||
"$": "Efficiency",
|
||||
"wn8": "WN8",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy"
|
||||
},
|
||||
"lethality": {
|
||||
"$": "Lethality",
|
||||
"average_damage": "Average damage",
|
||||
"damage_per_tier": "Damage per tier",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"average_kills": "Average kills"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"$": "Miscellaneous",
|
||||
"average_tier": "Average tier",
|
||||
"average_spots": "Average spots",
|
||||
"average_xp": "Average XP",
|
||||
"kills_to_death_ratio": "Kills to death ratio"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"link": {
|
||||
"$": "link",
|
||||
"description": "Links your Blitz and Discord account",
|
||||
"body": {
|
||||
"accounts_linked": "Accounts linked",
|
||||
"no_role_permissions": {
|
||||
"$": "%s failed to verify",
|
||||
"description": "I don't have the permission to manage roles."
|
||||
}
|
||||
},
|
||||
"embed": {
|
||||
"title": "Incorrect account?",
|
||||
"description": "Use the command again and select a username from the search results."
|
||||
}
|
||||
},
|
||||
"search_clans": {
|
||||
"$": "search-clans",
|
||||
"description": "Search clans",
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "The max number of clan results (default: %s)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"title": "Clan search for %s in region %s",
|
||||
"no_results": "No clans found"
|
||||
}
|
||||
},
|
||||
"search_players": {
|
||||
"$": "search-players",
|
||||
"description": "Search players",
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "The max number of player results (default: %s)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"title": "Player search for %s in region %s",
|
||||
"no_results": "No players found"
|
||||
}
|
||||
},
|
||||
"rating_leaderboard": {
|
||||
"$": "rating-leaderboard",
|
||||
"description": "Rating battles statistics",
|
||||
"subcommands": {
|
||||
"neighbors": {
|
||||
"$": "neighbors",
|
||||
"description": "Neighboring players on the leaderboard"
|
||||
},
|
||||
"league": {
|
||||
"$": "league",
|
||||
"description": "Top players of a league"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "How many neighbors to display (default: %s)"
|
||||
},
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "Season number (default: current)",
|
||||
"choices": {
|
||||
"current": "%s (current)"
|
||||
}
|
||||
},
|
||||
"league": {
|
||||
"$": "league",
|
||||
"description": "The league to display"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"top_players": "Top %s players",
|
||||
"no_participation": "# %s didn't play rating in season %s\n\nThis player did not participate in this season or did not get past calibration.",
|
||||
"no_ongoing_season": "# No ongoing season\n\nThere isn't a currently running rating season.",
|
||||
"deleted_player": "Deleted %s",
|
||||
"neighbors": "Rating neighbors",
|
||||
"more": "+ %s more"
|
||||
}
|
||||
},
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's played tanks and statistics"
|
||||
},
|
||||
"stats": {
|
||||
"$": "stats",
|
||||
"description": "Quick statistics for a period"
|
||||
},
|
||||
"owned_tanks": {
|
||||
"$": "owned-tanks",
|
||||
"description": "Shows all own tanks in a tier",
|
||||
"body": {
|
||||
"title": "# %s's owned tier %s tanks\n\n"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"$": "permissions",
|
||||
"description": "Checks wether the bot has the required permissions to function",
|
||||
"body": {
|
||||
"title": "# Permissions\n\n%s",
|
||||
"view_channels": "View channels: needed to find the message the refresh button was used on",
|
||||
"read_message_history": "Read message history: needed to find the message to refresh",
|
||||
"attach_files": "Attach files: needed to add images to image-based commands",
|
||||
"external_emojis": "External emojis: needed to add national flags and tank class emojis"
|
||||
}
|
||||
},
|
||||
"ping": {
|
||||
"$": "ping",
|
||||
"description": "Check wether the bot is alive.",
|
||||
"body": {
|
||||
"pong": "Pong 🏓",
|
||||
"pong_with_time": "Pong 🏓 - %sms"
|
||||
},
|
||||
"subcommands": {
|
||||
"blitzkit": {
|
||||
"$": "blitzkit",
|
||||
"description": "Ping BlitzKit"
|
||||
},
|
||||
"wotb": {
|
||||
"$": "wotb",
|
||||
"description": "Ping World of Tanks Blitz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"player_info": {
|
||||
"$": "player-info",
|
||||
"description": "Basic information about a player",
|
||||
"body": {
|
||||
"title": "%s's information",
|
||||
"nickname": "Nickname",
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"account_id": "Account ID",
|
||||
"created": "Created",
|
||||
"last_battle": "Last battle"
|
||||
}
|
||||
},
|
||||
"rating": {
|
||||
"$": "rating",
|
||||
"description": "Rating player's statistics",
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's rating statistics"
|
||||
},
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": {
|
||||
"today": "Today's rating statistics",
|
||||
"season": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"no_participation": "# %s hasn't played rating\n\nThis player hasn't participated in the rating gamemode this season.",
|
||||
"unrecorded_stats": "# Statistics currently unavailable\n\nWargaming may be currently be facing server downtime. If there is an on-going season, statistics should be available withing 24 hours."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"website": {}
|
||||
}
|
||||
@@ -1,603 +0,0 @@
|
||||
{
|
||||
"common": {
|
||||
"wn8_percentile": {
|
||||
"0": "非常差",
|
||||
"1": "差",
|
||||
"2": "较差",
|
||||
"3": "平均",
|
||||
"4": "高于平均",
|
||||
"5": "好",
|
||||
"6": "非常好",
|
||||
"7": "很好",
|
||||
"8": "Unicum",
|
||||
"9": "Super unicum"
|
||||
},
|
||||
"bkni_percentile": {
|
||||
"0": "Super malum",
|
||||
"1": "Malum",
|
||||
"2": "Very bad",
|
||||
"3": "差",
|
||||
"4": "较差",
|
||||
"5": "平均",
|
||||
"6": "高于平均",
|
||||
"7": "好",
|
||||
"8": "非常好",
|
||||
"9": "Unicum",
|
||||
"10": "Super unicum"
|
||||
},
|
||||
"nations": {
|
||||
"ussr": "苏联 (S系)",
|
||||
"germany": "德国 (D系)",
|
||||
"usa": "美国 (M系)",
|
||||
"china": "中国 (C系)",
|
||||
"uk": "英国 (Y系)",
|
||||
"france": "法国 (F系)",
|
||||
"japan": "日本 (R系)",
|
||||
"european": "欧盟 (E系)",
|
||||
"other": "X系"
|
||||
},
|
||||
"nations_adjectives": {
|
||||
"ussr": "苏联 (S系)",
|
||||
"germany": "德国 (D系)",
|
||||
"usa": "美国 (M系)",
|
||||
"china": "中国 (C系)",
|
||||
"uk": "英国 (Y系)",
|
||||
"france": "法国 (F系)",
|
||||
"japan": "日本 (R系)",
|
||||
"european": "欧盟 (E系)",
|
||||
"other": "X系"
|
||||
},
|
||||
"tank_class_short": {
|
||||
"-1": "无法识别",
|
||||
"0": "轻型坦克",
|
||||
"1": "中型坦克",
|
||||
"2": "重型坦克",
|
||||
"3": "坦克歼击车"
|
||||
},
|
||||
"tank_class_short_plural_lowercase": {
|
||||
"0": "轻型坦克",
|
||||
"1": "中型坦克",
|
||||
"2": "重型坦克",
|
||||
"3": "坦克歼击车"
|
||||
},
|
||||
"tank_class_medium": {
|
||||
"-1": "无法识别",
|
||||
"0": "轻型坦克",
|
||||
"1": "Medium",
|
||||
"2": "Heavy",
|
||||
"3": "Tank destroyer"
|
||||
},
|
||||
"tree_type": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Tech tree",
|
||||
"1": "Premium",
|
||||
"2": "Collector"
|
||||
},
|
||||
"regions": {
|
||||
"normal": {
|
||||
"com": "North America",
|
||||
"eu": "Europe",
|
||||
"asia": "Asia-Pacific"
|
||||
},
|
||||
"short": {
|
||||
"com": "NA",
|
||||
"eu": "EU",
|
||||
"asia": "APAC"
|
||||
}
|
||||
},
|
||||
"leagues": {
|
||||
"diamond": "Diamond",
|
||||
"platinum": "Platinum",
|
||||
"gold": "Gold",
|
||||
"silver": "Silver",
|
||||
"bronze": "Bronze"
|
||||
},
|
||||
"composite_stats": {
|
||||
"normalized_damage_dealt": "Damage",
|
||||
"normalized_damage_received": "Damage received",
|
||||
"normalized_deaths": "Deathrate",
|
||||
"normalized_frags": "Kills",
|
||||
"normalized_hits": "Hits",
|
||||
"normalized_losses": "Lossrate",
|
||||
"normalized_misses": "Misses",
|
||||
"normalized_shots": "Shots",
|
||||
"normalized_spotted": "Spots",
|
||||
"normalized_survived_battles": "Survival rate",
|
||||
"normalized_win_and_survived": "Winning and surviving rate",
|
||||
"normalized_wins": "Winrate",
|
||||
"normalized_xp": "XP",
|
||||
"normalized_battle_life_time": "Battle time",
|
||||
"cumulative_accuracy": "Accuracy",
|
||||
"cumulative_battles": "Battles",
|
||||
"cumulative_capture_points": "Total capture points",
|
||||
"cumulative_damage_dealt": "Total damage",
|
||||
"cumulative_damage_ratio": "Damage ratio",
|
||||
"cumulative_damage_received": "Total damage received",
|
||||
"cumulative_deaths": "Total deaths",
|
||||
"cumulative_dropped_capture_points": "Total dropped capture points",
|
||||
"cumulative_frags": "Total kills",
|
||||
"cumulative_hits": "Total hits",
|
||||
"cumulative_inaccuracy": "Inaccuracy",
|
||||
"cumulative_kills_to_death_ratio": "战损比",
|
||||
"cumulative_losses": "失败",
|
||||
"cumulative_misses": "总射击失误数",
|
||||
"cumulative_shots": "总射击数",
|
||||
"cumulative_spotted": "场均发现敌人",
|
||||
"cumulative_survived_battles": "幸存场次",
|
||||
"cumulative_win_and_survived": "胜利和幸存场次",
|
||||
"cumulative_wins": "胜利",
|
||||
"cumulative_xp": "总经验",
|
||||
"cumulative_wn8": "WN8",
|
||||
"cumulative_battle_life_time": "总战斗时间"
|
||||
}
|
||||
},
|
||||
"bot": {
|
||||
"common": {
|
||||
"errors": {
|
||||
"clan_not_found": "# 找不到军团\n找不到\"%s\"。请尝试从搜索结果中选择一个军团。",
|
||||
"player_not_found": "# 找不到用户\n无法找到用户 \"%s\"。 尝试从搜索结果中挑选用户,输入一个有效的用户名或使用 \"/link\" 命令。",
|
||||
"player_not_linked": "# 使用 `/link` 来开始\n我不知道你是谁,但你今天可以告诉我!",
|
||||
"tank_name_not_found": "# 坦克找不到\n无法找到名为 \"%s \"的坦克。",
|
||||
"tank_id_not_found": "# 坦克找不到\n无法找到ID \"%s\"的坦克。 试着输入坦克的名称而不是数字。",
|
||||
"no_tank_stats": "# 没有这个坦克的数据\n这个玩家没有数据。你可能找错人了。",
|
||||
"get_help": "Help Discord server",
|
||||
"uncaught_error": "# BlitzKit 崩溃了!\n非常抱歉。请加入[官方Discord](https://discord.gg/nDt7AjGJQH),以方便帮助你的问题。",
|
||||
"preview": "# 此命令处于预览\n\n您只能在[官方Discord服务器](https://discord.gg/nDt7AjGJQH)访问此命令。该命令将很快可用。",
|
||||
"query_too_small": "# 您的搜索太短了\n您的搜索必须至少 3 个字符长。",
|
||||
"query_too_long": "# 您的搜索太长了\n您的搜索必须最长为 100 个字符。"
|
||||
},
|
||||
"wn8": {
|
||||
"$": "WN8",
|
||||
"very_bad": "非常差",
|
||||
"bad": "差",
|
||||
"below_average": "较差",
|
||||
"average": "平均",
|
||||
"above_average": "高于平均",
|
||||
"good": "好",
|
||||
"very_good": "非常好",
|
||||
"great": "很好",
|
||||
"unicum": "Unicum",
|
||||
"super_unicum": "Super unicum"
|
||||
},
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "今日:",
|
||||
"description": "今日:"
|
||||
},
|
||||
"30": {
|
||||
"$": "30",
|
||||
"description": "30天"
|
||||
},
|
||||
"60": {
|
||||
"$": "60",
|
||||
"description": "60天"
|
||||
},
|
||||
"90": {
|
||||
"$": "90",
|
||||
"description": "90天"
|
||||
},
|
||||
"career": {
|
||||
"$": "玩家资料",
|
||||
"description": "玩家资料"
|
||||
},
|
||||
"custom": {
|
||||
"$": "自定义",
|
||||
"description": "自定义范围",
|
||||
"options": {
|
||||
"start": {
|
||||
"$": "开始时间",
|
||||
"description": "从今天开始于数天前"
|
||||
},
|
||||
"end": {
|
||||
"$": "结束时间",
|
||||
"description": "从今天开始于数天前"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"clan": {
|
||||
"$": "军团",
|
||||
"description": "The clan name or tag"
|
||||
},
|
||||
"tank": {
|
||||
"$": "tank",
|
||||
"description": "The tank to get stats for"
|
||||
},
|
||||
"username": {
|
||||
"$": "username",
|
||||
"description": "The Blitz username of the player"
|
||||
},
|
||||
"filters": {
|
||||
"nation": {
|
||||
"$": "nation",
|
||||
"description": "Nation"
|
||||
},
|
||||
"class": {
|
||||
"$": "class",
|
||||
"description": "Class"
|
||||
},
|
||||
"type": {
|
||||
"$": "type",
|
||||
"description": "Type"
|
||||
}
|
||||
},
|
||||
"region": {
|
||||
"$": "region",
|
||||
"description": "Region"
|
||||
},
|
||||
"tier": {
|
||||
"$": "tier",
|
||||
"description": "Tier",
|
||||
"choices": {
|
||||
"tier": "Tier %s - %s"
|
||||
}
|
||||
}
|
||||
},
|
||||
"periods": {
|
||||
"career": "Career",
|
||||
"today": "Today",
|
||||
"days": "%s days",
|
||||
"custom": "%s - %s days"
|
||||
},
|
||||
"filters": {
|
||||
"none": "No filters",
|
||||
"tier": "Tier %s"
|
||||
},
|
||||
"no_data": {
|
||||
"battles_in_period": "No battles played in this period",
|
||||
"battles_in_season": "No battles played in this season",
|
||||
"players_in_period": "No players in this period",
|
||||
"tanks_found": "No tanks found"
|
||||
},
|
||||
"buttons": {
|
||||
"refresh": "Refresh"
|
||||
},
|
||||
"hero_stats": {
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"tier": "Tier",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy",
|
||||
"kills": "Kills"
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
"auction": {
|
||||
"$": "auction",
|
||||
"description": "Tanks available right now in the auction",
|
||||
"body": {
|
||||
"title": "Blitz Auction",
|
||||
"subtitle": "%s available • next prices %s\nBid now: %s",
|
||||
"next": "Next price: %s",
|
||||
"available": "Available: %s / %s"
|
||||
},
|
||||
"errors": {
|
||||
"no_auction": "# No ongoing auction\n\nCurrently, there are no tanks available for purchase in the auction. If you think this is an error, please report this discrepancy in [the official Discord Server](https://discord.gg/nDt7AjGJQH)."
|
||||
},
|
||||
"actions": {
|
||||
"bid": "Bid now"
|
||||
}
|
||||
},
|
||||
"replay": {
|
||||
"$": "replay",
|
||||
"description": "Display replay results"
|
||||
},
|
||||
"research": {
|
||||
"$": "research",
|
||||
"description": "Lists the expenses in researching a line",
|
||||
"options": {
|
||||
"target_tank": {
|
||||
"$": "target-tank",
|
||||
"description": "The final tank to research in the line"
|
||||
},
|
||||
"starting_tank": {
|
||||
"$": "starting-tank",
|
||||
"description": "The starting tank in the line (inferred automatically if not provided)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": "Research",
|
||||
"total": "Total",
|
||||
"research": "Research: %s",
|
||||
"upgrades": "Upgrades: %s",
|
||||
"purchase": "Purchase: %s",
|
||||
"equipment": "Equipment: %s",
|
||||
"estimation": "# This is an estimation!\n\nThis list may include already researched tanks because of the inaccurate information Wargaming provides. Try providing a `starting-tank` from the line when using the command if you can."
|
||||
},
|
||||
"errors": {
|
||||
"non_tech_tree": "# %s is not on the tech tree\n\nYou cannot research a premium/collector tank.",
|
||||
"tier_1": "# %s is a tier I\n\nTier I tanks are always unlocked for free for all players.",
|
||||
"already_researched": "# %s is already researched\n\nTry providing a `starting-tank` when using the command to view the totals for a line you have already researched.",
|
||||
"start_end_equal": "# %s was provided twice\n\nMake sure `starting-tank` and `target-tank` are different.",
|
||||
"tanks_not_on_line": "# %s and %s are not on the same line\n\nMake sure `starting-tank` and `target-tank` are on the same tech-tree line.",
|
||||
"unordered": "# %s higher tiered to %s\n\nMake sure to provide %s as the `starting-tank` instead as it is the lower tiered tank."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"$": "about",
|
||||
"description": "All the info you need about the bot",
|
||||
"subcommands": {
|
||||
"commands": {
|
||||
"$": "commands",
|
||||
"description": "List of all commands and their descriptions",
|
||||
"body": "# Commands\n\nBlitzKit offers the following commands:\n\n"
|
||||
},
|
||||
"embeds": {
|
||||
"$": "embeds",
|
||||
"description": "How embeds work"
|
||||
},
|
||||
"introduction": {
|
||||
"$": "introduction",
|
||||
"description": "About the bot"
|
||||
},
|
||||
"invite": {
|
||||
"$": "invite",
|
||||
"description": "How to invite the bot"
|
||||
},
|
||||
"timezones": {
|
||||
"$": "timezones",
|
||||
"description": "How BlitzKit infers and uses your timezone"
|
||||
},
|
||||
"credits": {
|
||||
"$": "credits",
|
||||
"description": "People who have helped BlitzKit"
|
||||
}
|
||||
}
|
||||
},
|
||||
"breakdown": {
|
||||
"$": "breakdown",
|
||||
"description": "A period's breakdown by tanks played",
|
||||
"body": {
|
||||
"total": "Total",
|
||||
"battles": "Battles",
|
||||
"wn8": "WN8",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"unknown_tank": "Unknown tank %s"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"$": "debug",
|
||||
"description": "Debug information about the bot",
|
||||
"body": {
|
||||
"title": "# Debug\n\n",
|
||||
"version": "Version",
|
||||
"shard": {
|
||||
"$": "Shard",
|
||||
"default": "default"
|
||||
},
|
||||
"uptime": "Uptime"
|
||||
}
|
||||
},
|
||||
"evolution": {
|
||||
"$": "evolution",
|
||||
"description": "Evolution of statistics",
|
||||
"groups": {
|
||||
"player": {
|
||||
"$": "player",
|
||||
"description": "Player statistics"
|
||||
},
|
||||
"tank": {
|
||||
"$": "tank",
|
||||
"description": "Tank statistics"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inactive": {
|
||||
"$": "inactive",
|
||||
"description": "Lists all inactive players in a clan above a threshold",
|
||||
"options": {
|
||||
"threshold": {
|
||||
"$": "threshold",
|
||||
"description": "The number of days inactive (default: %s days)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": "Inactive for %s+ days",
|
||||
"listing": "%s days"
|
||||
}
|
||||
},
|
||||
"full_stats": {
|
||||
"$": "full-stats",
|
||||
"description": "Full in-game statistics",
|
||||
"body": {
|
||||
"cards": {
|
||||
"games": {
|
||||
"$": "Games",
|
||||
"winrate": "Winrate",
|
||||
"battles": "Battles",
|
||||
"wins_losses": "Wins / losses"
|
||||
},
|
||||
"efficiency": {
|
||||
"$": "Efficiency",
|
||||
"wn8": "WN8",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy"
|
||||
},
|
||||
"lethality": {
|
||||
"$": "Lethality",
|
||||
"average_damage": "Average damage",
|
||||
"damage_per_tier": "Damage per tier",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"average_kills": "Average kills"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"$": "Miscellaneous",
|
||||
"average_tier": "Average tier",
|
||||
"average_spots": "Average spots",
|
||||
"average_xp": "Average XP",
|
||||
"kills_to_death_ratio": "Kills to death ratio"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"link": {
|
||||
"$": "link",
|
||||
"description": "Links your Blitz and Discord account",
|
||||
"body": {
|
||||
"accounts_linked": "Accounts linked",
|
||||
"no_role_permissions": {
|
||||
"$": "%s failed to verify",
|
||||
"description": "I don't have the permission to manage roles."
|
||||
}
|
||||
},
|
||||
"embed": {
|
||||
"title": "Incorrect account?",
|
||||
"description": "Use the command again and select a username from the search results."
|
||||
}
|
||||
},
|
||||
"search_clans": {
|
||||
"$": "search-clans",
|
||||
"description": "Search clans",
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "The max number of clan results (default: %s)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"title": "Clan search for %s in region %s",
|
||||
"no_results": "No clans found"
|
||||
}
|
||||
},
|
||||
"search_players": {
|
||||
"$": "search-players",
|
||||
"description": "Search players",
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "The max number of player results (default: %s)"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"title": "Player search for %s in region %s",
|
||||
"no_results": "No players found"
|
||||
}
|
||||
},
|
||||
"rating_leaderboard": {
|
||||
"$": "rating-leaderboard",
|
||||
"description": "Rating battles statistics",
|
||||
"subcommands": {
|
||||
"neighbors": {
|
||||
"$": "neighbors",
|
||||
"description": "Neighboring players on the leaderboard"
|
||||
},
|
||||
"league": {
|
||||
"$": "league",
|
||||
"description": "Top players of a league"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"limit": {
|
||||
"$": "limit",
|
||||
"description": "How many neighbors to display (default: %s)"
|
||||
},
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "Season number (default: current)",
|
||||
"choices": {
|
||||
"current": "%s (current)"
|
||||
}
|
||||
},
|
||||
"league": {
|
||||
"$": "league",
|
||||
"description": "The league to display"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"top_players": "Top %s players",
|
||||
"no_participation": "# %s didn't play rating in season %s\n\nThis player did not participate in this season or did not get past calibration.",
|
||||
"no_ongoing_season": "# No ongoing season\n\nThere isn't a currently running rating season.",
|
||||
"deleted_player": "Deleted %s",
|
||||
"neighbors": "Rating neighbors",
|
||||
"more": "+ %s more"
|
||||
}
|
||||
},
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's played tanks and statistics"
|
||||
},
|
||||
"stats": {
|
||||
"$": "stats",
|
||||
"description": "Quick statistics for a period"
|
||||
},
|
||||
"owned_tanks": {
|
||||
"$": "owned-tanks",
|
||||
"description": "Shows all own tanks in a tier",
|
||||
"body": {
|
||||
"title": "# %s's owned tier %s tanks\n\n"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"$": "permissions",
|
||||
"description": "Checks wether the bot has the required permissions to function",
|
||||
"body": {
|
||||
"title": "# Permissions\n\n%s",
|
||||
"view_channels": "View channels: needed to find the message the refresh button was used on",
|
||||
"read_message_history": "Read message history: needed to find the message to refresh",
|
||||
"attach_files": "Attach files: needed to add images to image-based commands",
|
||||
"external_emojis": "External emojis: needed to add national flags and tank class emojis"
|
||||
}
|
||||
},
|
||||
"ping": {
|
||||
"$": "ping",
|
||||
"description": "Check wether the bot is alive.",
|
||||
"body": {
|
||||
"pong": "Pong 🏓",
|
||||
"pong_with_time": "Pong 🏓 - %sms"
|
||||
},
|
||||
"subcommands": {
|
||||
"blitzkit": {
|
||||
"$": "blitzkit",
|
||||
"description": "Ping BlitzKit"
|
||||
},
|
||||
"wotb": {
|
||||
"$": "wotb",
|
||||
"description": "Ping World of Tanks Blitz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"player_info": {
|
||||
"$": "player-info",
|
||||
"description": "Basic information about a player",
|
||||
"body": {
|
||||
"title": "%s's information",
|
||||
"nickname": "Nickname",
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"account_id": "Account ID",
|
||||
"created": "Created",
|
||||
"last_battle": "Last battle"
|
||||
}
|
||||
},
|
||||
"rating": {
|
||||
"$": "rating",
|
||||
"description": "Rating player's statistics",
|
||||
"subcommands": {
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's rating statistics"
|
||||
},
|
||||
"season": {
|
||||
"$": "season",
|
||||
"description": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"subtitle": {
|
||||
"today": "Today's rating statistics",
|
||||
"season": "This season's rating statistics"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"no_participation": "# %s hasn't played rating\n\nThis player hasn't participated in the rating gamemode this season.",
|
||||
"unrecorded_stats": "# Statistics currently unavailable\n\nWargaming may be currently be facing server downtime. If there is an on-going season, statistics should be available withing 24 hours."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"website": {}
|
||||
}
|
||||
@@ -1,11 +1,5 @@
|
||||
import { times } from 'lodash-es';
|
||||
import {
|
||||
CrewType,
|
||||
GunDefinition,
|
||||
ShellType,
|
||||
TankClass,
|
||||
TankType,
|
||||
} from '../../protos';
|
||||
import { CrewType, ShellType, TankClass, TankType } from '../../protos';
|
||||
|
||||
export const SHELL_NAMES: Record<ShellType, string> = {
|
||||
[ShellType.AP]: 'AP',
|
||||
@@ -13,21 +7,14 @@ export const SHELL_NAMES: Record<ShellType, string> = {
|
||||
[ShellType.HEAT]: 'HEAT',
|
||||
[ShellType.HE]: 'HE',
|
||||
};
|
||||
export const CREW_MEMBER_NAMES: Record<CrewType, string> = {
|
||||
[CrewType.COMMANDER]: 'Commander',
|
||||
[CrewType.DRIVER]: 'Driver',
|
||||
[CrewType.GUNNER]: 'Gunner',
|
||||
[CrewType.LOADER]: 'Loader',
|
||||
[CrewType.RADIOMAN]: 'Radioman',
|
||||
};
|
||||
export const GUN_TYPE_NAMES: Record<
|
||||
Exclude<GunDefinition['gun_type'], undefined>['$case'],
|
||||
string
|
||||
> = {
|
||||
auto_loader: 'Auto loader',
|
||||
auto_reloader: 'Auto reloader',
|
||||
regular: 'Regular',
|
||||
};
|
||||
export const CREW_MEMBER_NAMES = {
|
||||
[CrewType.COMMANDER]: 'commander',
|
||||
[CrewType.DRIVER]: 'driver',
|
||||
[CrewType.GUNNER]: 'gunner',
|
||||
[CrewType.LOADER]: 'loader',
|
||||
[CrewType.RADIOMAN]: 'radioman',
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* @deprecated use svg
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { deburr } from 'lodash-es';
|
||||
import { SUPPORTED_LOCALES } from '../../../i18n/src/strings';
|
||||
import { I18nString } from '../protos';
|
||||
import { fetchCamouflageDefinitions } from './camouflageDefinitions';
|
||||
import { fetchTankDefinitions } from './tankDefinitions';
|
||||
|
||||
@@ -11,12 +13,18 @@ export async function fetchTankNames() {
|
||||
|
||||
return await Promise.all(
|
||||
tankDefinitionsArray.map(async (tank) => {
|
||||
const searchableNameDeburr: I18nString = { locales: {} };
|
||||
|
||||
Object.entries(tank.name_full ?? tank.name).forEach(([key, value]) => {
|
||||
searchableNameDeburr.locales[key] = deburr(value);
|
||||
});
|
||||
|
||||
return {
|
||||
id: tank.id,
|
||||
name: tank.name,
|
||||
nameFull: tank.name_full,
|
||||
searchableName: tank.name_full ?? tank.name,
|
||||
searchableNameDeburr: deburr(tank.name_full ?? tank.name),
|
||||
searchableNameDeburr,
|
||||
camouflages: tank.camouflages
|
||||
?.map((id) => camouflageDefinitions.camouflages[id]?.name)
|
||||
.filter(Boolean)
|
||||
@@ -26,3 +34,11 @@ export async function fetchTankNames() {
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export const SEARCH_KEYS = [
|
||||
...SUPPORTED_LOCALES.map((locale) => [
|
||||
`searchableName.locales.${locale}`,
|
||||
`searchableNameDeburr.locales.${locale}`,
|
||||
]).flat(),
|
||||
'camouflages',
|
||||
];
|
||||
@@ -1,5 +1,4 @@
|
||||
const numberFormat = Intl.NumberFormat('en', { notation: 'compact' });
|
||||
|
||||
export function formatCompact(number: number) {
|
||||
export function formatCompact(locale: string, number: number) {
|
||||
const numberFormat = Intl.NumberFormat(locale, { notation: 'compact' });
|
||||
return numberFormat.format(number);
|
||||
}
|
||||
@@ -251,7 +251,7 @@ export const AverageDefinitions_AveragesEntry: MessageFns<AverageDefinitions_Ave
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? AverageDefinitionsEntry.fromPartial(object.value)
|
||||
: createBaseAverageDefinitionsEntry();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,13 +2,15 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
|
||||
message CamouflageDefinitions {
|
||||
map<uint32, Camouflage> camouflages = 1;
|
||||
}
|
||||
|
||||
message Camouflage {
|
||||
required uint32 id = 1;
|
||||
required string name = 2;
|
||||
optional string tank_name = 3;
|
||||
optional string tank_name_full = 4;
|
||||
required I18nString name = 2;
|
||||
optional I18nString tank_name = 3;
|
||||
optional I18nString tank_name_full = 4;
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
import { I18nString, createBaseI18nString } from "./i18n";
|
||||
|
||||
export const protobufPackage = "blitzkit";
|
||||
|
||||
@@ -20,9 +21,9 @@ export interface CamouflageDefinitions_CamouflagesEntry {
|
||||
|
||||
export interface Camouflage {
|
||||
id: number;
|
||||
name: string;
|
||||
tank_name?: string | undefined;
|
||||
tank_name_full?: string | undefined;
|
||||
name: I18nString;
|
||||
tank_name?: I18nString | undefined;
|
||||
tank_name_full?: I18nString | undefined;
|
||||
}
|
||||
|
||||
function createBaseCamouflageDefinitions(): CamouflageDefinitions {
|
||||
@@ -184,13 +185,13 @@ export const CamouflageDefinitions_CamouflagesEntry: MessageFns<CamouflageDefini
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? Camouflage.fromPartial(object.value)
|
||||
: createBaseCamouflage();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseCamouflage(): Camouflage {
|
||||
return { id: 0, name: "", tank_name: undefined, tank_name_full: undefined };
|
||||
return { id: 0, name: createBaseI18nString(), tank_name: undefined, tank_name_full: undefined };
|
||||
}
|
||||
|
||||
export const Camouflage: MessageFns<Camouflage> = {
|
||||
@@ -198,14 +199,14 @@ export const Camouflage: MessageFns<Camouflage> = {
|
||||
if (message.id !== 0) {
|
||||
writer.uint32(8).uint32(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
writer.uint32(18).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(18).fork()).join();
|
||||
}
|
||||
if (message.tank_name !== undefined && message.tank_name !== undefined) {
|
||||
writer.uint32(26).string(message.tank_name);
|
||||
if (message.tank_name !== undefined) {
|
||||
I18nString.encode(message.tank_name, writer.uint32(26).fork()).join();
|
||||
}
|
||||
if (message.tank_name_full !== undefined && message.tank_name_full !== undefined) {
|
||||
writer.uint32(34).string(message.tank_name_full);
|
||||
if (message.tank_name_full !== undefined) {
|
||||
I18nString.encode(message.tank_name_full, writer.uint32(34).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
@@ -230,7 +231,7 @@ export const Camouflage: MessageFns<Camouflage> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 3: {
|
||||
@@ -238,7 +239,7 @@ export const Camouflage: MessageFns<Camouflage> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.tank_name = reader.string();
|
||||
message.tank_name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 4: {
|
||||
@@ -246,7 +247,7 @@ export const Camouflage: MessageFns<Camouflage> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.tank_name_full = reader.string();
|
||||
message.tank_name_full = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -261,9 +262,9 @@ export const Camouflage: MessageFns<Camouflage> = {
|
||||
fromJSON(object: any): Camouflage {
|
||||
return {
|
||||
id: globalThis.Number(assertSet("Camouflage.id", object.id)),
|
||||
name: globalThis.String(assertSet("Camouflage.name", object.name)),
|
||||
tank_name: isSet(object.tank_name) ? globalThis.String(object.tank_name) : undefined,
|
||||
tank_name_full: isSet(object.tank_name_full) ? globalThis.String(object.tank_name_full) : undefined,
|
||||
name: I18nString.fromJSON(assertSet("Camouflage.name", object.name)),
|
||||
tank_name: isSet(object.tank_name) ? I18nString.fromJSON(object.tank_name) : undefined,
|
||||
tank_name_full: isSet(object.tank_name_full) ? I18nString.fromJSON(object.tank_name_full) : undefined,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -272,14 +273,14 @@ export const Camouflage: MessageFns<Camouflage> = {
|
||||
if (message.id !== 0) {
|
||||
obj.id = Math.round(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
if (message.tank_name !== undefined && message.tank_name !== undefined) {
|
||||
obj.tank_name = message.tank_name;
|
||||
if (message.tank_name !== undefined) {
|
||||
obj.tank_name = I18nString.toJSON(message.tank_name);
|
||||
}
|
||||
if (message.tank_name_full !== undefined && message.tank_name_full !== undefined) {
|
||||
obj.tank_name_full = message.tank_name_full;
|
||||
if (message.tank_name_full !== undefined) {
|
||||
obj.tank_name_full = I18nString.toJSON(message.tank_name_full);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
@@ -290,9 +291,15 @@ export const Camouflage: MessageFns<Camouflage> = {
|
||||
fromPartial<I extends Exact<DeepPartial<Camouflage>, I>>(object: I): Camouflage {
|
||||
const message = createBaseCamouflage();
|
||||
message.id = object.id ?? 0;
|
||||
message.name = object.name ?? "";
|
||||
message.tank_name = object.tank_name ?? undefined;
|
||||
message.tank_name_full = object.tank_name_full ?? undefined;
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
message.tank_name = (object.tank_name !== undefined && object.tank_name !== null)
|
||||
? I18nString.fromPartial(object.tank_name)
|
||||
: undefined;
|
||||
message.tank_name_full = (object.tank_name_full !== undefined && object.tank_name_full !== null)
|
||||
? I18nString.fromPartial(object.tank_name_full)
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,13 +2,15 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
|
||||
message ConsumableDefinitions {
|
||||
map<uint32, Consumable> consumables = 1;
|
||||
}
|
||||
|
||||
message Consumable {
|
||||
required uint32 id = 1;
|
||||
required string name = 2;
|
||||
required I18nString name = 2;
|
||||
required uint32 cooldown = 3;
|
||||
optional float duration = 4;
|
||||
required bool game_mode_exclusive = 5;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
import { I18nString, createBaseI18nString } from "./i18n";
|
||||
|
||||
export const protobufPackage = "blitzkit";
|
||||
|
||||
@@ -47,7 +48,7 @@ export interface ConsumableDefinitions_ConsumablesEntry {
|
||||
|
||||
export interface Consumable {
|
||||
id: number;
|
||||
name: string;
|
||||
name: I18nString;
|
||||
cooldown: number;
|
||||
duration?: number | undefined;
|
||||
game_mode_exclusive: boolean;
|
||||
@@ -240,13 +241,21 @@ export const ConsumableDefinitions_ConsumablesEntry: MessageFns<ConsumableDefini
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? Consumable.fromPartial(object.value)
|
||||
: createBaseConsumable();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseConsumable(): Consumable {
|
||||
return { id: 0, name: "", cooldown: 0, duration: undefined, game_mode_exclusive: false, include: [], exclude: [] };
|
||||
return {
|
||||
id: 0,
|
||||
name: createBaseI18nString(),
|
||||
cooldown: 0,
|
||||
duration: undefined,
|
||||
game_mode_exclusive: false,
|
||||
include: [],
|
||||
exclude: [],
|
||||
};
|
||||
}
|
||||
|
||||
export const Consumable: MessageFns<Consumable> = {
|
||||
@@ -254,8 +263,8 @@ export const Consumable: MessageFns<Consumable> = {
|
||||
if (message.id !== 0) {
|
||||
writer.uint32(8).uint32(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
writer.uint32(18).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(18).fork()).join();
|
||||
}
|
||||
if (message.cooldown !== 0) {
|
||||
writer.uint32(24).uint32(message.cooldown);
|
||||
@@ -295,7 +304,7 @@ export const Consumable: MessageFns<Consumable> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 3: {
|
||||
@@ -350,7 +359,7 @@ export const Consumable: MessageFns<Consumable> = {
|
||||
fromJSON(object: any): Consumable {
|
||||
return {
|
||||
id: globalThis.Number(assertSet("Consumable.id", object.id)),
|
||||
name: globalThis.String(assertSet("Consumable.name", object.name)),
|
||||
name: I18nString.fromJSON(assertSet("Consumable.name", object.name)),
|
||||
cooldown: globalThis.Number(assertSet("Consumable.cooldown", object.cooldown)),
|
||||
duration: isSet(object.duration) ? globalThis.Number(object.duration) : undefined,
|
||||
game_mode_exclusive: globalThis.Boolean(assertSet("Consumable.game_mode_exclusive", object.game_mode_exclusive)),
|
||||
@@ -368,8 +377,8 @@ export const Consumable: MessageFns<Consumable> = {
|
||||
if (message.id !== 0) {
|
||||
obj.id = Math.round(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
if (message.cooldown !== 0) {
|
||||
obj.cooldown = Math.round(message.cooldown);
|
||||
@@ -395,7 +404,9 @@ export const Consumable: MessageFns<Consumable> = {
|
||||
fromPartial<I extends Exact<DeepPartial<Consumable>, I>>(object: I): Consumable {
|
||||
const message = createBaseConsumable();
|
||||
message.id = object.id ?? 0;
|
||||
message.name = object.name ?? "";
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
message.cooldown = object.cooldown ?? 0;
|
||||
message.duration = object.duration ?? undefined;
|
||||
message.game_mode_exclusive = object.game_mode_exclusive ?? false;
|
||||
|
||||
@@ -2,14 +2,16 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
|
||||
message EquipmentDefinitions {
|
||||
map<string, EquipmentPreset> presets = 1;
|
||||
map<uint32, Equipment> equipments = 2;
|
||||
}
|
||||
|
||||
message Equipment {
|
||||
required string name = 1;
|
||||
required string description = 2;
|
||||
required I18nString name = 1;
|
||||
required I18nString description = 2;
|
||||
}
|
||||
|
||||
message EquipmentPreset {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
import { I18nString, createBaseI18nString } from "./i18n";
|
||||
|
||||
export const protobufPackage = "blitzkit";
|
||||
|
||||
@@ -25,8 +26,8 @@ export interface EquipmentDefinitions_EquipmentsEntry {
|
||||
}
|
||||
|
||||
export interface Equipment {
|
||||
name: string;
|
||||
description: string;
|
||||
name: I18nString;
|
||||
description: I18nString;
|
||||
}
|
||||
|
||||
export interface EquipmentPreset {
|
||||
@@ -235,7 +236,7 @@ export const EquipmentDefinitions_PresetsEntry: MessageFns<EquipmentDefinitions_
|
||||
message.key = object.key ?? "";
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? EquipmentPreset.fromPartial(object.value)
|
||||
: createBaseEquipmentPreset();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
@@ -317,22 +318,22 @@ export const EquipmentDefinitions_EquipmentsEntry: MessageFns<EquipmentDefinitio
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? Equipment.fromPartial(object.value)
|
||||
: createBaseEquipment();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseEquipment(): Equipment {
|
||||
return { name: "", description: "" };
|
||||
return { name: createBaseI18nString(), description: createBaseI18nString() };
|
||||
}
|
||||
|
||||
export const Equipment: MessageFns<Equipment> = {
|
||||
encode(message: Equipment, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.name !== "") {
|
||||
writer.uint32(10).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(10).fork()).join();
|
||||
}
|
||||
if (message.description !== "") {
|
||||
writer.uint32(18).string(message.description);
|
||||
if (message.description !== undefined) {
|
||||
I18nString.encode(message.description, writer.uint32(18).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
@@ -349,7 +350,7 @@ export const Equipment: MessageFns<Equipment> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 2: {
|
||||
@@ -357,7 +358,7 @@ export const Equipment: MessageFns<Equipment> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.description = reader.string();
|
||||
message.description = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -371,18 +372,18 @@ export const Equipment: MessageFns<Equipment> = {
|
||||
|
||||
fromJSON(object: any): Equipment {
|
||||
return {
|
||||
name: globalThis.String(assertSet("Equipment.name", object.name)),
|
||||
description: globalThis.String(assertSet("Equipment.description", object.description)),
|
||||
name: I18nString.fromJSON(assertSet("Equipment.name", object.name)),
|
||||
description: I18nString.fromJSON(assertSet("Equipment.description", object.description)),
|
||||
};
|
||||
},
|
||||
|
||||
toJSON(message: Equipment): unknown {
|
||||
const obj: any = {};
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
if (message.description !== "") {
|
||||
obj.description = message.description;
|
||||
if (message.description !== undefined) {
|
||||
obj.description = I18nString.toJSON(message.description);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
@@ -392,8 +393,12 @@ export const Equipment: MessageFns<Equipment> = {
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<Equipment>, I>>(object: I): Equipment {
|
||||
const message = createBaseEquipment();
|
||||
message.name = object.name ?? "";
|
||||
message.description = object.description ?? "";
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
message.description = (object.description !== undefined && object.description !== null)
|
||||
? I18nString.fromPartial(object.description)
|
||||
: createBaseI18nString();
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,6 +2,8 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
|
||||
message GameDefinitions {
|
||||
required string version = 1;
|
||||
repeated string nations = 2;
|
||||
@@ -10,7 +12,7 @@ message GameDefinitions {
|
||||
}
|
||||
|
||||
message GameMode {
|
||||
required string name = 1;
|
||||
required I18nString name = 1;
|
||||
}
|
||||
|
||||
message GameModeRole {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
import { I18nString, createBaseI18nString } from "./i18n";
|
||||
|
||||
export const protobufPackage = "blitzkit";
|
||||
|
||||
@@ -27,7 +28,7 @@ export interface GameDefinitions_RolesEntry {
|
||||
}
|
||||
|
||||
export interface GameMode {
|
||||
name: string;
|
||||
name: I18nString;
|
||||
}
|
||||
|
||||
export interface GameModeRole {
|
||||
@@ -259,7 +260,7 @@ export const GameDefinitions_GameModesEntry: MessageFns<GameDefinitions_GameMode
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? GameMode.fromPartial(object.value)
|
||||
: createBaseGameMode();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
@@ -337,19 +338,19 @@ export const GameDefinitions_RolesEntry: MessageFns<GameDefinitions_RolesEntry>
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? GameModeRole.fromPartial(object.value)
|
||||
: createBaseGameModeRole();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseGameMode(): GameMode {
|
||||
return { name: "" };
|
||||
return { name: createBaseI18nString() };
|
||||
}
|
||||
|
||||
export const GameMode: MessageFns<GameMode> = {
|
||||
encode(message: GameMode, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.name !== "") {
|
||||
writer.uint32(10).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(10).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
@@ -366,7 +367,7 @@ export const GameMode: MessageFns<GameMode> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -379,13 +380,13 @@ export const GameMode: MessageFns<GameMode> = {
|
||||
},
|
||||
|
||||
fromJSON(object: any): GameMode {
|
||||
return { name: globalThis.String(assertSet("GameMode.name", object.name)) };
|
||||
return { name: I18nString.fromJSON(assertSet("GameMode.name", object.name)) };
|
||||
},
|
||||
|
||||
toJSON(message: GameMode): unknown {
|
||||
const obj: any = {};
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
@@ -395,7 +396,9 @@ export const GameMode: MessageFns<GameMode> = {
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<GameMode>, I>>(object: I): GameMode {
|
||||
const message = createBaseGameMode();
|
||||
message.name = object.name ?? "";
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
message I18nString {
|
||||
map<string, string> locales = 1;
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/i18n.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
export const protobufPackage = "blitzkit";
|
||||
|
||||
export interface I18nString {
|
||||
locales: { [key: string]: string };
|
||||
}
|
||||
|
||||
export interface I18nString_LocalesEntry {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export function createBaseI18nString(): I18nString {
|
||||
return { locales: {} };
|
||||
}
|
||||
|
||||
export const I18nString: MessageFns<I18nString> = {
|
||||
encode(message: I18nString, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
Object.entries(message.locales).forEach(([key, value]) => {
|
||||
I18nString_LocalesEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join();
|
||||
});
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): I18nString {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseI18nString();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
const entry1 = I18nString_LocalesEntry.decode(reader, reader.uint32());
|
||||
if (entry1.value !== undefined) {
|
||||
message.locales[entry1.key] = entry1.value;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
fromJSON(object: any): I18nString {
|
||||
return {
|
||||
locales: isObject(object.locales)
|
||||
? Object.entries(object.locales).reduce<{ [key: string]: string }>((acc, [key, value]) => {
|
||||
acc[key] = String(value);
|
||||
return acc;
|
||||
}, {})
|
||||
: {},
|
||||
};
|
||||
},
|
||||
|
||||
toJSON(message: I18nString): unknown {
|
||||
const obj: any = {};
|
||||
if (message.locales) {
|
||||
const entries = Object.entries(message.locales);
|
||||
if (entries.length > 0) {
|
||||
obj.locales = {};
|
||||
entries.forEach(([k, v]) => {
|
||||
obj.locales[k] = v;
|
||||
});
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<I18nString>, I>>(base?: I): I18nString {
|
||||
return I18nString.fromPartial(base ?? ({} as any));
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<I18nString>, I>>(object: I): I18nString {
|
||||
const message = createBaseI18nString();
|
||||
message.locales = Object.entries(object.locales ?? {}).reduce<{ [key: string]: string }>((acc, [key, value]) => {
|
||||
if (value !== undefined) {
|
||||
acc[key] = globalThis.String(value);
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseI18nString_LocalesEntry(): I18nString_LocalesEntry {
|
||||
return { key: "", value: "" };
|
||||
}
|
||||
|
||||
export const I18nString_LocalesEntry: MessageFns<I18nString_LocalesEntry> = {
|
||||
encode(message: I18nString_LocalesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.key !== undefined) {
|
||||
writer.uint32(10).string(message.key);
|
||||
}
|
||||
if (message.value !== undefined) {
|
||||
writer.uint32(18).string(message.value);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): I18nString_LocalesEntry {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseI18nString_LocalesEntry();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.key = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 2: {
|
||||
if (tag !== 18) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.value = reader.string();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
fromJSON(object: any): I18nString_LocalesEntry {
|
||||
return {
|
||||
key: globalThis.String(assertSet("I18nString_LocalesEntry.key", object.key)),
|
||||
value: globalThis.String(assertSet("I18nString_LocalesEntry.value", object.value)),
|
||||
};
|
||||
},
|
||||
|
||||
toJSON(message: I18nString_LocalesEntry): unknown {
|
||||
const obj: any = {};
|
||||
if (message.key !== undefined) {
|
||||
obj.key = message.key;
|
||||
}
|
||||
if (message.value !== undefined) {
|
||||
obj.value = message.value;
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<I18nString_LocalesEntry>, I>>(base?: I): I18nString_LocalesEntry {
|
||||
return I18nString_LocalesEntry.fromPartial(base ?? ({} as any));
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<I18nString_LocalesEntry>, I>>(object: I): I18nString_LocalesEntry {
|
||||
const message = createBaseI18nString_LocalesEntry();
|
||||
message.key = object.key ?? "";
|
||||
message.value = object.value ?? "";
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
||||
|
||||
export type DeepPartial<T> = T extends Builtin ? T
|
||||
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
|
||||
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
|
||||
: T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial<T["value"]> }
|
||||
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
: Partial<T>;
|
||||
|
||||
type KeysOfUnion<T> = T extends T ? keyof T : never;
|
||||
export type Exact<P, I extends P> = P extends Builtin ? P
|
||||
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
|
||||
|
||||
function isObject(value: any): boolean {
|
||||
return typeof value === "object" && value !== null;
|
||||
}
|
||||
|
||||
function isSet(value: any): boolean {
|
||||
return value !== null && value !== undefined;
|
||||
}
|
||||
|
||||
function assertSet<T>(field: string, value: T | undefined): T {
|
||||
if (!isSet(value)) {
|
||||
throw new TypeError(`Required field ${field} is not set`);
|
||||
}
|
||||
|
||||
return value as T;
|
||||
}
|
||||
|
||||
export interface MessageFns<T> {
|
||||
encode(message: T, writer?: BinaryWriter): BinaryWriter;
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): T;
|
||||
fromJSON(object: any): T;
|
||||
toJSON(message: T): unknown;
|
||||
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
|
||||
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ export * from './camouflage_definitions.ts';
|
||||
export * from './consumable_definitions.ts';
|
||||
export * from './equipment_definitions.ts';
|
||||
export * from './game_definitions.ts';
|
||||
export * from './i18n.ts';
|
||||
export * from './map_definitions.ts';
|
||||
export * from './model_definitions.ts';
|
||||
export * from './provision_definitions.ts';
|
||||
|
||||
@@ -2,11 +2,13 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
|
||||
message MapDefinitions {
|
||||
map<int32, MapDefinition> maps = 1;
|
||||
}
|
||||
|
||||
message MapDefinition {
|
||||
required uint32 id = 1;
|
||||
required string name = 2;
|
||||
required I18nString name = 2;
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
import { I18nString, createBaseI18nString } from "./i18n";
|
||||
|
||||
export const protobufPackage = "blitzkit";
|
||||
|
||||
@@ -20,7 +21,7 @@ export interface MapDefinitions_MapsEntry {
|
||||
|
||||
export interface MapDefinition {
|
||||
id: number;
|
||||
name: string;
|
||||
name: I18nString;
|
||||
}
|
||||
|
||||
function createBaseMapDefinitions(): MapDefinitions {
|
||||
@@ -175,13 +176,13 @@ export const MapDefinitions_MapsEntry: MessageFns<MapDefinitions_MapsEntry> = {
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? MapDefinition.fromPartial(object.value)
|
||||
: createBaseMapDefinition();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseMapDefinition(): MapDefinition {
|
||||
return { id: 0, name: "" };
|
||||
return { id: 0, name: createBaseI18nString() };
|
||||
}
|
||||
|
||||
export const MapDefinition: MessageFns<MapDefinition> = {
|
||||
@@ -189,8 +190,8 @@ export const MapDefinition: MessageFns<MapDefinition> = {
|
||||
if (message.id !== 0) {
|
||||
writer.uint32(8).uint32(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
writer.uint32(18).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(18).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
@@ -215,7 +216,7 @@ export const MapDefinition: MessageFns<MapDefinition> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -230,7 +231,7 @@ export const MapDefinition: MessageFns<MapDefinition> = {
|
||||
fromJSON(object: any): MapDefinition {
|
||||
return {
|
||||
id: globalThis.Number(assertSet("MapDefinition.id", object.id)),
|
||||
name: globalThis.String(assertSet("MapDefinition.name", object.name)),
|
||||
name: I18nString.fromJSON(assertSet("MapDefinition.name", object.name)),
|
||||
};
|
||||
},
|
||||
|
||||
@@ -239,8 +240,8 @@ export const MapDefinition: MessageFns<MapDefinition> = {
|
||||
if (message.id !== 0) {
|
||||
obj.id = Math.round(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
@@ -251,7 +252,9 @@ export const MapDefinition: MessageFns<MapDefinition> = {
|
||||
fromPartial<I extends Exact<DeepPartial<MapDefinition>, I>>(object: I): MapDefinition {
|
||||
const message = createBaseMapDefinition();
|
||||
message.id = object.id ?? 0;
|
||||
message.name = object.name ?? "";
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -265,7 +265,7 @@ export const ModelDefinitions_ModelsEntry: MessageFns<ModelDefinitions_ModelsEnt
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? ModelDefinition.fromPartial(object.value)
|
||||
: createBaseModelDefinition();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
@@ -545,7 +545,7 @@ export const ModelDefinition_TurretsEntry: MessageFns<ModelDefinition_TurretsEnt
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? TurretModelDefinition.fromPartial(object.value)
|
||||
: createBaseTurretModelDefinition();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
@@ -623,7 +623,7 @@ export const ModelDefinition_TracksEntry: MessageFns<ModelDefinition_TracksEntry
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? TrackModelDefinition.fromPartial(object.value)
|
||||
: createBaseTrackModelDefinition();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
@@ -1248,7 +1248,7 @@ export const TurretModelDefinition_GunsEntry: MessageFns<TurretModelDefinition_G
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? GunModelDefinition.fromPartial(object.value)
|
||||
: createBaseGunModelDefinition();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ syntax = "proto2";
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/consumable_definitions.proto";
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
|
||||
message ProvisionDefinitions {
|
||||
map<uint32, Provision> provisions = 1;
|
||||
@@ -10,7 +11,7 @@ message ProvisionDefinitions {
|
||||
|
||||
message Provision {
|
||||
required uint32 id = 1;
|
||||
required string name = 2;
|
||||
required I18nString name = 2;
|
||||
optional float crew = 3;
|
||||
required bool game_mode_exclusive = 5;
|
||||
repeated ConsumableTankFilter include = 6;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
import { ConsumableTankFilter } from "./consumable_definitions";
|
||||
import { I18nString, createBaseI18nString } from "./i18n";
|
||||
|
||||
export const protobufPackage = "blitzkit";
|
||||
|
||||
@@ -21,7 +22,7 @@ export interface ProvisionDefinitions_ProvisionsEntry {
|
||||
|
||||
export interface Provision {
|
||||
id: number;
|
||||
name: string;
|
||||
name: I18nString;
|
||||
crew?: number | undefined;
|
||||
game_mode_exclusive: boolean;
|
||||
include: ConsumableTankFilter[];
|
||||
@@ -187,13 +188,13 @@ export const ProvisionDefinitions_ProvisionsEntry: MessageFns<ProvisionDefinitio
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? Provision.fromPartial(object.value)
|
||||
: createBaseProvision();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseProvision(): Provision {
|
||||
return { id: 0, name: "", crew: undefined, game_mode_exclusive: false, include: [], exclude: [] };
|
||||
return { id: 0, name: createBaseI18nString(), crew: undefined, game_mode_exclusive: false, include: [], exclude: [] };
|
||||
}
|
||||
|
||||
export const Provision: MessageFns<Provision> = {
|
||||
@@ -201,8 +202,8 @@ export const Provision: MessageFns<Provision> = {
|
||||
if (message.id !== 0) {
|
||||
writer.uint32(8).uint32(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
writer.uint32(18).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(18).fork()).join();
|
||||
}
|
||||
if (message.crew !== undefined && message.crew !== undefined) {
|
||||
writer.uint32(29).float(message.crew);
|
||||
@@ -239,7 +240,7 @@ export const Provision: MessageFns<Provision> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 3: {
|
||||
@@ -286,7 +287,7 @@ export const Provision: MessageFns<Provision> = {
|
||||
fromJSON(object: any): Provision {
|
||||
return {
|
||||
id: globalThis.Number(assertSet("Provision.id", object.id)),
|
||||
name: globalThis.String(assertSet("Provision.name", object.name)),
|
||||
name: I18nString.fromJSON(assertSet("Provision.name", object.name)),
|
||||
crew: isSet(object.crew) ? globalThis.Number(object.crew) : undefined,
|
||||
game_mode_exclusive: globalThis.Boolean(assertSet("Provision.game_mode_exclusive", object.game_mode_exclusive)),
|
||||
include: globalThis.Array.isArray(object?.include)
|
||||
@@ -303,8 +304,8 @@ export const Provision: MessageFns<Provision> = {
|
||||
if (message.id !== 0) {
|
||||
obj.id = Math.round(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
if (message.crew !== undefined && message.crew !== undefined) {
|
||||
obj.crew = message.crew;
|
||||
@@ -327,7 +328,9 @@ export const Provision: MessageFns<Provision> = {
|
||||
fromPartial<I extends Exact<DeepPartial<Provision>, I>>(object: I): Provision {
|
||||
const message = createBaseProvision();
|
||||
message.id = object.id ?? 0;
|
||||
message.name = object.name ?? "";
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
message.crew = object.crew ?? undefined;
|
||||
message.game_mode_exclusive = object.game_mode_exclusive ?? false;
|
||||
message.include = object.include?.map((e) => ConsumableTankFilter.fromPartial(e)) || [];
|
||||
|
||||
@@ -180,7 +180,7 @@ export const Reviews_ReviewsEntry: MessageFns<Reviews_ReviewsEntry> = {
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? Review.fromPartial(object.value)
|
||||
: createBaseReview();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -175,9 +175,7 @@ export const SkillDefinitions_ClassesEntry: MessageFns<SkillDefinitions_ClassesE
|
||||
): SkillDefinitions_ClassesEntry {
|
||||
const message = createBaseSkillDefinitions_ClassesEntry();
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? Skill.fromPartial(object.value)
|
||||
: createBaseSkill();
|
||||
message.value = (object.value !== undefined && object.value !== null) ? Skill.fromPartial(object.value) : undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,6 +2,8 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
|
||||
message TankDefinitions {
|
||||
map<uint32, TankDefinition> tanks = 1;
|
||||
}
|
||||
@@ -9,7 +11,6 @@ message TankDefinitions {
|
||||
message TankDefinition {
|
||||
required uint32 id = 1;
|
||||
map<uint32, uint32> roles = 2;
|
||||
optional string description = 3;
|
||||
required bool fixed_camouflage = 4;
|
||||
repeated int32 camouflages = 5;
|
||||
repeated int32 ancestors = 6;
|
||||
@@ -17,8 +18,8 @@ message TankDefinition {
|
||||
repeated Crew crew = 8;
|
||||
required uint32 health = 9;
|
||||
required string nation = 10;
|
||||
required string name = 11;
|
||||
optional string name_full = 12;
|
||||
required I18nString name = 11;
|
||||
optional I18nString name_full = 12;
|
||||
required TankType type = 13;
|
||||
required uint32 max_consumables = 14;
|
||||
required uint32 max_provisions = 15;
|
||||
@@ -65,7 +66,7 @@ message TankPrice {
|
||||
message TrackDefinition {
|
||||
required uint32 id = 1;
|
||||
required uint32 tier = 2;
|
||||
required string name = 3;
|
||||
required I18nString name = 3;
|
||||
required uint32 weight = 4;
|
||||
required float traverse_speed = 5;
|
||||
optional ResearchCost research_cost = 6;
|
||||
@@ -79,7 +80,7 @@ message TrackDefinition {
|
||||
|
||||
message EngineDefinition {
|
||||
required uint32 id = 1;
|
||||
required string name = 2;
|
||||
required I18nString name = 2;
|
||||
optional ResearchCost research_cost = 3;
|
||||
required uint32 tier = 4;
|
||||
required float fire_chance = 5;
|
||||
@@ -94,7 +95,7 @@ message TurretDefinition {
|
||||
required uint32 view_range = 3;
|
||||
required float traverse_speed = 4;
|
||||
optional ResearchCost research_cost = 5;
|
||||
required string name = 6;
|
||||
required I18nString name = 6;
|
||||
required uint32 tier = 7;
|
||||
required uint32 weight = 8;
|
||||
repeated GunDefinition guns = 9;
|
||||
@@ -145,7 +146,7 @@ message GunDefinitionBase {
|
||||
required float rotation_speed = 2;
|
||||
optional ResearchCost research_cost = 3;
|
||||
required uint32 weight = 4;
|
||||
required string name = 5;
|
||||
required I18nString name = 5;
|
||||
required uint32 tier = 6;
|
||||
repeated ShellDefinition shells = 7;
|
||||
required float camouflage_loss = 8;
|
||||
@@ -160,7 +161,7 @@ message GunDefinitionBase {
|
||||
|
||||
message ShellDefinition {
|
||||
required uint32 id = 1;
|
||||
required string name = 2;
|
||||
required I18nString name = 2;
|
||||
required uint32 velocity = 3;
|
||||
required uint32 armor_damage = 4;
|
||||
required uint32 module_damage = 5;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
import { I18nString, createBaseI18nString } from "./i18n";
|
||||
|
||||
export const protobufPackage = "blitzkit";
|
||||
|
||||
@@ -261,7 +262,6 @@ export interface TankDefinitions_TanksEntry {
|
||||
export interface TankDefinition {
|
||||
id: number;
|
||||
roles: { [key: number]: number };
|
||||
description?: string | undefined;
|
||||
fixed_camouflage: boolean;
|
||||
camouflages: number[];
|
||||
ancestors: number[];
|
||||
@@ -269,8 +269,8 @@ export interface TankDefinition {
|
||||
crew: Crew[];
|
||||
health: number;
|
||||
nation: string;
|
||||
name: string;
|
||||
name_full?: string | undefined;
|
||||
name: I18nString;
|
||||
name_full?: I18nString | undefined;
|
||||
type: TankType;
|
||||
max_consumables: number;
|
||||
max_provisions: number;
|
||||
@@ -317,7 +317,7 @@ export interface TankPrice {
|
||||
export interface TrackDefinition {
|
||||
id: number;
|
||||
tier: number;
|
||||
name: string;
|
||||
name: I18nString;
|
||||
weight: number;
|
||||
traverse_speed: number;
|
||||
research_cost?: ResearchCost | undefined;
|
||||
@@ -331,7 +331,7 @@ export interface TrackDefinition {
|
||||
|
||||
export interface EngineDefinition {
|
||||
id: number;
|
||||
name: string;
|
||||
name: I18nString;
|
||||
research_cost?: ResearchCost | undefined;
|
||||
tier: number;
|
||||
fire_chance: number;
|
||||
@@ -346,7 +346,7 @@ export interface TurretDefinition {
|
||||
view_range: number;
|
||||
traverse_speed: number;
|
||||
research_cost?: ResearchCost | undefined;
|
||||
name: string;
|
||||
name: I18nString;
|
||||
tier: number;
|
||||
weight: number;
|
||||
guns: GunDefinition[];
|
||||
@@ -397,7 +397,7 @@ export interface GunDefinitionBase {
|
||||
rotation_speed: number;
|
||||
research_cost?: ResearchCost | undefined;
|
||||
weight: number;
|
||||
name: string;
|
||||
name: I18nString;
|
||||
tier: number;
|
||||
shells: ShellDefinition[];
|
||||
camouflage_loss: number;
|
||||
@@ -412,7 +412,7 @@ export interface GunDefinitionBase {
|
||||
|
||||
export interface ShellDefinition {
|
||||
id: number;
|
||||
name: string;
|
||||
name: I18nString;
|
||||
velocity: number;
|
||||
armor_damage: number;
|
||||
module_damage: number;
|
||||
@@ -603,7 +603,7 @@ export const TankDefinitions_TanksEntry: MessageFns<TankDefinitions_TanksEntry>
|
||||
message.key = object.key ?? 0;
|
||||
message.value = (object.value !== undefined && object.value !== null)
|
||||
? TankDefinition.fromPartial(object.value)
|
||||
: createBaseTankDefinition();
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
@@ -612,7 +612,6 @@ function createBaseTankDefinition(): TankDefinition {
|
||||
return {
|
||||
id: 0,
|
||||
roles: {},
|
||||
description: undefined,
|
||||
fixed_camouflage: false,
|
||||
camouflages: [],
|
||||
ancestors: [],
|
||||
@@ -620,7 +619,7 @@ function createBaseTankDefinition(): TankDefinition {
|
||||
crew: [],
|
||||
health: 0,
|
||||
nation: "",
|
||||
name: "",
|
||||
name: createBaseI18nString(),
|
||||
name_full: undefined,
|
||||
type: 0,
|
||||
max_consumables: 0,
|
||||
@@ -652,9 +651,6 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
Object.entries(message.roles).forEach(([key, value]) => {
|
||||
TankDefinition_RolesEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).join();
|
||||
});
|
||||
if (message.description !== undefined && message.description !== undefined) {
|
||||
writer.uint32(26).string(message.description);
|
||||
}
|
||||
if (message.fixed_camouflage !== false) {
|
||||
writer.uint32(32).bool(message.fixed_camouflage);
|
||||
}
|
||||
@@ -682,11 +678,11 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
if (message.nation !== "") {
|
||||
writer.uint32(82).string(message.nation);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
writer.uint32(90).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(90).fork()).join();
|
||||
}
|
||||
if (message.name_full !== undefined && message.name_full !== undefined) {
|
||||
writer.uint32(98).string(message.name_full);
|
||||
if (message.name_full !== undefined) {
|
||||
I18nString.encode(message.name_full, writer.uint32(98).fork()).join();
|
||||
}
|
||||
if (message.type !== 0) {
|
||||
writer.uint32(104).int32(message.type);
|
||||
@@ -774,14 +770,6 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case 3: {
|
||||
if (tag !== 26) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.description = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 4: {
|
||||
if (tag !== 32) {
|
||||
break;
|
||||
@@ -873,7 +861,7 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 12: {
|
||||
@@ -881,7 +869,7 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name_full = reader.string();
|
||||
message.name_full = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 13: {
|
||||
@@ -1054,7 +1042,6 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
return acc;
|
||||
}, {})
|
||||
: {},
|
||||
description: isSet(object.description) ? globalThis.String(object.description) : undefined,
|
||||
fixed_camouflage: globalThis.Boolean(assertSet("TankDefinition.fixed_camouflage", object.fixed_camouflage)),
|
||||
camouflages: globalThis.Array.isArray(object?.camouflages)
|
||||
? object.camouflages.map((e: any) => globalThis.Number(e))
|
||||
@@ -1068,8 +1055,8 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
crew: globalThis.Array.isArray(object?.crew) ? object.crew.map((e: any) => Crew.fromJSON(e)) : [],
|
||||
health: globalThis.Number(assertSet("TankDefinition.health", object.health)),
|
||||
nation: globalThis.String(assertSet("TankDefinition.nation", object.nation)),
|
||||
name: globalThis.String(assertSet("TankDefinition.name", object.name)),
|
||||
name_full: isSet(object.name_full) ? globalThis.String(object.name_full) : undefined,
|
||||
name: I18nString.fromJSON(assertSet("TankDefinition.name", object.name)),
|
||||
name_full: isSet(object.name_full) ? I18nString.fromJSON(object.name_full) : undefined,
|
||||
type: tankTypeFromJSON(assertSet("TankDefinition.type", object.type)),
|
||||
max_consumables: globalThis.Number(assertSet("TankDefinition.max_consumables", object.max_consumables)),
|
||||
max_provisions: globalThis.Number(assertSet("TankDefinition.max_provisions", object.max_provisions)),
|
||||
@@ -1112,9 +1099,6 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
});
|
||||
}
|
||||
}
|
||||
if (message.description !== undefined && message.description !== undefined) {
|
||||
obj.description = message.description;
|
||||
}
|
||||
if (message.fixed_camouflage !== false) {
|
||||
obj.fixed_camouflage = message.fixed_camouflage;
|
||||
}
|
||||
@@ -1136,11 +1120,11 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
if (message.nation !== "") {
|
||||
obj.nation = message.nation;
|
||||
}
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
if (message.name_full !== undefined && message.name_full !== undefined) {
|
||||
obj.name_full = message.name_full;
|
||||
if (message.name_full !== undefined) {
|
||||
obj.name_full = I18nString.toJSON(message.name_full);
|
||||
}
|
||||
if (message.type !== 0) {
|
||||
obj.type = tankTypeToJSON(message.type);
|
||||
@@ -1214,7 +1198,6 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
message.description = object.description ?? undefined;
|
||||
message.fixed_camouflage = object.fixed_camouflage ?? false;
|
||||
message.camouflages = object.camouflages?.map((e) => e) || [];
|
||||
message.ancestors = object.ancestors?.map((e) => e) || [];
|
||||
@@ -1222,8 +1205,12 @@ export const TankDefinition: MessageFns<TankDefinition> = {
|
||||
message.crew = object.crew?.map((e) => Crew.fromPartial(e)) || [];
|
||||
message.health = object.health ?? 0;
|
||||
message.nation = object.nation ?? "";
|
||||
message.name = object.name ?? "";
|
||||
message.name_full = object.name_full ?? undefined;
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
message.name_full = (object.name_full !== undefined && object.name_full !== null)
|
||||
? I18nString.fromPartial(object.name_full)
|
||||
: undefined;
|
||||
message.type = object.type ?? 0;
|
||||
message.max_consumables = object.max_consumables ?? 0;
|
||||
message.max_provisions = object.max_provisions ?? 0;
|
||||
@@ -1582,7 +1569,7 @@ function createBaseTrackDefinition(): TrackDefinition {
|
||||
return {
|
||||
id: 0,
|
||||
tier: 0,
|
||||
name: "",
|
||||
name: createBaseI18nString(),
|
||||
weight: 0,
|
||||
traverse_speed: 0,
|
||||
research_cost: undefined,
|
||||
@@ -1603,8 +1590,8 @@ export const TrackDefinition: MessageFns<TrackDefinition> = {
|
||||
if (message.tier !== 0) {
|
||||
writer.uint32(16).uint32(message.tier);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
writer.uint32(26).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(26).fork()).join();
|
||||
}
|
||||
if (message.weight !== 0) {
|
||||
writer.uint32(32).uint32(message.weight);
|
||||
@@ -1664,7 +1651,7 @@ export const TrackDefinition: MessageFns<TrackDefinition> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 4: {
|
||||
@@ -1752,7 +1739,7 @@ export const TrackDefinition: MessageFns<TrackDefinition> = {
|
||||
return {
|
||||
id: globalThis.Number(assertSet("TrackDefinition.id", object.id)),
|
||||
tier: globalThis.Number(assertSet("TrackDefinition.tier", object.tier)),
|
||||
name: globalThis.String(assertSet("TrackDefinition.name", object.name)),
|
||||
name: I18nString.fromJSON(assertSet("TrackDefinition.name", object.name)),
|
||||
weight: globalThis.Number(assertSet("TrackDefinition.weight", object.weight)),
|
||||
traverse_speed: globalThis.Number(assertSet("TrackDefinition.traverse_speed", object.traverse_speed)),
|
||||
research_cost: isSet(object.research_cost) ? ResearchCost.fromJSON(object.research_cost) : undefined,
|
||||
@@ -1775,8 +1762,8 @@ export const TrackDefinition: MessageFns<TrackDefinition> = {
|
||||
if (message.tier !== 0) {
|
||||
obj.tier = Math.round(message.tier);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
if (message.weight !== 0) {
|
||||
obj.weight = Math.round(message.weight);
|
||||
@@ -1815,7 +1802,9 @@ export const TrackDefinition: MessageFns<TrackDefinition> = {
|
||||
const message = createBaseTrackDefinition();
|
||||
message.id = object.id ?? 0;
|
||||
message.tier = object.tier ?? 0;
|
||||
message.name = object.name ?? "";
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
message.weight = object.weight ?? 0;
|
||||
message.traverse_speed = object.traverse_speed ?? 0;
|
||||
message.research_cost = (object.research_cost !== undefined && object.research_cost !== null)
|
||||
@@ -1832,7 +1821,16 @@ export const TrackDefinition: MessageFns<TrackDefinition> = {
|
||||
};
|
||||
|
||||
function createBaseEngineDefinition(): EngineDefinition {
|
||||
return { id: 0, name: "", research_cost: undefined, tier: 0, fire_chance: 0, power: 0, weight: 0, unlocks: [] };
|
||||
return {
|
||||
id: 0,
|
||||
name: createBaseI18nString(),
|
||||
research_cost: undefined,
|
||||
tier: 0,
|
||||
fire_chance: 0,
|
||||
power: 0,
|
||||
weight: 0,
|
||||
unlocks: [],
|
||||
};
|
||||
}
|
||||
|
||||
export const EngineDefinition: MessageFns<EngineDefinition> = {
|
||||
@@ -1840,8 +1838,8 @@ export const EngineDefinition: MessageFns<EngineDefinition> = {
|
||||
if (message.id !== 0) {
|
||||
writer.uint32(8).uint32(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
writer.uint32(18).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(18).fork()).join();
|
||||
}
|
||||
if (message.research_cost !== undefined) {
|
||||
ResearchCost.encode(message.research_cost, writer.uint32(26).fork()).join();
|
||||
@@ -1884,7 +1882,7 @@ export const EngineDefinition: MessageFns<EngineDefinition> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 3: {
|
||||
@@ -1947,7 +1945,7 @@ export const EngineDefinition: MessageFns<EngineDefinition> = {
|
||||
fromJSON(object: any): EngineDefinition {
|
||||
return {
|
||||
id: globalThis.Number(assertSet("EngineDefinition.id", object.id)),
|
||||
name: globalThis.String(assertSet("EngineDefinition.name", object.name)),
|
||||
name: I18nString.fromJSON(assertSet("EngineDefinition.name", object.name)),
|
||||
research_cost: isSet(object.research_cost) ? ResearchCost.fromJSON(object.research_cost) : undefined,
|
||||
tier: globalThis.Number(assertSet("EngineDefinition.tier", object.tier)),
|
||||
fire_chance: globalThis.Number(assertSet("EngineDefinition.fire_chance", object.fire_chance)),
|
||||
@@ -1962,8 +1960,8 @@ export const EngineDefinition: MessageFns<EngineDefinition> = {
|
||||
if (message.id !== 0) {
|
||||
obj.id = Math.round(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
if (message.research_cost !== undefined) {
|
||||
obj.research_cost = ResearchCost.toJSON(message.research_cost);
|
||||
@@ -1992,7 +1990,9 @@ export const EngineDefinition: MessageFns<EngineDefinition> = {
|
||||
fromPartial<I extends Exact<DeepPartial<EngineDefinition>, I>>(object: I): EngineDefinition {
|
||||
const message = createBaseEngineDefinition();
|
||||
message.id = object.id ?? 0;
|
||||
message.name = object.name ?? "";
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
message.research_cost = (object.research_cost !== undefined && object.research_cost !== null)
|
||||
? ResearchCost.fromPartial(object.research_cost)
|
||||
: undefined;
|
||||
@@ -2012,7 +2012,7 @@ function createBaseTurretDefinition(): TurretDefinition {
|
||||
view_range: 0,
|
||||
traverse_speed: 0,
|
||||
research_cost: undefined,
|
||||
name: "",
|
||||
name: createBaseI18nString(),
|
||||
tier: 0,
|
||||
weight: 0,
|
||||
guns: [],
|
||||
@@ -2037,8 +2037,8 @@ export const TurretDefinition: MessageFns<TurretDefinition> = {
|
||||
if (message.research_cost !== undefined) {
|
||||
ResearchCost.encode(message.research_cost, writer.uint32(42).fork()).join();
|
||||
}
|
||||
if (message.name !== "") {
|
||||
writer.uint32(50).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(50).fork()).join();
|
||||
}
|
||||
if (message.tier !== 0) {
|
||||
writer.uint32(56).uint32(message.tier);
|
||||
@@ -2107,7 +2107,7 @@ export const TurretDefinition: MessageFns<TurretDefinition> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 7: {
|
||||
@@ -2158,7 +2158,7 @@ export const TurretDefinition: MessageFns<TurretDefinition> = {
|
||||
view_range: globalThis.Number(assertSet("TurretDefinition.view_range", object.view_range)),
|
||||
traverse_speed: globalThis.Number(assertSet("TurretDefinition.traverse_speed", object.traverse_speed)),
|
||||
research_cost: isSet(object.research_cost) ? ResearchCost.fromJSON(object.research_cost) : undefined,
|
||||
name: globalThis.String(assertSet("TurretDefinition.name", object.name)),
|
||||
name: I18nString.fromJSON(assertSet("TurretDefinition.name", object.name)),
|
||||
tier: globalThis.Number(assertSet("TurretDefinition.tier", object.tier)),
|
||||
weight: globalThis.Number(assertSet("TurretDefinition.weight", object.weight)),
|
||||
guns: globalThis.Array.isArray(object?.guns) ? object.guns.map((e: any) => GunDefinition.fromJSON(e)) : [],
|
||||
@@ -2183,8 +2183,8 @@ export const TurretDefinition: MessageFns<TurretDefinition> = {
|
||||
if (message.research_cost !== undefined) {
|
||||
obj.research_cost = ResearchCost.toJSON(message.research_cost);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
if (message.tier !== 0) {
|
||||
obj.tier = Math.round(message.tier);
|
||||
@@ -2213,7 +2213,9 @@ export const TurretDefinition: MessageFns<TurretDefinition> = {
|
||||
message.research_cost = (object.research_cost !== undefined && object.research_cost !== null)
|
||||
? ResearchCost.fromPartial(object.research_cost)
|
||||
: undefined;
|
||||
message.name = object.name ?? "";
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
message.tier = object.tier ?? 0;
|
||||
message.weight = object.weight ?? 0;
|
||||
message.guns = object.guns?.map((e) => GunDefinition.fromPartial(e)) || [];
|
||||
@@ -2858,7 +2860,7 @@ function createBaseGunDefinitionBase(): GunDefinitionBase {
|
||||
rotation_speed: 0,
|
||||
research_cost: undefined,
|
||||
weight: 0,
|
||||
name: "",
|
||||
name: createBaseI18nString(),
|
||||
tier: 0,
|
||||
shells: [],
|
||||
camouflage_loss: 0,
|
||||
@@ -2886,8 +2888,8 @@ export const GunDefinitionBase: MessageFns<GunDefinitionBase> = {
|
||||
if (message.weight !== 0) {
|
||||
writer.uint32(32).uint32(message.weight);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
writer.uint32(42).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(42).fork()).join();
|
||||
}
|
||||
if (message.tier !== 0) {
|
||||
writer.uint32(48).uint32(message.tier);
|
||||
@@ -2966,7 +2968,7 @@ export const GunDefinitionBase: MessageFns<GunDefinitionBase> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 6: {
|
||||
@@ -3064,7 +3066,7 @@ export const GunDefinitionBase: MessageFns<GunDefinitionBase> = {
|
||||
rotation_speed: globalThis.Number(assertSet("GunDefinitionBase.rotation_speed", object.rotation_speed)),
|
||||
research_cost: isSet(object.research_cost) ? ResearchCost.fromJSON(object.research_cost) : undefined,
|
||||
weight: globalThis.Number(assertSet("GunDefinitionBase.weight", object.weight)),
|
||||
name: globalThis.String(assertSet("GunDefinitionBase.name", object.name)),
|
||||
name: I18nString.fromJSON(assertSet("GunDefinitionBase.name", object.name)),
|
||||
tier: globalThis.Number(assertSet("GunDefinitionBase.tier", object.tier)),
|
||||
shells: globalThis.Array.isArray(object?.shells)
|
||||
? object.shells.map((e: any) => ShellDefinition.fromJSON(e))
|
||||
@@ -3098,8 +3100,8 @@ export const GunDefinitionBase: MessageFns<GunDefinitionBase> = {
|
||||
if (message.weight !== 0) {
|
||||
obj.weight = Math.round(message.weight);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
if (message.tier !== 0) {
|
||||
obj.tier = Math.round(message.tier);
|
||||
@@ -3145,7 +3147,9 @@ export const GunDefinitionBase: MessageFns<GunDefinitionBase> = {
|
||||
? ResearchCost.fromPartial(object.research_cost)
|
||||
: undefined;
|
||||
message.weight = object.weight ?? 0;
|
||||
message.name = object.name ?? "";
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
message.tier = object.tier ?? 0;
|
||||
message.shells = object.shells?.map((e) => ShellDefinition.fromPartial(e)) || [];
|
||||
message.camouflage_loss = object.camouflage_loss ?? 0;
|
||||
@@ -3163,7 +3167,7 @@ export const GunDefinitionBase: MessageFns<GunDefinitionBase> = {
|
||||
function createBaseShellDefinition(): ShellDefinition {
|
||||
return {
|
||||
id: 0,
|
||||
name: "",
|
||||
name: createBaseI18nString(),
|
||||
velocity: 0,
|
||||
armor_damage: 0,
|
||||
module_damage: 0,
|
||||
@@ -3183,8 +3187,8 @@ export const ShellDefinition: MessageFns<ShellDefinition> = {
|
||||
if (message.id !== 0) {
|
||||
writer.uint32(8).uint32(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
writer.uint32(18).string(message.name);
|
||||
if (message.name !== undefined) {
|
||||
I18nString.encode(message.name, writer.uint32(18).fork()).join();
|
||||
}
|
||||
if (message.velocity !== 0) {
|
||||
writer.uint32(24).uint32(message.velocity);
|
||||
@@ -3242,7 +3246,7 @@ export const ShellDefinition: MessageFns<ShellDefinition> = {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
message.name = I18nString.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 3: {
|
||||
@@ -3345,7 +3349,7 @@ export const ShellDefinition: MessageFns<ShellDefinition> = {
|
||||
fromJSON(object: any): ShellDefinition {
|
||||
return {
|
||||
id: globalThis.Number(assertSet("ShellDefinition.id", object.id)),
|
||||
name: globalThis.String(assertSet("ShellDefinition.name", object.name)),
|
||||
name: I18nString.fromJSON(assertSet("ShellDefinition.name", object.name)),
|
||||
velocity: globalThis.Number(assertSet("ShellDefinition.velocity", object.velocity)),
|
||||
armor_damage: globalThis.Number(assertSet("ShellDefinition.armor_damage", object.armor_damage)),
|
||||
module_damage: globalThis.Number(assertSet("ShellDefinition.module_damage", object.module_damage)),
|
||||
@@ -3365,8 +3369,8 @@ export const ShellDefinition: MessageFns<ShellDefinition> = {
|
||||
if (message.id !== 0) {
|
||||
obj.id = Math.round(message.id);
|
||||
}
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
if (message.name !== undefined) {
|
||||
obj.name = I18nString.toJSON(message.name);
|
||||
}
|
||||
if (message.velocity !== 0) {
|
||||
obj.velocity = Math.round(message.velocity);
|
||||
@@ -3410,7 +3414,9 @@ export const ShellDefinition: MessageFns<ShellDefinition> = {
|
||||
fromPartial<I extends Exact<DeepPartial<ShellDefinition>, I>>(object: I): ShellDefinition {
|
||||
const message = createBaseShellDefinition();
|
||||
message.id = object.id ?? 0;
|
||||
message.name = object.name ?? "";
|
||||
message.name = (object.name !== undefined && object.name !== null)
|
||||
? I18nString.fromPartial(object.name)
|
||||
: createBaseI18nString();
|
||||
message.velocity = object.velocity ?? 0;
|
||||
message.armor_damage = object.armor_damage ?? 0;
|
||||
message.module_damage = object.module_damage ?? 0;
|
||||
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": ["src/**/*"]
|
||||
"include": ["src/**/*", "../i18n/src/strings.ts"]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@blitzkit/i18n",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"dependencies": {
|
||||
"ts-deepmerge": "^7.0.2"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './literals';
|
||||
export * from './strings';
|
||||
export * from './unwrapper';
|
||||
@@ -0,0 +1,5 @@
|
||||
export function literals(string: string, literals: string[]) {
|
||||
return literals.reduce((accumulator, literal, index) => {
|
||||
return accumulator.replace(`%s${index + 1}`, literal);
|
||||
}, string);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import { merge } from 'ts-deepmerge';
|
||||
import en from '../strings/en.json';
|
||||
import es from '../strings/es.json';
|
||||
import fr from '../strings/fr.json';
|
||||
import ja from '../strings/ja.json';
|
||||
import pl from '../strings/pl.json';
|
||||
import pt from '../strings/pt.json';
|
||||
import ru from '../strings/ru.json';
|
||||
import uk from '../strings/uk.json';
|
||||
import zh from '../strings/zh.json';
|
||||
|
||||
export type BlitzKitStrings = typeof en;
|
||||
|
||||
const stringsRaw = { en, es, fr, ja, pl, pt, ru, uk, zh };
|
||||
|
||||
export const SUPPORTED_LOCALES = Object.keys(stringsRaw) as SupportedLocale[];
|
||||
|
||||
export const DEFAULT_LOCALE = SUPPORTED_LOCALES[0];
|
||||
|
||||
function redact(string: string) {
|
||||
const matches = [...string.matchAll(/%s\d+/g)];
|
||||
const characters = string
|
||||
.split('')
|
||||
.map((char) => (char === ' ' ? ' ' : '█')) as string[];
|
||||
|
||||
matches.forEach((match) => {
|
||||
const start = match.index;
|
||||
const matchText = match[0];
|
||||
for (let i = 0; i < matchText.length; i++) {
|
||||
characters[start + i] = matchText[i];
|
||||
}
|
||||
});
|
||||
|
||||
return characters.join('');
|
||||
}
|
||||
|
||||
function nuke(object: TranslationTree) {
|
||||
for (const key in object) {
|
||||
const typedKey = key as keyof typeof object;
|
||||
|
||||
if (typeof object[typedKey] === 'string') {
|
||||
const value = object[typedKey];
|
||||
object[typedKey] = redact(value as string);
|
||||
} else nuke(object[typedKey] as TranslationTree);
|
||||
}
|
||||
}
|
||||
|
||||
const stringsPartial: Partial<Record<SupportedLocale, TranslationTree>> = {};
|
||||
|
||||
for (const locale in stringsRaw) {
|
||||
if (locale === DEFAULT_LOCALE) {
|
||||
stringsPartial[DEFAULT_LOCALE] = stringsRaw[DEFAULT_LOCALE];
|
||||
continue;
|
||||
}
|
||||
|
||||
const localeStrings = stringsRaw[locale as SupportedLocale];
|
||||
stringsPartial[locale as SupportedLocale] = merge(
|
||||
stringsRaw[DEFAULT_LOCALE],
|
||||
localeStrings,
|
||||
);
|
||||
|
||||
if (import.meta.env.PUBLIC_DEBUG_MISSING_I18N === 'true') {
|
||||
nuke(stringsPartial[locale as SupportedLocale]!);
|
||||
}
|
||||
}
|
||||
|
||||
export const STRINGS = stringsPartial as Record<
|
||||
SupportedLocale,
|
||||
BlitzKitStrings
|
||||
>;
|
||||
|
||||
export type SupportedLocale = keyof typeof stringsRaw;
|
||||
|
||||
export const SUPPORTED_LOCALE_BLITZ_MAP: Record<SupportedLocale, string> = {
|
||||
en: 'en',
|
||||
es: 'es',
|
||||
fr: 'fr',
|
||||
ja: 'ja',
|
||||
pt: 'pt',
|
||||
ru: 'ru',
|
||||
uk: 'uk',
|
||||
zh: 'zh-Hans',
|
||||
pl: 'pl',
|
||||
};
|
||||
|
||||
export const SUPPORTED_LOCALE_FLAGS: Record<SupportedLocale, string> = {
|
||||
en: '🇺🇸',
|
||||
es: '🇪🇸',
|
||||
fr: '🇫🇷',
|
||||
ja: '🇯🇵',
|
||||
pt: '🇵🇹',
|
||||
ru: '🇷🇺',
|
||||
uk: '🇺🇦',
|
||||
zh: '🇨🇳',
|
||||
pl: '🇵🇱',
|
||||
};
|
||||
|
||||
export type TranslationTree = { [key: string]: TranslationNode };
|
||||
|
||||
export type TranslationNode = string | TranslationTree;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { I18nString } from '@blitzkit/core';
|
||||
import { DEFAULT_LOCALE } from './strings';
|
||||
|
||||
export function unwrapper(locale: string) {
|
||||
return function (i18nString: I18nString) {
|
||||
if (locale in i18nString.locales) {
|
||||
return i18nString.locales[locale];
|
||||
}
|
||||
|
||||
return i18nString.locales[DEFAULT_LOCALE];
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Loaded 100 of 291 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user