feat: update bot chunk 2

This commit is contained in:
tresabhi committed 2025-01-16 13:48:13 -06:00
1 parent d2b24fc953
commit 122b3f6478
17 files changed
+276 -203

No files matched your search

+15 -12
View File
@@ -7,6 +7,7 @@ import {
getWN8Percentile, getWN8Percentile,
TankDefinition, TankDefinition,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import { Locale } from 'discord.js'; import { Locale } from 'discord.js';
import { chunk } from 'lodash-es'; import { chunk } from 'lodash-es';
import * as Breakdown from '../../components/Breakdown'; import * as Breakdown from '../../components/Breakdown';
@@ -32,7 +33,7 @@ export async function renderBreakdown(
filters: StatFilters, filters: StatFilters,
locale: Locale, locale: Locale,
) { ) {
const { t, translate, unwrap } = translator(locale); const { strings, unwrap } = translator(locale);
const awaitedTankDefinitions = await tankDefinitions; const awaitedTankDefinitions = await tankDefinitions;
const awaitedTankAverages = await blitzStarsTankAverages; const awaitedTankAverages = await blitzStarsTankAverages;
const statsInPeriod = await getStatsInPeriod(region, id, start, end, locale); const statsInPeriod = await getStatsInPeriod(region, id, start, end, locale);
@@ -48,7 +49,7 @@ export async function renderBreakdown(
const orderedCareerWN8Full: (number | undefined)[] = []; const orderedCareerWN8Full: (number | undefined)[] = [];
if (tankStats === null) { 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) => { filteredOrder.forEach((id) => {
@@ -136,21 +137,21 @@ export async function renderBreakdown(
<Breakdown.Row <Breakdown.Row
key={id} key={id}
displayType="summary" displayType="summary"
title={t`bot.commands.breakdown.body.total`} title={strings.bot.commands.breakdown.body.total}
stats={[ stats={[
{ {
title: t`bot.commands.breakdown.body.battles`, title: strings.bot.commands.breakdown.body.battles,
current: currentBattles, current: currentBattles,
career: careerBattles, career: careerBattles,
}, },
{ {
title: t`bot.commands.breakdown.body.winrate`, title: strings.bot.commands.breakdown.body.winrate,
current: `${(100 * currentWinrate).toFixed(2)}%`, current: `${(100 * currentWinrate).toFixed(2)}%`,
career: `${(100 * careerWinrate).toFixed(2)}%`, career: `${(100 * careerWinrate).toFixed(2)}%`,
delta: currentWinrate - careerWinrate, delta: currentWinrate - careerWinrate,
}, },
{ {
title: t`bot.commands.breakdown.body.wn8`, title: strings.bot.commands.breakdown.body.wn8,
current: current:
currentWN8 === undefined currentWN8 === undefined
? undefined ? undefined
@@ -165,7 +166,7 @@ export async function renderBreakdown(
: getWN8Percentile(currentWN8), : getWN8Percentile(currentWN8),
}, },
{ {
title: t`bot.commands.breakdown.body.damage`, title: strings.bot.commands.breakdown.body.damage,
current: Math.round(currentDamage).toLocaleString(), current: Math.round(currentDamage).toLocaleString(),
career: Math.round(careerDamage).toLocaleString(), career: Math.round(careerDamage).toLocaleString(),
delta: currentDamage - careerDamage, delta: currentDamage - careerDamage,
@@ -192,16 +193,18 @@ export async function renderBreakdown(
title={ title={
tankDefinition tankDefinition
? unwrap(tankDefinition.name) ? unwrap(tankDefinition.name)
: translate('bot.commands.breakdown.body.unknown_tank', [`${id}`]) : literals(strings.bot.commands.breakdown.body.unknown_tank, [
`${id}`,
])
} }
stats={[ stats={[
{ {
title: t`bot.commands.breakdown.body.battles`, title: strings.bot.commands.breakdown.body.battles,
current: current.battles.toLocaleString(), current: current.battles.toLocaleString(),
career: career.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( current: `${(100 * (current.wins / current.battles)).toFixed(
2, 2,
)}%`, )}%`,
@@ -210,7 +213,7 @@ export async function renderBreakdown(
current.wins / current.battles - career.wins / career.battles, current.wins / current.battles - career.wins / career.battles,
}, },
{ {
title: t`bot.commands.breakdown.body.wn8`, title: strings.bot.commands.breakdown.body.wn8,
current: current:
currentWN8 === undefined currentWN8 === undefined
? undefined ? undefined
@@ -225,7 +228,7 @@ export async function renderBreakdown(
: getWN8Percentile(currentWN8), : getWN8Percentile(currentWN8),
}, },
{ {
title: t`bot.commands.breakdown.body.damage`, title: strings.bot.commands.breakdown.body.damage,
current: Math.round( current: Math.round(
current.damage_dealt / current.battles, current.damage_dealt / current.battles,
).toLocaleString(), ).toLocaleString(),
+7 -7
View File
@@ -22,7 +22,7 @@ export const verifyCommand = new Promise<CommandRegistry>((resolve) => {
), ),
async handler(interaction) { async handler(interaction) {
const { t, translate } = translator(interaction.locale); const { strings } = translator(interaction.locale);
const { id, region } = await resolvePlayerFromCommand(interaction); const { id, region } = await resolvePlayerFromCommand(interaction);
const discordId = BigInt(interaction.user.id); const discordId = BigInt(interaction.user.id);
const accountInfo = await getAccountInfo(region, id); const accountInfo = await getAccountInfo(region, id);
@@ -120,9 +120,9 @@ export const verifyCommand = new Promise<CommandRegistry>((resolve) => {
height: 16, height: 16,
}} }}
/> />
<span <span style={{ fontSize: 16 }}>
style={{ fontSize: 16 }} {strings.bot.commands.link.body.accounts_linked}
>{t`bot.commands.link.body.accounts_linked`}</span> </span>
</div> </div>
<div <div
@@ -174,7 +174,7 @@ export const verifyCommand = new Promise<CommandRegistry>((resolve) => {
{clanAccountInfo?.clan {clanAccountInfo?.clan
? `[${clanAccountInfo?.clan?.tag}] • ` ? `[${clanAccountInfo?.clan?.tag}] • `
: ''} : ''}
{translate(`common.regions.normal.${region}`)} {strings.common.regions.normal[region]}
</span> </span>
</div> </div>
</div> </div>
@@ -185,8 +185,8 @@ export const verifyCommand = new Promise<CommandRegistry>((resolve) => {
</CommandWrapper>, </CommandWrapper>,
embedInfo( embedInfo(
t`bot.commands.link.embed.title`, strings.bot.commands.link.embed.title,
t`bot.commands.link.embed.description`, strings.bot.commands.link.embed.description,
), ),
]; ];
}, },
+4 -3
View File
@@ -6,6 +6,7 @@ import {
getAccountInfo, getAccountInfo,
getTankStats, getTankStats,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import markdownEscape from 'markdown-escape'; import markdownEscape from 'markdown-escape';
import { import {
gameDefinitions, gameDefinitions,
@@ -27,14 +28,14 @@ export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
.addStringOption(addUsernameChoices), .addStringOption(addUsernameChoices),
async handler(interaction) { async handler(interaction) {
const { t, translate, unwrap } = translator(interaction.locale); const { strings, unwrap } = translator(interaction.locale);
const tier = Number(interaction.options.getString('tier')); const tier = Number(interaction.options.getString('tier'));
const { id, region } = await resolvePlayerFromCommand(interaction); const { id, region } = await resolvePlayerFromCommand(interaction);
const accountInfo = await getAccountInfo(region, id); const accountInfo = await getAccountInfo(region, id);
const tankStats = await getTankStats(region, id); const tankStats = await getTankStats(region, id);
if (tankStats === null) { if (tankStats === null) {
return t`bot.common.errors.no_tank_stats`; return strings.bot.common.errors.no_tank_stats;
} }
const filteredTanks = ( const filteredTanks = (
@@ -59,7 +60,7 @@ export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
const awaitedTankDefinitions = await tankDefinitions; const awaitedTankDefinitions = await tankDefinitions;
const awaitedGameDefinitions = await gameDefinitions; 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), markdownEscape(accountInfo.nickname),
TIER_ROMAN_NUMERALS[tier], TIER_ROMAN_NUMERALS[tier],
]); ]);
+7 -6
View File
@@ -1,3 +1,4 @@
import { literals } from '@blitzkit/i18n';
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
import { translator } from '../core/localization/translator'; import { translator } from '../core/localization/translator';
import { CommandRegistry } from '../events/interactionCreate'; import { CommandRegistry } from '../events/interactionCreate';
@@ -7,26 +8,26 @@ export const permissionsCommand = new Promise<CommandRegistry>((resolve) => {
command: createLocalizedCommand('permissions'), command: createLocalizedCommand('permissions'),
async handler(interaction) { async handler(interaction) {
const { t, translate } = translator(interaction.locale); const { strings } = translator(interaction.locale);
// friday the 13th permissions easter egg // friday the 13th permissions easter egg
const isFridayThe13th = const isFridayThe13th =
new Date().getDay() === 5 && new Date().getDate() === 13; new Date().getDay() === 5 && new Date().getDate() === 13;
const permissions = [ const permissions = [
[ [
interaction.appPermissions?.has('ViewChannel'), interaction.appPermissions?.has('ViewChannel'),
t`bot.commands.permissions.body.view_channels`, strings.bot.commands.permissions.body.view_channels,
], ],
[ [
interaction.appPermissions?.has('ReadMessageHistory'), interaction.appPermissions?.has('ReadMessageHistory'),
t`bot.commands.permissions.body.read_message_history`, strings.bot.commands.permissions.body.read_message_history,
], ],
[ [
interaction.appPermissions?.has('AttachFiles'), interaction.appPermissions?.has('AttachFiles'),
t`bot.commands.permissions.body.attach_files`, strings.bot.commands.permissions.body.attach_files,
], ],
[ [
interaction.appPermissions?.has('UseExternalEmojis'), interaction.appPermissions?.has('UseExternalEmojis'),
t`bot.commands.permissions.body.external_emojis`, strings.bot.commands.permissions.body.external_emojis,
], ],
]; ];
const body = permissions const body = permissions
@@ -39,7 +40,7 @@ export const permissionsCommand = new Promise<CommandRegistry>((resolve) => {
}) })
.join('\n'); .join('\n');
return translate('bot.commands.permissions.body.title', [body]); return literals(strings.bot.commands.permissions.body.title, [body]);
}, },
}); });
}); });
+4 -3
View File
@@ -1,3 +1,4 @@
import { literals } from '@blitzkit/i18n';
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
import { translator } from '../core/localization/translator'; import { translator } from '../core/localization/translator';
import { CommandRegistry } from '../events/interactionCreate'; import { CommandRegistry } from '../events/interactionCreate';
@@ -12,19 +13,19 @@ export const pingCommand = new Promise<CommandRegistry>((resolve) => {
]), ]),
async handler(interaction) { async handler(interaction) {
const { t, translate } = translator(interaction.locale); const { strings } = translator(interaction.locale);
const subcommand = interaction.options.getSubcommand(); const subcommand = interaction.options.getSubcommand();
const executionStart = Date.now(); const executionStart = Date.now();
if (subcommand === 'blitzkit') { if (subcommand === 'blitzkit') {
await interaction.editReply(t`bot.commands.ping.body.pong`); await interaction.editReply(strings.bot.commands.ping.body.pong);
} else { } else {
await fetch('https://api.wotblitz.com/'); await fetch('https://api.wotblitz.com/');
} }
const executionTime = Date.now() - executionStart; const executionTime = Date.now() - executionStart;
interaction.editReply( interaction.editReply(
translate('bot.commands.ping.body.pong_with_time', [ literals(strings.bot.commands.ping.body.pong_with_time, [
`${Math.round(executionTime)}`, `${Math.round(executionTime)}`,
]), ]),
); );
+9 -8
View File
@@ -1,4 +1,5 @@
import { getAccountInfo } from '@blitzkit/core'; import { getAccountInfo } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import markdownEscape from 'markdown-escape'; import markdownEscape from 'markdown-escape';
import { addUsernameChoices } from '../core/discord/addUsernameChoices'; import { addUsernameChoices } from '../core/discord/addUsernameChoices';
import { autocompleteUsername } from '../core/discord/autocompleteUsername'; import { autocompleteUsername } from '../core/discord/autocompleteUsername';
@@ -15,27 +16,27 @@ export const playerInfoCommand = new Promise<CommandRegistry>((resolve) => {
createLocalizedCommand('player-info').addStringOption(addUsernameChoices), createLocalizedCommand('player-info').addStringOption(addUsernameChoices),
async handler(interaction) { async handler(interaction) {
const { t, translate } = translator(interaction.locale); const { strings } = translator(interaction.locale);
const account = await resolvePlayerFromCommand(interaction); const account = await resolvePlayerFromCommand(interaction);
const { id, region: region } = account; const { id, region: region } = account;
const accountInfo = await getAccountInfo(region, id); const accountInfo = await getAccountInfo(region, id);
return embedInfo( return embedInfo(
translate('bot.commands.player_info.body.title', [ literals(strings.bot.commands.player_info.body.title, [
markdownEscape(accountInfo.nickname), markdownEscape(accountInfo.nickname),
]), ]),
markdownTable([ markdownTable([
[ [
t`bot.commands.player_info.body.nickname`, strings.bot.commands.player_info.body.nickname,
`${accountInfo.nickname}`, `${accountInfo.nickname}`,
], ],
[ [
t`bot.commands.player_info.body.battles`, strings.bot.commands.player_info.body.battles,
`${accountInfo.statistics.all.battles}`, `${accountInfo.statistics.all.battles}`,
], ],
[ [
t`bot.commands.player_info.body.winrate`, strings.bot.commands.player_info.body.winrate,
`${( `${(
100 * 100 *
(accountInfo.statistics.all.wins / (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}`, `${accountInfo.account_id}`,
], ],
[ [
t`bot.commands.player_info.body.created`, strings.bot.commands.player_info.body.created,
new Date(accountInfo.created_at * 1000).toLocaleDateString( new Date(accountInfo.created_at * 1000).toLocaleDateString(
interaction.locale, 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( new Date(accountInfo.last_battle_time * 1000).toLocaleDateString(
interaction.locale, interaction.locale,
), ),
+8 -7
View File
@@ -9,6 +9,7 @@ import {
getRatingNeighbors, getRatingNeighbors,
imgur, imgur,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import { SlashCommandSubcommandBuilder } from 'discord.js'; import { SlashCommandSubcommandBuilder } from 'discord.js';
import markdownEscape from 'markdown-escape'; import markdownEscape from 'markdown-escape';
import { Glow } from '../components/AllStatsOverview/components/HeroStat/components/Glow'; 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 const subcommand = interaction.options.getSubcommand(true) as
| 'season' | 'season'
| 'today'; | 'today';
const { t, translate } = translator(interaction.locale); const { strings } = translator(interaction.locale);
const { id, region } = await resolvePlayerFromCommand(interaction); const { id, region } = await resolvePlayerFromCommand(interaction);
const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan; const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan;
const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined; 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; const statsB2Array = (await getRatingNeighbors(region, id, 0)).neighbors;
if (statsB2Array === undefined) { if (statsB2Array === undefined) {
return translate('bot.commands.rating.errors.no_participation', [ return literals(strings.bot.commands.rating.errors.no_participation, [
markdownEscape(accountInfo.nickname), markdownEscape(accountInfo.nickname),
]); ]);
} }
@@ -98,10 +99,10 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
const league = getLeagueFromScore(statsB2.score); const league = getLeagueFromScore(statsB2.score);
if (!statsA) { if (!statsA) {
return t`bot.commands.rating.errors.unrecorded_stats`; return strings.bot.commands.rating.errors.unrecorded_stats;
} }
if (!statsB1) { if (!statsB1) {
return translate('bot.commands.rating.errors.no_participation', [ return literals(strings.bot.commands.rating.errors.no_participation, [
markdownEscape(accountInfo.nickname), markdownEscape(accountInfo.nickname),
]); ]);
} }
@@ -139,9 +140,9 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
<TitleBar <TitleBar
title={accountInfo.nickname} title={accountInfo.nickname}
image={clanImage} image={clanImage}
description={`${translate( description={`${
`bot.commands.rating.body.subtitle.${subcommand}`, strings.bot.commands.rating.body.subtitle[subcommand]
)} • ${new Date().toLocaleDateString(interaction.locale)}`} } • ${new Date().toLocaleDateString(interaction.locale)}`}
/> />
<div <div
+65 -38
View File
@@ -14,6 +14,7 @@ import {
RatingLeaderboard, RatingLeaderboard,
Region, Region,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import { import {
APIApplicationCommandOptionChoice, APIApplicationCommandOptionChoice,
Locale, Locale,
@@ -54,28 +55,32 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
); );
function addOptions(option: SlashCommandSubcommandBuilder) { function addOptions(option: SlashCommandSubcommandBuilder) {
const { t, translate } = translator(Locale.EnglishUS); const { strings } = translator(Locale.EnglishUS);
return option return option
.addIntegerOption((option) => .addIntegerOption((option) =>
option option
.setName(t`bot.commands.rating_leaderboard.options.limit`) .setName(strings.bot.commands.rating_leaderboard.options.limit.$)
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
'bot.commands.rating_leaderboard.options.limit', (strings) =>
strings.bot.commands.rating_leaderboard.options.limit.$,
undefined, undefined,
true, true,
), ),
) )
.setDescription( .setDescription(
translate( literals(
'bot.commands.rating_leaderboard.options.limit.description', strings.bot.commands.rating_leaderboard.options.limit
.description,
[`${DEFAULT_LIMIT}`], [`${DEFAULT_LIMIT}`],
), ),
) )
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
'bot.commands.rating_leaderboard.options.limit.description', (strings) =>
strings.bot.commands.rating_leaderboard.options.limit
.description,
[`${DEFAULT_LIMIT}`], [`${DEFAULT_LIMIT}`],
), ),
) )
@@ -85,22 +90,24 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
) )
.addStringOption((option) => .addStringOption((option) =>
option option
.setName(t`bot.commands.rating_leaderboard.options.season`) .setName(strings.bot.commands.rating_leaderboard.options.season.$)
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
'bot.commands.rating_leaderboard.options.season', (strings) =>
strings.bot.commands.rating_leaderboard.options.season.$,
undefined, undefined,
true, true,
), ),
) )
.setDescription( .setDescription(
translate( strings.bot.commands.rating_leaderboard.options.season
'bot.commands.rating_leaderboard.options.season.description', .description,
),
) )
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
'bot.commands.rating_leaderboard.options.season.description', (strings) =>
strings.bot.commands.rating_leaderboard.options.season
.description,
), ),
) )
.setRequired(false) .setRequired(false)
@@ -112,15 +119,18 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
return { return {
name: current name: current
? translate( ? literals(
'bot.commands.rating_leaderboard.options.season.choices.current', strings.bot.commands.rating_leaderboard.options.season
.choices.current,
[`${number}`], [`${number}`],
) )
: `${number}`, : `${number}`,
value: `${number}`, value: `${number}`,
name_localizations: current name_localizations: current
? localizationObject( ? localizationObject(
'bot.commands.rating_leaderboard.options.season.choices.current', (strings) =>
strings.bot.commands.rating_leaderboard.options
.season.choices.current,
[`${number}`], [`${number}`],
) )
: undefined, : undefined,
@@ -145,35 +155,45 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
modify(option: SlashCommandSubcommandBuilder) { modify(option: SlashCommandSubcommandBuilder) {
option option
.addStringOption((option) => { .addStringOption((option) => {
const { t, translate } = translator(Locale.EnglishUS); const { strings } = translator(Locale.EnglishUS);
return option return option
.setName(t`bot.commands.rating_leaderboard.options.league`) .setName(
strings.bot.commands.rating_leaderboard.options.league.$,
)
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
'bot.commands.rating_leaderboard.options.league', (strings) =>
strings.bot.commands.rating_leaderboard.options.league
.$,
undefined, undefined,
true, true,
), ),
) )
.setDescription( .setDescription(
translate( strings.bot.commands.rating_leaderboard.options.league
'bot.commands.rating_leaderboard.options.league.description', .description,
),
) )
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
'bot.commands.rating_leaderboard.options.league.description', (strings) =>
strings.bot.commands.rating_leaderboard.options.league
.description,
), ),
) )
.addChoices( .addChoices(
...LEAGUES.map( ...LEAGUES.map(
({ name }, value) => ({ name }, value) =>
({ ({
name: translate(`common.leagues.${name}`), name: (
strings.common.leagues as Record<string, string>
)[name],
value: `${value}`, value: `${value}`,
name_localizations: localizationObject( name_localizations: localizationObject(
`common.leagues.${name}`, (strings) =>
(
strings.common.leagues as Record<string, string>
)[name],
), ),
}) satisfies APIApplicationCommandOptionChoice<string>, }) satisfies APIApplicationCommandOptionChoice<string>,
), ),
@@ -189,7 +209,7 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
// BIG TODO: title seems to be in english // BIG TODO: title seems to be in english
async handler(interaction) { async handler(interaction) {
const { t, translate } = translator(interaction.locale); const { strings } = translator(interaction.locale);
const subcommand = interaction.options.getSubcommand(true) as const subcommand = interaction.options.getSubcommand(true) as
| 'league' | 'league'
| 'neighbors'; | 'neighbors';
@@ -223,7 +243,8 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
regionRatingInfo !== null && regionRatingInfo !== null &&
regionRatingInfo.detail !== undefined 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 const result = isCurrentSeason
@@ -268,8 +289,9 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
clan: clanData[player.id]?.clan?.tag, clan: clanData[player.id]?.clan?.tag,
nickname: nickname:
clanData[index]?.account_name ?? clanData[index]?.account_name ??
translate( literals(
'bot.commands.rating_leaderboard.body.deleted_player', strings.bot.commands.rating_leaderboard.body
.deleted_player,
[`${player.id}`], [`${player.id}`],
), ),
}) satisfies SimplifiedPlayer, }) satisfies SimplifiedPlayer,
@@ -289,12 +311,14 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
: regionRatingInfo.count) - result[result.length - 1].position; : regionRatingInfo.count) - result[result.length - 1].position;
titleName = `${ titleName = `${
leagueInfo 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); titleImage = imgur(leagueInfo.icon);
titleDescription = translate( titleDescription = literals(
'bot.commands.rating_leaderboard.body.top_players', strings.bot.commands.rating_leaderboard.body.top_players,
[`${limit}`], [`${limit}`],
); );
} else { } else {
@@ -307,7 +331,8 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
regionRatingInfo !== null && regionRatingInfo !== null &&
regionRatingInfo.detail !== undefined 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); const accountInfo = await getAccountInfo(region, id);
@@ -334,8 +359,9 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
if (playerIndex === -1) { if (playerIndex === -1) {
throw new UserError( throw new UserError(
translate( literals(
'bot.commands.rating_leaderboard.body.no_participation', strings.bot.commands.rating_leaderboard.body
.no_participation,
[markdownEscape(accountInfo.nickname), `${season}`], [markdownEscape(accountInfo.nickname), `${season}`],
), ),
); );
@@ -373,7 +399,8 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clan.emblem_set_id}.png` ? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clan.emblem_set_id}.png`
: undefined; : undefined;
titleName = neighbors ? accountInfo.nickname : ''; titleName = neighbors ? accountInfo.nickname : '';
titleDescription = t`bot.commands.rating_leaderboard.body.neighbors`; titleDescription =
strings.bot.commands.rating_leaderboard.body.neighbors;
playersAfter = playersAfter =
(regionRatingInfo === null (regionRatingInfo === null
? archivedLeaderboard.version!.value.entries.length ? archivedLeaderboard.version!.value.entries.length
@@ -422,8 +449,8 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
{items} {items}
{playersAfter > 0 && ( {playersAfter > 0 && (
<Leaderboard.Gap <Leaderboard.Gap
message={translate( message={literals(
'bot.commands.rating_leaderboard.body.more', strings.bot.commands.rating_leaderboard.body.more,
[`${playersAfter.toLocaleString(interaction.locale)}`], [`${playersAfter.toLocaleString(interaction.locale)}`],
)} )}
/> />
+64 -45
View File
@@ -9,6 +9,7 @@ import {
TankType, TankType,
TIER_ROMAN_NUMERALS, TIER_ROMAN_NUMERALS,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import { escapeMarkdown, Locale } from 'discord.js'; import { escapeMarkdown, Locale } from 'discord.js';
import { CommandWrapper } from '../components/CommandWrapper'; import { CommandWrapper } from '../components/CommandWrapper';
import { TitleBar } from '../components/TitleBar'; import { TitleBar } from '../components/TitleBar';
@@ -28,26 +29,27 @@ import { CommandRegistry } from '../events/interactionCreate';
import { theme } from '../stitches.config'; import { theme } from '../stitches.config';
export const researchCommand = new Promise<CommandRegistry>((resolve) => { export const researchCommand = new Promise<CommandRegistry>((resolve) => {
const { t } = translator(Locale.EnglishUS); const { strings } = translator(Locale.EnglishUS);
resolve({ resolve({
command: createLocalizedCommand('research') command: createLocalizedCommand('research')
.addStringOption((option) => .addStringOption((option) =>
option option
.setName(t`bot.commands.research.options.target_tank`) .setName(strings.bot.commands.research.options.target_tank.$)
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
'bot.commands.research.options.target_tank', (strings) => strings.bot.commands.research.options.target_tank.$,
undefined, undefined,
true, true,
), ),
) )
.setDescription( .setDescription(
t`bot.commands.research.options.target_tank.description`, strings.bot.commands.research.options.target_tank.description,
) )
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
'bot.commands.research.options.target_tank.description', (strings) =>
strings.bot.commands.research.options.target_tank.description,
), ),
) )
.setAutocomplete(true) .setAutocomplete(true)
@@ -55,20 +57,22 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
) )
.addStringOption((option) => .addStringOption((option) =>
option option
.setName(t`bot.commands.research.options.starting_tank`) .setName(strings.bot.commands.research.options.starting_tank.$)
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
'bot.commands.research.options.starting_tank', (strings) =>
strings.bot.commands.research.options.starting_tank.$,
undefined, undefined,
true, true,
), ),
) )
.setDescription( .setDescription(
t`bot.commands.research.options.starting_tank.description`, strings.bot.commands.research.options.starting_tank.description,
) )
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
'bot.commands.research.options.starting_tank.description', (strings) =>
strings.bot.commands.research.options.starting_tank.description,
), ),
) )
.setAutocomplete(true) .setAutocomplete(true)
@@ -77,7 +81,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
.addStringOption(addUsernameChoices), .addStringOption(addUsernameChoices),
async handler(interaction) { async handler(interaction) {
const { t, translate, unwrap } = translator(interaction.locale); const { strings, unwrap } = translator(interaction.locale);
const awaitedTankDefinitions = await tankDefinitions; const awaitedTankDefinitions = await tankDefinitions;
const targetTankId = await resolveTankId( const targetTankId = await resolveTankId(
interaction.options.getString('target-tank', true), interaction.options.getString('target-tank', true),
@@ -98,15 +102,16 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
); );
if (targetTankId === startingTankId) { if (targetTankId === startingTankId) {
return translate('bot.commands.research.errors.start_end_equal', [ return literals(
escapeMarkdown(unwrap(targetTank.name)), strings.bot.commands.research.errors.start_end_equal,
]); [escapeMarkdown(unwrap(targetTank.name))],
);
} }
const startingTank = awaitedTankDefinitions.tanks[startingTankId]; const startingTank = awaitedTankDefinitions.tanks[startingTankId];
if (startingTank.tier > targetTank.tier) { if (startingTank.tier > targetTank.tier) {
return translate('bot.commands.research.errors.unordered', [ return literals(strings.bot.commands.research.errors.unordered, [
escapeMarkdown(unwrap(startingTank.name)), escapeMarkdown(unwrap(startingTank.name)),
escapeMarkdown(unwrap(targetTank.name)), escapeMarkdown(unwrap(targetTank.name)),
escapeMarkdown(unwrap(targetTank.name)), escapeMarkdown(unwrap(targetTank.name)),
@@ -114,20 +119,23 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
} }
if (!targetTankAncestry.includes(startingTankId)) { if (!targetTankAncestry.includes(startingTankId)) {
return translate('bot.commands.research.errors.tanks_not_on_line', [ return literals(
escapeMarkdown(unwrap(targetTank.name)), strings.bot.commands.research.errors.tanks_not_on_line,
escapeMarkdown(unwrap(startingTank.name)), [
]); escapeMarkdown(unwrap(targetTank.name)),
escapeMarkdown(unwrap(startingTank.name)),
],
);
} }
} else { } else {
if (targetTank.type !== TankType.RESEARCHABLE) { if (targetTank.type !== TankType.RESEARCHABLE) {
return translate('bot.commands.research.errors.non_tech_tree', [ return literals(strings.bot.commands.research.errors.non_tech_tree, [
escapeMarkdown(unwrap(targetTank.name)), escapeMarkdown(unwrap(targetTank.name)),
]); ]);
} }
if (targetTank.tier === 1) { if (targetTank.tier === 1) {
return translate('bot.commands.research.errors.tier_1', [ return literals(strings.bot.commands.research.errors.tier_1, [
escapeMarkdown(unwrap(targetTank.name)), escapeMarkdown(unwrap(targetTank.name)),
]); ]);
} }
@@ -135,13 +143,14 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
const tankStats = await getTankStats(region, id); const tankStats = await getTankStats(region, id);
if (tankStats === null) { 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)) { if (tankStats.some(({ tank_id }) => tank_id === targetTankId)) {
return translate('bot.commands.research.errors.already_researched', [ return literals(
escapeMarkdown(unwrap(targetTank.name)), strings.bot.commands.research.errors.already_researched,
]); [escapeMarkdown(unwrap(targetTank.name))],
);
} }
const foundAncestor = targetTankAncestry.find( const foundAncestor = targetTankAncestry.find(
@@ -255,7 +264,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
<TitleBar <TitleBar
title={nickname} title={nickname}
image={clanImage} image={clanImage}
description={`${t`bot.commands.research.body.subtitle`} • ${ description={`${strings.bot.commands.research.body.subtitle} • ${
targetTank.name targetTank.name
}`} }`}
/> />
@@ -292,7 +301,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
}} }}
> >
{t`bot.commands.research.body.total`} {strings.bot.commands.research.body.total}
</span> </span>
</div> </div>
@@ -497,11 +506,14 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
}} }}
> >
{translate('bot.commands.research.body.research', [ {literals(
`${costs[index].research?.toLocaleString( strings.bot.commands.research.body.research,
interaction.locale, [
)}`, `${costs[index].research?.toLocaleString(
])} interaction.locale,
)}`,
],
)}
</span> </span>
</div> </div>
@@ -527,9 +539,10 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
}} }}
> >
{translate('bot.commands.research.body.upgrades', [ {literals(
costs[index].upgrades.toLocaleString(), strings.bot.commands.research.body.upgrades,
])} [costs[index].upgrades.toLocaleString()],
)}
</span> </span>
</div> </div>
)} )}
@@ -555,11 +568,14 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
}} }}
> >
{translate('bot.commands.research.body.purchase', [ {literals(
costs[index].purchase.toLocaleString( strings.bot.commands.research.body.purchase,
interaction.locale, [
), costs[index].purchase.toLocaleString(
])} interaction.locale,
),
],
)}
</span> </span>
</div> </div>
@@ -584,11 +600,14 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
}} }}
> >
{translate('bot.commands.research.body.equipment', [ {literals(
costs[index].equipment.toLocaleString( strings.bot.commands.research.body.equipment,
interaction.locale, [
), costs[index].equipment.toLocaleString(
])} interaction.locale,
),
],
)}
</span> </span>
</div> </div>
</div> </div>
@@ -602,7 +621,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
return startingTankRaw return startingTankRaw
? image ? image
: [t`bot.commands.research.body.estimation`, image]; : [strings.bot.commands.research.body.estimation, image];
}, },
autocomplete(interaction) { autocomplete(interaction) {
+14 -11
View File
@@ -1,4 +1,5 @@
import { ClanList, fetchBlitz, Region } from '@blitzkit/core'; import { ClanList, fetchBlitz, Region } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import { Locale } from 'discord.js'; import { Locale } from 'discord.js';
import markdownEscape from 'markdown-escape'; import markdownEscape from 'markdown-escape';
import { addClanChoices } from '../core/discord/addClanChoices'; import { addClanChoices } from '../core/discord/addClanChoices';
@@ -19,25 +20,27 @@ export const searchClansCommand = new Promise<CommandRegistry>((resolve) => {
addClanChoices(option).setAutocomplete(false), addClanChoices(option).setAutocomplete(false),
) )
.addIntegerOption((option) => { .addIntegerOption((option) => {
const { t, translate } = translator(Locale.EnglishUS); const { strings } = translator(Locale.EnglishUS);
return option return option
.setName(t`bot.commands.search_clans.options.limit`) .setName(strings.bot.commands.search_clans.options.limit.$)
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
'bot.commands.search_clans.options.limit', (strings) => strings.bot.commands.search_clans.options.limit.$,
undefined, undefined,
true, true,
), ),
) )
.setDescription( .setDescription(
translate('bot.commands.search_clans.options.limit.description', [ literals(
`${DEFAULT_LIMIT}`, strings.bot.commands.search_clans.options.limit.description,
]), [`${DEFAULT_LIMIT}`],
),
) )
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
'bot.commands.search_clans.options.limit.description', (strings) =>
strings.bot.commands.search_clans.options.limit.description,
[`${DEFAULT_LIMIT}`], [`${DEFAULT_LIMIT}`],
), ),
) )
@@ -46,7 +49,7 @@ export const searchClansCommand = new Promise<CommandRegistry>((resolve) => {
}), }),
async handler(interaction) { async handler(interaction) {
const { translate } = translator(interaction.locale); const { strings } = translator(interaction.locale);
const region = interaction.options.getString('region') as Region; const region = interaction.options.getString('region') as Region;
const clan = interaction.options.getString('clan')!; const clan = interaction.options.getString('clan')!;
const limit = interaction.options.getInteger('limit') ?? DEFAULT_LIMIT; const limit = interaction.options.getInteger('limit') ?? DEFAULT_LIMIT;
@@ -56,12 +59,12 @@ export const searchClansCommand = new Promise<CommandRegistry>((resolve) => {
}); });
return embedInfo( return embedInfo(
translate('bot.commands.search_clans.body.title', [ literals(strings.bot.commands.search_clans.body.title, [
markdownEscape(clan), markdownEscape(clan),
translate(`common.regions.normal.${region}`), strings.common.regions.normal[region],
]), ]),
clanList.length === 0 clanList.length === 0
? translate('bot.commands.search_clans.body.no_results') ? strings.bot.commands.search_clans.body.no_results
: `\`\`\`\n${clanList : `\`\`\`\n${clanList
.map((clan) => `${clan.name} [${clan.tag}]`) .map((clan) => `${clan.name} [${clan.tag}]`)
.join('\n')}\n\`\`\``, .join('\n')}\n\`\`\``,
+14 -11
View File
@@ -4,6 +4,7 @@ import {
Region, Region,
usernamePattern, usernamePattern,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import { Locale } from 'discord.js'; import { Locale } from 'discord.js';
import markdownEscape from 'markdown-escape'; import markdownEscape from 'markdown-escape';
import { addRegionChoices } from '../core/discord/addRegionChoices'; import { addRegionChoices } from '../core/discord/addRegionChoices';
@@ -17,7 +18,7 @@ import { CommandRegistry } from '../events/interactionCreate';
const DEFAULT_LIMIT = 25; const DEFAULT_LIMIT = 25;
export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => { export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => {
const { t, translate } = translator(Locale.EnglishUS); const { strings } = translator(Locale.EnglishUS);
resolve({ resolve({
command: createLocalizedCommand('search-players') command: createLocalizedCommand('search-players')
@@ -27,22 +28,24 @@ export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => {
) )
.addIntegerOption((option) => .addIntegerOption((option) =>
option option
.setName(t`bot.commands.search_players.options.limit`) .setName(strings.bot.commands.search_players.options.limit.$)
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
'bot.commands.search_players.options.limit', (strings) => strings.bot.commands.search_players.options.limit.$,
undefined, undefined,
true, true,
), ),
) )
.setDescription( .setDescription(
translate('bot.commands.search_players.options.limit.description', [ literals(
`${DEFAULT_LIMIT}`, strings.bot.commands.search_players.options.limit.description,
]), [`${DEFAULT_LIMIT}`],
),
) )
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
'bot.commands.search_players.options.limit.description', (strings) =>
strings.bot.commands.search_players.options.limit.description,
[`${DEFAULT_LIMIT}`], [`${DEFAULT_LIMIT}`],
), ),
) )
@@ -51,7 +54,7 @@ export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => {
), ),
async handler(interaction) { async handler(interaction) {
const { translate } = translator(interaction.locale); const { strings } = translator(interaction.locale);
const region = interaction.options.getString('region') as Region; const region = interaction.options.getString('region') as Region;
const name = interaction.options.getString('username')!; const name = interaction.options.getString('username')!;
const limit = interaction.options.getInteger('limit') ?? 25; const limit = interaction.options.getInteger('limit') ?? 25;
@@ -64,13 +67,13 @@ export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => {
: []; : [];
return embedInfo( return embedInfo(
translate('bot.commands.search_players.body.title', [ literals(strings.bot.commands.search_players.body.title, [
markdownEscape(trimmedSearch), markdownEscape(trimmedSearch),
translate(`common.regions.normal.${region}`), strings.common.regions.normal[region],
]), ]),
`\`\`\`${ `\`\`\`${
players.length === 0 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') : players.map((player) => player.nickname).join('\n')
}\`\`\``, }\`\`\``,
); );
@@ -32,7 +32,7 @@ export function AllStatsOverview({
locale, locale,
supplementaryStats, supplementaryStats,
}: AllStatsOverviewProps) { }: AllStatsOverviewProps) {
const { t, translate } = translator(locale); const { strings } = translator(locale);
const percentile = const percentile =
typeof supplementaryStats.WN8 === 'number' typeof supplementaryStats.WN8 === 'number'
? getWN8Percentile(supplementaryStats.WN8) ? getWN8Percentile(supplementaryStats.WN8)
@@ -63,18 +63,18 @@ export function AllStatsOverview({
}} }}
> >
<WN8SurroundingStat <WN8SurroundingStat
label={t`bot.common.hero_stats.battles`} label={strings.bot.common.hero_stats.battles}
value={stats.battles.toLocaleString()} value={stats.battles.toLocaleString()}
align={WN8SurroundingStatAlign.Right} align={WN8SurroundingStatAlign.Right}
/> />
<WN8SurroundingStat <WN8SurroundingStat
label={t`bot.common.hero_stats.winrate`} label={strings.bot.common.hero_stats.winrate}
value={`${(100 * (stats.wins / stats.battles)).toFixed(2)}%`} value={`${(100 * (stats.wins / stats.battles)).toFixed(2)}%`}
align={WN8SurroundingStatAlign.Right} align={WN8SurroundingStatAlign.Right}
padded padded
/> />
<WN8SurroundingStat <WN8SurroundingStat
label={t`bot.common.hero_stats.damage`} label={strings.bot.common.hero_stats.damage}
value={Math.round( value={Math.round(
stats.damage_dealt / stats.battles, stats.damage_dealt / stats.battles,
).toLocaleString()} ).toLocaleString()}
@@ -82,7 +82,7 @@ export function AllStatsOverview({
padded padded
/> />
<WN8SurroundingStat <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)} value={(stats.damage_dealt / stats.damage_received).toFixed(2)}
align={WN8SurroundingStatAlign.Right} align={WN8SurroundingStatAlign.Right}
/> />
@@ -90,7 +90,7 @@ export function AllStatsOverview({
<HeroStat <HeroStat
value={heroStat} value={heroStat}
subtitle={translate(`common.wn8_percentile.${percentile}`)} subtitle={strings.common.wn8_percentile[percentile]}
color={color} color={color}
/> />
@@ -103,25 +103,25 @@ export function AllStatsOverview({
}} }}
> >
<WN8SurroundingStat <WN8SurroundingStat
label={t`bot.common.hero_stats.tier`} label={strings.bot.common.hero_stats.tier}
value={ value={
supplementaryStats.tier ? supplementaryStats.tier.toFixed(2) : '--' supplementaryStats.tier ? supplementaryStats.tier.toFixed(2) : '--'
} }
/> />
<WN8SurroundingStat <WN8SurroundingStat
label={t`bot.common.hero_stats.survival`} label={strings.bot.common.hero_stats.survival}
value={`${(100 * (stats.survived_battles / stats.battles)).toFixed( value={`${(100 * (stats.survived_battles / stats.battles)).toFixed(
2, 2,
)}%`} )}%`}
padded padded
/> />
<WN8SurroundingStat <WN8SurroundingStat
label={t`bot.common.hero_stats.accuracy`} label={strings.bot.common.hero_stats.accuracy}
value={`${(100 * (stats.hits / stats.shots)).toFixed(2)}%`} value={`${(100 * (stats.hits / stats.shots)).toFixed(2)}%`}
padded padded
/> />
<WN8SurroundingStat <WN8SurroundingStat
label={t`bot.common.hero_stats.kills`} label={strings.bot.common.hero_stats.kills}
value={(stats.frags / stats.battles).toFixed(2)} value={(stats.frags / stats.battles).toFixed(2)}
/> />
</div> </div>
+2 -2
View File
@@ -12,7 +12,7 @@ interface NoDataProps {
} }
export function NoData({ type, locale }: NoDataProps) { export function NoData({ type, locale }: NoDataProps) {
const { translate } = translator(locale); const { strings } = translator(locale);
return ( return (
<div <div
@@ -23,7 +23,7 @@ export function NoData({ type, locale }: NoDataProps) {
}} }}
> >
<span style={{ fontSize: 16, color: theme.colors.textLowContrast }}> <span style={{ fontSize: 16, color: theme.colors.textLowContrast }}>
{translate(`bot.common.no_data.${type}`)} {strings.bot.common.no_data[type]}
</span> </span>
</div> </div>
); );
+4 -3
View File
@@ -1,3 +1,4 @@
import { literals } from '@blitzkit/i18n';
import { Locale } from 'discord.js'; import { Locale } from 'discord.js';
import { go } from 'fuzzysort'; import { go } from 'fuzzysort';
import markdownEscape from 'markdown-escape'; import markdownEscape from 'markdown-escape';
@@ -11,7 +12,7 @@ export async function resolveTankId(
locale: Locale, locale: Locale,
techTreeOnly = false, techTreeOnly = false,
) { ) {
const { translate } = translator(locale); const { strings } = translator(locale);
const number = typeof tank === 'string' ? Number(tank) : tank; const number = typeof tank === 'string' ? Number(tank) : tank;
if (Number.isNaN(number)) { if (Number.isNaN(number)) {
@@ -26,7 +27,7 @@ export async function resolveTankId(
if (searchResult.length === 0) { if (searchResult.length === 0) {
throw new UserError( throw new UserError(
translate('bot.common.errors.tank_name_not_found', [ literals(strings.bot.common.errors.tank_name_not_found, [
markdownEscape(`${tank}`), markdownEscape(`${tank}`),
]), ]),
); );
@@ -40,7 +41,7 @@ export async function resolveTankId(
return number; return number;
} else { } else {
throw new UserError( throw new UserError(
translate('bot.common.errors.tank_id_not_found', [`${number}`]), literals(strings.bot.common.errors.tank_id_not_found, [`${number}`]),
); );
} }
} }
@@ -1,4 +1,5 @@
import { fetchTankDefinitions, TIER_ROMAN_NUMERALS } from '@blitzkit/core'; import { fetchTankDefinitions, TIER_ROMAN_NUMERALS } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import { Locale } from 'discord.js'; import { Locale } from 'discord.js';
import { StatFilters } from '../blitzstars/filterStats'; import { StatFilters } from '../blitzstars/filterStats';
import { translator } from '../localization/translator'; import { translator } from '../localization/translator';
@@ -7,22 +8,21 @@ export async function filtersToDescription(
{ nation, tier, type, class: tankClass, tank }: StatFilters, { nation, tier, type, class: tankClass, tank }: StatFilters,
locale: Locale, locale: Locale,
) { ) {
const { translate } = translator(locale); const { strings } = translator(locale);
const awaitedTankDefinitions = await fetchTankDefinitions(); const awaitedTankDefinitions = await fetchTankDefinitions();
const info: string[] = []; const info: string[] = [];
// TODO: somehow localize tank names? // TODO: somehow localize tank names?
if (tank) return awaitedTankDefinitions.tanks[tank].name; 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) { if (tier) {
info.push( 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 (tankClass) info.push(strings.common.tank_class_short[tankClass]);
if (type) info.push(translate(`common.tree_type.${type}`)); if (type) info.push(strings.common.tree_type[type]);
return info.length === 0 return info.length === 0 ? strings.bot.common.filters.none : info.join(', ');
? translate('bot.common.filters.none')
: info.join(', ');
} }
@@ -3,16 +3,22 @@ import { translator } from '../localization/translator';
import { localizationObject } from './localizationObject'; import { localizationObject } from './localizationObject';
export function addClanChoices(option: SlashCommandStringOption) { export function addClanChoices(option: SlashCommandStringOption) {
const { translate } = translator(Locale.EnglishUS); const { strings } = translator(Locale.EnglishUS);
return option return option
.setName('clan') .setName('clan')
.setNameLocalizations( .setNameLocalizations(
localizationObject('bot.common.options.clan', undefined, true), localizationObject(
(strings) => strings.bot.common.options.clan.$,
undefined,
true,
),
) )
.setDescription(translate('bot.common.options.clan.description')) .setDescription(strings.bot.common.options.clan.description)
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject('bot.common.options.clan.description'), localizationObject(
(strings) => strings.bot.common.options.clan.description,
),
) )
.setAutocomplete(true) .setAutocomplete(true)
.setMinLength(2) .setMinLength(2)
@@ -17,34 +17,40 @@ import { localizationObject } from './localizationObject';
export function addFilterOptions< export function addFilterOptions<
Option extends SlashCommandBuilder | SlashCommandSubcommandBuilder, Option extends SlashCommandBuilder | SlashCommandSubcommandBuilder,
>(option: Option, nations: string[]) { >(option: Option, nations: string[]) {
const { translate } = translator(Locale.EnglishUS); const { strings } = translator(Locale.EnglishUS);
return ( return (
option option
.addStringOption((option) => .addStringOption((option) =>
option option
.setName(translate('bot.common.options.filters.nation')) .setName(strings.bot.common.options.filters.nation.$)
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
'bot.common.options.filters.nation', (strings) => strings.bot.common.options.filters.nation.$,
undefined, undefined,
true, true,
), ),
) )
.setDescription( .setDescription(strings.bot.common.options.filters.nation.description)
translate('bot.common.options.filters.nation.description'),
)
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject('bot.common.options.filters.nation.description'), localizationObject(
(strings) =>
strings.bot.common.options.filters.nation.description,
),
) )
.addChoices( .addChoices(
...nations.map( ...nations.map(
(nation) => (nation) =>
({ ({
value: nation, value: nation,
name: translate(`common.nations.${nation}`), name: (strings.common.nations as Record<string, string>)[
nation
],
name_localizations: localizationObject( name_localizations: localizationObject(
`common.nations.${nation}`, (strings) =>
(strings.common.nations as Record<string, string>)[
nation
],
), ),
}) satisfies APIApplicationCommandOptionChoice, }) satisfies APIApplicationCommandOptionChoice,
), ),
@@ -54,28 +60,28 @@ export function addFilterOptions<
.addStringOption((option) => addTierChoices(option).setRequired(false)) .addStringOption((option) => addTierChoices(option).setRequired(false))
.addStringOption((option) => .addStringOption((option) =>
option option
.setName(translate('bot.common.options.filters.class')) .setName(strings.bot.common.options.filters.class.$)
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
'bot.common.options.filters.class', (strings) => strings.bot.common.options.filters.class.$,
undefined, undefined,
true, true,
), ),
) )
.setDescription( .setDescription(strings.bot.common.options.filters.class.description)
translate('bot.common.options.filters.class.description'),
)
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject('bot.common.options.filters.class.description'), localizationObject(
(strings) => strings.bot.common.options.filters.class.description,
),
) )
.addChoices( .addChoices(
...TANK_CLASSES.map( ...TANK_CLASSES.map(
(tankType) => (tankType) =>
({ ({
value: `${tankType}`, value: `${tankType}`,
name: translate(`common.tank_class_short.${tankType}`), name: strings.common.tank_class_short[tankType],
name_localizations: localizationObject( name_localizations: localizationObject(
`common.tank_class_short.${tankType}`, (strings) => strings.common.tank_class_short[tankType],
), ),
}) satisfies APIApplicationCommandOptionChoice, }) satisfies APIApplicationCommandOptionChoice,
), ),
@@ -84,28 +90,28 @@ export function addFilterOptions<
) )
.addStringOption((option) => .addStringOption((option) =>
option option
.setName(translate('bot.common.options.filters.type')) .setName(strings.bot.common.options.filters.type.$)
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
'bot.common.options.filters.type', (strings) => strings.bot.common.options.filters.type.$,
undefined, undefined,
true, true,
), ),
) )
.setDescription( .setDescription(strings.bot.common.options.filters.type.description)
translate('bot.common.options.filters.type.description'),
)
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject('bot.common.options.filters.type.description'), localizationObject(
(strings) => strings.bot.common.options.filters.type.description,
),
) )
.addChoices( .addChoices(
...TANK_TYPES.map( ...TANK_TYPES.map(
(treeType) => (treeType) =>
({ ({
value: TANK_TYPE_COMMAND_NAMES[treeType], value: TANK_TYPE_COMMAND_NAMES[treeType],
name: translate(`common.tree_type.${treeType}`), name: strings.common.tree_type[treeType],
name_localizations: localizationObject( name_localizations: localizationObject(
`common.tree_type.${treeType}`, (strings) => strings.common.tree_type[treeType],
), ),
}) satisfies APIApplicationCommandOptionChoice, }) satisfies APIApplicationCommandOptionChoice,
), ),