UNPKG

i18ntk

Version:

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

502 lines (365 loc) 78.7 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/), ## [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 `DEEPL_API_KEY`, while LibreTranslate supports `LIBRETRANSLATE_URL` and optional `LIBRETRANSLATE_API_KEY`. - Auto Translate provider networking now keeps HTTPS, host allowlist, response-size, private-network, and redacted security logging protections in place for additional providers. ### Fixed - `i18ntk-complete` now fills missing target-language keys from the English source value with a language prefix such as `[DE] Home` instead of writing `NOT_TRANSLATED`; this works for both `locales/en/*.json` and monolith `locales/en.json` layouts. ### Security - Eliminated all 21 dynamic `require()` calls flagged by Socket.dev: 20 `require(path.join(__dirname, ...))` patterns in `i18ntk-js.js`, `i18ntk-py.js`, `i18ntk-java.js`, `i18ntk-php.js`, and `i18ntk-go.js` converted to static string literal requires. - Added `SecurityUtils.validatePath()` gate around the remaining dynamic `require()` in `i18ntk-translate.js` `loadCustomTranslateFn`. - Created `utils/translate/safe-network.js` — a secure HTTPS wrapper with URL host/path allowlist validation, response size limits (100KB), suspicious query parameter detection, and security event logging. All outbound network access now flows through this validated layer. - Replaced direct `https.get` call in `utils/translate/api.js` with `safeHttpGet` from the safe-network wrapper. ### Docs - README.md updated for v3.3.0 Auto Translate providers and secure provider operations. - SECURITY.md updated with Socket.dev analysis disclaimer and guidance on expected alerts for a CLI/i18n toolkit. - CHANGELOG.md and `package.json` versionInfo updated for v3.3.0. ### Socket.dev Analysis Disclaimer This package is a developer CLI and runtime helper that performs file I/O, network access (translation provider APIs on user request), and environment variable access. As such, Socket.dev will flag the following alerts that are **expected and by design**: | Alert | Why it's expected | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Network access | Only contacts configured translation providers via HTTPS when user invokes auto-translate. All outbound calls flow through `safe-network.js` with host/path allowlist validation, response size limits, private-network blocking, and redacted security event logging. No telemetry, no unexpected outbound calls. | | Environment variable access | Centralized through `env-manager.js` with a strict allowlist. Blocks `SECRET`, `PASSWORD`, `KEY`, `TOKEN`, `AWS_*`, `NPM_*`, and 15+ other patterns. | | Filesystem access | Reads/writes only project locale files and reports within validated paths. All FS operations gated by `SecurityUtils.validatePath`. | | URL strings | Hardcoded default provider URLs for Google, DeepL, and LibreTranslate used only for auto-translation. No external resource loading. | The v3.3.0 release resolves the actionable dynamic-require alert by eliminating all 21 instances. ## [3.2.0] - 2026-05-16 ### Security - **CRITICAL**: Fixed invalid `crypto.createCipherGCM`/`createDecipherGCM` API calls in `admin-pin.js` — replaced with `crypto.createCipheriv`/`createDecipheriv`. - **CRITICAL**: Fixed missing `SecurityUtils` imports in `admin-pin.js`, `security-config.js`, and `scripts/security-check.js` causing `ReferenceError` at runtime. - **CRITICAL**: Removed encryption key stored alongside ciphertext in `admin-pin.js`. The AES key was stored in the same JSON file as the encrypted PIN, providing zero cryptographic protection. Encryption key is now derived via HKDF from the scrypt hash. - Enforced HTTPS-only for G