Extracting Translation Keys with i18next-parser

Automating String Extraction for Modern i18n Pipelines

Automating the extraction of translation strings is a foundational requirement for scalable Translation Workflows & CI/CD Pipeline Sync. This guide provides a deterministic configuration strategy for i18next-parser, ensuring consistent key generation, namespace isolation, and seamless handoff to localization infrastructure. By treating extraction as a deterministic build step rather than a manual chore, engineering teams guarantee catalog integrity across distributed codebases.

The Manual Extraction Bottleneck

Relying on manual key registration introduces orphaned strings, inconsistent context metadata, and catalog drift across environments. Without an automated AST-based scanner, engineering velocity degrades and localization managers struggle to maintain parity in distributed repositories, ultimately delaying deployment cycles for Weblate Self-Hosted Setup. Automated extraction eliminates human error in key naming conventions and provides a reliable audit trail for every localized string.

Parser Architecture & Deterministic Merge Strategy

i18next-parser operates by traversing the Abstract Syntax Tree (AST) of source files, identifying t() and useTranslation() calls, and extracting static keys with optional context. The architecture enforces a strict merge pipeline: scan → extract → sort → merge → validate.

This deterministic approach prevents overwriting existing translations while flagging newly discovered keys for immediate review. The parser respects existing {{lng}}/{{ns}}.json catalogs, applying a diff-based merge strategy that preserves translator work while injecting new keys with a configurable placeholder value.

Framework-Specific Configuration

Production deployments require explicit lexer routing to handle framework-specific syntax. Below are hardened configurations for modern frontend stacks.

React / Next.js (JSX/TSX)

// i18next-parser.config.js
module.exports = {
 contextSeparator: '_',
 keySeparator: '.',
 defaultNs: 'translation',
 defaultValue: '__STRING_NOT_TRANSLATED__',
 output: 'locales/{{lng}}/{{ns}}.json',
 input: ['src/**/*.{js,jsx,ts,tsx}'],
 lexers: {
 js: ['JavascriptLexer'],
 jsx: ['JsxLexer'],
 ts: ['JavascriptLexer'],
 tsx: ['JsxLexer']
 },
 sort: true,
 createOldCatalogs: false
};

Implementation Notes:

  • Explicitly map .tsx files to JsxLexer to capture interpolated variables, dynamic attributes, and component-level t() calls.
  • Set sort: false during local feature development to preserve commit history readability and reduce diff noise. Re-enable sort: true in CI/CD pipelines to enforce canonical key ordering.
  • Use createOldCatalogs: false to prevent legacy key accumulation; rely on your translation management system (TMS) to handle key deprecation.

Vue 3 (Single File Components)

// i18next-parser.config.js
module.exports = {
 contextSeparator: '_',
 keySeparator: '.',
 defaultNs: 'translation',
 defaultValue: '__STRING_NOT_TRANSLATED__',
 output: 'locales/{{lng}}/{{ns}}.json',
 input: ['src/**/*.{vue,js,ts}'],
 lexers: {
 vue: ['VueLexer'],
 js: ['JavascriptLexer'],
 ts: ['JavascriptLexer']
 },
 vueOptions: {
 template: ['VueLexer'],
 script: ['JavascriptLexer']
 },
 sort: true
};

Implementation Notes:

  • Vue SFCs require dual-lexer routing to parse both <template> interpolation and <script setup> blocks. The vueOptions object ensures the parser correctly isolates template directives from composition API logic.
  • Ensure keySeparator matches your vue-i18n or @intlify/unplugin-vue-i18n configuration to prevent nested object flattening errors during runtime hydration.

Production Debugging & Resolution Steps

1. Enable Verbose AST Traversal

Execute the parser with the --verbose flag to inspect file resolution paths and lexer assignment:

npx i18next-parser --verbose

Resolution: Missing keys typically stem from glob pattern mismatches or unregistered file extensions in the lexers object. Verify input globs against your actual directory structure. If a file type is ignored, explicitly add it to lexers (e.g., mdx: ['JsxLexer']).

2. Resolve Dynamic Key Warnings

The parser cannot safely evaluate runtime expressions like t(`page.${section}`) or t(dynamicKey). It will skip these or output malformed keys. Resolution:

  • Implement customValueTemplate to output explicit placeholder warnings in your JSON catalog:
customValueTemplate: '${defaultValue} [DYNAMIC_KEY_DETECTED]'
  • Refactor dynamic calls to static key arrays or mapping objects:
const keys = ['page.home', 'page.dashboard', 'page.settings'];
const label = t(keys[sectionIndex]);

This guarantees AST visibility and reliable extraction.

3. Prevent Namespace Overlap & Catalog Corruption

Concurrent extraction runs or local cache contamination can corrupt the master JSON catalog, causing duplicate keys or namespace collisions. Resolution:

  • Configure merge and sort flags to run sequentially in your extraction script.
  • Always execute extraction in an isolated CI runner with a clean workspace. Add a pre-extraction cleanup step:
rm -rf locales/en/translation.json.tmp
npx i18next-parser --config i18next-parser.config.js
  • Enforce a strict defaultNs fallback in your i18n initialization to prevent cross-namespace leakage during runtime.

Finalizing the Extraction Workflow

Standardizing extraction rules eliminates manual key drift and establishes a predictable localization cadence. By integrating i18next-parser into pre-commit hooks and CI pipelines, teams guarantee that every feature branch generates translation-ready catalogs. This deterministic approach maintains strict version control, reduces merge conflicts in localization files, and accelerates cross-lingual product delivery without compromising engineering velocity.