UNPKG

endfield-mcp

Version:

MCP Server for Arknights: Endfield (TypeScript / stdio + Streamable HTTP)

87 lines (86 loc) • 4.07 kB
/** * Localization (i18n) resolution layer. * * Endfield separates values from strings: most tables store `{id, text}` * objects where `text` is empty and `id` is an int64 hash. The actual * string lives in `I18nTextTable_<LANG>.json` under that hash, and looks * like `{"key": "-7078064683023630592", "value": "管理员"}`. * * This module owns that lookup. It lazily loads one or more language * tables (default CN), builds an in-memory `Map<string, string>` index, * and exposes `resolveText()` for readers to call without knowing which * language is active. * * ## Key format * * I18n keys are stored as strings in the upstream JSON even though they * look like int64 numbers. JS `number` can't represent int64 exactly * (Number.MAX_SAFE_INTEGER is 2^53-1), so we keep them as strings * end-to-end. The `{id, text}` objects in game tables also store `id` * as a number, so callers convert via `String(loc.id)` before resolving. */ import { SUPPORTED_LANGUAGES } from "./datasets.js"; import type { JsonStore } from "./stores.js"; /** * The `{id, text}` shape embedded in nearly every Endfield table. * * `id` is a string, not a number: Endfield's localization ids are int64 * hashes that exceed JS Number.MAX_SAFE_INTEGER, so tables must be parsed * with `JsonStore.readJsonInt64Safe()` (which wraps large integer literals * in quotes). `text` is conventionally empty upstream; the real string is * keyed by `id` in the i18n table. */ export interface LocalizedText { id: string; text: string; } /** Supported language codes (CN, EN, JP, TC, KR). */ export type LanguageCode = (typeof SUPPORTED_LANGUAGES)[number]; export declare function bindTextStore(store: JsonStore): void; /** * Set the default language used when `resolveText()` is called without an * explicit language. Must be one of SUPPORTED_LANGUAGES. */ export declare function setDefaultLanguage(lang: string): void; export declare function getDefaultLanguage(): LanguageCode; /** Drop all loaded language indices. Called by startupSync after refresh. */ export declare function clearTextCaches(): void; /** * Load (and cache) one language's i18n index. * * The i18n file is a flat object: `{ "-7078064683023630592": "管理员", ... }`. * Keys are int64 hash values stored as strings (because JS number can't * represent int64 exactly — see notes on CharacterTable id handling). * Values are the localized strings. * * We build an in-memory `Map<string, string>` eagerly on first access. * With ~50k entries per language this takes a few hundred ms — acceptable * because it happens once per language per process lifetime. */ export declare function loadLanguageIndex(lang: LanguageCode): Map<string, string>; /** * Resolve a `{id, text}` object to an actual string. * * Behaviour: * - If `text` is non-empty, return it directly (some tables pre-fill it). * - Otherwise look up `String(id)` in the requested (or default) language. * - On miss, return the fallback string (default: the id itself, so the * caller can see something went wrong without a crash). * * Callers pass an explicit `lang` only when they need a non-default * language (e.g. a future "get this in English" tool option). The vast * majority of reads use the process default. */ export declare function resolveText(loc: LocalizedText | undefined | null, lang?: LanguageCode, fallback?: string): string; /** * Resolve in a specific language, returning null on miss (vs resolveText * which returns a fallback). Used when callers want to distinguish * "found" from "not found" without ambiguity. */ export declare function tryResolveText(loc: LocalizedText | undefined | null, lang: LanguageCode): string | null; /** * Convenience: resolve the same localization across all supported * languages. Returns `{CN: "...", EN: "...", ...}` with null for misses. * Useful for tools that want to show multilingual names at once. */ export declare function resolveTextAllLanguages(loc: LocalizedText | undefined | null): Record<LanguageCode, string | null>;