Per-file const maps for template / static keys
Problem
Translation calls often use template strings with placeholders, e.g. t(`foo.${NS}.bar`). To decide whether a key is fully static, the tool substitutes placeholders from a const map (identifiers → string values).
If the project is scanned as one merged blob with a single map built from all files merged together, two different files could each define const NS = 'a' and const NS = 'b'. A merged map can only keep one value for NS, so rebuilds and “resolved” keys can be wrong: false positives, wrong prefixes, or keys attributed to the wrong file.
What we do
Production paths walk each source file separately:
-
scanProjectKeyObservations(packages/cli/src/core/extractor/keySites/orchestrate.ts)
For each file: read contents →buildConstStringMap(content)for that file only →scanKeyObservations(..., constMap)→ attachfilePathto spans. -
scanProjectLiteralKeyUsage(packages/cli/src/core/extractor/keySites/projectUsage.ts)
Delegates toliteralKeyUsageFromObservations(scanProjectKeyObservations(ctx)), so usage sets and uncertain prefixes use the same per-file resolution. -
scanProjectDynamicKeySites(packages/cli/src/core/extractor/dynamic/orchestrate.ts)
For each file:findDynamicKeySitesForFile→ inside the JS provider,buildConstStringMap(text)again per file (findDynamicKeySitesInJavascriptFile).
validate, cleanup (via buildKeyReferenceContext → scanProjectLiteralKeyUsage + dynamic scan), sync, fill, and related commands all rely on these orchestrators, not a single global const map across the tree.
When merged text is still used
analyzeDynamicKeysFromSourceText (merged string) exists for callers that already have concatenated source (e.g. tests). It does not apply per-file const maps or cross-file comment suppression. Prefer scanProjectDynamicKeySites(ctx) for real projects.
See also
- ADR 005: Dynamic key rebuild & prefix
- JSON output spec (merged-text caveat)
- Key sites & dynamic