i18ntk 2.0.4 → 2.2.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.
Files changed (57) hide show
  1. package/README.md +38 -60
  2. package/main/i18ntk-analyze.js +49 -44
  3. package/main/i18ntk-complete.js +75 -74
  4. package/main/i18ntk-fixer.js +3 -3
  5. package/main/i18ntk-init.js +5 -5
  6. package/main/i18ntk-scanner.js +2 -2
  7. package/main/i18ntk-sizing.js +35 -35
  8. package/main/i18ntk-summary.js +4 -4
  9. package/main/i18ntk-ui.js +54 -8
  10. package/main/i18ntk-usage.js +14 -14
  11. package/main/i18ntk-validate.js +6 -5
  12. package/main/manage/commands/AnalyzeCommand.js +40 -35
  13. package/main/manage/commands/FixerCommand.js +2 -2
  14. package/main/manage/commands/ScannerCommand.js +2 -2
  15. package/main/manage/commands/ValidateCommand.js +9 -9
  16. package/main/manage/index.js +147 -75
  17. package/main/manage/managers/LanguageMenu.js +7 -2
  18. package/main/manage/services/UsageService.js +7 -7
  19. package/package.json +269 -290
  20. package/settings/settings-cli.js +3 -3
  21. package/ui-locales/de.json +161 -166
  22. package/ui-locales/en.json +13 -18
  23. package/ui-locales/es.json +171 -184
  24. package/ui-locales/fr.json +155 -161
  25. package/ui-locales/ja.json +192 -243
  26. package/ui-locales/ru.json +145 -196
  27. package/ui-locales/zh.json +179 -185
  28. package/utils/cli-helper.js +26 -98
  29. package/utils/extractors/regex.js +39 -12
  30. package/utils/i18n-helper.js +88 -40
  31. package/{scripts → utils}/locale-optimizer.js +61 -60
  32. package/utils/security-check-improved.js +16 -13
  33. package/utils/security.js +6 -4
  34. package/main/i18ntk-go.js +0 -283
  35. package/main/i18ntk-java.js +0 -380
  36. package/main/i18ntk-js.js +0 -512
  37. package/main/i18ntk-manage.js +0 -1694
  38. package/main/i18ntk-php.js +0 -462
  39. package/main/i18ntk-py.js +0 -379
  40. package/main/i18ntk-settings.js +0 -23
  41. package/main/manage/index-fixed.js +0 -1447
  42. package/main/manage/services/ConfigurationService-fixed.js +0 -449
  43. package/scripts/build-lite.js +0 -279
  44. package/scripts/deprecate-versions.js +0 -317
  45. package/scripts/export-translations.js +0 -84
  46. package/scripts/fix-all-i18n.js +0 -215
  47. package/scripts/fix-and-purify-i18n.js +0 -213
  48. package/scripts/fix-locale-control-chars.js +0 -110
  49. package/scripts/lint-locales.js +0 -80
  50. package/scripts/prepublish.js +0 -348
  51. package/scripts/security-check.js +0 -117
  52. package/scripts/sync-translations.js +0 -151
  53. package/scripts/sync-ui-locales.js +0 -20
  54. package/scripts/validate-all-translations.js +0 -139
  55. package/scripts/verify-deprecations.js +0 -157
  56. package/scripts/verify-translations.js +0 -63
  57. package/utils/security-fixed.js +0 -607
package/README.md CHANGED
@@ -1,74 +1,64 @@
1
- # šŸš€ i18ntk - The Ultra-Fast, Zero-Dependency i18n Translation Toolkit
1
+ # i18ntk v2.2.0
2
2
 
3
- <div align="center">
3
+ Zero-dependency i18n toolkit for initialization, scanning, analysis, validation, usage tracking, and translation completion.
4
4
 
5
5
  ![i18ntk Logo](docs/screenshots/i18ntk-logo-public.PNG)
6
6
 
