i18ntk 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -68,6 +68,7 @@ class I18nValidator {
68
68
  this.config = config;
69
69
  this.errors = [];
70
70
  this.warnings = [];
71
+ this.keyNamingViolations = [];
71
72
  this.rl = null;
72
73
  }
73
74
 
@@ -167,6 +168,8 @@ class I18nValidator {
167
168
  const key = sanitizedArg.substring(2);
168
169
  if (['en', 'de', 'es', 'fr', 'ru', 'ja', 'zh'].includes(key)) {
169
170
  baseArgs.uiLanguage = key;
171
+ } else if (key === 'enforce-key-style') {
172
+ baseArgs.enforceKeyStyle = true;
170
173
  }
171
174
  }
172
175
  });
@@ -573,6 +576,25 @@ class I18nValidator {
573
576
  // Validate structure
574
577
  const structural = this.validateStructure(sourceContent, targetContent, language, fileName);
575
578
 
579
+ // Check key naming conventions
580
+ if (this.config.enforceKeyStyle) {
581
+ const keyNamingResult = this.validateKeyNaming(sourceContent);
582
+ keyNamingResult.violations.forEach(v => {
583
+ this.addWarning(
584
+ `Key naming violation in ${language}/${fileName}`,
585
+ { key: v.key, suggestedFix: v.suggestedFix, reason: v.reason, style: keyNamingResult.style }
586
+ );
587
+ this.keyNamingViolations.push({
588
+ language,
589
+ fileName,
590
+ key: v.key,
591
+ suggestedFix: v.suggestedFix,
592
+ reason: v.reason,
593
+ style: keyNamingResult.style
594
+ });
595
+ });
596
+ }
597
+
576
598
  // Validate translations
577
599
  const translations = this.validateTranslation(targetContent, language, fileName);
578
600
  this.checkPlaceholders(sourceContent, targetContent, language, fileName);
@@ -652,7 +674,68 @@ class I18nValidator {
652
674
  return warnings;
653
675
  }
654
676
 
655
- // Show help message
677
+ validateKeyNaming(sourceObj, style) {
678
+ const keyStyle = style || this.config.keyStyle || 'dot.notation';
679
+ const allKeys = this.getAllKeys(sourceObj);
680
+ const validators = {
681
+ 'dot.notation': /^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*)*$/,
682
+ 'snake_case': /^[a-z][a-z0-9]*(_[a-z][a-z0-9]*)*$/,
683
+ 'camelCase': /^[a-z][a-zA-Z0-9]*$/,
684
+ 'kebab-case': /^[a-z][a-z0-9]*(-[a-z][a-z0-9]*)*$/,
685
+ 'flat': /^[a-zA-Z][a-zA-Z0-9]*$/
686
+ };
687
+ const regex = validators[keyStyle];
688
+ if (!regex) {
689
+ return { violations: [], totalKeys: allKeys.size, violationCount: 0, style: keyStyle };
690
+ }
691
+ const violations = [];
692
+ for (const key of allKeys) {
693
+ const sanitizedKey = SecurityUtils.sanitizeInput(key);
694
+ if (!regex.test(sanitizedKey)) {
695
+ violations.push({
696
+ key: sanitizedKey,
697
+ suggestedFix: this.suggestKeyFix(sanitizedKey, keyStyle),
698
+ reason: `Key "${sanitizedKey}" does not match "${keyStyle}" naming convention`
699
+ });
700
+ }
701
+ }
702
+ return {
703
+ violations,
704
+ totalKeys: allKeys.size,
705
+ violationCount: violations.length,
706
+ style: keyStyle
707
+ };
708
+ }
709
+
710
+ suggestKeyFix(key, style) {
711
+ const sanitizedKey = SecurityUtils.sanitizeInput(key);
712
+ const segments = [];
713
+ const rawTokens = sanitizedKey.split(/[._\-]/);
714
+ for (const token of rawTokens) {
715
+ if (!token) continue;
716
+ const camelTokens = token.split(/(?=[A-Z])/).filter(Boolean);
717
+ segments.push(...camelTokens);
718
+ }
719
+ if (segments.length === 0) {
720
+ return sanitizedKey;
721
+ }
722
+ switch (style) {
723
+ case 'dot.notation':
724
+ return segments.map(s => s.toLowerCase()).join('.');
725
+ case 'snake_case':
726
+ return segments.map(s => s.toLowerCase()).join('_');
727
+ case 'camelCase':
728
+ return segments.map((s, i) => i === 0 ? s.toLowerCase() : s.charAt(0).toUpperCase() + s.slice(1).toLowerCase()).join('');
729
+ case 'kebab-case':
730
+ return segments.map(s => s.toLowerCase()).join('-');
731
+ case 'flat':
732
+ return segments.map((s, i) => i === 0 ? s.toLowerCase() : s.charAt(0).toUpperCase() + s.slice(1).toLowerCase()).join('');
733
+ default:
734
+ return sanitizedKey;
735
+ }
736
+ }
737
+
738
+ // Show help message
656
739
  showHelp() {
657
740
  console.log(t('validate.help_message'));
658
741
  }
@@ -895,8 +978,29 @@ class I18nValidator {
895
978
  console.log('');
896
979
  });
897
980
  }
898
-
899
- // Recommendations
981
+
982
+ // Key naming violations summary
983
+ if (this.keyNamingViolations.length > 0) {
984
+ console.log('');
985
+ console.log(t('validate.separator'));
986
+ console.log('🔑 Key Naming Convention Violations');
987
+ console.log('');
988
+ const displayStyle = this.config.keyStyle || 'dot.notation';
989
+ console.log(` Expected style: ${displayStyle}`);
990
+ console.log(` Violations found: ${this.keyNamingViolations.length}`);
991
+ console.log('');
992
+ console.log(' Suggested fixes:');
993
+ this.keyNamingViolations.slice(0, 10).forEach((v, i) => {
994
+ console.log(` ${i + 1}. "${v.key}" → "${v.suggestedFix}" (${v.language}/${v.fileName})`);
995
+ });
996
+ if (this.keyNamingViolations.length > 10) {
997
+ console.log(` ... and ${this.keyNamingViolations.length - 10} more`);
998
+ }
999
+ console.log('');
1000
+ console.log(' 💡 Tip: Use i18ntk:fix-keys to auto-fix or manually rename keys.');
1001
+ }
1002
+
1003
+ // Recommendations
900
1004
  console.log('');
901
1005
  console.log(t('validate.separator'));
902
1006
  console.log(t('validate.recommendationsSection'));
