Merge branch 'main' into dev

This commit is contained in:
TrèsAbhi committed 2025-11-13 12:40:59 -06:00
commit 697d1fa1b4
16 files changed
+490 -164

No files matched your search

+1 -1
View File
@@ -117,10 +117,10 @@ jobs:
env: env:
ARCHIVE_URL: ${{ github.event.inputs.archive_url }} ARCHIVE_URL: ${{ github.event.inputs.archive_url }}
run: | run: |
mkdir -p temp/game
wget -q -O temp/archive.zip $ARCHIVE_URL wget -q -O temp/archive.zip $ARCHIVE_URL
unzip -q temp/archive.zip -d temp/archive unzip -q temp/archive.zip -d temp/archive
rm temp/archive.zip rm temp/archive.zip
mkdir -p temp/game
mv temp/archive/app/* temp/game mv temp/archive/app/* temp/game
- name: (WGPKG) Download client - name: (WGPKG) Download client
+2 -1
View File
@@ -17,6 +17,7 @@ env:
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }} GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
PUBLIC_WARGAMING_APPLICATION_ID: ${{ secrets.PUBLIC_WARGAMING_APPLICATION_ID }} PUBLIC_WARGAMING_APPLICATION_ID: ${{ secrets.PUBLIC_WARGAMING_APPLICATION_ID }}
GH_TOKEN: ${{ secrets.GH_TOKEN }} GH_TOKEN: ${{ secrets.GH_TOKEN }}
PUBLIC_ASSET_BASE: ${{ secrets.PUBLIC_ASSET_BASE }}
jobs: jobs:
build: build:
@@ -34,4 +35,4 @@ jobs:
- run: bun run setup - run: bun run setup
- name: Find reviews - name: Find reviews
run: bun packages/scripts/src/reviews.ts run: bun run build:reviews
+3
View File
@@ -150,6 +150,7 @@
"ownedtanks", "ownedtanks",
"padder", "padder",
"partytown", "partytown",
"patchnotes",
"PIXELFORMAT", "PIXELFORMAT",
"playerachievements", "playerachievements",
"playerinfo", "playerinfo",
@@ -164,6 +165,8 @@
"protobuf", "protobuf",
"protoc", "protoc",
"protos", "protos",
"proxyclient",
"prunestrings",
"Pyogenics", "Pyogenics",
"ratingleaderboard", "ratingleaderboard",
"raycaster", "raycaster",
+7 -2
View File
@@ -66,6 +66,7 @@
"@octokit/rest": "^22.0.0", "@octokit/rest": "^22.0.0",
"@prisma/client": "^6.16.2", "@prisma/client": "^6.16.2",
"@types/adm-zip": "^0.5.7", "@types/adm-zip": "^0.5.7",
"@types/bun": "^1.3.1",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/lz4js": "^0.2.1", "@types/lz4js": "^0.2.1",
"@types/three": "^0.180.0", "@types/three": "^0.180.0",
@@ -911,7 +912,7 @@
"@types/babel__traverse": ["@types/[email protected]", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], "@types/babel__traverse": ["@types/[email protected]", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
"@types/bun": ["@types/[email protected].0", "", { "dependencies": { "bun-types": "1.3.0" } }, "sha512-+lAGCYjXjip2qY375xX/scJeVRmZ5cY0wyHYyCYxNcdEXrQ4AOe3gACgd4iQ8ksOslJtW4VNxBJ8llUwc3a6AA=="], "@types/bun": ["@types/[email protected].1", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="],
"@types/debug": ["@types/[email protected]", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], "@types/debug": ["@types/[email protected]", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
@@ -1115,7 +1116,7 @@
"buffer-from": ["[email protected]", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], "buffer-from": ["[email protected]", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
"bun-types": ["[email protected].0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="], "bun-types": ["[email protected].1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="],
"c12": ["[email protected]", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^16.6.1", "exsolve": "^1.0.7", "giget": "^2.0.0", "jiti": "^2.4.2", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw=="], "c12": ["[email protected]", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^16.6.1", "exsolve": "^1.0.7", "giget": "^2.0.0", "jiti": "^2.4.2", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw=="],
@@ -2553,6 +2554,8 @@
"@blitzkit/bot/prisma": ["[email protected]", "", { "dependencies": { "@prisma/config": "6.17.1", "@prisma/engines": "6.17.1" }, "peerDependencies": { "typescript": ">=5.1.0" }, "optionalPeers": ["typescript"], "bin": { "prisma": "build/index.js" } }, "sha512-ac6h0sM1Tg3zu8NInY+qhP/S9KhENVaw9n1BrGKQVFu05JT5yT5Qqqmb8tMRIE3ZXvVj4xcRA5yfrsy4X7Yy5g=="], "@blitzkit/bot/prisma": ["[email protected]", "", { "dependencies": { "@prisma/config": "6.17.1", "@prisma/engines": "6.17.1" }, "peerDependencies": { "typescript": ">=5.1.0" }, "optionalPeers": ["typescript"], "bin": { "prisma": "build/index.js" } }, "sha512-ac6h0sM1Tg3zu8NInY+qhP/S9KhENVaw9n1BrGKQVFu05JT5yT5Qqqmb8tMRIE3ZXvVj4xcRA5yfrsy4X7Yy5g=="],
"@blitzkit/scripts/@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.3.0" } }, "sha512-+lAGCYjXjip2qY375xX/scJeVRmZ5cY0wyHYyCYxNcdEXrQ4AOe3gACgd4iQ8ksOslJtW4VNxBJ8llUwc3a6AA=="],
"@blitzkit/website/vite": ["[email protected]", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg=="], "@blitzkit/website/vite": ["[email protected]", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg=="],
"@discordjs/rest/@discordjs/collection": ["@discordjs/[email protected]", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="], "@discordjs/rest/@discordjs/collection": ["@discordjs/[email protected]", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="],
@@ -2697,6 +2700,8 @@
"@blitzkit/bot/prisma/@prisma/engines": ["@prisma/[email protected]", "", { "dependencies": { "@prisma/debug": "6.17.1", "@prisma/engines-version": "6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac", "@prisma/fetch-engine": "6.17.1", "@prisma/get-platform": "6.17.1" } }, "sha512-D95Ik3GYZkqZ8lSR4EyFOJ/tR33FcYRP8kK61o+WMsyD10UfJwd7+YielflHfKwiGodcqKqoraWw8ElAgMDbPw=="], "@blitzkit/bot/prisma/@prisma/engines": ["@prisma/[email protected]", "", { "dependencies": { "@prisma/debug": "6.17.1", "@prisma/engines-version": "6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac", "@prisma/fetch-engine": "6.17.1", "@prisma/get-platform": "6.17.1" } }, "sha512-D95Ik3GYZkqZ8lSR4EyFOJ/tR33FcYRP8kK61o+WMsyD10UfJwd7+YielflHfKwiGodcqKqoraWw8ElAgMDbPw=="],
"@blitzkit/scripts/@types/bun/bun-types": ["[email protected]", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="],
"@octokit/endpoint/@octokit/types/@octokit/openapi-types": ["@octokit/[email protected]", "", {}, "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA=="], "@octokit/endpoint/@octokit/types/@octokit/openapi-types": ["@octokit/[email protected]", "", {}, "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA=="],
"@octokit/graphql/@octokit/types/@octokit/openapi-types": ["@octokit/[email protected]", "", {}, "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA=="], "@octokit/graphql/@octokit/types/@octokit/openapi-types": ["@octokit/[email protected]", "", {}, "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA=="],
+2 -1
View File
@@ -35,7 +35,8 @@
"build:reviews": "cd packages/scripts && bun build:reviews", "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", "prunestrings": "cd packages/scripts && bun prunestrings",
"setup": "bun install && bun run build:prisma && bun run build:protos && bun run build:proxyclient && bun run build:catalogitemaccesssor" "setup": "bun install && bun run build:prisma && bun run build:protos && bun run build:proxyclient",
"patchnotes": "cd packages/scripts && bun run patchnotes"
}, },
"type": "module", "type": "module",
"workspaces": [ "workspaces": [
+1
View File
@@ -10,6 +10,7 @@
"@octokit/rest": "^22.0.0", "@octokit/rest": "^22.0.0",
"@prisma/client": "^6.16.2", "@prisma/client": "^6.16.2",
"@types/adm-zip": "^0.5.7", "@types/adm-zip": "^0.5.7",
"@types/bun": "^1.3.1",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/lz4js": "^0.2.1", "@types/lz4js": "^0.2.1",
"@types/three": "^0.180.0", "@types/three": "^0.180.0",
+1 -1
View File
@@ -1,4 +1,4 @@
import { assertSecret } from './assertSecret'; import { assertSecret } from "./assertSecret";
export function asset(path: string) { export function asset(path: string) {
return `${assertSecret(import.meta.env.PUBLIC_ASSET_BASE)}/${path}`; return `${assertSecret(import.meta.env.PUBLIC_ASSET_BASE)}/${path}`;
+1
View File
@@ -6,4 +6,5 @@ export const youtubers = [
{ id: 'UCLMEfqtlwLDN-UXX21RiEww', name: 'WoT Blitz Best Replays' }, { id: 'UCLMEfqtlwLDN-UXX21RiEww', name: 'WoT Blitz Best Replays' },
{ id: 'UC3fZbetRUFoJL0IEN7IhG0Q', name: 'EconomicsMate' }, { id: 'UC3fZbetRUFoJL0IEN7IhG0Q', name: 'EconomicsMate' },
{ id: 'UCtsUVwBlhEnUunAKLn2dtsg', name: 'Megalion69' }, { id: 'UCtsUVwBlhEnUunAKLn2dtsg', name: 'Megalion69' },
{ id: 'UCJjATWiGfOHoQYfutEwAIIg', name: 'WoTB Joe' },
]; ];
+2 -2
View File
@@ -661,7 +661,7 @@
"select_dialog_title": "Поиск танка", "select_dialog_title": "Поиск танка",
"swap_dialog_title": "Заменить танк", "swap_dialog_title": "Заменить танк",
"clear_filters": "Сбросить фильтры", "clear_filters": "Сбросить фильтры",
"login": "Войти, чтобы воспользоваться", "login": "Войдите, чтобы воспользоваться",
"search_bar_hint": "Поиск танков...", "search_bar_hint": "Поиск танков...",
"recent": "Недавние", "recent": "Недавние",
"select_all": "Выбрать всё", "select_all": "Выбрать всё",
@@ -908,7 +908,7 @@
}, },
"stats": { "stats": {
"thickness_and_angle": "{thickness}мм {angle}°", "thickness_and_angle": "{thickness}мм {angle}°",
"nominal": "{thickness}1мм номинала", "nominal": "{thickness}мм номинала",
"ricochet_loss": "{loss}% пробития" "ricochet_loss": "{loss}% пробития"
} }
} }
+150 -150
View File
@@ -1,23 +1,23 @@
{ {
"test": { "test": {
"default": "测试", "default": "测试",
"long": "This is a long test string. You MUST NEVER see this in the UI. My favorite fruit is {fruit} because it has the color of {color}. I like it so much that I will say its name 3 times! {fruit}! {fruit}! {fruit}! Once again, it's {color}, not {not_color}.", "long": "这是一个测试用长字符串。你绝对不会在用户界面中看见这些。我最喜欢的水果是{fruit}因为它的颜色是{color}的。我如此喜欢它,以至于我会把它的名字念3次!{fruit}!{fruit}!{fruit}!重申一次,它是{color}的而不是{not_color}的。",
"fox": "褐色的狐狸迅速地跳过那只懒狗" "fox": "褐色的狐狸迅速地跳过那只懒狗"
}, },
"common": { "common": {
"name": "BlitzKit", "name": "BlitzKit",
"units": { "units": {
"m": "{value}m", "m": "{value} 公尺",
"mm": "{value}mm", "mm": "{value} 毫米",
"deg": "{value}°", "deg": "{value} 度°",
"hp": "{value}hp", "hp": "{value} 生命值",
"x": "x{value}", "x": "x{value}",
"percentage": "{value}%", "percentage": "{value}%",
"deg_s": "{value}°/s" "deg_s": "{value}度°/秒"
}, },
"gun_types": { "gun_types": {
"auto_loader": "弹夹型战车", "auto_loader": "弹夹型坦克",
"auto_reloader": "自动装填型战车", "auto_reloader": "自动装填型坦克",
"regular": "单发" "regular": "单发"
}, },
"shells": { "shells": {
@@ -101,8 +101,8 @@
}, },
"tank_class_short": { "tank_class_short": {
"-1": "未识别", "-1": "未识别",
"0": "轻型战车", "0": "轻型坦克",
"1": "中型战车", "1": "中型坦克",
"2": "重型战车", "2": "重型战车",
"3": "驱逐战车" "3": "驱逐战车"
}, },
@@ -186,11 +186,11 @@
"bot": { "bot": {
"common": { "common": {
"errors": { "errors": {
"clan_not_found": "# 找不到军团\n找不到 \"{search}\". 请尝试选从搜索结果中择一个军团。", "clan_not_found": "# 找不到公会\n找不到\"{search}\"。请尝试从搜索结果中选择一个公会。",
"player_not_found": "# Could not find user\nI couldn't find user \"{search}\". Try picking an user from the search result, typing in a valid username, or using the `/link` command.", "player_not_found": "# 找不到玩家\n无法找到玩家 “{search}”。 尝试从搜索结果中选择玩家,或输入一个有效的玩家名称, 或使用“/link”命令。",
"player_not_linked": "# 使用 `/link` 来开始\n我不知道你是谁,但你今天可以告诉我!", "player_not_linked": "# 使用 `/link` 来开始\n我不知道你是谁,但你今天可以告诉我!",
"tank_name_not_found": "# 找不到坦克\n找不到名称为 \"{search}\"的坦克。", "tank_name_not_found": "# 找不到坦克\n找不到名为 “{search}” 的坦克。",
"tank_id_not_found": "# 找不到坦克\n找不到ID为 \"{search}\"的坦克. 尝试输入坦克的名称。", "tank_id_not_found": "# 找不到坦克\n无法找到ID为 “{search}” 的坦克。 请尝试输入坦克的名称而不是数字。",
"no_tank_stats": "# 没有这辆战车的数据\n这个玩家没有可用资料。 这可能不是你要找的玩家。", "no_tank_stats": "# 没有这辆战车的数据\n这个玩家没有可用资料。 这可能不是你要找的玩家。",
"get_help": "Discord的协助服务器", "get_help": "Discord的协助服务器",
"uncaught_error": "# BlitzKit 发生错误!\n我们对此感到抱歉。 欢迎加入[官方Discord](https://discord.gg/nDt7AjGJQH),以方便帮助你解决问题。", "uncaught_error": "# BlitzKit 发生错误!\n我们对此感到抱歉。 欢迎加入[官方Discord](https://discord.gg/nDt7AjGJQH),以方便帮助你解决问题。",
@@ -284,19 +284,19 @@
"name": "阶级", "name": "阶级",
"description": "阶级", "description": "阶级",
"choices": { "choices": {
"tier": "坦克等级 {tier_1} - {tier_2}" "tier": "{tier_1} - {tier_2} 阶"
} }
} }
}, },
"periods": { "periods": {
"career": "玩家资料", "career": "玩家资料",
"today": "今日:", "today": "今日:",
"days": "{days} days", "days": "{days} 天",
"custom": "{day_1} - {day_2} days" "custom": "{day_1} - {day_2} 天"
}, },
"filters": { "filters": {
"none": "无筛选器", "none": "无筛选器",
"tier": "坦克等级 {tier}" "tier": "{tier} 阶"
}, },
"no_data": { "no_data": {
"battles_in_period": "在这段时间里没有参与任何战斗", "battles_in_period": "在这段时间里没有参与任何战斗",
@@ -339,19 +339,19 @@
"body": { "body": {
"subtitle": "研发", "subtitle": "研发",
"total": "全部", "total": "全部",
"research": "Research: {cost}", "research": "研发:{cost}",
"upgrades": "Upgrades: {cost}", "upgrades": "升级:{cost}",
"purchase": "Purchase: {cost}", "purchase": "购买:{cost}",
"equipment": "Equipment: {cost}", "equipment": "装备:{cost}",
"estimation": "# 这是一个估计值!\n\n这个列表可能包含已经研发过的战车,因为 Wargaming 提供了不正确的资料。 如果可以,请尝试在同一研发线路中提供一个 “起始战车” 。" "estimation": "# 这是一个估计值!\n\n这个列表可能包含已经研发过的战车,因为 Wargaming 提供了不正确的资料。 如果可以,请尝试在同一研发线路中提供一个 “起始战车” 。"
}, },
"errors": { "errors": {
"non_tech_tree": "# {tank} is not on the tech tree\n\nYou cannot research a premium/collector tank.", "non_tech_tree": "# \"{tank}\" 不在科技树里\n\n你不能研发一个 加值/收藏家 坦克。",
"tier_1": "# {tank} 是一级坦克\n\n一级坦克一直是对所有玩家免费解锁的。", "tier_1": "# {tank} 是一级坦克\n\n一级坦克一直是对所有玩家免费解锁的。",
"already_researched": "# {tank} is already researched\n\nTry providing a `starting-tank` when using the command to view the totals for a line you have already researched.", "already_researched": "# \"{tank}\" 已完成研发\n\n请尝试在同一研发线路上提供“起始坦克”, 以查看全部您已研发过的坦克。",
"start_end_equal": "# {tank} was provided twice\n\nMake sure `starting-tank` and `target-tank` are different.", "start_end_equal": "# \"{tank}\" 重复提供了\n\n请确认 \"初始坦克\" 和 \"目标坦克\" 是不同的。",
"tanks_not_on_line": "# {tank_1} and {tank_2} are not on the same line\n\nMake sure `starting-tank` and `target-tank` are on the same tech-tree line.", "tanks_not_on_line": "# “{tank_1}” 和 “{tank_2}” 不在同一个研发线路上\n\n请确认“起始坦克” 和 “目标坦克” 在同一研发线路中。",
"unordered": "# {tank_1} higher tiered to {tank_2}\n\nMake sure to provide {tank_2} as the `starting-tank` instead as it is the lower tiered tank." "unordered": "# “{tank_1}” 阶级比 “{tank_2}” 高\n\n请以提供 {tank_2} 作为起始坦克,因为它的阶级更低。"
} }
}, },
"about": { "about": {
@@ -394,7 +394,7 @@
"wn8": "WN8", "wn8": "WN8",
"winrate": "胜率", "winrate": "胜率",
"damage": "伤害", "damage": "伤害",
"unknown_tank": "未知坦克{id}" "unknown_tank": "未知坦克 {id}"
} }
}, },
"debug": { "debug": {
@@ -430,12 +430,12 @@
"options": { "options": {
"threshold": { "threshold": {
"name": "阈值", "name": "阈值",
"description": "The number of days inactive (default: {days} days)" "description": "未上线天数( 默认:{days} 天)"
} }
}, },
"body": { "body": {
"subtitle": "Inactive for {days}+ days", "subtitle": "{days}+ 天未上线",
"listing": "{days} days" "listing": "{days} 天"
} }
}, },
"full_stats": { "full_stats": {
@@ -478,7 +478,7 @@
"body": { "body": {
"accounts_linked": "帐号已绑定", "accounts_linked": "帐号已绑定",
"no_role_permissions": { "no_role_permissions": {
"title": "{name} failed to verify", "title": "{name} 验证失败",
"description": "我没有管理身份的权限。" "description": "我没有管理身份的权限。"
} }
}, },
@@ -493,11 +493,11 @@
"options": { "options": {
"limit": { "limit": {
"name": "限制", "name": "限制",
"description": "The max number of clan results (default: {limit})" "description": "公会结果的最大显示数量 (默认:{limit})"
} }
}, },
"body": { "body": {
"title": "Clan search for {search} in region {region}", "title": "在地区 {region} 中搜索公会 {search}",
"no_results": "没有找到该公会" "no_results": "没有找到该公会"
} }
}, },
@@ -507,11 +507,11 @@
"options": { "options": {
"limit": { "limit": {
"name": "限制", "name": "限制",
"description": "The max number of player results (default: {limit})" "description": "玩家结果的最大显示数量 (默认:{limit})"
} }
}, },
"body": { "body": {
"title": "Player search for {search} in region {region}", "title": "在地区 {region} 中搜索玩家 {search}",
"no_results": "未找到玩家" "no_results": "未找到玩家"
} }
}, },
@@ -531,13 +531,13 @@
"options": { "options": {
"limit": { "limit": {
"name": "限制", "name": "限制",
"description": "How many neighbors to display (default: {count})" "description": "显示附近有多少玩家(默认:{count})"
}, },
"season": { "season": {
"name": "赛季", "name": "赛季",
"description": "赛季数 (默认:当前)", "description": "赛季数 (默认:当前)",
"choices": { "choices": {
"current": "{season} (current)" "current": "{season} (当前)"
} }
}, },
"league": { "league": {
@@ -546,12 +546,12 @@
} }
}, },
"body": { "body": {
"top_players": "Top {count} players", "top_players": "前 {count} 玩家",
"no_participation": "# {player} didn't play rating in season {season}\n\nThis player did not participate in this season or did not get past calibration.", "no_participation": "# {player} 没有在赛季 {season} 中进行过评价战斗\n\n该玩家没有参加该赛季或没有完成校准。",
"no_ongoing_season": "# 没有进行中的赛季\n\n目前没有赛季。", "no_ongoing_season": "# 没有进行中的赛季\n\n目前没有赛季。",
"deleted_player": "删除{id}", "deleted_player": "已删除玩家 {id}",
"neighbors": "对邻居进行评分", "neighbors": "对邻居进行评分",
"more": "+ {count} more" "more": "+ {count} 更多"
} }
}, },
"today": { "today": {
@@ -566,7 +566,7 @@
"name": "已拥有的战车", "name": "已拥有的战车",
"description": "显示该阶级中所有您已拥有的战车", "description": "显示该阶级中所有您已拥有的战车",
"body": { "body": {
"title": "# {name}'s owned tier {tier} tanks\n\n" "title": "# {name} 所拥有的 {tier} 阶坦克\n\n"
} }
}, },
"permissions": { "permissions": {
@@ -585,7 +585,7 @@
"description": "检查机器人是否处于活动状态。", "description": "检查机器人是否处于活动状态。",
"body": { "body": {
"pong": "Pong 🏓", "pong": "Pong 🏓",
"pong_with_time": "Pong 🏓 - {time}ms" "pong_with_time": "Pong 🏓 - {time} 微秒"
}, },
"subcommands": { "subcommands": {
"blitzkit": { "blitzkit": {
@@ -602,7 +602,7 @@
"name": "玩家信息", "name": "玩家信息",
"description": "玩家基本信息", "description": "玩家基本信息",
"body": { "body": {
"title": "{name}的信息", "title": "{name} 的信息",
"nickname": "昵称", "nickname": "昵称",
"battles": "战斗场次", "battles": "战斗场次",
"winrate": "胜率", "winrate": "胜率",
@@ -631,7 +631,7 @@
} }
}, },
"errors": { "errors": {
"no_participation": "# {name}还没有玩过评级模式。", "no_participation": "# {name} 未曾游玩评价战斗\n\n该玩家未参与本赛季的评价战斗。",
"unrecorded_stats": "# 统计数据目前无法使用\n\nWargaming 可能暂停了服务器。 如果有连续的赛季,统计数据可能在24小时内提供。" "unrecorded_stats": "# 统计数据目前无法使用\n\nWargaming 可能暂停了服务器。 如果有连续的赛季,统计数据可能在24小时内提供。"
} }
} }
@@ -644,7 +644,7 @@
}, },
"settings": { "settings": {
"title": "设置", "title": "设置",
"description": "调整BlitzKit设置", "description": "更改 BlitzKit 设置",
"dev_mode": "开发者模式", "dev_mode": "开发者模式",
"language": "语言" "language": "语言"
}, },
@@ -661,13 +661,13 @@
"select_dialog_title": "搜索坦克", "select_dialog_title": "搜索坦克",
"swap_dialog_title": "交换坦克", "swap_dialog_title": "交换坦克",
"clear_filters": "清除筛选", "clear_filters": "清除筛选",
"login": "Login to use this", "login": "登录以使用它",
"search_bar_hint": "搜寻战车……", "search_bar_hint": "搜寻战车……",
"recent": "最近查看的", "recent": "最近查看的",
"select_all": "全选", "select_all": "全选",
"count_singular": "1辆战车", "count_singular": "1辆战车",
"count_plural": "{count} tanks", "count_plural": "{count} 辆坦克",
"sorting_by": "Sorting by {name}", "sorting_by": "按 {name} 排序",
"no_tanks_found": { "no_tanks_found": {
"body": "找不到战车。", "body": "找不到战车。",
"search_again": "请尝试重新搜索。", "search_again": "请尝试重新搜索。",
@@ -688,7 +688,7 @@
"fire.caliber": "口径", "fire.caliber": "口径",
"fire.standardPenetration": "标准炮弹穿透力", "fire.standardPenetration": "标准炮弹穿透力",
"fire.premiumPenetration": "加值炮弹穿透力", "fire.premiumPenetration": "加值炮弹穿透力",
"fire.tertiaryPenetration": "tertiary penetration", "fire.tertiaryPenetration": "第三种炮弹穿透力",
"fire.damage": "炮弹伤害值", "fire.damage": "炮弹伤害值",
"fire.moduleDamage": "模组伤害值", "fire.moduleDamage": "模组伤害值",
"fire.shellVelocity": "炮弹飞行速度", "fire.shellVelocity": "炮弹飞行速度",
@@ -730,12 +730,12 @@
}, },
"home": { "home": {
"pwa": { "pwa": {
"title": "安装Blitz Kit App", "title": "安装 BlitzKit 应用程序",
"new": "NEW", "new": "新增",
"checking": "正在检查兼容性……", "checking": "正在检查兼容性……",
"instructions": "Instructions for Apple devices.", "instructions": "Apple 设备的说明。",
"install": "安装", "install": "安装",
"dismiss": "忽略" "dismiss": "取消"
}, },
"discord": { "discord": {
"join_short": "加入超級酷的人群!", "join_short": "加入超級酷的人群!",
@@ -743,16 +743,16 @@
"action": "Discord" "action": "Discord"
}, },
"hero": { "hero": {
"credit": "By {name} ❤️" "credit": "由 {name} 制作 ❤️"
}, },
"hot_tanks": { "hot_tanks": {
"title": "受欢迎的坦克", "title": "受欢迎的坦克",
"subtitle": "Last {days} days" "subtitle": "过去 {days} 天"
}, },
"other_projects": { "other_projects": {
"title": "其他酷炫的项目" "title": "其他酷炫的项目"
}, },
"help_translate": "Please help translate {name} to {language}!", "help_translate": "请帮忙将 {name} 翻译成 {language}!",
"seo_description": "战车世界闪击战 全方位工具" "seo_description": "战车世界闪击战 全方位工具"
}, },
"docs": { "docs": {
@@ -764,49 +764,49 @@
"tools": { "tools": {
"playlist": { "playlist": {
"reset": "重置", "reset": "重置",
"shuffle": "Shuffle", "shuffle": "换一批",
"remove": "Remove played", "remove": "移除已游玩的",
"tracking": "BlitzKit is tracking your battles", "tracking": "BlitzKit 正在追踪您的战斗记录",
"sort": { "sort": {
"button": "排序依据", "button": "排序依据",
"last_played": "Last played", "last_played": "最后一次游玩",
"least_played": "Least played" "least_played": "最少游玩的"
}, },
"table": { "table": {
"index": "#", "index": "#",
"never": "Never", "never": "从不",
"tank": "战车", "tank": "坦克",
"last_played": "Last played", "last_played": "最后一次游玩",
"battles": "Career battles", "battles": "生涯战斗数",
"unrecorded": "--", "unrecorded": "--",
"wins": "胜利" "wins": "胜利"
}, },
"large_warning": { "large_warning": {
"title": "That's a lot of tanks!", "title": "坦克数量太多了!",
"description": "Are you sure you want to create a playlist of {count} tanks? That's {time} hours of gameplay at 50% winrate!", "description": "您确定要创建包含 {count} 个坦克的游玩列表吗?以50%胜率计算,这需要 {time} 小时的游玩时间!",
"cancel": "取消", "cancel": "取消",
"proceed": "Proceed" "proceed": "继续操作"
}, },
"generate": "Generate playlist", "generate": "创建游玩列表",
"name": "Playlist", "name": "遊玩列表",
"description": "Tank playlist generator", "description": "坦克游玩列表生成器",
"seo_description": "Don't know what to play in World of Tanks Blitz? Use BlitzKit Playlist to get suggestions!", "seo_description": "想不到在坦克世界闪击战玩什么? 使用BlitzKit 游玩列表来获得建议!",
"button": "Generate", "button": "生成",
"pool_size": "{count} possible tanks" "pool_size": "{count} 辆可生成的坦克"
}, },
"mixer": { "mixer": {
"name": "Mixer", "name": "组装",
"button": "Mix and match", "button": "混合搭配",
"description": "Mix tank modules", "description": "混合坦克模块",
"seo_description": "Mix and match hulls, turrets, and guns of tanks in World of Tanks Blitz", "seo_description": "《坦克世界:闪击战》的车体, 炮塔, 主炮混合搭配",
"screenshot": "Screenshot", "screenshot": "屏幕截图",
"randomize": "Randomize" "randomize": "随机搭配"
}, },
"guess": { "guess": {
"name": "猜坦克", "name": "猜坦克",
"button": "猜猜看", "button": "猜猜看",
"description": "战车剪影小游戏", "description": "坦克剪影小游戏",
"seo_description": "看剪影猜战车", "seo_description": "看剪影猜坦克",
"search": { "search": {
"placeholder": "输入你的猜想……", "placeholder": "输入你的猜想……",
"skip": "跳过", "skip": "跳过",
@@ -814,22 +814,22 @@
"next": "下一个", "next": "下一个",
"no_results": "沒有結果" "no_results": "沒有結果"
}, },
"stats": "{correct} / {total} guessed correctly" "stats": "猜对了 {correct} / {total}"
}, },
"tankopedia": { "tankopedia": {
"search": "搜索属性……", "search": "搜索属性……",
"name": "战车百科", "name": "战车百科",
"button": "搜索战车", "button": "搜索战车",
"description": "闪击战战车百科全书", "description": "闪击战坦克百科全书",
"seo_description": "战车世界闪击战的所有坦克参数, 装甲, 等等...", "seo_description": "《坦克世界:闪击战》的所有坦克参数, 装甲, 等等...",
"tank_seo_title": "{name} - Tier {tier} {nationality} {class} | {website} Tankopedia | World of Tanks Blitz (WoTB)", "tank_seo_title": "{name} - {tier} 阶 {nationality} {class} | {website} 坦克百科 | 坦克世界闪击战 (WoTB)",
"tank_seo_description": "{name} armor, statistics, equipment, provisions, and more. {dpm} DPM, {alpha}hp alpha, {penetration}mm penetration, {speed}kph top speed, {health}hp health.", "tank_seo_description": "{name} 装甲,统计资料,装备,规定配给等。 {dpm} 每分钟伤害, {alpha} 伤害值, {penetration}毫米 穿透, {speed}公里/小時 最高速度, {health} 生命值。",
"visualizers": { "visualizers": {
"reload": { "reload": {
"skip": "跳过" "skip": "跳过"
}, },
"assault": { "assault": {
"title": "Assault shells" "title": "突击弹"
}, },
"rotator": { "rotator": {
"hull": "车体", "hull": "车体",
@@ -852,10 +852,10 @@
"dead_rail": "死亡铁道" "dead_rail": "死亡铁道"
}, },
"flexibility": { "flexibility": {
"yaw": "Yaw", "yaw": "水平角度",
"pitch": "Pitch", "pitch": "俯仰角度",
"min": "Min", "min": "最少俯角",
"max": "Max" "max": "最大仰角"
} }
}, },
"sandbox": { "sandbox": {
@@ -901,15 +901,15 @@
"track": "履带" "track": "履带"
}, },
"status": { "status": {
"penetration": "{damage}hp penetration", "penetration": "{damage}生命值 击穿",
"blocked": "抵挡伤害", "blocked": "抵挡伤害",
"ricochet": "跳弹", "ricochet": "跳弹",
"splash": "{damage}hp splash" "splash": "{damage}生命值 溅射"
}, },
"stats": { "stats": {
"thickness_and_angle": "{thickness}mm {angle}°", "thickness_and_angle": "{thickness}毫米 {angle}度°",
"nominal": "{thickness}mm nominal", "nominal": "{thickness}毫米 装甲厚度",
"ricochet_loss": "{loss}% penetration" "ricochet_loss": "{loss}% 击穿"
} }
} }
}, },
@@ -929,13 +929,13 @@
"compare": "比较", "compare": "比较",
"swap": { "swap": {
"button": "调换", "button": "调换",
"title": "调换战车" "title": "调换坦克"
}, },
"vanilla": "原版", "vanilla": "原版",
"opentest": "开放测试", "opentest": "开放测试",
"full_name": "全称", "full_name": "全称",
"nation": "国别", "nation": "国别",
"class": "战车车型", "class": "坦克车型",
"tier": "阶级", "tier": "阶级",
"type": "战车类型", "type": "战车类型",
"dev_id": "开发参数:ID", "dev_id": "开发参数:ID",
@@ -947,20 +947,20 @@
"tech_tree": { "tech_tree": {
"title": "科技树", "title": "科技树",
"battle": "一场比赛", "battle": "一场比赛",
"battles": "{count} battles", "battles": "{count} 战斗场次",
"route": "Route {index} of {count}" "route": "路线 {index} / {count}"
}, },
"game_modes": { "game_modes": {
"title": "游戏模式技能" "title": "游戏模式技能"
}, },
"review": { "review": {
"title": "回顾影片", "title": "回顾影片",
"join": "Apply to {name} YouTuber program" "join": "应用到 {name} YouTuber程序"
}, },
"configuration": { "configuration": {
"title": "配置设定", "title": "配置设定",
"modules": { "modules": {
"title": "战车模块", "title": "坦克模块",
"stock": "白板", "stock": "白板",
"upgrade": "顶级配置" "upgrade": "顶级配置"
}, },
@@ -975,7 +975,7 @@
"consumables": { "consumables": {
"title": "消耗品", "title": "消耗品",
"clear": "清除", "clear": "清除",
"info": "黄色高亮消耗品不影响战车参数。" "info": "黄色高亮消耗品不影响坦克参数。"
}, },
"skills": { "skills": {
"title": "乘员技能", "title": "乘员技能",
@@ -991,15 +991,15 @@
"title": "属性", "title": "属性",
"compare": { "compare": {
"label": "比较", "label": "比较",
"class": "Tier {tier} {class}", "class": "{tier}阶 {class}",
"tier": "All of tier {tier}", "tier": "所有 {tier} 阶",
"all": "所有战车" "all": "所有坦克"
}, },
"values": { "values": {
"shell_index": "Shell {index}", "shell_index": "炮弹 {index}",
"at_distance": "At {distance}m", "at_distance": "在 {distance} 公尺",
"at_distance_slider_label": "距离", "at_distance_slider_label": "距离",
"dispersion_at_distance": "Dispersion at {distance}m", "dispersion_at_distance": "在 {distance} 公尺的扩散度",
"gun_flexibility": "炮管转动界限", "gun_flexibility": "炮管转动界限",
"speed": "速度", "speed": "速度",
"terrain_coefficients": "地形系数", "terrain_coefficients": "地形系数",
@@ -1015,13 +1015,13 @@
"dpmEffective": "60秒内生效", "dpmEffective": "60秒内生效",
"shells": "炮弹 ", "shells": "炮弹 ",
"mostOptimalShellIndex": "最优炮弹", "mostOptimalShellIndex": "最优炮弹",
"shellReloads": "Reloads", "shellReloads": "装填时间",
"shellReload": "装填时间", "shellReload": "装填时间",
"intraClip": "炮弹装填", "intraClip": "炮弹装填",
"caliber": "口径", "caliber": "口径",
"penetration": "穿深", "penetration": "穿深",
"damage": "伤害", "damage": "伤害",
"damageWithoutAssault": "Damage without assault shells", "damageWithoutAssault": "无突击弹的伤害",
"clipDamage": "弹匣伤害期望值", "clipDamage": "弹匣伤害期望值",
"moduleDamage": "模组伤害", "moduleDamage": "模组伤害",
"explosionRadius": "溅射半径", "explosionRadius": "溅射半径",
@@ -1101,14 +1101,14 @@
}, },
"compare": { "compare": {
"name": "比较", "name": "比较",
"button": "战车比较", "button": "坦克比较",
"description": "比较战车参数", "description": "比较坦克参数",
"seo_description": "比较《战车世界:闪击战》中的战车参数和装备配置", "seo_description": "比较《坦克世界:闪击战》中的坦克参数和装备配置",
"actions": { "actions": {
"add": { "add": {
"button": "添加", "button": "添加",
"title": "添加战车", "title": "添加坦克",
"description": "选择要加入比较的战车" "description": "选择要加入比较的坦克"
}, },
"clear": "清除", "clear": "清除",
"deltas": { "deltas": {
@@ -1144,20 +1144,20 @@
}, },
"performance": { "performance": {
"name": "性能表现", "name": "性能表现",
"button": "查看战车", "button": "查看坦克",
"description": "战车性能统计", "description": "坦克性能统计",
"seo_description": "最好的战车及其在战车世界闪击战中的表现", "seo_description": "最好的坦克及其在《坦克世界:闪击战》中的表现",
"estimation": { "estimation": {
"body": "Estimated stats based on {count} players. Updated {age} ago.", "body": "基于 {count} 个玩家的估计数据。更新于 {age} 之前。",
"hours": "{count} hours", "hours": "{count} 小时",
"minutes": "{count} minutes" "minutes": "{count} 分钟"
}, },
"player_count": { "player_count": {
"label": "玩家数量" "label": "玩家数量"
}, },
"table": { "table": {
"tanks": { "tanks": {
"header": "战车", "header": "坦克",
"total": "全部" "total": "全部"
}, },
"stats": { "stats": {
@@ -1181,18 +1181,18 @@
"name": "图库", "name": "图库",
"button": "浏览全部", "button": "浏览全部",
"description": "Blitz玩家头像", "description": "Blitz玩家头像",
"seo_description": "所有战车世界闪击战玩家头像", "seo_description": "所有《坦克世界:闪击战》玩家头像",
"last_updated": "Last updated on {time}", "last_updated": "最后更新于 {time}",
"search": { "search": {
"hint": "搜索頭像……", "hint": "搜索頭像……",
"results": "{count} avatars" "results": "{count} 头像"
} }
}, },
"session": { "session": {
"name": "场次", "name": "场次",
"button": "开始追踪", "button": "开始追踪",
"description": "即时场次统计", "description": "即时场次统计",
"seo_description": "在游玩 战车世界闪击战 时,实时追踪你的统计数据", "seo_description": "在游玩《坦克世界:闪击战》时,实时追踪你的统计数据",
"search": { "search": {
"lookup": "查询玩家以开始使用", "lookup": "查询玩家以开始使用",
"hint": "搜索玩家……", "hint": "搜索玩家……",
@@ -1200,14 +1200,14 @@
"no_results": "找不到玩家" "no_results": "找不到玩家"
}, },
"controls": { "controls": {
"title": "Tracking {name}", "title": "正在追踪 {name}",
"subtitle": "Since {time}", "subtitle": "起始于 {time}",
"reset": "重置", "reset": "重置",
"change": "变更" "change": "变更"
}, },
"no_cc": { "no_cc": {
"title": "你正在尝试追踪一个 CC 帐戶", "title": "你正在尝试追踪一个 CC 帐戶",
"body": "CC(社群贡献者)账戶没有公开的战车统计数据。 我们正在为CC账戶添加嵌入功能,敬请期待。", "body": "CC(社群贡献者)账戶没有公开的坦克统计数据。 我们正在为CC账戶添加嵌入功能,敬请期待。",
"alright": "好的" "alright": "好的"
}, },
"no_battles": { "no_battles": {
@@ -1215,16 +1215,16 @@
"hint": "去玩一场游戏吧" "hint": "去玩一场游戏吧"
}, },
"table": { "table": {
"tank": "战车", "tank": "坦克",
"total": "全部", "total": "全部",
"remove": "移除" "remove": "移除"
} }
}, },
"tier_list": { "tier_list": {
"name": "阶级列表", "name": "阶级列表",
"button": "排名战车", "button": "排名坦克",
"description": "战车世界闪击战 战车等级排名", "description": "《坦克世界:闪击战》坦克等级排名",
"seo_description": "基于玩家评分和统计表现,从最佳到最差排名的《战车世界:闪击战》战车等级列表", "seo_description": "基于玩家评分和统计表现,从最佳到最差排名的《坦克世界:闪击战》坦克等级列表",
"buttons": { "buttons": {
"reset": "重置", "reset": "重置",
"share": "分享" "share": "分享"
@@ -1234,7 +1234,7 @@
"name": "嵌入", "name": "嵌入",
"button": "立即创建", "button": "立即创建",
"description": "用于串流的嵌入", "description": "用于串流的嵌入",
"seo_description": "创建具有极高自订化的《战车世界:闪击战》串流嵌入功能", "seo_description": "创建具有极高自订化的《坦克世界:闪击战》串流嵌入功能",
"coming_soon": "更多嵌入功能即将推出。", "coming_soon": "更多嵌入功能即将推出。",
"suggest": "建议与想法", "suggest": "建议与想法",
"preview": { "preview": {
@@ -1261,7 +1261,7 @@
"cancel": "取消", "cancel": "取消",
"success": { "success": {
"title": "拷贝 URL", "title": "拷贝 URL",
"info": "Generated the URL for {name}. The embed will start tracking as soon as the URL is pasted. Reset at any time by right-clicking on PC or long-pressing on mobile and then selecting \"Reset\".", "info": "已为 {name} 生成 URL。 当 URL 粘贴后,嵌入功能将开始追踪。 您可以随时在 PC 上点击右键或手机上长按并选择「重置」来重置。",
"back": "返回", "back": "返回",
"copy": "拷贝 URL" "copy": "拷贝 URL"
} }
@@ -1285,13 +1285,13 @@
"height": "高度", "height": "高度",
"showTotal": "显示总计", "showTotal": "显示总计",
"listGap": "列表间距", "listGap": "列表间距",
"listMaxTanks": "最多战车数量", "listMaxTanks": "最多坦克数量",
"cardRadius": "卡片半径", "cardRadius": "卡片半径",
"cardHeaderBackgroundColor": "卡片标题背景颜色", "cardHeaderBackgroundColor": "卡片标题背景颜色",
"cardHeaderPadding": "卡片标题內间距", "cardHeaderPadding": "卡片标题內间距",
"cardTitle": "卡片标题", "cardTitle": "卡片标题",
"cardTitleTypeColor": "卡片标题(战车类型)颜色", "cardTitleTypeColor": "卡片标题(坦克类型)颜色",
"cardTitleClassIcon": "卡片标题(战车车型)颜色", "cardTitleClassIcon": "卡片标题(坦克车型)颜色",
"cardBodyBackgroundColor": "卡片內容背景颜色", "cardBodyBackgroundColor": "卡片內容背景颜色",
"cardBodyPadding": "卡片內容內間距", "cardBodyPadding": "卡片內容內間距",
"columnGap": "栏间距", "columnGap": "栏间距",
@@ -1312,13 +1312,13 @@
"name": "图表", "name": "图表",
"button": "瘋狂研究", "button": "瘋狂研究",
"description": "大量图标", "description": "大量图标",
"seo_description": "有关战车世界闪击战 战车、玩家与事件的各种图表与图形" "seo_description": "有关《坦克世界:闪击战》坦克、玩家与事件的各种图表与图形"
}, },
"rating": { "rating": {
"name": "评价战斗", "name": "评价战斗",
"button": "查看排行榜", "button": "查看排行榜",
"description": "完整评价战斗排行榜", "description": "完整评价战斗排行榜",
"seo_description": "《战车世界:闪击战》即时及已存档的完整评分排行榜" "seo_description": "《坦克世界:闪击战》即时及已存档的完整评分排行榜"
}, },
"discord": { "discord": {
"name": "Discord机器人", "name": "Discord机器人",
@@ -1336,7 +1336,7 @@
"name": "玩家", "name": "玩家",
"button": "查询玩家", "button": "查询玩家",
"description": "定期玩家统计", "description": "定期玩家统计",
"seo_description": "战车世界闪击战 定期玩家统计" "seo_description": "《坦克世界:闪击战》定期玩家统计"
}, },
"home": { "home": {
"name": "主页", "name": "主页",
@@ -1345,14 +1345,14 @@
"seo_description": "开始使用 BlitzKit" "seo_description": "开始使用 BlitzKit"
}, },
"api": { "api": {
"name": "API", "name": "应用程序接口(API)",
"button": "To the docs", "button": "前往文档",
"description": "BlitzKit hosted API", "description": "BlitzKit 已托管的应用程序接口(API)",
"seo_description": "BlitzKit hosted static API for World of Tanks Blitz" "seo_description": "BlitzKit 托管的《坦克世界:闪击战》静态应用程序接口(API)"
} }
}, },
"footer": { "footer": {
"motto": "战车世界闪击战 全方位工具", "motto": "《坦克世界:闪击战》全方位工具",
"copyright": "本网站与 Wargaming战游网 或任何服务无关", "copyright": "本网站与 Wargaming战游网 或任何服务无关",
"about": { "about": {
"title": "关于", "title": "关于",
+2 -1
View File
@@ -44,7 +44,8 @@
"build:proxyclient": "bun src/buildProxyClient.ts", "build:proxyclient": "bun src/buildProxyClient.ts",
"build:catalogitemaccesssor": "bun src/buildCatalogItemAccessor.ts", "build:catalogitemaccesssor": "bun src/buildCatalogItemAccessor.ts",
"prunestrings": "bun src/pruneStrings.ts", "prunestrings": "bun src/pruneStrings.ts",
"build:protos": "bun src/protos.ts" "build:protos": "bun src/protos.ts",
"patchnotes": "bun src/patchNotes.ts"
}, },
"type": "module" "type": "module"
} }
+314
View File
@@ -0,0 +1,314 @@
import {
availableProvisions,
createDefaultProvisions,
createDefaultSkills,
fetchConsumableDefinitions,
fetchEquipmentDefinitions,
fetchModelDefinitions,
fetchProvisionDefinitions,
fetchSkillDefinitions,
fetchTankDefinitions,
TankDefinition,
tankIcon,
} from "@blitzkit/core";
import { checkConsumableProvisionInclusivity } from "@blitzkit/core/src/blitzkit/checkConsumableProvisionInclusivity";
import strings from "@blitzkit/i18n/strings/en.json";
import { writeFile } from "fs/promises";
import { isEqual } from "lodash-es";
import { tankCharacteristics } from "../../website/src/core/blitzkit/tankCharacteristics";
import { genericDefaultEquipmentMatrix } from "../../website/src/stores/duel/constants";
const domain = "https://opentest.blitzkit.app";
import.meta.env.PUBLIC_ASSET_BASE = "https://blitzkit.github.io/assets";
const currentTankDefinitions = await fetchTankDefinitions();
const currentConsumableDefinitions = await fetchConsumableDefinitions();
const currentProvisionDefinitions = await fetchProvisionDefinitions();
const currentEquipmentDefinitions = await fetchEquipmentDefinitions();
const currentSkillDefinitions = await fetchSkillDefinitions();
const currentModelDefinitions = await fetchModelDefinitions();
import.meta.env.PUBLIC_ASSET_BASE = "https://blitzkit.github.io/assets-preview";
const previewTankDefinitions = await fetchTankDefinitions();
const previewConsumableDefinitions = await fetchConsumableDefinitions();
const previewProvisionDefinitions = await fetchProvisionDefinitions();
const previewEquipmentDefinitions = await fetchEquipmentDefinitions();
const previewSkillDefinitions = await fetchSkillDefinitions();
const previewModelDefinitions = await fetchModelDefinitions();
let notes = "# BlitzKit OpenTest Patch Notes\n\n";
const newTanks: TankDefinition[] = [];
for (const id in previewTankDefinitions.tanks) {
if (!(id in currentTankDefinitions.tanks)) {
newTanks.push(previewTankDefinitions.tanks[id]);
}
}
newTanks.sort((a, b) => b.tier - a.tier);
import.meta.env.PUBLIC_ASSET_BASE = "https://blitzkit.github.io/assets-preview";
if (newTanks.length > 0) {
notes += "## New Tanks\n\n";
for (const tank of newTanks) {
notes += `### [${tank.name.locales.en}](${domain}/tanks/${tank.slug})\n`;
notes += `![](${tankIcon(tank.id)})\n\n`;
}
notes += "\n";
}
const changedTanks: [TankDefinition, TankDefinition][] = [];
for (const stringId in previewTankDefinitions.tanks) {
const id = Number(stringId);
if (newTanks.some((tank) => tank.id === id)) continue;
const current = currentTankDefinitions.tanks[id];
const preview = previewTankDefinitions.tanks[id];
if (isEqual(current, preview)) continue;
changedTanks.push([current, preview]);
}
changedTanks.sort((a, b) => b[1].tier - a[1].tier);
import.meta.env.PUBLIC_ASSET_BASE = "https://blitzkit.github.io/assets";
if (changedTanks.length > 0) {
notes += "## Changed Tanks\n\n";
for (const [current, preview] of changedTanks) {
const currentTurret = current.turrets.at(-1)!;
const previewTurret = preview.turrets.at(-1)!;
const currentGun = currentTurret.guns.at(-1)!;
const previewGun = previewTurret.guns.at(-1)!;
const currentShell = currentGun.shells[0];
const previewShell = previewGun.shells[0];
const currentEngine = current.engines.at(-1)!;
const previewEngine = preview.engines.at(-1)!;
const currentTracks = current.tracks.at(-1)!;
const previewTracks = preview.tracks.at(-1)!;
const currentTankModel = currentModelDefinitions.models[current.id];
const previewTankModel = previewModelDefinitions.models[preview.id];
const currentConsumables = Object.values(
currentConsumableDefinitions.consumables
).filter((consumable) =>
checkConsumableProvisionInclusivity(consumable, current, currentGun)
);
const previewConsumables = Object.values(
previewConsumableDefinitions.consumables
).filter((consumable) =>
checkConsumableProvisionInclusivity(consumable, preview, previewGun)
);
const addedConsumables = previewConsumables.filter(
(previewConsumable) =>
!currentConsumables.some(
(currentConsumable) => currentConsumable.id === previewConsumable.id
)
);
const removedConsumables = currentConsumables.filter(
(currentConsumable) =>
!previewConsumables.some(
(previewConsumable) => previewConsumable.id === currentConsumable.id
)
);
const currentProvisions = availableProvisions(
current,
currentGun,
currentProvisionDefinitions
);
const previewProvisions = availableProvisions(
preview,
previewGun,
previewProvisionDefinitions
);
const addedProvisions = previewProvisions.filter(
(previewProvision) =>
!currentProvisions.some(
(currentProvision) => currentProvision.id === previewProvision.id
)
);
const removedProvisions = currentProvisions.filter(
(currentProvision) =>
!previewProvisions.some(
(previewProvision) => previewProvision.id === currentProvision.id
)
);
const currentEquipment = currentEquipmentDefinitions.presets[
current.equipment_preset
].slots
.map(({ left, right }) => [left, right])
.flat();
const previewEquipment = previewEquipmentDefinitions.presets[
preview.equipment_preset
].slots
.map(({ left, right }) => [left, right])
.flat();
const addedEquipment = previewEquipment
.filter(
(previewEquipment) =>
!currentEquipment.some(
(currentEquipment) => currentEquipment === previewEquipment
)
)
.map((id) => previewEquipmentDefinitions.equipments[id]);
const removedEquipment = currentEquipment
.filter(
(currentEquipment) =>
!previewEquipment.some(
(previewEquipment) => previewEquipment === currentEquipment
)
)
.map((id) => currentEquipmentDefinitions.equipments[id]);
const currentCharacteristics = tankCharacteristics(
{
tank: current,
gun: currentGun,
shell: currentShell,
applyDynamicArmor: false,
applyReactiveArmor: false,
applySpallLiner: false,
assaultDistance: 0,
crewSkills: createDefaultSkills(currentSkillDefinitions),
camouflage: true,
consumables: [],
engine: currentEngine,
provisions: createDefaultProvisions(
current,
currentGun,
currentProvisionDefinitions
),
equipmentMatrix: genericDefaultEquipmentMatrix,
stockEngine: current.engines[0],
stockGun: current.turrets[0].guns[0],
stockTrack: current.tracks[0],
stockTurret: current.turrets[0],
track: currentTracks,
turret: currentTurret,
},
{
equipmentDefinitions: currentEquipmentDefinitions,
provisionDefinitions: currentProvisionDefinitions,
tankModelDefinition: currentTankModel,
}
);
const previewCharacteristics = tankCharacteristics(
{
tank: preview,
gun: previewGun,
shell: previewShell,
applyDynamicArmor: false,
applyReactiveArmor: false,
applySpallLiner: false,
assaultDistance: 0,
crewSkills: createDefaultSkills(previewSkillDefinitions),
camouflage: true,
consumables: [],
engine: previewEngine,
provisions: createDefaultProvisions(
preview,
previewGun,
previewProvisionDefinitions
),
equipmentMatrix: genericDefaultEquipmentMatrix,
stockEngine: preview.engines[0],
stockGun: preview.turrets[0].guns[0],
stockTrack: preview.tracks[0],
stockTurret: preview.turrets[0],
track: previewTracks,
turret: previewTurret,
},
{
equipmentDefinitions: previewEquipmentDefinitions,
provisionDefinitions: previewProvisionDefinitions,
tankModelDefinition: previewTankModel,
}
);
const changedCharacteristics: string[] = [];
for (const key in currentCharacteristics) {
const characteristicKey = key as keyof typeof currentCharacteristics;
if (
currentCharacteristics[characteristicKey] !==
previewCharacteristics[characteristicKey]
) {
changedCharacteristics.push(characteristicKey);
}
}
notes += `### [${preview.name.locales.en}](${domain}/tanks/${preview.slug})\n`;
notes += `![](${tankIcon(preview.id)})\n\n`;
if (addedConsumables.length + removedConsumables.length > 0) {
notes += `Consumables: `;
notes += [
...addedConsumables.map(
(consumable) => `🟢 ${consumable.name.locales.en}`
),
...removedConsumables.map(
(consumable) => `🔴 ${consumable.name.locales.en}`
),
].join(", ");
notes += `\n`;
}
if (addedProvisions.length + removedProvisions.length > 0) {
notes += `Provisions: `;
notes += [
...addedProvisions.map(
(provision) => `🟢 ${provision.name.locales.en}`
),
...removedProvisions.map(
(provision) => `🔴 ${provision.name.locales.en}`
),
].join(", ");
notes += `\n`;
}
if (addedEquipment.length + removedEquipment.length > 0) {
notes += `-Equipment: `;
notes += [
...addedEquipment.map((equipment) => `🟢 ${equipment.name.locales.en}`),
...removedEquipment.map(
(equipment) => `🔴 ${equipment.name.locales.en}`
),
].join(", ");
notes += `\n`;
}
if (changedCharacteristics.length > 0) {
notes += `Characteristics:\n`;
for (const characteristicUntyped of changedCharacteristics) {
const characteristic =
characteristicUntyped as keyof typeof currentCharacteristics;
const name =
strings.website.tools.tankopedia.characteristics.values[
characteristic
];
const before = currentCharacteristics[characteristic];
const after = previewCharacteristics[characteristic];
notes += `- ${
typeof before === "number" && typeof after === "number"
? after > before
? "⬆️"
: "🔻"
: "✏️"
} ${name}: \`${
typeof before === "number" ? before.toFixed(2) : before
}\` → \`${typeof after === "number" ? after.toFixed(2) : after}\`\n`;
}
}
}
}
await writeFile("../../temp/patch-notes.md", notes);
+2 -2
View File
@@ -14,7 +14,7 @@ const exec = promisify(execSync);
let executableFileExtension: string; let executableFileExtension: string;
if (existsSync("node_modules/.bin/protoc-gen-ts_proto.exe")) { if (existsSync("../../node_modules/.bin/protoc-gen-ts_proto.exe")) {
executableFileExtension = ".exe"; executableFileExtension = ".exe";
} else { } else {
executableFileExtension = ""; executableFileExtension = "";
@@ -32,7 +32,7 @@ for (const root of roots) {
while (files.length > 0) { while (files.length > 0) {
let command = [ let command = [
"protoc", "protoc",
`--plugin=./node_modules/.bin/protoc-gen-ts_proto${executableFileExtension}`, `--plugin=../../node_modules/.bin/protoc-gen-ts_proto${executableFileExtension}`,
"--ts_proto_opt=esModuleInterop=true", "--ts_proto_opt=esModuleInterop=true",
"--ts_proto_opt=oneof=unions-value", "--ts_proto_opt=oneof=unions-value",
// "--ts_proto_opt=removeEnumPrefix=true", // "--ts_proto_opt=removeEnumPrefix=true",
+1 -1
View File
@@ -70,7 +70,7 @@ for (const tank of tanksSanitized) {
), ),
}; };
console.log(`${++done} done; found ${items.length} for ${tank.name}`); console.log(`${++done} done; found ${items.length} for ${tank.name.locales.en}`);
await new Promise((resolve) => setTimeout(resolve, 1000 / 5)); await new Promise((resolve) => setTimeout(resolve, 1000 / 5));
} catch (error) { } catch (error) {
@@ -65,8 +65,6 @@ export function Lighting() {
] as const; ] as const;
const color = new Color(); const color = new Color();
if (isHalloween()) color.set(1, 0, 0);
return ( return (
<HelpingSpotLight <HelpingSpotLight
key={index} key={index}
@@ -1,4 +1,5 @@
export function isHalloween() { export function isHalloween() {
const data = new Date(); const data = new Date();
return false;
return data.getMonth() === 9 && data.getDate() === 31; return data.getMonth() === 9 && data.getDate() === 31;
} }