7
- **The fastest and most comprehensive i18n toolkit ever built.**
8
-
9
7
  [![npm version](https://img.shields.io/npm/v/i18ntk.svg?color=brightgreen)](https://www.npmjs.com/package/i18ntk)
10
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
- [![Performance](https://img.shields.io/badge/Performance-97%25%20Faster-blue.svg)](https://github.com/vladnoskv/i18ntk#performance)
12
- [![Zero Dependencies](https://img.shields.io/badge/Dependencies-ZERO-red.svg)](https://github.com/vladnoskv/i18ntk#features)
13
8
  [![npm downloads](https://img.shields.io/npm/dt/i18ntk.svg)](https://www.npmjs.com/package/i18ntk)
14
- [![GitHub stars](https://img.shields.io/github/stars/vladnoskv/i18ntk?style=social)](https://github.com/vladnoskv/i18ntk)
15
- [![Socket Badge](https://socket.dev/api/badge/npm/package/i18ntk/2.0.4)](https://socket.dev/npm/package/i18ntk/overview/2.0.4)
16
-
17
- [šŸ“¦ Install Now](#-installation) • [⚔ Quick Start](#-quick-start) • [šŸ“š Documentation](#-documentation) • [šŸŽÆ Features](#-why-choose-i18ntk)
18
-
19
- ---
9
+ [![node](https://img.shields.io/badge/node-%3E%3D16-339933)](https://nodejs.org)
10
+ [![dependencies](https://img.shields.io/badge/dependencies-0-success)](https://www.npmjs.com/package/i18ntk)
11
+ [![license](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)
12
+ [![socket](https://socket.dev/api/badge/npm/package/i18ntk/2.2.0)](https://socket.dev/npm/package/i18ntk/overview/2.2.0)
20
13
 
21
- ## ⚔ Lightning Fast Performance
14
+ ## Upgrade Notice
22
15
 
23
- **15.38ms** for 200k translation keys • **<2MB** memory usage • **97% faster** than traditional tools
16
+ Versions earlier than `2.2.0` may contain known stability and security issues.
17
+ They are considered unsupported for production use. Upgrade to `2.2.0` or newer.
24
18
 
25
- **v2.0.4**
19
+ ## Why i18ntk
26
20
 
27
- </div>
21
+ - Zero runtime dependencies
22
+ - Works across JS/TS, React, Vue, Angular, and generic projects
23
+ - Supports non-interactive CI runs (`--no-prompt`)
24
+ - Includes usage/coverage validation and missing-key completion
25
+ - Ships with runtime translation helpers via `i18ntk/runtime`
28
26
 
29
- ## šŸ“¦ Installation
27
+ ## Install
30
28
 
31
29
  ```bash
32
- # Install globally (recommended)
30
+ # global (recommended for CLI use)
33
31
  npm install -g i18ntk
34
32
 
35
- # Or use with npx (no installation required)
36
- npx i18ntk
33
+ # local
34
+ npm install --save-dev i18ntk
37
35
 
38
- # Or install locally in your project
39
- npm install i18ntk --save-dev
36
+ # one-off
37
+ npx i18ntk --help
40
38
  ```
41
39
 
42
- ## ⚔ Quick Start
43
-
44
- Get your i18n project up and running in **60 seconds**:
40
+ ## Quick Start
45
41
 
46
42
  ```bash
47
- # 1. Install i18ntk
48
- npm install -g i18ntk
49
-
50
- # 2. Initialize your project
51
- i18ntk init
52
-
53
- # 3. Analyze your translations
54
- i18ntk analyze
43
+ # initialize locales/project settings
44
+ i18ntk --command=init
55
45
 
56
- # 4. Fix any issues
57
- i18ntk fixer --interactive
46
+ # analyze translation completeness
47
+ i18ntk --command=analyze
58
48
 
59
- # 5. Validate everything
60
- i18ntk validate
49
+ # validate translation structure/content
50
+ i18ntk --command=validate
61
51
 
62
- # 6. Mangage Mre
52
+ # complete missing keys
53
+ i18ntk --command=complete
63
54
  ```
64
55
 
65
- That's it! Your i18n infrastructure is ready. šŸŽ‰
56
+ ## Command Model (v2)
66
57
 
67
- ## v2 Command Model
68
-
69
- Primary CLI commands:
58
+ Primary CLI:
70
59
 
71
60
  ```bash
61
+ i18ntk
72
62
  i18ntk --command=init
73
63
  i18ntk --command=analyze
74
64
  i18ntk --command=validate
@@ -80,7 +70,7 @@ i18ntk --command=summary
80
70
  i18ntk --command=debug
81
71
  ```
82
72
 
83
- Standalone binaries:
73
+ Standalone executables:
84
74
 
85
75
  ```bash
86
76
  i18ntk-init
@@ -96,19 +86,8 @@ i18ntk-fixer
96
86
  i18ntk-backup
97
87
  ```
98
88
 
99
- Backup helper:
100
-
101
- ```bash
102
- i18ntk-backup --help
103
- i18ntk-backup create ./locales
104
- i18ntk-backup list
105
- i18ntk-backup restore <backup-file>
106
- ```
107
-
108
89
  ## Common Flags
109
90
 
110
- Most commands support:
111
-
112
91
  - `--source-dir <path>`
113
92
  - `--i18n-dir <path>`
114
93
  - `--output-dir <path>`
@@ -120,13 +99,13 @@ Most commands support:
120
99
 
121
100
  ## Configuration
122
101
 
123
- i18ntk reads project settings from `.i18ntk-config` in the project root.
102
+ i18ntk reads project settings from `.i18ntk-config` in your project root.
124
103
 
125
104
  Example:
126
105
 
127
106
  ```json
128
107
  {
129
- "version": "2.0.0",
108
+ "version": "2.2.0",
130
109
  "sourceDir": "./locales",
131
110
  "i18nDir": "./locales",
132
111
  "outputDir": "./i18ntk-reports",
@@ -155,7 +134,7 @@ setLanguage('fr');
155
134
  console.log(getLanguage());
156
135
  ```
157
136
 
158
- ## Docs
137
+ ## Documentation
159
138
 
160
139
  - [Documentation Index](docs/README.md)
161
140
  - [API Reference](docs/api/API_REFERENCE.md)
@@ -163,8 +142,7 @@ console.log(getLanguage());
163
142
  - [Runtime API Guide](docs/runtime.md)
164
143
  - [Scanner Guide](docs/scanner-guide.md)
165
144
  - [Environment Variables](docs/environment-variables.md)
166
- - [Migration Guide v2.0.0](docs/migration-guide-v2.0.0.md)
167
- - [Release Runbook](DEVUPDATE.md)
145
+ - [Migration Guide v2.2.0](docs/migration-guide-v2.2.0.md)
168
146
 
169
147
  ## License
170
148
 
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  /**
3
3
  * I18NTK TRANSLATION ANALYSIS SCRIPT
4
4
  *
@@ -27,7 +27,7 @@ const SetupEnforcer = require('../utils/setup-enforcer');
27
27
  }
28
28
  })();
29
29
 
30
- loadTranslations( 'en', path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
30
+ loadTranslations('en', path.resolve(__dirname, '..', 'ui-locales'));
31
31
 
32
32
  const PROJECT_ROOT = process.cwd();
33
33
 
@@ -67,7 +67,7 @@ class I18nAnalyzer {
67
67
  this.config = { ...baseConfig, ...(this.config || {}) };
68
68
 
69
69
  const uiLanguage = (this.config && this.config.uiLanguage) || 'en';
70
- loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
70
+ loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
71
71
 
72
72
  this.sourceDir = this.config.sourceDir;
73
73
  this.sourceLanguageDir = path.join(this.sourceDir, this.config.sourceLanguage);
@@ -143,6 +143,17 @@ class I18nAnalyzer {
143
143
  }
144
144
 
145
145
  // Get all available languages
146
+ isValidLanguageCode(code) {
147
+ if (!code || typeof code !== 'string') return false;
148
+ return /^[a-z]{2}(?:-[A-Za-z0-9]{2,8})*$/i.test(code.trim());
149
+ }
150
+
151
+ isExcludedLanguageDirectory(name) {
152
+ if (!name || typeof name !== 'string') return true;
153
+ const lowered = name.toLowerCase();
154
+ return lowered.startsWith('backup-') || lowered === 'backup' || lowered === 'reports' || lowered === 'i18ntk-reports';
155
+ }
156
+
146
157
  getAvailableLanguages() {
147
158
  try {
148
159
  const items = SecurityUtils.safeReaddirSync(this.sourceDir, process.cwd(), { withFileTypes: true });
@@ -157,7 +168,18 @@ class I18nAnalyzer {
157
168
  const directories = items
158
169
  .filter(item => item.isDirectory())
159
170
  .map(item => item.name)
160
- .filter(name => name !== 'node_modules' && !name.startsWith('.') && name !== this.config.sourceLanguage);
171
+ .filter(name =>
172
+ name !== 'node_modules' &&
173
+ !name.startsWith('.') &&
174
+ name !== this.config.sourceLanguage &&
175
+ !this.isExcludedLanguageDirectory(name) &&
176
+ this.isValidLanguageCode(name)
177
+ )
178
+ .filter(name => {
179
+ const dirPath = path.join(this.sourceDir, name);
180
+ const dirItems = SecurityUtils.safeReaddirSync(dirPath, process.cwd(), { withFileTypes: true }) || [];
181
+ return dirItems.some(item => item.isFile() && item.name.endsWith('.json'));
182
+ });
161
183
 
162
184
  // Check for monolith files (language.json files)
163
185
  const files = items
@@ -170,31 +192,14 @@ class I18nAnalyzer {
170
192
  // Add monolith files as languages (without .json extension)
171
193
  const monolithLanguages = files
172
194
  .map(file => file.replace('.json', ''))
173
- .filter(lang => !languages.includes(lang) && lang !== this.config.sourceLanguage);
195
+ .filter(lang =>
196
+ !languages.includes(lang) &&
197
+ lang !== this.config.sourceLanguage &&
198
+ !this.isExcludedLanguageDirectory(lang) &&
199
+ this.isValidLanguageCode(lang)
200
+ );
174
201
  languages.push(...monolithLanguages);
175
-
176
- // Check for nested structures
177
- for (const dir of directories) {
178
- const dirPath = path.join(this.sourceDir, dir);
179
- try {
180
- const dirItems = SecurityUtils.safeReaddirSync(dirPath, process.cwd(), { withFileTypes: true });
181
- if (dirItems) {
182
- const jsonFiles = dirItems
183
- .filter(item => item.isFile() && item.name.endsWith('.json'))
184
- .map(item => item.name.replace('.json', ''));
185
-
186
- // If directory contains JSON files, it's likely a language directory
187
- if (jsonFiles.length > 0) {
188
- if (!languages.includes(dir)) {
189
- languages.push(dir);
190
- }
191
- }
192
- }
193
- } catch (error) {
194
- // Skip directories we can't read
195
- }
196
- }
197
-
202
+
198
203
  return [...new Set(languages)].sort();
199
204
  } catch (error) {
200
205
  console.error('Error reading source directory:', error.message);
@@ -707,7 +712,6 @@ try {
707
712
  throw new Error(t('analyze.failedToWriteReportFile') || 'Failed to write report file securely');
708
713
  }
709
714
 
710
- console.log(`Report saved to: ${reportPath}`);
711
715
  return reportPath;
712
716
 
713
717
  } catch (error) {
@@ -775,20 +779,21 @@ try {
775
779
  console.log(t('analyze.analyzing', { language }) || `\nšŸ”„ Analyzing ${language}...`);
776
780
  }
777
781
 
778
- const analysis = this.analyzeLanguage(language);
779
- const report = this.generateLanguageReport(analysis);
780
-
781
- // Save report
782
- const reportPath = await this.saveReport(language, report);
783
-
784
- if (!args.json) {
785
- console.log(t('analyze.completed', { language }) || `āœ… Analysis completed for ${language}`);
786
- console.log(t('analyze.progress', {
787
- translated: results.length,
788
- total: languages.length
789
- }) || ` Progress: ${results.length}/${languages.length} languages processed`);
790
- console.log(t('analyze.reportSaved', { reportPath }) || ` Report saved: ${reportPath}`);
791
- }
782
+ const analysis = this.analyzeLanguage(language);
783
+ const report = this.generateLanguageReport(analysis);
784
+
785
+ // Save report
786
+ const reportPath = await this.saveReport(language, report);
787
+ const processedCount = results.length + 1;
788
+
789
+ if (!args.json) {
790
+ console.log(t('analyze.completed', { language }) || `āœ… Analysis completed for ${language}`);
791
+ console.log(t('analyze.progress', {
792
+ translated: processedCount,
793
+ total: languages.length
794
+ }) || ` Progress: ${processedCount}/${languages.length} languages processed`);
795
+ console.log(t('analyze.reportSaved', { reportPath }) || ` Report saved: ${reportPath}`);
796
+ }
792
797
 
793
798
  results.push({
794
799
  language,
@@ -884,7 +889,7 @@ try {
884
889
  this.config = { ...baseConfig, ...this.config };
885
890
 
886
891
  const uiLanguage = this.config.uiLanguage || 'en';
887
- loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
892
+ loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
888
893
 
889
894
  this.sourceDir = this.config.sourceDir;
890
895
  this.sourceLanguageDir = path.join(this.sourceDir, this.config.sourceLanguage);
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  /**
3
3
  * I18NTK TRANSLATION COMPLETION SCRIPT
4
4
  *
@@ -19,15 +19,15 @@ const { loadTranslations, t } = require('../utils/i18n-helper');
19
19
  const { getGlobalReadline, closeGlobalReadline } = require('../utils/cli');
20
20
  const SetupEnforcer = require('../utils/setup-enforcer');
21
21
 
22
- // Ensure setup is complete before running, except for help output.
23
- (async () => {
24
- const isHelpRequest = process.argv.slice(2).some(arg => arg === '--help' || arg === '-h');
25
- if (isHelpRequest) {
26
- return;
27
- }
28
- try {
29
- await SetupEnforcer.checkSetupCompleteAsync();
30
- } catch (error) {
22
+ // Ensure setup is complete before running, except for help output.
23
+ (async () => {
24
+ const isHelpRequest = process.argv.slice(2).some(arg => arg === '--help' || arg === '-h');
25
+ if (isHelpRequest) {
26
+ return;
27
+ }
28
+ try {
29
+ await SetupEnforcer.checkSetupCompleteAsync();
30
+ } catch (error) {
31
31
  console.error('Setup check failed:', error.message);
32
32
  process.exit(1);
33
33
  }
@@ -37,7 +37,7 @@ loadTranslations();
37
37
 
38
38
 
39
39
 
40
- class I18nCompletionTool {
40
+ class I18nCompletionTool {
41
41
  constructor(config = {}) {
42
42
  this.config = config;
43
43
  this.sourceDir = null;
@@ -109,57 +109,57 @@ class I18nCompletionTool {
109
109
  parsed.autoTranslate = true;
110
110
  } else if (key === 'dry-run') {
111
111
  parsed.dryRun = true;
112
- } else if (key === 'no-prompt') {
113
- parsed.noPrompt = true;
114
- } else if (key === 'help' || key === 'h') {
115
- parsed.help = true;
116
- }
117
- }
118
- });
112
+ } else if (key === 'no-prompt') {
113
+ parsed.noPrompt = true;
114
+ } else if (key === 'help' || key === 'h') {
115
+ parsed.help = true;
116
+ }
117
+ }
118
+ });
119
119
 
120
120
  return parsed;
121
121
  }
122
122
 
123
- // Get all available languages
124
- getAvailableLanguages() {
123
+ // Get all available languages
124
+ getAvailableLanguages() {
125
125
  if (!SecurityUtils.safeExistsSync(this.sourceDir, this.config.projectRoot)) {
126
126
  throw new Error(`Source directory not found: ${this.sourceDir}`);
127
127
  }
128
128
 
129
129
  // Check for monolith JSON files (en.json, es.json, etc.)
130
- const files = SecurityUtils.safeReaddirSync(this.sourceDir, this.config.projectRoot);
131
- const languagesFromFiles = files
132
- .filter(file => file.endsWith('.json'))
133
- .map(file => path.basename(file, '.json'))
134
- .filter(code => this.isValidLanguageCode(code));
135
-
136
- // Also check for directory-based structure for backward compatibility
137
- const directories = SecurityUtils.safeReaddirSync(this.sourceDir, this.config.projectRoot)
138
- .filter(item => {
139
- if (this.isExcludedLanguageDirectory(item)) return false;
140
- if (!this.isValidLanguageCode(item)) return false;
141
- const itemPath = path.join(this.sourceDir, item);
142
- const stat = SecurityUtils.safeStatSync(itemPath, this.config.projectRoot);
143
- if (!stat || !stat.isDirectory()) return false;
144
-
145
- const localeFiles = SecurityUtils.safeReaddirSync(itemPath, this.config.projectRoot)
146
- .filter(name => name.endsWith('.json'));
147
- return localeFiles.length > 0;
148
- });
149
-
150
- return [...new Set([...languagesFromFiles, ...directories])];
151
- }
152
-
153
- isValidLanguageCode(code) {
154
- if (!code || typeof code !== 'string') return false;
155
- return /^[a-z]{2}(?:-[A-Za-z0-9]{2,8})*$/i.test(code.trim());
156
- }
157
-
158
- isExcludedLanguageDirectory(name) {
159
- if (!name || typeof name !== 'string') return true;
160
- const lowered = name.toLowerCase();
161
- return lowered.startsWith('backup-') || lowered === 'backup' || lowered === 'reports' || lowered === 'i18ntk-reports';
162
- }
130
+ const files = SecurityUtils.safeReaddirSync(this.sourceDir, this.config.projectRoot);
131
+ const languagesFromFiles = files
132
+ .filter(file => file.endsWith('.json'))
133
+ .map(file => path.basename(file, '.json'))
134
+ .filter(code => this.isValidLanguageCode(code));
135
+
136
+ // Also check for directory-based structure for backward compatibility
137
+ const directories = SecurityUtils.safeReaddirSync(this.sourceDir, this.config.projectRoot)
138
+ .filter(item => {
139
+ if (this.isExcludedLanguageDirectory(item)) return false;
140
+ if (!this.isValidLanguageCode(item)) return false;
141
+ const itemPath = path.join(this.sourceDir, item);
142
+ const stat = SecurityUtils.safeStatSync(itemPath, this.config.projectRoot);
143
+ if (!stat || !stat.isDirectory()) return false;
144
+
145
+ const localeFiles = SecurityUtils.safeReaddirSync(itemPath, this.config.projectRoot)
146
+ .filter(name => name.endsWith('.json'));
147
+ return localeFiles.length > 0;
148
+ });
149
+
150
+ return [...new Set([...languagesFromFiles, ...directories])];
151
+ }
152
+
153
+ isValidLanguageCode(code) {
154
+ if (!code || typeof code !== 'string') return false;
155
+ return /^[a-z]{2}(?:-[A-Za-z0-9]{2,8})*$/i.test(code.trim());
156
+ }
157
+
158
+ isExcludedLanguageDirectory(name) {
159
+ if (!name || typeof name !== 'string') return true;
160
+ const lowered = name.toLowerCase();
161
+ return lowered.startsWith('backup-') || lowered === 'backup' || lowered === 'reports' || lowered === 'i18ntk-reports';
162
+ }
163
163
 
164
164
  // Get all JSON files from a language directory
165
165
  getLanguageFiles(language) {
@@ -481,7 +481,8 @@ class I18nCompletionTool {
481
481
  this.config = { ...baseConfig, ...(this.config || {}) };
482
482
 
483
483
  const uiLanguage = (this.config && this.config.uiLanguage) || 'en';
484
- loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));this.sourceDir = this.config.sourceDir;
484
+ loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
485
+ this.sourceDir = this.config.sourceDir;
485
486
  this.sourceLanguageDir = path.join(this.sourceDir, this.config.sourceLanguage);
486
487
  } else {
487
488
  await this.initialize();
@@ -552,28 +553,28 @@ class I18nCompletionTool {
552
553
  console.log(t("complete.languagesProcessed", { languagesProcessed: languages.length }));
553
554
  console.log(t("complete.missingKeysAdded", { missingKeysAdded: missingKeys.length }));
554
555
 
555
- if (!args.dryRun && allChanges.length > 0 && !args.noPrompt) {
556
- const rl = this.rl || this.initReadline();
557
- const answer = await this.prompt('\n' + t('complete.generateReportPrompt') + ' (Y/N): ');
558
-
559
- if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
560
- await this.generateReport(allChanges, languages);
556
+ if (!args.dryRun && allChanges.length > 0 && !args.noPrompt) {
557
+ const rl = this.rl || this.initReadline();
558
+ const answer = await this.prompt('\n' + t('complete.generateReportPrompt') + ' (Y/N): ');
559
+
560
+ if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
561
+ await this.generateReport(allChanges, languages);
561
562
  }
562
563
  }
563
564
 
564
- if (!args.dryRun) {
565
- console.log('\n' + t("complete.nextStepsTitle"));
566
- console.log(t("complete.separator"));
567
- console.log('1. Run usage analysis:');
568
- console.log(' i18ntk --command=usage');
569
- console.log('2. Validate translations:');
570
- console.log(' i18ntk --command=validate');
571
- console.log('3. Analyze translation status:');
572
- console.log(' i18ntk --command=analyze');
573
- console.log('\n' + t("complete.allKeysAvailable"));
574
- } else {
575
- console.log('\n' + t("complete.runWithoutDryRun"));
576
- }
565
+ if (!args.dryRun) {
566
+ console.log('\n' + t("complete.nextStepsTitle"));
567
+ console.log(t("complete.separator"));
568
+ console.log('1. Run usage analysis:');
569
+ console.log(' i18ntk --command=usage');
570
+ console.log('2. Validate translations:');
571
+ console.log(' i18ntk --command=validate');
572
+ console.log('3. Analyze translation status:');
573
+ console.log(' i18ntk --command=analyze');
574
+ console.log('\n' + t("complete.allKeysAvailable"));
575
+ } else {
576
+ console.log('\n' + t("complete.runWithoutDryRun"));
577
+ }
577
578
 
578
579
  // Only prompt when run from the menu (i.e., when a callback or menu context is present)
579
580
  if (typeof this.prompt === "function" && args.fromMenu) {
@@ -605,4 +606,4 @@ if (require.main === module) {
605
606
  });
606
607
  }
607
608
 
608
- module.exports = I18nCompletionTool;
609
+ module.exports = I18nCompletionTool;
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  /**
4
4
  * I18NTK TRANSLATION FIXER SCRIPT
@@ -27,7 +27,7 @@ const SetupEnforcer = require('../utils/setup-enforcer');
27
27
  }
28
28
  })();
29
29
 
30
- loadTranslations('en', path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
30
+ loadTranslations('en', path.resolve(__dirname, '..', 'ui-locales'));
31
31
 
32
32
  class I18nFixer {
33
33
  constructor(config = {}) {
@@ -51,7 +51,7 @@ class I18nFixer {
51
51
  this.config = { ...baseConfig, ...(this.config || {}) };
52
52
 
53
53
  const uiLanguage = (this.config && this.config.uiLanguage) || 'en';
54
- loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
54
+ loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
55
55
 
56
56
  this.sourceDir = this.config.sourceDir;
57
57
  this.outputDir = this.config.outputDir;
@@ -1122,7 +1122,7 @@ class I18nInitializer {
1122
1122
 
1123
1123
  try {
1124
1124
  // Import locale optimizer directly
1125
- const LocaleOptimizer = require('../scripts/locale-optimizer');
1125
+ const LocaleOptimizer = require('../utils/locale-optimizer');
1126
1126
 
1127
1127
  // First run dry run to show current state
1128
1128
  console.log('\nšŸ” Running locale optimization preview...');
@@ -1139,12 +1139,12 @@ class I18nInitializer {
1139
1139
  console.log('\nāœ… Package optimization completed!');
1140
1140
  } else {
1141
1141
  console.log('\nšŸ’” You can run locale optimization later with:');
1142
- console.log(' node scripts/locale-optimizer.js --interactive');
1142
+ console.log(' node utils/locale-optimizer.js --interactive');
1143
1143
  }
1144
1144
  } catch (error) {
1145
1145
  console.log('\nāš ļø Could not offer locale optimization:', error.message);
1146
1146
  console.log('\nšŸ’” You can run locale optimization later with:');
1147
- console.log(' node scripts/locale-optimizer.js --interactive');
1147
+ console.log(' node utils/locale-optimizer.js --interactive');
1148
1148
  }
1149
1149
  } catch (error) {
1150
1150
  console.log('\nāš ļø Could not offer locale optimization:', error.message);
@@ -1178,7 +1178,7 @@ class I18nInitializer {
1178
1178
  // Load translations for UI messages
1179
1179
  const uiLanguage = this.config.uiLanguage || 'en';
1180
1180
  const { loadTranslations } = require('../utils/i18n-helper');
1181
- loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
1181
+ loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
1182
1182
  }
1183
1183
 
1184
1184
  // Setup is now handled centrally by config manager
@@ -1261,7 +1261,7 @@ class I18nInitializer {
1261
1261
  // Load translations for UI messages
1262
1262
  const uiLanguage = this.config.uiLanguage || 'en';
1263
1263
  const { loadTranslations } = require('../utils/i18n-helper');
1264
- loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
1264
+ loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
1265
1265
 
1266
1266
  // Skip i18n framework check in non-interactive mode
1267
1267
  console.log('Running initialization in non-interactive mode...');
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  /**
4
4
  * I18NTK TEXT SCANNER
@@ -47,7 +47,7 @@ class I18nTextScanner {
47
47
  }
48
48
 
49
49
  loadLocale() {
50
- const uiLocalesDir = path.join(__dirname, '..', 'resources', 'i18n', 'ui-locales');
50
+ const uiLocalesDir = path.join(__dirname, '..', 'ui-locales');
51
51
  const localeFile = path.join(uiLocalesDir, 'en.json');
52
52
 
53
53
  try {