Barrier: dynamic and non-literal translation keys
The wall
Static analysis can only prove keys that appear as string literals in source (e.g. t('foo.bar')). Anything else is unknown at analysis time:
t(user.role + '.label')t(`prefix.${id}`)with${…}- Keys loaded from JSON, CMS, or env at runtime
If we pretended those were static, we would delete real keys, mark false positives, or ship broken i18n. That destroys trust.
What we automated
- Heuristic detection (
packages/cli/src/core/extractor/dynamic/, orchestrated viapackages/cli/src/core/extractor/dynamic/orchestrate.ts): per-file scan (extension-only: TS/JS-like sources); flag when the first argument is not a simple'…'/"…"string. Comment regions (//, block comments) are detected so sites inside comments can be labeledcommented. - Skip false positives such as
function t(declarations (wrapper definitions), so we do not warn on your helper’s signature. - Single pipeline for commands:
validateusesscanProjectDynamicKeySites(rich paths/lines);syncuses the same helper for warnings.analyzeDynamicKeysFromSourceTextremains for merged-text / programmatic use without per-file paths. validate --json: includes adynamicblock (count + capped site list) for scripts and CI.
What we report to the user (human mode)
- Warnings, not errors — dynamic usage does not fail
validateby itself. - Short preview snippets so developers can jump to the call site and fix, ignore, or add keys manually.
What the user must handle manually
- Design: prefer static keys, key maps, or enums for anything safety-critical.
- Runtime: ensure dynamic paths still exist in locale JSON (the tool cannot enumerate them).
- Review: use warnings as a checklist, not an auto-fix.
Non-interactive modes (CI, --json, no TTY)
- Dynamic keys do not trigger prompts — there is nothing to “pick”; we only emit data (
--json) or print warnings (human). - Ambiguity is for config files, not dynamic keys: multiple
i18nprune.config.*files without--configwill exit 1 in non-interactive environments (see config docs).
Mental model
We detect and disclose; we do not guess keys.
That keeps the tool honest and puts control with the developer for anything runtime-built.