From 2d282a3261f16346e42177a6d1b247cdbe232871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Tue, 13 Jan 2026 13:18:55 -0600 Subject: [PATCH] feat: game strings api --- packages/website-ue/src/core/api/abstract.ts | 50 +++++++++++++------ packages/website-ue/src/core/api/server.ts | 26 ++++++++-- .../api/game-strings/[locale]/[group].json.ts | 25 ++++++++++ 3 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 packages/website-ue/src/pages/api/game-strings/[locale]/[group].json.ts diff --git a/packages/website-ue/src/core/api/abstract.ts b/packages/website-ue/src/core/api/abstract.ts index 899967a85..abebe26bf 100644 --- a/packages/website-ue/src/core/api/abstract.ts +++ b/packages/website-ue/src/core/api/abstract.ts @@ -63,29 +63,41 @@ export abstract class AbstractAPI { return this._stringsCache[locale]; } - private _gameStringsCache: Record< - string, - Record> - > = {}; + private _gameStringsCache: Record> = {}; protected abstract _gameStrings( - locale: string, - prefix: string + locale: string ): Promise>; - async gameStrings(locale: string, prefix: string) { + async gameStrings(locale: string) { this.assertLocale(locale); if (this._gameStringsCache[locale] === undefined) { - this._gameStringsCache[locale] = {}; + this._gameStringsCache[locale] = await this._gameStrings(locale); } - if (this._gameStringsCache[locale][prefix] === undefined) { - this._gameStringsCache[locale][prefix] = await this._gameStrings( - locale, - prefix - ); + return this._gameStringsCache[locale]; + } + + private _groupedGameStringsCache: Record< + string, + Record> + > = {}; + protected abstract _groupedGameStrings( + locale: string, + group: string + ): Promise>; + async groupedGameStrings(locale: string, group: string) { + this.assertLocale(locale); + + if (this._groupedGameStringsCache[locale] === undefined) { + this._groupedGameStringsCache[locale] = {}; } - return this._gameStringsCache[locale][prefix]; + if (this._groupedGameStringsCache[locale][group] === undefined) { + this._groupedGameStringsCache[locale][group] = + await this._groupedGameStrings(locale, group); + } + + return this._groupedGameStringsCache[locale][group]; } private _avatarCache: Record = {}; @@ -127,4 +139,14 @@ export abstract class AbstractAPI { return this._backgroundsCache; } + + private _gameStringGroupsCache: string[] | undefined; + protected abstract _gameStringGroups(): Promise; + async gameStringGroups() { + if (this._gameStringGroupsCache === undefined) { + this._gameStringGroupsCache = await this._gameStringGroups(); + } + + return this._gameStringGroupsCache; + } } diff --git a/packages/website-ue/src/core/api/server.ts b/packages/website-ue/src/core/api/server.ts index edf49de35..55a2b23f9 100644 --- a/packages/website-ue/src/core/api/server.ts +++ b/packages/website-ue/src/core/api/server.ts @@ -29,7 +29,7 @@ export class ServerAPI extends AbstractAPI { super(); } - protected async _gameStrings(locale: string, prefix: string) { + protected async _gameStrings(locale: string) { const group = this.metadata.group("ClientConfigsEntity"); if (group.length !== 1) { @@ -98,11 +98,17 @@ export class ServerAPI extends AbstractAPI { ); } + return strings; + } + + protected async _groupedGameStrings(locale: string, group: string) { + const strings = await this.gameStrings(locale); const filtered: Record = {}; for (const key in strings) { - if (key.startsWith(`${prefix}__`)) { - filtered[key] = strings[key]; + if (key.startsWith(`${group}__`)) { + const trimmed = key.substring(group.length + 2); + filtered[trimmed] = strings[key]; } } @@ -124,7 +130,7 @@ export class ServerAPI extends AbstractAPI { protected async _tankList() { const group = this.metadata.group("TankEntity"); const list: TankListEntry[] = []; - const strings = await this.gameStrings("en", "TankEntity"); + const strings = await this.groupedGameStrings("en", "TankEntity"); for (const item of group) { const tankCatalog = item.TankCatalog(); @@ -214,4 +220,16 @@ export class ServerAPI extends AbstractAPI { return { name, stuff_ui, profile_background, sellable }; } + + protected async _gameStringGroups() { + const defaultGameStrings = await this.gameStrings(locales.default); + const groups = new Set(); + + for (const key in defaultGameStrings) { + const [group] = key.split("__"); + groups.add(group); + } + + return Array.from(groups.values()); + } } diff --git a/packages/website-ue/src/pages/api/game-strings/[locale]/[group].json.ts b/packages/website-ue/src/pages/api/game-strings/[locale]/[group].json.ts new file mode 100644 index 000000000..e4ec3459c --- /dev/null +++ b/packages/website-ue/src/pages/api/game-strings/[locale]/[group].json.ts @@ -0,0 +1,25 @@ +import locales from "@blitzkit/i18n/locales.json"; +import type { GetStaticPaths, GetStaticPathsResult } from "astro"; +import { api } from "../../../../core/api/dynamic"; + +export const getStaticPaths = (async () => { + const paths: GetStaticPathsResult = []; + const groups = await api.gameStringGroups(); + + for (const { locale } of locales.supported) { + for (const group of groups) { + paths.push({ params: { locale, group } }); + } + } + + return paths; +}) satisfies GetStaticPaths; + +export async function GET({ + params, +}: { + params: { locale: string; group: string }; +}) { + const strings = await api.groupedGameStrings(params.locale, params.group); + return Response.json(strings); +}