User page in-game badge widget (#2841)
Some checks are pending
E2E Tests / e2e (push) Waiting to run
Tests and checks on push / run-checks-and-tests (push) Waiting to run
Updates translation progress / update-translation-progress-issue (push) Waiting to run

This commit is contained in:
Kalle
2026-02-28 16:52:37 +02:00
committed by GitHub
parent 35fccae6f6
commit 4cc3a9807c
1601 changed files with 27026 additions and 3 deletions

View File

@@ -15,6 +15,71 @@ import {
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const BADGE_DIR = path.join(__dirname, "badge");
const OUTPUT_DIR = path.join(__dirname, "output");
const ALL_LOCALE_FOLDERS = [
"da",
"de",
"en",
"es-ES",
"es-US",
"fr-CA",
"fr-EU",
"he",
"it",
"ja",
"ko",
"nl",
"pl",
"pt-BR",
"ru",
"zh",
];
const BADGE_TEMPLATE_RULES = [
{
prefix: "CoopGrade_Normal_",
templateKey: "CoopGrade_Normal_",
lookupDict: "CommonMsg/Coop/CoopStageName",
},
{
prefix: "CoopGrade_Pair_",
templateKey: "CoopGrade_Normal_",
lookupDict: "CommonMsg/Coop/CoopStageName",
},
{
prefix: "CoopGrade_Underground_",
templateKey: "CoopGrade_Normal_",
lookupDict: "CommonMsg/Coop/CoopStageName",
},
{
prefix: "CoopBossKillNum_",
templateKey: "CoopBossKillNum_",
lookupDict: "CommonMsg/Coop/CoopEnemy",
},
{
prefix: "CoopRareEnemyKillNum_",
templateKey: "CoopRareEnemyKillNum_",
lookupDict: "CommonMsg/Coop/CoopEnemy",
},
{
prefix: "GearTotalRarity_",
templateKey: "GearTotalRarity_",
lookupDict: "CommonMsg/Gear/GearBrandName",
},
{
prefix: "WinCount_WeaponSp_",
templateKey: "WinCount_WeaponSp_",
lookupDict: "CommonMsg/Weapon/WeaponName_Special",
},
{
prefix: "WeaponLevel_",
templateKey: "WeaponLevel_",
lookupDict: "CommonMsg/Weapon/WeaponName_Main",
},
];
// ⚠️ keep same order as https://github.com/IPLSplatoon/IPLMapGen2/blob/main/data.js
const stages = [
"Scorch Gorge",
@@ -147,6 +212,120 @@ async function main() {
`${JSON.stringify({ ...jsonCurrent, ...translationsMap }, null, 2)}\n`,
);
}
generateBadgeData(langDicts);
}
function generateBadgeData(langDicts) {
const badgeFiles = fs
.readdirSync(BADGE_DIR)
.filter((f) => f.endsWith(".png"));
const badgeIds = badgeFiles
.map((f) => f.replace("Badge_", "").replace(".png", ""))
.sort();
const englishDict = langDicts.find(([code]) => code === "EUen")?.[1];
invariant(englishDict, "Missing English language dict");
const englishBadgeTranslations = buildBadgeTranslations(
badgeIds,
englishDict,
);
for (const langCode of LANG_JSONS_TO_CREATE) {
const langDict = langDicts.find(([code]) => code === langCode)?.[1];
invariant(langDict, `Missing translations for ${langCode}`);
const translationsMap = buildBadgeTranslations(badgeIds, langDict);
const folder = translationJsonFolderName(langCode);
writeBadgeJson(folder, translationsMap);
}
for (const folder of ALL_LOCALE_FOLDERS) {
const jsonPath = path.join(
__dirname,
"..",
"locales",
folder,
"game-badges.json",
);
if (fs.existsSync(jsonPath)) continue;
writeBadgeJson(folder, englishBadgeTranslations);
}
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
}
const tsContent = [
"export const GAME_BADGE_IDS = [",
...badgeIds.map((id) => `\t"${id}",`),
"] as const;",
"",
"export type GameBadgeId = (typeof GAME_BADGE_IDS)[number];",
"",
].join("\n");
fs.writeFileSync(path.join(OUTPUT_DIR, "game-badge-ids.ts"), tsContent);
}
function buildBadgeTranslations(badgeIds, langDict) {
const badgeMsg = langDict["CommonMsg/Badge/BadgeMsg"];
const translationsMap = {};
for (const id of badgeIds) {
if (badgeMsg[id] && !badgeMsg[id].includes("[group=")) {
translationsMap[id] = badgeMsg[id];
continue;
}
const lvMatch = id.match(/_Lv(\d+)$/);
if (!lvMatch) {
translationsMap[id] = badgeMsg[id] ?? id;
continue;
}
const lvSuffix = `Lv${lvMatch[1]}`;
const rule = BADGE_TEMPLATE_RULES.find((r) => id.startsWith(r.prefix));
if (!rule) {
translationsMap[id] = badgeMsg[id] ?? id;
continue;
}
const variantName = id
.slice(rule.prefix.length)
.replace(`_${lvSuffix}`, "");
const templateKey = `${rule.templateKey}${lvSuffix}`;
const template = badgeMsg[templateKey];
if (!template) {
translationsMap[id] = id;
continue;
}
const lookupValue = langDict[rule.lookupDict]?.[variantName];
if (!lookupValue) {
translationsMap[id] = id;
continue;
}
translationsMap[id] = template.replace(
/\[group=\d+ type=\w+ params=[\w ]+\]/,
lookupValue,
);
}
return translationsMap;
}
function writeBadgeJson(folder, translationsMap) {
fs.writeFileSync(
path.join(__dirname, "..", "locales", folder, "game-badges.json"),
`${JSON.stringify(translationsMap, null, 2)}\n`,
);
}
void main();