@@ -530,20 +530,20 @@ class FixerCommand {
530
530
  this.dryRun = args.dryRun || false;
531
531
  this.force = args.force || false;
532
532
 
533
- if (!args.json) {
534
- console.log(t('fixer.starting'));
535
- console.log(t('fixer.sourceDirectory', { dir: path.resolve(this.sourceDir) }));
536
- console.log(t('fixer.dryRunMode', { mode: this.dryRun ? 'ON' : 'OFF' }));
537
- }
533
+ const languages = this.getAvailableLanguages();
534
+
535
+ if (!args.json) {
536
+ console.log(t('fixer.starting', { languages: languages.join(', ') || 'none' }));
537
+ console.log(t('fixer.sourceDirectory', { sourceDir: path.resolve(this.sourceDir) }));
538
+ console.log(t('fixer.dryRunMode', { mode: this.dryRun ? 'ON' : 'OFF' }));
539
+ }
538
540
 
539
541
  // Create backup unless disabled
540
542
  if (!args.noBackup && !this.dryRun && this.config?.backup?.enabled === true) {
541
543
  await this.createBackup();
542
544
  }
543
545
 
544
- const languages = this.getAvailableLanguages();
545
-
546
- if (languages.length === 0) {
546
+ if (languages.length === 0) {
547
547
  const error = t('fixer.noLanguages') || 'No target languages found.';
548
548
  if (args.json) {
549
549
  jsonOutput.setStatus('error', error);
@@ -573,14 +573,16 @@ class FixerCommand {
573
573
  totalIssues += fixes.totalIssues;
574
574
  totalFixed += fixes.fixedIssues;
575
575
 
576
- if (!args.json) {
577
- console.log(t('fixer.languageFixed', {
578
- language,
579
- issues: fixes.totalIssues,
580
- fixed: fixes.fixedIssues
581
- }));
582
- }
583
- }
576
+ if (!args.json) {
577
+ const skipped = Math.max(0, fixes.totalIssues - fixes.fixedIssues);
578
+ console.log(t('fixer.languageFixed', {
579
+ language,
580
+ issues: fixes.totalIssues,
581
+ fixed: fixes.fixedIssues,
582
+ skipped
583
+ }));
584
+ }
585
+ }
584
586
 
585
587
  // Prepare JSON output
586
588
  if (args.json) {
@@ -595,11 +597,11 @@ class FixerCommand {
595
597
  return { success: true, totalIssues, totalFixed, results };
596
598
  }
597
599
 
598
- // Summary
599
- console.log(t('fixer.summary'));
600
- console.log('='.repeat(50));
601
- console.log(t('fixer.totalIssues', { count: totalIssues }));
602
- console.log(t('fixer.totalFixed', { count: totalFixed }));
600
+ // Summary
601
+ console.log(t('fixer.summary'));
602
+ console.log('='.repeat(50));
603
+ console.log(t('fixer.totalIssues', { totalIssues }));
604
+ console.log(t('fixer.totalFixed', { count: totalFixed }));
603
605
 
604
606
  if (this.backupDir && !args.noBackup && this.config?.backup?.enabled === true) {
605
607
  console.log(t('fixer.backupLocation', { dir: this.backupDir }));
@@ -1220,7 +1220,10 @@ class I18nManager {
1220
1220
  { path: path.join(process.cwd(), 'scripts', 'debug', 'logs'), name: 'Debug Logs', type: 'logs' },
1221
1221
  { path: path.join(process.cwd(), 'scripts', 'debug', 'reports'), name: 'Debug Reports', type: 'reports' },
1222
1222
  { path: path.join(process.cwd(), 'settings', 'backups'), name: 'Settings Backups', type: 'backups' },
1223
- { path: path.join(process.cwd(), 'utils', 'i18ntk-reports'), name: 'Utils Reports', type: 'reports' }
1223
+ { path: path.join(process.cwd(), 'utils', 'i18ntk-reports'), name: 'Utils Reports', type: 'reports' },
1224
+ { path: path.join(process.cwd(), '.cache'), name: 'Cache', type: 'cache', includeAllFiles: true },
1225
+ { path: path.join(process.cwd(), 'settings', '.cache'), name: 'Settings Cache', type: 'cache', includeAllFiles: true },
1226
+ { path: path.join(process.cwd(), '.cache-ultra'), name: 'Performance Cache', type: 'cache', includeAllFiles: true }
1224
1227
  ].filter(dir => dir.path && typeof dir.path === 'string');
1225
1228
 
1226
1229
  try {
@@ -1233,7 +1236,9 @@ class I18nManager {
1233
1236
  for (const dir of targetDirs) {
1234
1237
  const validatedDirPath = SecurityUtils.validatePath(dir.path, projectRoot);
1235
1238
  if (validatedDirPath && SecurityUtils.safeExistsSync(validatedDirPath, projectRoot)) {
1236
- const files = this.getAllReportFiles(validatedDirPath, validatedDirPath);
1239
+ const files = this.getAllReportFiles(validatedDirPath, validatedDirPath, {
1240
+ includeAllFiles: dir.includeAllFiles === true
1241
+ });
1237
1242
  if (files.length > 0) {
1238
1243
  availableDirs.push({
1239
1244
  ...dir,
@@ -1368,12 +1373,13 @@ class I18nManager {
1368
1373
  await this.showInteractiveMenu();
1369
1374
  }
1370
1375
 
1371
- getAllReportFiles(dir, rootDir = dir) {
1376
+ getAllReportFiles(dir, rootDir = dir, options = {}) {
1372
1377
  if (!dir || typeof dir !== 'string') {
1373
1378
  return [];
1374
1379
  }
1375
1380
 
1376
- let files = [];
1381
+ let files = [];
1382
+ const includeAllFiles = options.includeAllFiles === true;
1377
1383
 
1378
1384
  try {
1379
1385
  const validatedDir = SecurityUtils.validatePath(dir, rootDir);
@@ -1399,8 +1405,8 @@ class I18nManager {
1399
1405
  const stat = fs.statSync(safeFullPath);
1400
1406
 
1401
1407
  if (stat.isDirectory()) {
1402
- files.push(...this.getAllReportFiles(safeFullPath, rootDir));
1403
- } else if (
1408
+ files.push(...this.getAllReportFiles(safeFullPath, rootDir, options));
1409
+ } else if (includeAllFiles || (
1404
1410
  // Common report file extensions
1405
1411
  item.endsWith('.json') ||
1406
1412
  item.endsWith('.html') ||
@@ -1415,7 +1421,7 @@ class I18nManager {
1415
1421
  item.includes('report_') ||
1416
1422
  item.includes('analysis-') ||
1417
1423
  item.includes('validation-')
1418
- ) {
1424
+ )) {
1419
1425
  files.push(safeFullPath);
1420
1426
  }
1421
1427
  } catch (error) {
@@ -129,7 +129,10 @@ module.exports = class FileManagementService {
129
129
  { path: path.join(process.cwd(), 'scripts', 'debug', 'logs'), name: 'Debug Logs', type: 'logs' },
130
130
  { path: path.join(process.cwd(), 'scripts', 'debug', 'reports'), name: 'Debug Reports', type: 'reports' },
131
131
  { path: path.join(process.cwd(), 'settings', 'backups'), name: 'Settings Backups', type: 'backups' },
132
- { path: path.join(process.cwd(), 'utils', 'i18ntk-reports'), name: 'Utils Reports', type: 'reports' }
132
+ { path: path.join(process.cwd(), 'utils', 'i18ntk-reports'), name: 'Utils Reports', type: 'reports' },
133
+ { path: path.join(process.cwd(), '.cache'), name: 'Cache', type: 'cache', includeAllFiles: true },
134
+ { path: path.join(process.cwd(), 'settings', '.cache'), name: 'Settings Cache', type: 'cache', includeAllFiles: true },
135
+ { path: path.join(process.cwd(), '.cache-ultra'), name: 'Performance Cache', type: 'cache', includeAllFiles: true }
133
136
  ].filter(dir => dir.path && typeof dir.path === 'string');
134
137
 
135
138
  try {
@@ -140,7 +143,9 @@ module.exports = class FileManagementService {
140
143
  // Check which directories exist and have files
141
144
  for (const dir of targetDirs) {
142
145
  if (SecurityUtils.safeExistsSync(dir.path)) {
143
- const files = this.getAllReportFiles(dir.path);
146
+ const files = this.getAllReportFiles(dir.path, {
147
+ includeAllFiles: dir.includeAllFiles === true
148
+ });
144
149
  if (files.length > 0) {
145
150
  availableDirs.push({
146
151
  ...dir,
@@ -267,12 +272,13 @@ module.exports = class FileManagementService {
267
272
  * @param {string} dir - Directory to scan
268
273
  * @returns {string[]} Array of file paths
269
274
  */
270
- getAllReportFiles(dir) {
275
+ getAllReportFiles(dir, options = {}) {
271
276
  if (!dir || typeof dir !== 'string') {
272
277
  return [];
273
278
  }
274
279
 
275
280
  let files = [];
281
+ const includeAllFiles = options.includeAllFiles === true;
276
282
 
277
283
  try {
278
284
  if (!SecurityUtils.safeExistsSync(dir)) {
@@ -287,8 +293,8 @@ module.exports = class FileManagementService {
287
293
  const stat = fs.statSync(fullPath);
288
294
 
289
295
  if (stat.isDirectory()) {
290
- files.push(...this.getAllReportFiles(fullPath));
291
- } else if (
296
+ files.push(...this.getAllReportFiles(fullPath, options));
297
+ } else if (includeAllFiles || (
292
298
  // Common report file extensions
293
299
  item.endsWith('.json') ||
294
300
  item.endsWith('.html') ||
@@ -303,7 +309,7 @@ module.exports = class FileManagementService {
303
309
  item.includes('report_') ||
304
310
  item.includes('analysis-') ||
305
311
  item.includes('validation-')
306
- ) {
312
+ )) {
307
313
  files.push(fullPath);
308
314
  }
309
315
  } catch (error) {
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "i18ntk",
3
- "version": "3.2.0",
3
+ "version": "4.0.0",
4
4
  "description": "i18n Tool Kit - Zero-dependency internationalization toolkit for setup, scanning, analysis, validation, auto translation, fixing, reporting, and runtime translation loading.",
5
5
  "readmeFilename": "README.md",
6
6
  "keywords": [
7
7
  "i18ntk",
8
- "i18n-toolkit",
9
8
  "i18n",
10
9
  "internationalization",
11
10
  "localization",
@@ -123,6 +122,7 @@
123
122
  "utils/formats/json.js",
124
123
  "utils/translate/placeholder.js",
125
124
  "utils/translate/api.js",
125
+ "utils/translate/safe-network.js",
126
126
  "utils/translate/traverse.js",
127
127
  "utils/translate/report.js",
128
128
  "utils/translate/cli.js",
@@ -161,5 +161,5 @@
161
161
  "access": "public"
162
162
  },
163
163
  "preferGlobal": true,
164
- "readme": "# i18ntk v3.2.0\n\nZero-dependency internationalization toolkit for setup, scanning, analysis, validation, usage tracking, translation completion, automatic JSON locale translation, reporting, and runtime translation loading.\n\n![i18ntk Logo](https://raw.githubusercontent.com/vladnoskv/i18ntk/main/docs/screenshots/i18ntk-logo-public.PNG)\n\n[![npm version](https://img.shields.io/npm/v/i18ntk.svg?color=brightgreen)](https://www.npmjs.com/package/i18ntk)\n[![npm downloads](https://img.shields.io/npm/dt/i18ntk.svg)](https://www.npmjs.com/package/i18ntk)\n[![node](https://img.shields.io/badge/node-%3E%3D16-339933)](https://nodejs.org)\n[![dependencies](https://img.shields.io/badge/dependencies-0-success)](https://www.npmjs.com/package/i18ntk)\n[![license](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)\n[![socket](https://socket.dev/api/badge/npm/package/i18ntk/3.2.0)](https://socket.dev/npm/package/i18ntk/overview/3.2.0)\n\n## Install\n\n```bash\n# global CLI use\nnpm install -g i18ntk\n\n# local project use\nnpm install --save-dev i18ntk\n\n# one-off execution\nnpx i18ntk --help\n```\n\nRequirements:\n\n- Node.js `>=16.0.0`\n- npm `>=8.0.0`\n- No runtime dependencies\n\n## What's New in 3.2.0\n\n- **SECURITY**: Fixed 4 critical runtime-crash bugs (invalid crypto APIs, missing imports) across admin-pin.js, security-config.js, and scripts/security-check.js.\n- **SECURITY**: Removed encryption key stored alongside ciphertext in admin-pin.js; encryption key is now derived via HKDF.\n- **SECURITY**: Enforced HTTPS-only for Google Translate API requests; fixed http.get timeout for Node.js <16.14 compatibility.\n- **SECURITY**: Added path validation to backup restore/verify operations; locked down FileManagementService PIN verification stubs.\n\nSee [CHANGELOG.md](./CHANGELOG.md) and [docs/migration-guide-v3.2.0.md](./docs/migration-guide-v3.2.0.md) for release details.\n\n## Quick Start\n\nInitialize a project:\n\n```bash\ni18ntk\n# or\ni18ntk --command=init\n```\n\nRun common checks:\n\n```bash\ni18ntk --command=analyze\ni18ntk --command=validate\ni18ntk --command=usage\ni18ntk --command=sizing\ni18ntk --command=summary\n```\n\nComplete or fix translation files:\n\n```bash\ni18ntk --command=complete\ni18ntk-fixer --help\n```\n\nAuto-translate locale JSON:\n\n```bash\ni18ntk --command=translate\n# or\ni18ntk-translate locales/en/common.json de --report-stdout\n```\n\nThe full onboarding guide is in [docs/getting-started.md](./docs/getting-started.md).\n\n## Main Commands\n\nPrimary CLI:\n\n```bash\ni18ntk\ni18ntk --help\ni18ntk --command=init\ni18ntk --command=analyze\ni18ntk --command=validate\ni18ntk --command=usage\ni18ntk --command=scanner\ni18ntk --command=sizing\ni18ntk --command=complete\ni18ntk --command=translate\ni18ntk --command=summary\ni18ntk --command=debug\n```\n\nStandalone executables:\n\n```bash\ni18ntk-init\ni18ntk-analyze\ni18ntk-validate\ni18ntk-usage\ni18ntk-scanner\ni18ntk-sizing\ni18ntk-complete\ni18ntk-summary\ni18ntk-doctor\ni18ntk-fixer\ni18ntk-backup\ni18ntk-translate\n```\n\nNote: manager route `i18ntk --command=backup` is disabled in current builds. Use `i18ntk-backup` directly for backup operations.\n\n## Common Options\n\nMost commands support:\n\n- `--source-dir <path>`\n- `--i18n-dir <path>`\n- `--output-dir <path>`\n- `--source-language <code>`\n- `--ui-language <code>`\n- `--no-prompt`\n- `--dry-run`\n- `--help`\n\nExample:\n\n```bash\ni18ntk --command=analyze --source-dir=./src --i18n-dir=./locales --output-dir=./i18ntk-reports\n```\n\n## Auto Translate\n\nInteractive manager flow:\n\n```bash\ni18ntk\n# choose \"Auto Translate (Beta)\"\n```\n\nDirect CLI examples:\n\n```bash\ni18ntk-translate locales/en/common.json de\ni18ntk-translate locales/en/common.json fr --dry-run --report-stdout\ni18ntk-translate locales/en es --source-dir locales/en --files \"*.json\" --no-confirm --preserve-placeholders\n```\n\nThe manager flow asks for:\n\n- source locale directory, either the folder with JSON files or a locale root such as `./locales`\n- source language code\n- one or more target languages, or `all`\n- one JSON file or all JSON files in the source directory\n\nIf you select a locale root such as `./locales` and choose source language `en`, the manager automatically uses `./locales/en` when that folder contains the source JSON files.\n\nBefore writing files, the manager can run a dry-run preview. After confirmation it writes translated files under sibling target-language folders, for example:\n\n```text\nlocales/en/common.json\nlocales/de/common.json\nlocales/fr/common.json\n```\n\n### Placeholder Handling\n\nAuto Translate detects common placeholders such as:\n\n- `{name}`\n- `{{count}}`\n- `%s`\n- `%d`\n- `:id`\n- `%{name}`\n- `${value}`\n\nUseful flags:\n\n- `--preserve-placeholders`: translate text around placeholders and reinsert original tokens\n- `--skip-placeholders`: copy placeholder-bearing strings unchanged\n- `--send-placeholders`: send placeholder-bearing strings through translation after masking\n- `--custom-regex <regex>`: add project-specific placeholder detection\n\n### Protected Terms and Keys\n\nAuto Translate can create and use a project-local protection file:\n\n```bash\ni18ntk-translate locales/en/common.json de --create-protection-file --protection-file ./i18ntk-auto-translate.json\n```\n\nExample `i18ntk-auto-translate.json`:\n\n```json\n{\n \"version\": 1,\n \"terms\": [\"BrandName\", \"PRODUCT_CODE\", \"API\"],\n \"keys\": [\"app.brandName\", \"legal.companyName\", \"product.*.symbol\"],\n \"values\": [\"BrandName Ltd\", \"support@example.com\"],\n \"patterns\": [\"[A-Z]{2,}-\\\\d+\"]\n}\n```\n\n- `terms` are masked before translation and restored exactly afterward.\n- `keys` are exact key paths or `*` wildcard paths copied unchanged.\n- `values` are exact source values copied unchanged.\n- `patterns` are JavaScript regex strings for advanced protected substrings.\n\nUseful flags:\n\n- `--protection-file <path>`\n- `--create-protection-file`\n- `--no-protection`\n\nOpen Settings and choose `Auto Translate Beta` to edit defaults for placeholder mode, concurrency, batch size, retry settings, report output, BOM output, protection file path, first-run setup prompt, and update prompt.\n\nSee [docs/auto-translate.md](./docs/auto-translate.md) for the full Auto Translate guide.\n\n## Validation\n\nValidation checks locale structure, completeness, placeholders, and content risks.\n\nIn 3.1.2, warning types are more specific:\n\n- `Potential risky content`: URL, email address, or secret-like value\n- `Possible untranslated English content`: target-language value appears to contain too much English\n\nEnglish-content warnings include:\n\n- detected English percentage\n- configured threshold\n- matched word count\n- sample matched words\n\nTune warnings in `.i18ntk-config`:\n\n```json\n{\n \"englishContentThresholdPercent\": 10,\n \"allowedEnglishTerms\": [\"BrandName\", \"PRODUCT_CODE\"]\n}\n```\n\n## Sizing Analysis\n\n`i18ntk-sizing` reports translation file sizes, key counts, average value length, and file-set mismatches across language folders.\n\n```bash\ni18ntk-sizing --source-dir ./locales --format table\ni18ntk-sizing --source-dir ./locales --detailed --output-dir ./i18ntk-reports\n```\n\nUse `--detailed` to print per-file rows in the terminal.\n\n## Runtime API\n\nUse `i18ntk/runtime` when an application needs to read locale JSON files at runtime.\n\n```js\nconst runtime = require('i18ntk/runtime');\n\nruntime.initRuntime({\n baseDir: './locales',\n language: 'en',\n fallbackLanguage: 'en',\n keySeparator: '.',\n preload: true\n});\n\nconsole.log(runtime.t('common.hello'));\nruntime.setLanguage('fr');\nconsole.log(runtime.getLanguage());\nconsole.log(runtime.getAvailableLanguages());\nruntime.refresh('fr');\n```\n\nSee [docs/runtime.md](./docs/runtime.md) for runtime details.\n\n## Configuration\n\ni18ntk uses a project-local `.i18ntk-config` file.\n\nExample:\n\n```json\n{\n \"version\": \"3.2.0\",\n \"sourceDir\": \"./locales\",\n \"i18nDir\": \"./locales\",\n \"outputDir\": \"./i18ntk-reports\",\n \"sourceLanguage\": \"en\",\n \"defaultLanguages\": [\"de\", \"es\", \"fr\", \"ru\"],\n \"englishContentThresholdPercent\": 10,\n \"allowedEnglishTerms\": [\"BrandName\", \"PRODUCT_CODE\"],\n \"autoTranslate\": {\n \"placeholderMode\": \"preserve\",\n \"concurrency\": 6,\n \"batchSize\": 100,\n \"progressInterval\": 25,\n \"retryCount\": 3,\n \"retryDelay\": 1000,\n \"timeout\": 15000,\n \"dryRunFirst\": true,\n \"reportStdout\": true,\n \"bom\": false,\n \"protectionEnabled\": true,\n \"protectionFile\": \"./i18ntk-auto-translate.json\",\n \"promptProtectionSetup\": true,\n \"promptProtectionUpdate\": true\n },\n \"setup\": {\n \"completed\": true\n }\n}\n```\n\nSee [docs/api/CONFIGURATION.md](./docs/api/CONFIGURATION.md) for the full configuration model.\n\n## Public Package Contents\n\nThe public package intentionally ships runtime and CLI files only. The publish staging script excludes development-only content such as tests, scripts, docs, release staging folders, local config files, and generated protection files.\n\nThe package includes:\n\n- CLI entry points under `main/`\n- manager commands and services\n- runtime API files under `runtime/`\n- settings UI files required at runtime\n- bundled internal UI locales\n- shared utilities required by the shipped commands\n- `README.md`, `CHANGELOG.md`, `LICENSE`, and policy files\n\nThe public package manifest includes `readmeFilename: \"README.md\"`, and the release staging script fails if `README.md` is missing or empty.\n\n## Documentation\n\n- [Documentation Index](./docs/README.md)\n- [Getting Started](./docs/getting-started.md)\n- [API Reference](./docs/api/API_REFERENCE.md)\n- [Configuration Guide](./docs/api/CONFIGURATION.md)\n- [Runtime API Guide](./docs/runtime.md)\n- [Auto Translate Guide](./docs/auto-translate.md)\n- [Scanner Guide](./docs/scanner-guide.md)\n- [Environment Variables](./docs/environment-variables.md)\n- [Migration Guide v3.2.0](./docs/migration-guide-v3.2.0.md)\n- [Migration Guide v3.1.1](./docs/migration-guide-v3.1.1.md)\n- [Migration Guide v3.0.0](./docs/migration-guide-v3.0.0.md)\n- [Migration Guide v2.6.0](./docs/migration-guide-v2.6.0.md)\n- [Migration Guide v2.5.1](./docs/migration-guide-v2.5.1.md)\n\n## Security\n\n- No API key is required for the default Auto Translate flow.\n- Do not store secrets in locale files, `.i18ntk-config`, or protection files.\n- Project-specific brand/product terms should be configured by the user, not hardcoded into the package.\n- Report security issues using [SECURITY.md](./SECURITY.md).\n\n## Community\n\n- [Contributing](./CONTRIBUTING.md)\n- [Code of Conduct](./CODE_OF_CONDUCT.md)\n- [Funding](./FUNDING.md)\n\n## License\n\nMIT. See [LICENSE](./LICENSE).\n"
164
+ "readme": "# i18ntk v4.0.0\n\nA i18n toolkit - A zero-dependency internationalization toolkit for setup, scanning, analysis, validation, usage tracking, translation completion, automatic JSON locale translation, reporting, and runtime translation loading.\n\n![i18ntk Logo](https://raw.githubusercontent.com/vladnoskv/i18ntk/main/docs/screenshots/i18ntk-logo-public.PNG)\n\n[![npm version](https://img.shields.io/npm/v/i18ntk.svg?color=brightgreen)](https://www.npmjs.com/package/i18ntk)\n[![npm downloads](https://img.shields.io/npm/dt/i18ntk.svg)](https://www.npmjs.com/package/i18ntk)\n[![node](https://img.shields.io/badge/node-%3E%3D16-339933)](https://nodejs.org)\n[![dependencies](https://img.shields.io/badge/dependencies-0-success)](https://www.npmjs.com/package/i18ntk)\n[![license](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)\n[![socket](https://socket.dev/api/badge/npm/package/i18ntk/4.0.0)](https://socket.dev/npm/package/i18ntk/overview/4.0.0)\n\n## Install\n\n```bash\n# global CLI use\nnpm install -g i18ntk\n\n# local project use\nnpm install --save-dev i18ntk\n\n# one-off execution\nnpx i18ntk --help\n```\n\nRequirements:\n\n- Node.js `>=16.0.0`\n- npm `>=8.0.0`\n- No runtime dependencies\n\n## What's New in 4.0.0\n\n- **SIZING**: `--predict-expansion` flag computes per-key expansion ratios across languages with Safe/Warning/Critical risk tiers for UI layout planning.\n- **WATCH**: `watchLocales()` now returns an EventEmitter-compatible watcher with debounced `change`/`add`/`unlink`/`error` events and SHA-256 hash tracking.\n- **USAGE**: `--cleanup` and `--dry-run-delete` flags identify dead translation keys with confidence scores.\n- **VALIDATOR**: `--enforce-key-style` enforces dot.notation, snake_case, camelCase, kebab-case, or flat naming conventions.\n- **SCANNER**: `--source-language` supports multi-language hardcoded text detection with 12+ language profiles.\n- **BACKUP**: `--incremental` flag creates differential backups with SHA-256 hashing and chained restores.\n- **RUNTIME**: `lazy: true` option defers locale file loading until first key access for lower memory usage.\n- **PROTECTION**: Context-aware rules (`after:word`, `before:word`, `standalone`, `surrounded:left,right`) for precise term masking.\n- **FIX**: `initRuntime()` now returns independent instances with isolated language and cache state.\n\nSee [CHANGELOG.md](./CHANGELOG.md) for more release details.\n\n## Quick Start\n\nInitialize a project:\n\n```bash\ni18ntk\n# or with explicit command\ni18ntk --command=init\n```\n\nRun common checks:\n\n```bash\ni18ntk --command=analyze\ni18ntk --command=validate\ni18ntk --command=usage\ni18ntk --command=sizing\ni18ntk --command=summary\n```\n\nComplete or fix translation files:\n\n```bash\ni18ntk --command=complete\ni18ntk-fixer --help\n```\n\nAuto-translate locale JSON:\n\n```bash\ni18ntk --command=translate\n# or\ni18ntk-translate locales/en/common.json de --report-stdout\n```\n\nThe full onboarding guide is in [docs/getting-started.md](./docs/getting-started.md).\n\n## Main Commands\n\nPrimary CLI:\n\n```bash\ni18ntk\ni18ntk --help\ni18ntk --command=init\ni18ntk --command=analyze\ni18ntk --command=validate\ni18ntk --command=usage\ni18ntk --command=scanner\ni18ntk --command=sizing\ni18ntk --command=complete\ni18ntk --command=translate\ni18ntk --command=summary\ni18ntk --command=debug\n```\n\nStandalone executables:\n\n```bash\ni18ntk-init\ni18ntk-analyze\ni18ntk-validate\ni18ntk-usage\ni18ntk-scanner\ni18ntk-sizing\ni18ntk-complete\ni18ntk-summary\ni18ntk-doctor\ni18ntk-fixer\ni18ntk-backup\ni18ntk-translate\n```\n`n\nNote: manager route `i18ntk --command=backup` is disabled in current builds. Use `i18ntk-backup` (or legacy `i18ntk-backup`) directly for backup operations.\n\n## Common Options\n\nMost commands support:\n\n- `--source-dir <path>`\n- `--i18n-dir <path>`\n- `--output-dir <path>`\n- `--source-language <code>`\n- `--ui-language <code>`\n- `--no-prompt`\n- `--dry-run`\n- `--help`\n\nExample:\n\n```bash\ni18ntk --command=analyze --source-dir=./src --i18n-dir=./locales --output-dir=./i18ntk-reports\n```\n\n## Auto Translate\n\nInteractive manager flow:\n\n```bash\ni18ntk\n# choose \"Auto Translate (Beta)\"\n```\n\nDirect CLI examples:\n\n```bash\ni18ntk-translate locales/en/common.json de\ni18ntk-translate locales/en/common.json fr --dry-run --report-stdout\ni18ntk-translate locales/en es --source-dir locales/en --files \"*.json\" --no-confirm --preserve-placeholders\n```\n\nProvider examples:\n\n```bash\nexport DEEPL_API_KEY=\"your-deepl-api-key\"\ni18ntk-translate locales/en/common.json de --provider deepl --no-confirm --preserve-placeholders\n\nexport LIBRETRANSLATE_URL=\"https://libretranslate.com/translate\"\nexport LIBRETRANSLATE_API_KEY=\"optional-api-key\"\ni18ntk-translate locales/en/common.json es --provider libretranslate --no-confirm --preserve-placeholders\n```\n\n`google` remains the default provider. You can also set `I18NTK_TRANSLATE_PROVIDER=deepl` or `I18NTK_TRANSLATE_PROVIDER=libretranslate`.\n\nProvider requests are HTTPS-only and response-size limited, and security logs redact provider query strings and response bodies. DeepL is pinned to official DeepL hosts by default; set `I18NTK_ALLOW_CUSTOM_TRANSLATE_HOSTS=1` only for a trusted DeepL-compatible proxy. Custom LibreTranslate URLs are blocked for localhost/private IP ranges unless `I18NTK_ALLOW_PRIVATE_TRANSLATE_URLS=1` is set for trusted local testing. Keep provider API keys in environment variables or a secret manager.\n\nThe manager flow asks for:\n\n- source locale directory, either the folder with JSON files or a locale root such as `./locales`\n- source language code\n- one or more target languages, or `all`\n- one JSON file or all JSON files in the source directory\n\nIf you select a locale root such as `./locales` and choose source language `en`, the manager automatically uses `./locales/en` when that folder contains the source JSON files.\n\nBefore writing files, the manager can run a dry-run preview. After confirmation it writes translated files under sibling target-language folders, for example:\n\n```text\nlocales/en/common.json\nlocales/de/common.json\nlocales/fr/common.json\n```\n\n### Placeholder Handling\n\nAuto Translate detects common placeholders such as:\n\n- `{name}`\n- `{{count}}`\n- `%s`\n- `%d`\n- `:id`\n- `%{name}`\n- `${value}`\n\nUseful flags:\n\n- `--preserve-placeholders`: translate text around placeholders and reinsert original tokens\n- `--skip-placeholders`: copy placeholder-bearing strings unchanged\n- `--send-placeholders`: send placeholder-bearing strings through translation after masking\n- `--custom-regex <regex>`: add project-specific placeholder detection\n\n### Protected Terms and Keys\n\nAuto Translate can create and use a project-local protection file:\n\n```bash\ni18ntk-translate locales/en/common.json de --create-protection-file --protection-file ./i18ntk-auto-translate.json\n```\n\nExample `i18ntk-auto-translate.json`:\n\n```json\n{\n \"version\": 1,\n \"terms\": [\n \"BrandName\",\n \"PRODUCT_CODE\",\n { \"value\": \"OK\", \"context\": \"after:Click|Press|Tap\" },\n { \"value\": \"API\", \"context\": \"standalone\" }\n ],\n \"keys\": [\"app.brandName\", \"legal.companyName\", \"product.*.symbol\"],\n \"values\": [\"BrandName Ltd\", \"support@example.com\"],\n \"patterns\": [\"[A-Z]{2,}-\\\\d+\"]\n}\n```\n\n- `terms` are masked before translation and restored exactly afterward.\n - **Plain strings**: masked everywhere (backward compatible).\n - **Context objects**: masked only in specific contexts (`after:word`, `before:word`, `standalone`, `surrounded:left,right`).\n- `keys` are exact key paths or `*` wildcard paths copied unchanged.\n- `values` are exact source values copied unchanged.\n- `patterns` are JavaScript regex strings for advanced protected substrings.\n\nUseful flags:\n\n- `--protection-file <path>`\n- `--create-protection-file`\n- `--no-protection`\n\nOpen Settings and choose `Auto Translate Beta` to edit defaults for placeholder mode, concurrency, batch size, retry settings, report output, BOM output, protection file path, first-run setup prompt, and update prompt.\n\nSee [docs/auto-translate.md](./docs/auto-translate.md) for the full Auto Translate guide.\n\n## Validation\n\nValidation checks locale structure, completeness, placeholders, and content risks.\n\nIn 3.1.2, warning types are more specific:\n\n- `Potential risky content`: URL, email address, or secret-like value\n- `Possible untranslated English content`: target-language value appears to contain too much English\n\nEnglish-content warnings include:\n\n- detected English percentage\n- configured threshold\n- matched word count\n- sample matched words\n\nTune warnings in `.i18ntk-config`:\n\n```json\n{\n \"englishContentThresholdPercent\": 10,\n \"allowedEnglishTerms\": [\"BrandName\", \"PRODUCT_CODE\"]\n}\n```\n\n## Sizing Analysis\n\n`i18ntk-sizing` reports translation file sizes, key counts, average value length, and file-set mismatches across language folders.\n\n```bash\ni18ntk-sizing --source-dir ./locales --format table\ni18ntk-sizing --source-dir ./locales --detailed --output-dir ./i18ntk-reports\n```\n\nUse `--detailed` to print per-file rows in the terminal.\n\n### Expansion Prediction (New in 4.0.0)\n\nPredict UI layout overflow risk by analyzing per-key character-count expansion across languages:\n\n```bash\ni18ntk-sizing --source-dir ./locales --predict-expansion --output-report\n```\n\nExpansion ratios are classified into risk tiers:\n\n- **Safe** (<30% expansion): no UI impact expected\n- **Warning** (30–50%): may overflow in tight layouts — test on target languages\n- **Critical** (>50%): high risk of truncation — review UI element sizing\n\nThe report includes a built-in language-pair expansion reference table (EN→DE +35%, EN→RU +50%, EN→JA −40%, etc.) and lists the top-30 most-expanded keys.\n\n## Scanner: Multi-Language Detection (New in 4.0.0)\n\n`i18ntk-scanner` now supports detecting hardcoded text in multiple source languages beyond English:\n\n```bash\ni18ntk-scanner --source-dir ./src --source-language de\ni18ntk-scanner --source-dir ./src --source-language ja --output-report\n```\n\nSupported language profiles (12+): English, German, French, Spanish, Japanese, Chinese, Russian, Korean, Arabic, Hindi, and more. Each profile includes language-specific character ranges, stopword lists for false-positive filtering, and transliteration rules for key generation.\n\n## Usage: Dead Key Detection (New in 4.0.0)\n\n`i18ntk-usage` can identify translation keys that are defined but never referenced in source code:\n\n```bash\ni18ntk-usage --source-dir ./src --i18n-dir ./locales --cleanup\ni18ntk-usage --source-dir ./src --i18n-dir ./locales --cleanup --dry-run-delete\n```\n\nEach dead key receives a confidence score (0.0–1.0) factoring:\n- Dynamic key patterns (e.g., `` t(`prefix.${dynamic}`) ``) — lower score\n- Key appears in source code comments or JSDoc — medium score\n- Parent file recently modified (<30 days) — medium score\n- No references found anywhere — high score (>0.8)\n\nThe `--dry-run-delete` flag writes a `.dead-keys.json` report for review before any destructive action.\n\n## Validator: Key Naming Conventions (New in 4.0.0)\n\nEnforce consistent translation key naming across your project:\n\n```bash\ni18ntk-validate --enforce-key-style\n```\n\nConfigure the expected style in `.i18ntk-config`:\n\n```json\n{\n \"keyStyle\": \"dot.notation\"\n}\n```\n\nSupported styles: `dot.notation`, `snake_case`, `camelCase`, `kebab-case`, `flat`. Violations are reported as warnings with suggested canonical forms.\n\n## Watch: Hot Reload (New in 4.0.0)\n\n`utils/watch-locales.js` now provides debounced file watching with EventEmitter support:\n\n```js\nconst watchLocales = require('i18ntk/utils/watch-locales');\nconst watcher = watchLocales('./locales');\n\nwatcher.on('change', (filePath) => {\n console.log('Locale changed:', filePath);\n});\n\nwatcher.on('add', (filePath) => {\n console.log('Locale added:', filePath);\n});\n\n// Later:\nwatcher.stop();\n```\n\nFeatures: 300ms debounce (configurable), SHA-256 hash tracking to skip no-change saves, and a maximum of 50 watched directories.\n\n### Migration\n\nThe `watchLocales` return value gained EventEmitter methods in v4.0.0. Existing stop-function usage still works:\n\n```js\nconst stop = watchLocales('./locales', onChange);\n```\n\nCan be updated to:\n\n```js\nconst watcher = watchLocales('./locales');\nwatcher.on('change', onChange);\nwatcher.stop();\n```\n\nPassing a callback as the second argument is still supported — it auto-subscribes to `change` and `add` events.\n\n## Backup: Incremental Mode (New in 4.0.0)\n\nCreate differential backups that only include changed files:\n\n```bash\ni18ntk-backup create ./locales --incremental\n```\n\nIncremental backups store SHA-256 hashes per file and a parent-chain reference. Restoring an incremental backup automatically chains from the oldest full backup through each incremental diff in order. Chain depth is capped at 10 increments. Use `verify` to validate the hash chain.\n\n## Runtime: Lazy Loading (New in 4.0.0)\n\nReduce memory usage by deferring locale file loads until first key access:\n\n```js\nconst runtime = require('i18ntk/runtime');\n\nconst i18n = runtime.initRuntime({\n baseDir: './locales',\n language: 'en',\n lazy: true\n});\n\nconsole.log(i18n.t('common.hello')); // loads common.json on first access\n```\n\nWhen `lazy: true`, the runtime builds a key-to-file manifest on first access and loads individual files on demand. Files are loaded once and cached. If the manifest is missing or incomplete, the runtime falls back to full eager loading for that language. Manifest size is capped at 100KB with path containment validation.\n\n## Runtime API\n\nUse `i18ntk/runtime` when an application needs to read locale JSON files at runtime.\n\n```js\nconst runtime = require('i18ntk/runtime');\n\nconst i18n = runtime.initRuntime({\n baseDir: './locales',\n language: 'en',\n fallbackLanguage: 'en',\n keySeparator: '.',\n preload: true\n});\n\nconsole.log(i18n.t('common.hello'));\ni18n.setLanguage('fr');\nconsole.log(i18n.getLanguage());\nconsole.log(i18n.getAvailableLanguages());\ni18n.refresh('fr');\n```\n\nSee [docs/runtime.md](./docs/runtime.md) for runtime details.\n\n## Configuration\n\ni18ntk uses a project-local `.i18ntk-config` file.\n\nExample:\n\n```json\n{\n \"version\": \"4.0.0\",\n \"sourceDir\": \"./locales\",\n \"i18nDir\": \"./locales\",\n \"outputDir\": \"./i18ntk-reports\",\n \"sourceLanguage\": \"en\",\n \"defaultLanguages\": [\"de\", \"es\", \"fr\", \"ru\"],\n \"englishContentThresholdPercent\": 10,\n \"allowedEnglishTerms\": [\"BrandName\", \"PRODUCT_CODE\"],\n \"autoTranslate\": {\n \"placeholderMode\": \"preserve\",\n \"concurrency\": 6,\n \"batchSize\": 100,\n \"progressInterval\": 25,\n \"retryCount\": 3,\n \"retryDelay\": 1000,\n \"timeout\": 15000,\n \"dryRunFirst\": true,\n \"reportStdout\": true,\n \"bom\": false,\n \"protectionEnabled\": true,\n \"protectionFile\": \"./i18ntk-auto-translate.json\",\n \"promptProtectionSetup\": true,\n \"promptProtectionUpdate\": true\n },\n \"setup\": {\n \"completed\": true\n }\n}\n```\n\nSee [docs/api/CONFIGURATION.md](./docs/api/CONFIGURATION.md) for the full configuration model.\n\n## Public Package Contents\n\nThe public package intentionally ships runtime and CLI files only. The publish staging script excludes development-only content such as tests, scripts, docs, release staging folders, local config files, and generated protection files.\n\nThe package includes:\n\n- CLI entry points under `main/`\n- manager commands and services\n- runtime API files under `runtime/`\n- settings UI files required at runtime\n- bundled internal UI locales\n- shared utilities required by the shipped commands\n- `README.md`, `CHANGELOG.md`, `LICENSE`, and policy files\n\nThe public package manifest includes `readmeFilename: \"README.md\"`, and the release staging script fails if `README.md` is missing or empty.\n\n## Documentation\n\n- [Documentation Index](./docs/README.md)\n- [Getting Started](./docs/getting-started.md)\n- [API Reference](./docs/api/API_REFERENCE.md)\n- [Configuration Guide](./docs/api/CONFIGURATION.md)\n- [Runtime API Guide](./docs/runtime.md)\n- [Auto Translate Guide](./docs/auto-translate.md)\n- [Scanner Guide](./docs/scanner-guide.md)\n- [Environment Variables](./docs/environment-variables.md)\n- [Migration Guide v3.2.0](./docs/migration-guide-v3.2.0.md)\n- [Migration Guide v3.1.1](./docs/migration-guide-v3.1.1.md)\n- [Migration Guide v3.0.0](./docs/migration-guide-v3.0.0.md)\n\n## Security\n\n- No API key is required for the default Auto Translate flow.\n- Do not store secrets in locale files, `.i18ntk-config`, or protection files.\n- Project-specific brand/product terms should be configured by the user, not hardcoded into the package.\n- Report security issues using [SECURITY.md](./SECURITY.md).\n\n## Community\n\n- [Contributing](./CONTRIBUTING.md)\n- [Code of Conduct](./CODE_OF_CONDUCT.md)\n- [Funding](./FUNDING.md)\n\n## License\n\nMIT. See [LICENSE](./LICENSE).\n"
165
165
  }
@@ -471,11 +471,11 @@ export interface BasicI18nRuntime {
471
471
  */
472
472
  getAvailableLanguages(): string[];
473
473
 
474
- /**
475
- * Refresh translations
476
- */
477
- refresh(): void;
478
- }
474
+ /**
475
+ * Refresh translations
476
+ */
477
+ refresh(language?: string): void;
478
+ }
479
479
 
480
480
  /**
481
481
  * Initialize the enhanced i18ntk runtime (async, returns full I18nRuntime)
@@ -486,16 +486,22 @@ export declare function initI18nRuntime(config: I18nConfig): Promise<I18nRuntime
486
486
  * Initialize the basic lightweight runtime (synchronous)
487
487
  * This is the default export from 'i18ntk/runtime'
488
488
  */
489
- export declare function initRuntime(options: {
490
- baseDir: string;
491
- language?: string;
492
- fallbackLanguage?: string;
493
- keySeparator?: string;
494
- preload?: boolean;
495
- }): BasicI18nRuntime;
496
-
497
- /**
498
- * Type guards (runtime checks, not exported by actual code)
489
+ export declare function initRuntime(options: {
490
+ baseDir: string;
491
+ language?: string;
492
+ fallbackLanguage?: string;
493
+ keySeparator?: string;
494
+ preload?: boolean;
495
+ lazy?: boolean;
496
+ }): BasicI18nRuntime;
497
+
498
+ /**
499
+ * Build the lightweight runtime lazy-loading key manifest for a locale path.
500
+ */
501
+ export declare function loadKeyManifest(baseDir?: string): Map<string, string>;
502
+
503
+ /**
504
+ * Type guards (runtime checks, not exported by actual code)
499
505
  */
500
506
  export declare function isI18nRuntime(obj: any): obj is I18nRuntime;
501
507
  export declare function isBasicI18nRuntime(obj: any): obj is BasicI18nRuntime;
@@ -538,4 +544,4 @@ declare global {
538
544
  /**
539
545
  * Export all interfaces and types
540
546
  */
541
- export * from './enhanced';
547
+ export * from './enhanced';
@@ -4,10 +4,11 @@
4
4
  export interface InitOptions {
5
5
  baseDir?: string;
6
6
  language?: string;
7
- fallbackLanguage?: string;
8
- keySeparator?: string;
9
- preload?: boolean;
10
- }
7
+ fallbackLanguage?: string;
8
+ keySeparator?: string;
9
+ preload?: boolean;
10
+ lazy?: boolean;
11
+ }
11
12
 
12
13
  export type TranslateParams = Record<string, unknown>;
13
14
 
@@ -24,6 +25,7 @@ export function initRuntime(options?: InitOptions): {
24
25
  };
25
26
 
26
27
  export function setLanguage(lang: string): void;
27
- export function getLanguage(): string;
28
- export function getAvailableLanguages(): string[];
29
- export function refresh(lang?: string): void;
28
+ export function getLanguage(): string;
29
+ export function getAvailableLanguages(): string[];
30
+ export function refresh(lang?: string): void;
31
+ export function loadKeyManifest(baseDir?: string): Map<string, string>;