{"record":{"id":"810c553611994ec4","repo":"BigPizzaV3/CodexPlusPlus","slug":"could-not-find-varname-in-i18n-en-ts","errorCode":null,"errorMessage":"Could not find ${varName} in i18n-en.ts","messagePattern":"Could not find (.+?) in i18n-en\\.ts","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"tools/i18n-verify.mjs","lineNumber":62,"sourceCode":"        // tr 是 vlm-test-translation.ts 注入的翻译回调：1 参->plain，2 参->template。\n        if (fn === \"t\" || (fn === \"tr\" && node.arguments.length === 1)) usedPlain.add(literal);\n        else if (fn === \"tf\" || (fn === \"tr\" && node.arguments.length >= 2)) usedTemplate.add(literal);\n      }\n    }\n    ts.forEachChild(node, visit);\n  };\n  visit(sf);\n}\n\nfor (const f of SRC_FILES) scanFile(f);\n\n// ── Read the dictionary keys out of i18n-en.ts. ─────────────────────────────\nconst dictSource = readFileSync(path.join(appRoot, \"src\", \"i18n-en.ts\"), \"utf8\");\n\nfunction recordKeys(varName) {\n  const re = new RegExp(`export const ${varName}\\\\s*:\\\\s*Record<string,\\\\s*string>\\\\s*=\\\\s*\\\\{`);\n  const match = re.exec(dictSource);\n  if (!match) throw new Error(`Could not find ${varName} in i18n-en.ts`);\n  const start = match.index + match[0].length - 1; // position of \"{\"\n  let depth = 0;\n  let i = start;\n  let inStr = null;\n  let escaped = false;\n  for (; i < dictSource.length; i++) {\n    const ch = dictSource[i];\n    if (inStr) {\n      if (escaped) escaped = false;\n      else if (ch === \"\\\\\") escaped = true;\n      else if (ch === inStr) inStr = null;\n      continue;\n    }\n    if (ch === '\"' || ch === \"'\" || ch === \"`\") inStr = ch;\n    else if (ch === \"{\") depth++;\n    else if (ch === \"}\") {\n      depth--;\n      if (depth === 0) { i++; break; }","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/tools/i18n-verify.mjs#L44-L80","documentation":"tools/i18n-verify.mjs reads src/i18n-en.ts and locates each exported dictionary via a regex `export const ${varName}: Record<string, string> = {`. If the regex doesn't match, it throws `Could not find ${varName} in i18n-en.ts`, meaning the expected exported Record declaration is absent or formatted differently.","triggerScenarios":"recordKeys('MESSAGES') (or another varName) run against an i18n-en.ts that lacks `export const MESSAGES: Record<string, string> = {` — the dict was renamed, moved to another file, typed differently (e.g. `satisfies Record<...>`), or formatted with different spacing/line breaks the regex can't span.","commonSituations":"Refactoring i18n-en.ts to use a different type annotation or `as const`; renaming the export; splitting dictionaries into multiple files while the verify script still expects them in i18n-en.ts; prettier reformatting that breaks the single-line pattern.","solutions":["Ensure i18n-en.ts contains `export const <varName>: Record<string, string> = {` exactly for each varName the script checks","Update recordKeys' regex (or the script's varName list) to match the new declaration style or file","If the type changed (e.g. satisfies/as const), relax the regex to accept it","Verify the script's appRoot points at the app whose src/i18n-en.ts you edited"],"exampleFix":"// before\nexport const MESSAGES = { ... } satisfies Record<string, string>;\n// after\nexport const MESSAGES: Record<string, string> = { ... };","handlingStrategy":"try-catch","validationCode":"if (!/export const MESSAGES\\s*:\\s*Record<string,\\s*string>\\s*=\\s*\\{/.test(dictSource)) throw new Error('MESSAGES declaration not found in i18n-en.ts');","typeGuard":null,"tryCatchPattern":"try { const keys = recordKeys('MESSAGES'); } catch (e) { if (String(e.message).startsWith('Could not find')) { console.error('i18n dict missing/renamed:', e.message); process.exit(1); } throw e; }","preventionTips":["Keep the exported `: Record<string, string> = {` annotation style when editing i18n-en.ts","Update i18n-verify.mjs whenever dictionary names, files, or type annotations change","Run the i18n verify script in CI to catch renames early"],"tags":["tooling","i18n","regex","typescript"],"backgroundTag":"resource-not-found","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}