UNPKG

i18ntk

Version:

i18n Tool Kit - Zero-dependency internationalization toolkit for setup, scanning, analysis, validation, auto translation, fixing, reporting, and runtime translation loading.

492 lines (367 loc) 84.2 kB
# CHANGELOG All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [4.7.3] - 2026-07-07 ### Fixed - **PUBLISH INTEGRITY:** `utils/language-menu.js` and `utils/promptPin.js` were missing from the `files` array in `package.json`, causing `MODULE_NOT_FOUND` on install. Both added to `files` array in `package.json` and `package.public.json`. - **4.7.2 deprecated** — published with the missing-module bug. All users should upgrade to 4.7.3. - **Publish integrity test:** New `tests/publish-integrity.test.js` validates every production `require()` resolves to a file listed in the `files` array. Prevents future missing-module regressions. ## [4.7.2] - 2026-07-07 ### FIXED - **Dynamic CLI language selector** — Option 12 now derives available languages and native display names from `SettingsManager.getAvailableLanguages()` instead of stale hardcoded 7-language lists. - **Future-proof prompt range** — Language selection prompts now render the numeric upper bound from the current available language count, so future UI locale expansion does not leave stale `0-8` prompt text behind. - **Fallback manager parity** — `main/manage/index.js` now instantiates `SettingsManager`, shows the real current UI language, persists `language` and `uiLanguage`, and uses the same 23-language registry as the rest of the CLI. ## [4.7.1] - 2026-07-07 ### Added - **23 UI locale languages** — Expanded from 7 to 23: Italian, Portuguese, Dutch, Polish, Swedish, Ukrainian, Czech, Turkish, Korean, Arabic, Hindi, Thai, Vietnamese, Hebrew, Greek, Hungarian. All 2,211 keys auto-translated with placeholder preservation via i18ntk's own pipeline. 95-98% translation completeness, 0 missing keys. - **Native language names** — `settings.languages.{code}` entries added to all 23 locale files with names in native script (Italiano, 日本語, العربية, हिन्दी, etc.). `getAvailableLanguages()` returns all 23 with display names. - **Settings schema expanded** — `language` and `uiLanguage` enum constraints expanded from 7 to 23 entries. Language selector in settings UI and CLI picks up all available languages. ### Changed - **Framework detection centralized** — `manage/index.js` `detectEnvironmentAndFramework()` now calls `detectProjectFramework()` from the centralized detector instead of a 6-framework inline check. Detects all 30+ supported frameworks. - **Hardcoded `framework.supported` removed** — Config templates (`config-manager.js`) and runtime config (`.i18ntk-config`) no longer ship a static framework list. Only actually-detected frameworks appear. - **`checkI18nDependencies()` expanded** — Framework package lists unified across `manage/index.js`, `i18ntk-manage.js`, `InitService.js`, and `FrameworkDetectionService.js` (8→29 entries each). - **Hardcoded 7-language lists expanded to 23** — Updated in 12 production files: `i18n-usage.js`, `i18n-validate.js`, `ValidateCommand.js`, `UsageService.js`, `FrameworkDetectionService.js`, `ConfigurationService.js`, `i18ntk-manage.js`, `locale-optimizer.js` ×2, `env-manager.js`, `i18ntk-ui.js`, `manage/index.js`. - **Default config template expanded** — `config-helper.js` `supportedLanguages` and template skeleton files expanded from 8 to 23 languages. - **Missing key validator** — Default constructor argument expanded from 7 to 23 languages. - **Version bumped to 4.7.1** for language expansion and framework detection cleanup. ### Verified - Language switching tested via `i18n-helper.loadTranslations()` across all 23 locales — all return non-English values. - 69 core tests pass, 98 sandbox tests pass. - Package JSON manifest sync test passes (version, versionInfo, nextVersion aligned). - All 23 locale files have valid JSON syntax. ## [4.7.0] - 2026-07-07 ### Added - **13 new FRAMEWORK_PATTERNS:** `i18ntk-runtime` (hooks, `<t>` component), `nuxt` (`$tc()`, `localePath()`), `lingui` (`<Translate>` component), `formatjs` (`<FormattedMessage>`), `ngx-translate` (pipe, service patterns), `next-intl`, `svelte-i18n`, `solid-i18n` (`<Translate>`), `fastapi`, `ruby-on-rails` (`I18n.t/l/translate`), `react-native-localize`, `ionic`. Each has framework-specific scanning regex patterns. - **8 missing FRAMEWORK_COMPATIBILITY entries:** `nuxt`, `nuxt-i18n`, `next-intl`, `ngx-translate`, `svelte-i18n`, `solid-i18n`, `expo`, `vanilla` with min versions. - **Non-Node project detection:** `detectFramework()` now checks Python (`requirements.txt`, `pyproject.toml`, `setup.py`), Rust (`Cargo.toml`), Go (`go.mod`), Ruby (`Gemfile`) when no `package.json` exists. Detects Django, Flask, FastAPI, Rails, and generic i18n usage. - **20+ new WRAPPER_SKIP_PATTERNS:** `I18n.t(`, `I18n.translate(`, `useTranslate(`, `t.get(`, `$tc(`, `translateService.instant(`, `formatMessage(`, `bundle.get_message(`, `i18n.NewMessage(`, `_(`, `fluent!`, `ts!` and more. - **Expanded KNOWN_WRAPPERS in Lens scanner:** Added `$_`, `$tc`, `gettext`, `gettext_lazy`, `I18n.t`, `I18n.translate`, `I18n.l`, `I18n.localize`. - **Expanded NAMESPACE_HELPERS in both scanners:** Added `useTranslate`, `useSpeak`, `withTranslation`. - **Framework-aware report-model.js:** `scanSourceFiles()` accepts optional framework parameter, uses `getFrameworkPatterns()` for framework-specific key extraction. - **Expanded CLI init framework list:** `checkI18nDependencies()` now scans 27+ npm package names instead of 7. - **Sandbox test suite:** 98 new tests covering framework detection against real package.json, requirements.txt, Cargo.toml, go.mod, Gemfile fixtures. Coverage validation for all FRAMEWORK_PATTERNS, FRAMEWORK_SUGGESTIONS, FRAMEWORK_COMPATIBILITY, WRAPPER_SKIP_PATTERNS, and SCANNER_EXTENSIONS. ### Changed - **Version bumped to 4.7.0** for the comprehensive framework detection expansion. - **detectFramework()** no longer returns `null` when only non-Node project files are present. Cascades through 5 detection phases: Node → Python → Rust → Go → Ruby. ## [4.6.1] - 2026-07-05 ### Fixed - **LANGUAGE_CONFIG missing 22+ languages:** `i18ntk-init.js` and `InitService.js` expanded from 21 to 61 languages with native names. All common ISO 639-1 codes now display proper names instead of "Unknown". - **Init silently truncating defaultLanguages:** When `defaultLanguages` is an empty array or `null`, init no longer silently falls back to 5 languages. - **Auto Translate exiting non-zero on success:** Residual untranslated values (placeholders, branded terms) no longer cause non-zero exit codes. Only real failures produce exit 1. - **supportedExtensions silently overridden:** `i18ntk-init.js` no longer unconditionally overrides `supportedExtensions` from config with the format adapter's single extension. - **allowedEnglishTerms in two places:** `validation-risk.js` now exports `resolveAllowedEnglishTerms()` which accepts both per-call options and project-level config terms as fallback sources. ## [4.6.0] - 2026-07-04 ### Added - **Framework Detection (10 new frameworks):** Added Rust (fluent, gettext-rs), Remix (remix-i18next), Gatsby (gatsby-plugin-react-i18next), Astro (astro-i18next, @astrojs/i18n), Qwik (qwik-speak, qwik-i18n), SolidJS (@solid-primitives/i18n), Ember (ember-intl), React Native (react-native-localize), Expo (expo-localization), and Ionic (ionic-angular/react/vue) to `utils/framework-detector.js`. - **FRAMEWORK_COMPATIBILITY:** Extended compatibility metadata with Rust, Fluent, Remix, Gatsby, Astro, Qwik, Ember, React Native, and Ionic version requirements. - **Rust/Cargo.toml detection:** `FrameworkDetectionService` now detects Rust projects via `Cargo.toml`. Supports `fluent`, `gettext-rs`, and generic Rust framework types. - **JSX Component Detection (Workbench & Lens):** Added `findJsxComponentKeys()` to both `keyDetector.ts` (Workbench) and `scanner.ts` (Lens) for detecting `<Trans i18nKey>`, `<FormattedMessage id>`, `<FormattedMessage defaultMessage>`, `<t message>`, and `<Translate id>` JSX components. - **ICU/Fluent placeholder support:** Added `$variable` (Fluent), `{var, plural, ...}`, `{var, select, ...}`, `{var, number}`, and `{var, date}` ICU MessageFormat patterns to `extractPlaceholders()` with overlap deduplication and token length safety. - **Framework-specific exclude defaults:** Added `.nuxt`, `.output`, `.astro`, `.svelte-kit`, `.cache`, `__generated__`, and `target` to default exclude lists in all scanners and configs. - **Framework-specific locale discovery paths:** Added `app/i18n`, `src/lib/i18n`, `content/locales`, `messages`, and `lang` to locale directory candidates. - **Framework-specific activation events:** Workbench and Lens now activate on Next.js, Astro, Remix, Svelte, Nuxt, Gatsby config files and Cargo.toml. - **Translation Grid:** Added `messages` and `lang` filename patterns to the custom editor selectors. - **Framework suggestions:** Expanded `getFrameworkSuggestions()` in FrameworkDetectionService with all newly supported frameworks by language. ### Changed - **File extensions (all packages):** Added `.astro`, `.mdx`, `.mjs`, `.mts`, `.cjs`, `.cts`, `.rs` to `SOURCE_EXTENSIONS` in all scanners and file-walk functions. Astro single-file components, ESM modules, and Rust source files are now scanned for translation keys. - **Document selectors (Workbench & Lens):** Added `astro` language ID and extended pattern globs to include `mjs,mts,cjs,cts,astro,html`. - **Locate discovery excludes:** Added `.nuxt`, `.output`, `.astro`, `.svelte-kit`, `.cache`, `__generated__`, `target` to `DISCOVERY_EXCLUDES`. - **Config-helper:** Extended `supportedExtensions` to match new file types; excludeDirs now includes all framework-specific directories. - **Framework detection expansion (FrameworkDetectionService):** JS framework detection expanded from 7 to 15+ frameworks. `checkI18nDependencies()` i18n framework list expanded from 8 to 26 entries covering all new frameworks. - **Health score:** Penalty is now capped at `(totalKeys - 1) * 2` and uses a linear decay curve (`40%` max) to prevent negative or zero scores on small key sets with many issues. - **Test output:** manifest-sync test updated to match new 4.6.0 versionInfo. ### Fixed - **Dot/snake key style validation:** The hybrid regex now correctly validates both dot path and snake_case segments simultaneously, matching the documented behavior. - **Manifest sync:** `package.public.json` `supportedFrameworks` synced with updated `package.json` to include all new framework entries. - **Centralized Architecture:** All framework data (extensions, patterns, suggestions, exclude dirs, source dirs, wrapper skip patterns) now lives in one place — `utils/framework-detector.js`. The scanner (`i18ntk-scanner.js`), managed scanner (`ScannerCommand.js`), report model (`report-model.js`), and usage source resolver (`usage-source.js`) all import from this single source of truth. - **Duplicate method removal:** `detectFramework()`, `getFrameworkPatterns()`, and `getFrameworkSpecific()` were duplicated with slight variations across 4+ files. All consumers now call the centralized `detectProjectFramework()`, `getFrameworkPatterns()`, and `getFrameworkSuggestions()` exports. - **Hardcoded extension lists eliminated:** `SOURCE_EXTENSIONS` (report model), `SCANNER_EXTENSIONS` (scanner commands), `EXCLUDE_DIRS` (walk functions), and `SOURCE_DIRS` (usage resolver) are now defined once and imported everywhere. - **Framework-specific registration:** Adding a new framework now requires changes in only ONE file (`framework-detector.js`) instead of 6+ scattered locations. ## [4.5.4] - 2026-06-19 ### Fixed - **Analyze:** Fixed `this.provideSetupGuidance is not a function` when no target locales are available. Analyze now prints setup guidance instead of crashing. - **Manager Route:** Manager-routed commands now propagate subcommand failures and no longer print `Operation completed successfully!` after a runtime failure. - **Complete:** Fixed `i18ntk-complete --help` by wiring the shared help renderer and keeping help output side-effect free. - **Validate:** Removed mixed failure/success output. Validation only prints successful completion when the validation result succeeds. - **Summary:** Guarded empty locale roots so `Average keys per language` prints `0` instead of `NaN`, and missing locale roots exit as invalid setup/argument failures. - **Analyze Reports:** Report write failures now fail analyze with a non-zero exit code instead of continuing with success wording. ### Changed - **CLI Flags:** Added canonical aliases: `--code-dir` / `--source-code-dir` for application source files, `--locales-dir` / `--i18n-dir` for locale files, and `--source-locale` for source language. Legacy `--source-dir`, `--i18n-dir`, and `--source-language` remain supported. - **Exit Codes:** Standardized automation behavior: `0` for success, `1` for validation/report/runtime failures, and `2` for invalid arguments or missing setup in non-interactive mode. - **CI Behavior:** Commands skip prompts when `--no-prompt` is passed, `CI=true`, stdin is not a TTY, or stdout is not a TTY. - **Complete Summary:** Completion output now distinguishes locales scanned, target locales changed, unique source keys added, total key insertions, files modified, files skipped, and dry-run status. ### Documentation - Updated README, API, configuration, scanner, and environment-variable docs with canonical CLI flags, legacy alias notes, and CI exit-code behavior. ### Tests - Added CLI reliability regression coverage for the analyze crash, manager failure propagation, complete help output, directory/source-locale aliases, summary `NaN`, non-interactive prompt suppression, validation wording, and completion summary labels. ## [4.5.3] - 2026-06-19 ### Fixed - **Usage Scanner (Critical):** Fixed `supportedExtensions` default fallback in `config-helper.js` that excluded `.tsx` and `.jsx` files from source scanning. The default was `['.json', '.js', '.ts']` — missing `.jsx` and `.tsx`. In a Next.js project with 2704 keys across 1087 files, this caused the scanner to find only 57 keys (2.1%) instead of 2702 (99.9%) because all `.tsx` component files were silently ignored. The fix adds `.jsx` and `.tsx` to the default fallback: `['.json', '.js', '.jsx', '.ts', '.tsx']`. - **Usage Dead Code:** Cleaned up unreachable initializer in `i18ntk-usage.js` that was supposed to set default `includeExtensions` but never ran because `supportedExtensions` was always set by `config-helper.js`. Added `.vue` and `.svelte` to the fallback for completeness. ## [4.5.2] - 2026-06-19 ### Fixed - **Complete (Namespace Wrapper):** Fixed critical bug where missing keys were inserted at the wrong nesting level in target locale files. When a file (e.g., `auth.json`) contains a namespace wrapper matching its filename (`{ "auth": { ... } }`), the `complete` command now detects this wrapper and inserts keys inside it (`auth.panel.sign_in`) instead of at root level (`panel.sign_in`). This prevents runtime lookup failures for `t("auth.panel.sign_in")`. - **Translate (--output-dir):** Fixed bug where the `--output-dir` flag wrote translated files directly to `<output-dir>/<filename>` instead of `<output-dir>/<targetLang>/<filename>`. This caused all translations (regardless of target language) to land in the same directory, silently overwriting files from other languages in multi-language projects. When `args.outputDir` is provided, `processFile()` now appends `targetLang` to construct the correct output path. ### Tests - Added `tests/regression-v452.test.js` with 18 regression tests covering: - Complete command namespace wrapper detection (parseKeyPath, setNestedValue, hasNestedKey, wrapper detection logic) - Validate getAllKeys leaf-only mode and completeness calculation - Runtime alias parameter support (localeDir/targetLocale/sourceLocale) - Scanner source directory fallback when sourceDir equals i18nDir - Doctor auto-detection of languages from i18n directory - Version consistency across package files - Added `--output-dir` target language subdirectory tests to `tests/regression-v452.test.js`: verifies `processFile()` places output in `<outputDir>/<targetLang>/<file>` and that CLI `--output-dir` produces the correct nested path - Added 8 tests in `tests/usage-insights.test.js` for hardcoded text false-positive filtering: - JS/TS built-in type name rejection (Promise, Boolean, String) - Code expression operator rejection (&&, ||, ===, !==, =>) - Template literal interpolation rejection (${...}) - Real human text still correctly detected (welcome messages, form labels) ## [4.5.1] - 2026-06-19 ### Fixed - **Complete:** Fixed wrong nesting level when adding missing keys to target locale files that have a namespace wrapper matching the file name. Previously, `parseKeyPath("auth.panel.sign_in")` returned `{ file: "auth.json", key: "panel.sign_in" }`, and `setNestedValue` inserted `panel` at the root level instead of inside the existing `auth` wrapper. The fix detects namespace wrappers (e.g., `auth.json` containing `{ "auth": { ... } }`) and prepends the namespace to the insertion path so keys go inside the wrapper. - **Validate:** `getAllKeys()` no longer reports parent namespace objects (e.g., `footer`) as missing keys alongside their leaf children (`footer.copyright`). Only leaf (string) keys are now compared during structural validation. - **Validate:** Completion percentage now compares against source locale total keys, not target locale self-count. A locale with 14 of 42 source keys now correctly shows 33% instead of 100%. - **Doctor:** No longer flags unconfigured locales (`de`, `ru`) as "missing". Now auto-detects available languages from the i18n directory structure, only checking against actually-configured languages. - **Scanner:** Now detects when `sourceDir` was set to the locale directory (common after setup) and falls back to `./src` for source code scanning instead of scanning locale JSON files. - **Runtime:** `initRuntime()` now accepts alias parameter names for better developer experience: `localeDir` → `baseDir`, `targetLocale` → `language`, `sourceLocale` → `fallbackLanguage`, `projectRoot` + `localeDir` → `baseDir` resolution. ## [4.5.0] - 2026-06-19 ### Security — Prototype Pollution Hardened - **safe-json.js:** Added `stripPrototypePollution()` function that recursively filters `__proto__`, `constructor`, and `prototype` keys from parsed JSON locale files. Applied to all `readJsonSafe()` calls. - **runtime/index.js:** `deepMerge()` now blocks `__proto__`, `constructor`, and `prototype` keys during locale data merging. `readJsonSafe()` now applies `stripPrototypeKeys()` to all parsed JSON, ensuring prototype pollution protection at runtime data ingestion point. - **settings-manager.js:** `mergeWithDefaults()` now filters prototype pollution keys from user-supplied settings before spreading into defaults. - **safe-json.js:** Exported `stripPrototypePollution` for use by other modules. ### Fixed - **Backup:** Removed duplicate `const sourceDir` declaration that caused SyntaxError at module load (was unrecoverable crash for all backup operations). - **Backup:** Added `try/catch` around `JSON.parse()` in restore path to handle corrupt backup files gracefully with a descriptive error message. - **Complete:** Added missing `getUnifiedConfig` import from `utils/config-helper` (was ReferenceError at runtime). - **Report:** Replaced 3 direct `fs.writeFileSync` calls with `SecurityUtils.safeWriteFileSync` for path containment on report output. - **Report Model:** Replaced direct `fs.existsSync` and `fs.readFileSync` with `SecurityUtils` wrappers. Malformed JSON locale files now skipped gracefully with a warning instead of aborting report generation. - **Runtime:** Lazy-load failures now log to console when `I18NTK_DEBUG` is set (was silently swallowed). - **Settings Manager:** `_saveImmediately()` now re-throws errors instead of silently logging them, so callers can react to save failures. - **Config Manager:** Fire-and-forget legacy config migration now has proper `.catch()` error handling instead of an unobserved promise. - **i18n-helper:** `stripBOMAndComments()` now safely handles null/undefined inputs. ### Changed - **Version:** Bumped to 4.5.0 (minor version due to scope and severity of security fixes). - **i18n-helper deepMerge:** Synchronized with runtime `deepMerge` — now uses `Object.keys` (safe) instead of `for...in`, handles null target/fallback, and filters `__proto__`/`constructor`/`prototype` keys for consistent prototype pollution protection across all code paths. - **Testing:** Added `tests/edge-case-hardening.test.js` with 33 new tests covering prototype pollution protection, SecurityUtils edge cases, backup corrupt handling, report malformed JSON resilience, validation risk detection null-safety, config manager robustness, version consistency, and deepMerge edge cases. - **Audit Complete:** Comprehensive security audit (24 findings) and error-handling audit (42 findings) completed with critical fixes applied. ## [4.4.5] - 2026-06-08 ### Fixed - Removed orphaned duplicate code block from `main/i18ntk-scanner.js` that caused a SyntaxError when loading the scanner CLI. - Fixed `utils/safe-json.js` where a duplicate `readJsonSafe` function overwrote the SecurityUtils-based implementation with an insecure version that referenced an undefined `fs` variable. - Added periodic cache eviction to `missingKeyCache` in `utils/i18n-helper.js` to prevent unbounded memory growth in long-running processes. - Replaced silent error swallowing in `utils/watch-locales.js` with stderr logging so file-watcher failures are visible. - Routed `utils/report-model.js` through `SecurityUtils.safeExistsSync` and `SecurityUtils.safeReadFileSync` for consistent path containment and file-size validation. - **Framework detection:** Removed `async` keyword from `detectFramework()` that caused callers to receive unresolved Promises instead of framework objects, silently losing framework-specific translation patterns. - **Framework detection:** Fixed `react-i18next` entry using `dependencies` instead of `deps`, which made the most popular React i18n framework completely invisible to dependency-based detection. - **Framework detection:** Replaced broken `.source` concatenation that produced a String instead of a RegExp for the `useTranslation()` destructuring pattern. - **Runtime:** `t(null)` and `t(undefined)` now return strings instead of raw null/undefined, preventing crashes in string-based renderers. - **Runtime:** Added JSON nesting depth limit (max 1000 levels) to `readJsonSafe` to prevent stack overflow DoS from malicious deeply-nested locale files. - **Runtime:** Fixed path containment boundary in `readJsonSafe` using `path.dirname()` which was too lax; now uses resolved parent directory. - **Security:** `validateConfig` now runs `isSafePath` validation on absolute paths instead of skipping them entirely (`return` in forEach was bypassing all checks for absolute config paths). ### Added - **Framework detection:** Added support for ngx-translate (Angular), next-intl (Next.js), nuxt-i18n (Nuxt), svelte-i18n (Svelte), and solid-i18n (Solid) framework detection via dependency lookup. - `detectFramework()` now also checks the `dependencies` property as a fallback for the `deps` array, ensuring backward compatibility. - Created `tests/fixtures/test.json` fixture so file system security tests validate real file reads instead of passing vacuously. ### Changed - Removed dead `{ gte }` import from `version-utils` and unused `FRAMEWORK_COMPATIBILITY` object from `framework-detector.js`. - Security test `logSecurityEvent` now properly sets `I18NTK_DEBUG` and `I18NTK_ENABLE_SECURITY_LOGS` env vars and uses try/catch to verify non-throw behavior. - `validateConfig` "reject invalid configuration" test now uses `assert.strictEqual` for stronger path traversal assertions. ## [4.4.4] - 2026-06-05 ### Fixed - Likely-untranslated reporting now ignores placeholder-only and symbol/dynamic values such as `{file}`, `{path}`, and icon-prefixed labels instead of treating them as untranslated English. - Dynamic values with translated surrounding copy and English placeholder tokens, such as `"command": "指示: {command}"`, are no longer flagged as untranslated. ### Changed - `.i18ntk-config` now accepts a top-level `extensions` object for VS Code Workbench and Lens settings. The CLI preserves this section during config validation and ignores unknown extension-owned nested keys. - Documented shared config edge cases so editor extensions can sync workspace defaults without changing CLI behavior. ## [4.4.3] - 2026-06-04 ### Fixed - `package.public.json` now includes the `./report` export entry (`./utils/report-model.js`) that was missing, fixing the sync check during public package builds. ## [4.4.2] - 2026-06-02 ### Fixed - Auto Translate `processFile()` now accepts source file paths relative to the current project, matching direct CLI behavior and avoiding safe-read failures in programmatic callers. - Auto Translate now treats protected product terms as allowed English when deciding whether existing target values should be kept in `only-missing` mode. - Auto Translate detects and retries more visibly broken target values, including replacement-character artifacts, mojibake, repeated question marks, and target-language prefix leftovers. ### Added - Added regression coverage for relative source paths, protected product terms, broken target values, placeholder handling, and managed Auto Translate residual checks. ## [4.4.1] - 2026-06-02 ### Security - **HIGH**: Backup operations (`create`, `restore`, `list`, `verify`) now validate all path arguments via `SecurityUtils.validatePath()`. Previously, `i18ntk-backup` accepted arbitrary `--output` and source directory paths without any validation, enabling writes outside project boundaries. - **HIGH**: Backup `handleCreate`, `handleRestore` now use `SecurityUtils.safeWriteFileSync`, `safeReadFileSync`, `safeMkdirSync` instead of raw `fs.promises`/`fs` calls. - **HIGH**: `i18ntk-complete` now validates `--source-dir` CLI override through `SecurityUtils.validatePath()` and sanitizes `--source-language` through `SecurityUtils.sanitizeInput()` instead of accepting raw user input. - **HIGH**: `config-helper` dual-path resolution (when both `--source-dir` and `--i18n-dir` are explicit) now wraps each resolved path in `SecurityUtils.validatePath()`. - **MEDIUM**: JSON parsing now enforces maximum depth (1000) and maximum size (50 MB) limits in `safeParseJSON` to prevent denial-of-service via deeply nested or oversized JSON files. - **MEDIUM**: LibreTranslate custom URL (`LIBRETRANSLATE_URL`) now requires `I18NTK_ALLOW_CUSTOM_LIBRETRANSLATE_HOST=1` env flag to add arbitrary hosts to the allowed list, bringing parity with DeepL's gated approach. - **MEDIUM**: `sanitizeInput` default character whitelist tightened — removed `\\`, `{`, `}` characters that could enable path traversal or template injection. - **MEDIUM**: VSCode Workbench `workspaceScanner.ts` now validates auto-translate report paths with `normalizeWithinRoot()` and rejects JSON content > 50 MB. - **MEDIUM**: VSCode Workbench `localeFileService.ts` now validates `addKey()` write paths via `isPathWithinRoot()` and rejects locale files > 10 MB before parsing. - **LOW**: i18ntk Lens `scanner.ts` now rejects custom wrapper names > 100 characters to prevent ReDoS via malicious VSCode config values. ### Added - `SecurityUtils.MAX_JSON_SIZE`, `SecurityUtils.MAX_JSON_DEPTH`, `SecurityUtils.MAX_FILENAME_LENGTH` constants for configurable safety limits. ## [4.4.0] - 2026-06-02 ### Added - Dead-key detection now uses resolved dynamic key data from usage insights instead of crude text-overlap heuristics. Keys expanded from template literals or const arrays are properly tracked and marked with low confidence. - Locale JSON import detection: `import en from '../../locales/en/foo.json'` is detected and property accesses are tracked as key usages. - Confidence-split unused key reports: confirmed (≥80%), likely (40-80%), possibly used (<40%). - `--strict-unused` flag: only reports high-confidence confirmed unused keys. - `--json` flag: outputs structured JSON report for automation and CI/CD. - `--prune` / `--prune-keep` flags: removes stale report files, keeping N most recent. - Mojibake detection: replacement-character artifacts like `Abwicklungspr?fung` and `L?ser` detected during translation analysis. - Client-boundary warnings: flags `"use client"` files that import locale JSON, which bypasses i18ntk runtime and increases bundle size. - Copy-formatter detection: identifies local `const tx = ...` functions that do not call known translation runtimes. - Wrapper configuration: `.i18ntk-config` now supports `usage.translationFunctions`, `usage.serverWrappers`, and `usage.copyFormatters`. - Next.js App Router detection: identifies `"use server"` / `"use client"` directives and reports component type. - VSCode `i18ntk.clearDiagnostics` command. Stale diagnostics now cleared at scan start. - VSCode new diagnostic codes: `i18ntk.clientBoundary` (warning), `i18ntk.copyFormatter` (warning). - Lens scanner: `detectSuspectedCopyFormatters()` and `findClientBoundaryLocaleImports()` exported. - Auto Translate now writes `i18ntk-reports/auto-translate/latest.json` when residual untranslated values remain after the final targeted retry, so follow-up tooling can retry only unresolved keys. - i18ntk Workbench and i18ntk Lens can read Auto Translate residual reports, show the affected key in the VS Code editor, and offer a quick action to add intentionally unchanged keys to Auto Translate protection. - Bounded dynamic expansion suggestions in usage report with explicit-map recommendation pattern. - Telemetry/event literal classification: known-key strings inside `trackEvent()`, `emitDomainEvent()`, `analytics.track()`, etc. are classified as `literal-telemetry` and excluded from translation usage counts. Non-translation calls get context notes in the report. - Object-method translation calls: `input.tx("key")`, `helper.tx("key")`, and `.tx(\`key.${var}\`)`are now recognized as translation calls alongside standalone`tx()`. - Local wrapper resolution: functions like `const text = (key, fallback) => tx(key)` that internally call known translation runtimes are detected and their string-literal invocations resolved to keys with `local-wrapper` match type. ### Fixed - `--source-dir` and `--i18n-dir` no longer forced to the same value when both are explicitly passed via CLI. - Path display (`displayPaths`) now reflects CLI overrides instead of only config file values. - Dead-key detection `_matchesDynamicPattern` replaced with `_matchesDynamicPrefix` using actual resolved data. - Locale JSON import detection properly deduplicates namespace prefix (e.g., `leaderboard.error` not `leaderboard.leaderboard.error`). - Literal key matching no longer credits telemetry/event call strings (e.g., `trackEvent("leaderboard.view")`) as translation usage, preventing CLI false negatives on genuinely unused keys. - Object-method `tx()` calls and local wrapper functions are now included in usage analysis, preventing Lens false positives on keys used through these patterns. ### Changed - VSCode workbench bumped to 1.1.0, lens extension to 1.1.0. - Major changes list in package.json and package.public.json updated for 4.4.0. ## [4.3.3] - 2026-06-01 ### Fixed - Usage extraction no longer reports ordinary method calls such as `get("next")`, `headers.get("etag")`, `set(...)`, or `setItem(...)` as missing translation keys. - Usage insights now resolve `tx(...)` wrapper calls and bounded dynamic `tx` template keys, reducing false unused-key reports for local wrappers. - Key naming validation now supports hybrid dot-path plus snake_case segment keys, such as `namespace.section.snake_case_leaf`, while still rejecting malformed separators and uppercase segments. - Usage documentation now treats unused-key reports as advisory; do not bulk-delete keys from an unused report without manual verification or a more precise usage scan. ## [4.3.2] - 2026-05-31 ### Changed - Documentation, README badges, and migration guidance now reference the current 4.3.2 release. - Release metadata now marks 4.3.0 for npm deprecation because its npm tarball is unavailable. ## [4.3.1] - 2026-05-31 ### Fixed - Published tarball now includes `utils/english-placeholder-checker.js`, resolving `MODULE_NOT_FOUND` at startup for `i18ntk-fixer --check-placeholders` and manager option 7. - Language-specific CLI entry points (`main/i18ntk-go.js`, `main/i18ntk-java.js`, `main/i18ntk-js.js`, `main/i18ntk-php.js`, `main/i18ntk-py.js`) and their shared `utils/mini-commander.js` dependency are now included in the published package. - Removed inconsistent `.js` extension suffixes from require paths in `main/i18ntk-js.js`. ## [4.3.0] - 2026-05-31 ### Fixed - Auto Translate now treats single-word uppercase target-language placeholders such as `[AR] Email` and `[AR] Password` as untranslated target values, matching the existing multi-word `[AR] What We Offer` detection. - Auto Translate now treats bracketed target-language placeholders case-insensitively, so `[zh] Email` and `[TR] Password` are both retried for the matching target language. - Managed Auto Translate now checks every selected source file for a target language before reporting leftover failures, instead of stopping after the first failed file. - Auto Translate no longer fails a run when a provider legitimately returns a short all-caps acronym or code unchanged, such as `XP`. - Manager option 7 and `i18ntk-fixer --check-placeholders` now run an English source placeholder audit, reporting any `[LANG] ...` values left in English locale files; a clean project reports `0` placeholders. - The management command router no longer prints a generic operation-success message when a command returns `{ success: false }`. ## [4.2.1] - 2026-05-31 ### Changed - Auto Translate now treats uppercase target-language placeholders such as `[AR] What We Offer` as untranslated target values when the bracketed code matches the target language, so target-aware mode sends the source text for translation instead of keeping the placeholder copy. - Auto Translate now performs a final pre-write leftover check and retries values that still look like placeholder-prefixed untranslated text, untranslated markers, source-language copies, or broken output. - Auto Translate reports leftover values in the post-translation report and exits with validation failure when leftovers remain after the final retry, instead of reporting a clean completion. ### Fixed - Usage analysis no longer writes its inferred app source fallback, such as `src`, back into the shared locale configuration when `sourceDir` and `i18nDir` are both the locale directory. - Manager sizing now reads the configured i18n directory unless `--source-dir` is explicitly provided, so running sizing after usage no longer silently analyzes the wrong directory. - Manager sizing now treats a failed sizing analysis as a command failure instead of printing a generic operation success. - Validation summary reports now include warning and error details, including content-risk warning payloads, instead of only totals. ## [4.2.0] - 2026-05-30 ### Security - Shared path validation no longer permits artifact-like filenames such as `.lock` or `.temp-config.json` to bypass base-directory containment. - Shared path validation now rejects Windows cross-drive escape cases where `path.relative()` returns an absolute path. - Custom `I18NTK_INTERNAL_PATH_PREFIXES` entries can no longer mark arbitrary outside directories as internal roots. - Backup restore now rejects backup entry names containing path separators, absolute paths, traversal, or non-JSON names before writing restored files. - Runtime locale loading now validates language identifiers before resolving single-file or directory locale paths, blocking `../` language names from reading JSON outside `baseDir`. - Auto Translate provider URL validation now blocks IPv4-mapped IPv6 loopback/private hosts. ### Changed - Main runtime now includes production-safe features from the enhanced runtime surface: per-call language overrides, synchronous `translateBatch()`, and `clearCache()` / `getCacheInfo()` helpers. - `i18ntk/runtime/enhanced` remains available as a legacy public subpath for compatibility, while new production integrations should prefer the lightweight `i18ntk/runtime` API. - Usage analysis now indexes known translation keys back to source files, including direct i18n calls and literal key references that were previously missed. - Usage analysis now expands simple dynamic templates backed by literal constants, bounded literal arrays, object maps, and ternaries to exact available keys before falling back to unresolved dynamic-expression reporting. - Usage reports now list unresolved dynamic key expressions separately instead of treating broad wildcard prefixes as proof that every matching key is used. - Usage reports now include namespace/file naming recommendations such as preferring `shop.*` keys and `shop.json` for `/shop` page or route files. - Usage reports now list likely hardcoded user-facing text with suggested translation keys, and prefer an existing source key when the inline text matches a source translation value. - Translation analysis and init reports now default to Markdown for readable output, with `reports.format` supporting `markdown`, `json`, or `text` through settings and config. - Init default target languages now include English (`en`) before `de`, `es`, `fr`, and `ru` when the UI is running in another language. - Confirmation prompts now accept localized native yes/no input for supported UI languages while retaining English fallback tokens. - Auto Translate has moved out of beta in menus and documentation, and its settings are exposed with localized labels. - Auto Translate now keeps existing translated target values by default and only translates missing, marker, source-copy, or likely English target strings; use `--translate-all` to force a full re-translation. - Auto Translate now treats visibly corrupt target strings such as `?????`, Unicode replacement characters, and common mojibake as needing retranslation from the source language. - Auto Translate now defaults to 12 concurrent provider requests and allows Google concurrency up to 100 instead of the old 25-request cap; DeepL and LibreTranslate remain capped lower to avoid provider/account throttling. - Auto Translate progress output now separates string translation from placeholder-safe text-segment translation and shows the active key path during progress updates. - Placeholder detection now covers ICU plural/select blocks, i18next nested `$t(...)` references, and wider named printf formats such as `%(total).2f`. - Manager menu output is now grouped with clearer spacing and aligned option numbers. - Documentation now consolidates migration guidance around `4.2.0` and removes stale old per-version migration guides from the working docs tree. - Removed stale duplicate development artifacts `main/manage/index-fixed.js` and `utils/security-fixed.js` to reduce audit drift and prevent accidental reuse. - Updated public, root, and development package metadata for the 4.2.0 release line. ### Fixed - Runtime JSON loading now preserves valid translation strings containing comment-like text such as `/* token */` by parsing valid JSON before using the comment-stripping fallback. - Enhanced runtime now exports the top-level `translateBatch()`, `translateBatchEncrypted()`, and `tTyped()` helpers declared by its TypeScript definitions, and those declarations now reflect async return values. - Usage analysis no longer scans the project root when `sourceDir` and `i18nDir` both point at the locale directory; it now uses a detected app source directory or disables usage scanning with a clear warning. - Init backup prompts, completion summaries, report prompts, and report status text now use bundled UI locale keys instead of hard-coded English. - Bundled UI locales were regenerated from `ui-locales/en.json` for newly added, source-copy, and corrupt target strings. - JSON report output is now pretty-printed object JSON instead of a single JSON string containing escaped newlines. - The managed Auto Translate command no longer forces UI translations back to English after the user has selected another UI language. - Manager validation output no longer prints duplicate source/i18n/output directory blocks before the validator summary. - `i18ntk-setup --help` now exits after printing help instead of running setup and writing project files. - `npm run languages:list` and `npm run languages:status` now produce non-interactive output instead of opening the settings menu. - `i18ntk-backup create locales` now recursively backs up modular locale layouts such as `locales/en/common.json`, and restore safely recreates nested JSON paths without allowing traversal. - Removed a stale bundled `locales/es/navigation.json` fixture that made `i18ntk-doctor` report a dangling namespace after setup/init tests. ## [4.1.0] - 2026-05-21 ### Fixed - Runtime: stale manifest entries (deleted files after manifest construction) no longer cause unhandled exceptions; loadedFiles set before load with try/catch guard. - Runtime: `refresh()` now correctly clears the key manifest for the refreshed language, preventing stale file references. - Runtime: null `baseDir` guard prevents cascading `validatePath(null)` errors in `loadKeyManifestFromDir`. - Backup: `handleVerify` hash-chain verification rewritten for incremental backups — rebuilds full state oldest→newest before per-entry hash comparison; no longer reports false "Missing file" errors for unchanged files. - Backup: `cleanupOldBackups` and `handleCleanup` now preserve parent backups of incremental chains by scanning kept backups for `_meta.parent` references before deletion. - Backup: `--incremental=false` is now correctly parsed as falsy (string-to-boolean conversion fixed). - Backup: `buildRestoreChain` detects circular parent references via visited-set traversal. - Sizing: `this.adminAuth` undefined crash in `run()` fixed — changed to correct `adminAuth` local variable. - Sizing: duplicate `analyze()` method removed; format-based display logic (`--format=json` vs table) restored to the surviving method. - Sizing: setup-check IIFE now guarded with `require.main === module`, preventing unexpected `process.exit()` on `require()`. - Scanner: `frameworks.vanilla` key added to `getFrameworkSpecific` — no longer returns `undefined` for vanilla projects. - Scanner: `--source-language` CLI flag now correctly propagates through config chain to `scanFile` and `generateSuggestion` (camelCase vs hyphen key mismatch fixed). - Scanner: `isTextInLanguage` now always validates character ratio unconditionally even for no-stopword language profiles. - Watch: `{ onChange: fn }` object-format callbacks are now properly subscribed to change/add/unlink events. - Watch: debounce `setTimeout` timers are now stored per-watcher and cleared on `emitter.stop()`, preventing memory leaks and spurious I/O after stop. - Watch: `'unlink'` events are now subscribed for backward-compatible plain-function callback users. - Usage: duplicate `require.main === module` block removed (caused `TypeError: Identifier 'main' has already been declared` at execution). - Usage: `_keyInSourceComments` optimized from O(n\*m) to O(n+m) by pre-computing a `Set` of all comment strings once before the dead key loop. - Usage: `--cleanup=false` and `--dry-run-delete=false` now correctly parse as falsy via `toBool()` helper. - Usage: broken `detectFrameworkPatterns()` call with `undefined` arguments removed. - Usage: dead `return;` in `analyze()` removed so the result object is now actually returned. - Validator: missing `try` block in `run()` added so errors are caught by the existing `catch(error)` handler. - Validator: `--enforce-key-style=true/false` now correctly parsed (previously silently ignored due to `!includes('=')` guard). - Validator: `flat` style no longer produces false positives for nested keys — validates only the leaf segment (last `.`-delimited part). - Validator: `suggestKeyFix` for `flat` style now returns `segments.map(s => s.toLowerCase()).join('')` instead of camelCase. - Validator: `getLanguageFiles` no longer crashes when `excludeFiles` config property is undefined. - Validator: `enforceKeyStyle` now correctly propagated from CLI args to `this.config.enforceKeyStyle` in `run()`. - Protection: `standalone` mode boundary check now handles opening/closing punctuation (`(`, `[`, `{`, `"`, `'`, `-`, `–`, `—`) and CJK marks (`。`, `、`, `」`). - Protection: `\b` word-boundary assertions replaced with Unicode-aware `(^|[\s\p{P}])` / `([\s\p{P}]|$)` patterns with `u` flag for non-ASCII language support. - Protection: `surrounded` context rule parser now uses `indexOf(',')` split instead of greedy `(.+,.+)` regex to correctly parse multi-word right-side expressions. - Protection: `hasProtectionRules` no longer throws `TypeError` when `terms` property is undefined. - Protection: `shouldPreserveWholeValue` now respects context rules by only matching `type === 'global'` entries. - Manager option 7 ("Fix placeholder translations") now interpolates fixer status values correctly instead of printing raw `{languages}`, `{sourceDir}`, `{skipped}`, or `{totalIssues}` placeholders. - Delete Reports settings now include cache cleanup targets. - Public package metadata updated. ### Security - Watch module: debounce timers properly cleaned up on stop and callback subscriptions corrected for object-format and unlink handlers. - Runtime: loadedFiles lock-before-load pattern prevents duplicate I/O and stale manifest crash. - Backup: circular parent reference detection; `--incremental=false` string truthy bypass closed. - Sizing: adminAuth variable reference corrected; require()-time `process.exit()` guarded. - Scanner: vanilla framework key prevents `undefined` return; stopword-less validRatio enforced. - Usage: O(n+m) comment scanning prevents DoS via large codebase with many dead keys; `toBool()` prevents flag injection. - Validator: try/catch pairing restored; `flat` leaf-segment prevents false-positive flood. - Protection: Unicode-aware punctuation boundaries for CJK/Cyrillic/Arabic; standalone boundaries include the expanded punctuation set. ## [4.0.0] - 2026-05-21 ### Added - **Sizing Expansion Prediction**: `i18ntk-sizing` now supports `--predict-expansion` flag that computes per-key character-count expansion ratios across languages and classifies them into Safe/Warning/Critical risk tiers for UI layout planning. Includes a built-in language-pair expansion reference table (EN→DE 35%, EN→RU 50%, EN→JA -40%, etc.). - **Watch Hot Reload**: `utils/watch-locales.js` rewritten as an EventEmitter-compatible watcher with debouncing (300ms default) and SHA-256 hash tracking to skip no-change saves. Returns a callable watcher object with `change`, `add`, `unlink`, `error` events and `stop()`. - **Usage Dead Key Detection**: `i18ntk-usage` adds `--cleanup` and `--dry-run-delete` flags that identify unused translation keys with confidence scores (0.0–1.0) factoring dynamic access patterns, comment references, and file recency. Produces a `.dead-keys.json` report for safe review before deletion. - **Validator Key Naming Convention**: `i18ntk-validate` adds `--enforce-key-style` flag and `keyStyle` config setting supporting `dot.notation`, `snake_case`, `camelCase`, `kebab-case`, and `flat` conventions. Reports all violating keys with suggested canonical forms. - **Scanner Multi-Language Detection**: `i18ntk-scanner` adds `--source-language` flag with character-class profiles for 12+ languages (English, German, French, Spanish, Japanese, Chinese, Russian, Korean, Arabic, Hindi, etc.). Language-specific stopword lists and key generation with transliteration for non-Latin scripts. - **Backup Incremental Mode**: `i18ntk-backup` adds `--incremental` flag producing differential backups with SHA-256 file hashing, parent-chain metadata, and chained restore (oldest full → incremental diffs in order). `verify` validates the hash chain. Chain depth capped at 10. - **Runtime Lazy Loading**: `runtime/index.js` adds `lazy: true` option to `initRuntime()`. Defers locale file loading until the first key access, guided by an auto-generated key-to-file manifest. Falls back to eager loading if manifest is missing. Manifest capped at 100KB with path containment validation. - **Protection Context-Aware Rules**: `utils/translate/protection.js` extends the protection config schema to support context rules (`after:word`, `before:word`, `standalone`, `surrounded:left,right`). Plain string terms remain fully backward compatible. Total context rules capped at 100. ### Fixed - `i18ntk/runtime` `initRuntime()` now returns independent runtime instances with separate language, fallback language, base directory, and cache state. Later `initRuntime()` calls no longer overwrite earlier returned runtimes or the module-level compatibility singleton. ### Changed - `watchLocales()` now returns a callable watcher object with EventEmitter methods instead