UNPKG

i18ntk

Version:

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

519 lines (378 loc) 83.5 kB
# CHANGELOG Release notes explain what changed, who benefits, and whether you need to take action. Older entries retain more technical detail for historical reference. ## [5.1.1] - 2026-07-19 ### At a glance 5.1.1 is a recommended update for everyone using 5.1.0. It makes translation status more dependable in CI and smooths out runtime compatibility for browser, Node, and enhanced-runtime applications. ### What you will notice - **Release checks reflect real translation work.** Empty values and untranslated markers are now visible in the result. Strict validation blocks the release when they remain. - **Progress is easier to understand.** The validation and usage commands report the same unfinished strings, and incomplete work is never shown as 100% complete. - **TypeScript suggestions match your application.** Browser projects no longer see Node-only methods, and existing 5.x imports continue to compile. - **Language selectors can show the full list sooner.** Applications can discover available locales without downloading every translation first. - **Fallback behavior is consistent.** Presence checks and translation lookups follow the same regional and configured fallbacks. - **Existing enhanced-runtime applications work as expected again.** Named translation groups, encryption startup, and cache preferences are honored. ### Do I need to change anything? For most 5.1.0 projects, no. Upgrade with: ```bash npm install i18ntk@5.1.1 ``` - Use normal `validate` when unfinished translations should be reported but allowed. - Use `validate --strict` when unfinished translations must block deployment. - For new runtime integrations, choose the explicit entry for your environment: `runtime/node`, `runtime/static`, `runtime/fetch`, or `runtime/core`. ### A note for enhanced-runtime users `runtime/enhanced` remains available during 5.x, but it is deprecated. If encrypted values must survive an application restart, supply and securely retain a stable encryption key. Cache settings for refresh time, maximum languages, and disabling the cache now take effect rather than acting as placeholders. ## [5.1.0] - 2026-07-19 ### What this release means for you - **Use the runtime in more places.** Choose a dedicated entry point for Node servers, browsers, Edge routes, React, React Native, or bundled translation files. Server and client rendering can now share the same translation behavior without pulling Node filesystem code into browser bundles. - **Safer server rendering.** Every runtime you create is isolated, making it suitable for concurrent requests, tests, multiple React roots, and multi-tenant services. The runtime no longer takes control of application process handlers or timers. - **Fixer commands use the folders you specify.** `--code-dir` is now only application code and `--locales-dir` is only translations. Source folders such as `app` and `components` are no longer reported as languages. - **CI receives dependable results.** Fixer and validator `--json` output contains one parseable document, invalid locale layouts return a failure, and requested languages and markers are respected. - **Completion percentages are accurate.** Numbers, booleans, nulls, and other settings no longer make complete translations look incomplete. Translatable strings inside arrays are still counted. - **Installed documentation works.** All guides linked from the README are included, and the accidental duplicate package tree has been removed. ### Runtime improvements - Locale fallback now follows regional parents before the configured fallback, such as `pt-BR` to `pt` to `en`. - Node projects can reliably combine `projectRoot` and a relative `localeDir`, even when launched from another working directory. - Missing keys and broken locale files are reported separately, so an unreadable resource is not mistaken for untranslated copy. - React components update when either the locale or loaded resources change, including refreshes that keep the same locale. - Project translations always take precedence over compatibility fallbacks. Plugins, observers, and failed in-progress loads cannot corrupt runtime state. - The former enhanced runtime remains available for 5.x applications, but now uses the same isolated runtime behavior. Migrate to the environment-specific entry points before the next major release. ### Upgrade notes - Existing CLI commands and locale layouts continue to work. Monolith files, namespaced folders, and regional locale directories are supported. - Node applications should import `i18ntk/runtime/node`. - Browser, Edge, and React Native applications should use `i18ntk/runtime/static`, `i18ntk/runtime/fetch`, or `i18ntk/runtime/core`. - React applications can add `i18ntk/runtime/react` for `I18nProvider`, `useTranslation`, and `useLocale`. - `i18ntk/runtime/enhanced` is deprecated but remains compatible throughout 5.x. ## [5.0.0] - 2026-07-11 ### Highlights - **Better translation quality checks.** Catch placeholder and tag mismatches, untranslated source text, corrupted characters, suspicious markers, and unsafe bidirectional text before it reaches users. - **Safer Auto Translate.** Unresolved translations now report a failure instead of a false success. Protected product names and approved acronyms stay untouched and are no longer repeatedly selected for translation. - **More accurate project support.** i18ntk better recognises mixed projects and supports Laravel, Spring Boot, Nuxt, next-intl, and a wider range of locale folder layouts. - **Smarter scanning.** Find translation usage across monolithic, namespaced, regional, and underscore-style locale structures while reducing false positives from routes, imports, styles, and metadata. - **Clearer translation status.** Source-copy markers are identified separately from completed translations, so coverage reports more accurately reflect work still to do. - **More flexible locales.** Regional and legacy language codes such as `pt-BR`, `zh_CN`, and `iw-IL` resolve to their supported language where appropriate. Right-to-left languages are handled more clearly in CLI output. - **Faster repeat scans.** Unchanged files can be reused during a session, helping larger projects complete repeat checks sooner. - **LLM-ready guidance.** The package now includes an i18ntk skill for Codex, Claude Code, GitHub Copilot, and compatible agents. Use menu option 15 or `i18ntk --command=skills` to discover and install it. - **Framework-aware configuration upgrades.** Older project setups are identified during startup and can be updated from the interactive UI with framework-specific source types, safe exclusions, cached scanning, richer reports, and performance defaults. Existing settings are preserved. - **Compact version output.** `i18ntk --version` now provides a concise release summary and links to the full changelog instead of printing the complete release history. - **Platform-aware setup.** Framework detection now recognises platform dependencies even without a separate i18n library, and configuration upgrades automatically merge matching source extensions plus safe build, generated-file, and lockfile exclusions without overwriting user rules. - **Reliable setup and release checks.** Setup reports only verified prerequisites, interactive prompts are not interrupted by the startup watchdog, and the public-package verifier permits the documented public files included by the manifest. ### Fixed - **Scanner startup.** Fixed a pattern that could prevent the hardcoded-text scanner from starting. - **Separate source and locale folders.** Existing projects can keep application source and locale files in different directories without validation looking in the wrong place. - **Auto Translate previews.** A dry run now succeeds when every target value is already translated instead of reporting a false validation failure. - **Scanner reports.** `--output-report` now reliably creates the detailed report users request. - **Clearer configuration guidance.** Projects already on v5 are now told when optional framework defaults are available, rather than being described as out of date. - **Path containment.** Secure writes now resolve existing parent symlinks and Windows junctions before writing, preventing a new file from escaping its approved project directory. ### Licensing - Changed i18ntk 5.0.0 and later from MIT to a dual-license model: PolyForm Noncommercial 1.0.0 for permitted personal/noncommercial use and a separate commercial license for business use. The major version reflects this material licensing change. - Added `COMMERCIAL-LICENSE.md` defining common commercial-use cases, the licensing request path, and the treatment of prior MIT releases. - Documented optional custom integration support for commercial customers, with scope, fees, response targets, and deliverables established by separate written agreement. - This change is prospective: versions already distributed under MIT retain their original license grants. - Added `i18ntk-license` to help licensed public sites publish an optional verification marker. It does not collect visitor data or send information to i18ntk. ## [4.7.3] - 2026-07-07 ### Fixed - Fixed an installation issue that could prevent some CLI commands from starting. - Version 4.7.2 had this installation issue; upgrade to 4.7.3 or later. ## [4.7.2] - 2026-07-07 ### FIXED - The CLI language picker now shows the languages available in your installation, using their native names. - Language selection remains accurate as more interface languages are added. ## [4.7.1] - 2026-07-07 ### Added - The CLI interface is now available in 23 languages, including Arabic, Czech, Greek, Hebrew, Hindi, Italian, Japanese, Korean, Polish, Portuguese, Swedish, Thai, Turkish, Ukrainian, and Vietnamese. - Language names appear in their native form in the selector. ### Changed - Project setup and framework detection now recognise a broader range of projects and keep configuration focused on what is actually detected. - New projects can start with the full set of supported interface languages. ## [4.7.0] - 2026-07-07 ### Added - Added support for more i18n libraries and frameworks, including Nuxt, next-intl, Lingui, FormatJS, ngx-translate, Svelte, Solid, FastAPI, Rails, React Native, and Ionic. - Project detection now also works for Python, Rust, Go, and Ruby projects. - Key discovery recognises more translation helpers, components, and namespace patterns. ### Changed - Framework detection now works even when a project does not use Node.js. ## [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:** Added support for `<Trans>`, `<FormattedMessage>`, `<t>`, and `<Translate>` components when finding translation keys. - **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 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. - **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. ### Fixed - **Dot/snake key style validation:** The hybrid regex now correctly validates both dot path and snake_case segments simultaneously, matching the documented behavior. ## [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. ## [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. - 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. ### Changed - Removed dead `{ gte }` import from `version-utils` and unused `FRAMEWORK_COMPATIBILITY` object from `framework-detector.js`. ## [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 ## [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. ## [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. ### 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. - 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. - 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. ## [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. ## [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 of only a bare `stop` function. Existing `const stop = watchLocales(...); stop();` usage remains supported. The returned object fires `change`, `add`, `unlink`, `error` events. If a callback function is passed as the second argument, it is auto-subscribed to `change` and `add` for backward compatibility. - **BREAKING**: `i18ntk-sizing` JSON reports now include `expansionPredictions` at the top level when `--predict-expansion` is used. This field is additive — existing report fields are preserved. ## [3.3.0] - 2026-05-20 ### Changed - Auto Translate now supports `--provider google|deepl|libretranslate`; DeepL uses `DEEP