i18ntk 2.1.0 → 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 (53) hide show
  1. package/README.md +10 -6
  2. package/main/i18ntk-analyze.js +63 -63
  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 +95 -96
  10. package/main/i18ntk-usage.js +14 -14
  11. package/main/i18ntk-validate.js +6 -5
  12. package/main/manage/commands/AnalyzeCommand.js +67 -67
  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 +7 -4
  17. package/main/manage/managers/LanguageMenu.js +7 -2
  18. package/main/manage/services/UsageService.js +7 -7
  19. package/package.json +20 -41
  20. package/settings/settings-cli.js +3 -3
  21. package/ui-locales/de.json +12 -11
  22. package/ui-locales/en.json +12 -11
  23. package/ui-locales/es.json +12 -11
  24. package/ui-locales/fr.json +12 -11
  25. package/ui-locales/ja.json +12 -11
  26. package/ui-locales/ru.json +12 -11
  27. package/ui-locales/zh.json +12 -11
  28. package/utils/i18n-helper.js +161 -166
  29. package/{scripts → utils}/locale-optimizer.js +61 -60
  30. package/main/i18ntk-go.js +0 -283
  31. package/main/i18ntk-java.js +0 -380
  32. package/main/i18ntk-js.js +0 -512
  33. package/main/i18ntk-manage.js +0 -1694
  34. package/main/i18ntk-php.js +0 -462
  35. package/main/i18ntk-py.js +0 -379
  36. package/main/i18ntk-settings.js +0 -23
  37. package/main/manage/index-fixed.js +0 -1447
  38. package/scripts/build-lite.js +0 -279
  39. package/scripts/deprecate-versions.js +0 -317
  40. package/scripts/export-translations.js +0 -84
  41. package/scripts/fix-all-i18n.js +0 -236
  42. package/scripts/fix-and-purify-i18n.js +0 -233
  43. package/scripts/fix-locale-control-chars.js +0 -110
  44. package/scripts/lint-locales.js +0 -80
  45. package/scripts/prepublish-dev.js +0 -221
  46. package/scripts/prepublish.js +0 -362
  47. package/scripts/security-check.js +0 -117
  48. package/scripts/sync-translations.js +0 -151
  49. package/scripts/sync-ui-locales.js +0 -20
  50. package/scripts/validate-all-translations.js +0 -195
  51. package/scripts/verify-deprecations.js +0 -157
  52. package/scripts/verify-translations.js +0 -63
  53. package/utils/security-fixed.js +0 -609
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # i18ntk v2.1.0
1
+ # i18ntk v2.2.0
2
2
 
3
3
  Zero-dependency i18n toolkit for initialization, scanning, analysis, validation, usage tracking, and translation completion.
4
4
 
@@ -9,7 +9,12 @@ Zero-dependency i18n toolkit for initialization, scanning, analysis, validation,
9
9
  [![node](https://img.shields.io/badge/node-%3E%3D16-339933)](https://nodejs.org)
10
10
  [![dependencies](https://img.shields.io/badge/dependencies-0-success)](https://www.npmjs.com/package/i18ntk)
11
11
  [![license](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)
12
- [![socket](https://socket.dev/api/badge/npm/package/i18ntk/2.1.0)](https://socket.dev/npm/package/i18ntk/overview/2.1.0)
12
+ [![socket](https://socket.dev/api/badge/npm/package/i18ntk/2.2.0)](https://socket.dev/npm/package/i18ntk/overview/2.2.0)
13
+
14
+ ## Upgrade Notice
15
+
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.
13
18
 
14
19
  ## Why i18ntk
15
20
 
@@ -100,7 +105,7 @@ Example:
100
105
 
101
106
  ```json
102
107
  {
103
- "version": "2.1.0",
108
+ "version": "2.2.0",
104
109
  "sourceDir": "./locales",
105
110
  "i18nDir": "./locales",
106
111
  "outputDir": "./i18ntk-reports",
@@ -137,9 +142,8 @@ console.log(getLanguage());
137
142
  - [Runtime API Guide](docs/runtime.md)
138
143
  - [Scanner Guide](docs/scanner-guide.md)
139
144
  - [Environment Variables](docs/environment-variables.md)
140
- - [Migration Guide v2.1.0](docs/migration-guide-v2.1.0.md)
141
- - [Release Runbook](DEVUPDATE.md)
145
+ - [Migration Guide v2.2.0](docs/migration-guide-v2.2.0.md)
142
146
 
143
147
  ## License
144
148
 
145
- MIT
149
+ MIT
@@ -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);
@@ -142,44 +142,44 @@ class I18nAnalyzer {
142
142
  }
143
143
  }
144
144
 
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
-
157
- getAvailableLanguages() {
158
- try {
159
- const items = SecurityUtils.safeReaddirSync(this.sourceDir, process.cwd(), { withFileTypes: true });
160
- if (!items) {
161
- console.error('Error reading source directory: Unable to access directory');
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
+
157
+ getAvailableLanguages() {
158
+ try {
159
+ const items = SecurityUtils.safeReaddirSync(this.sourceDir, process.cwd(), { withFileTypes: true });
160
+ if (!items) {
161
+ console.error('Error reading source directory: Unable to access directory');
162
162
  return [];
163
163
  }
164
164
 
165
165
  const languages = [];
166
166
 
167
167
  // Check for directory-based structure
168
- const directories = items
169
- .filter(item => item.isDirectory())
170
- .map(item => item.name)
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
- });
168
+ const directories = items
169
+ .filter(item => item.isDirectory())
170
+ .map(item => item.name)
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
+ });
183
183
 
184
184
  // Check for monolith files (language.json files)
185
185
  const files = items
@@ -190,17 +190,17 @@ class I18nAnalyzer {
190
190
  languages.push(...directories);
191
191
 
192
192
  // Add monolith files as languages (without .json extension)
193
- const monolithLanguages = files
194
- .map(file => file.replace('.json', ''))
195
- .filter(lang =>
196
- !languages.includes(lang) &&
197
- lang !== this.config.sourceLanguage &&
198
- !this.isExcludedLanguageDirectory(lang) &&
199
- this.isValidLanguageCode(lang)
200
- );
201
- languages.push(...monolithLanguages);
202
-
203
- return [...new Set(languages)].sort();
193
+ const monolithLanguages = files
194
+ .map(file => file.replace('.json', ''))
195
+ .filter(lang =>
196
+ !languages.includes(lang) &&
197
+ lang !== this.config.sourceLanguage &&
198
+ !this.isExcludedLanguageDirectory(lang) &&
199
+ this.isValidLanguageCode(lang)
200
+ );
201
+ languages.push(...monolithLanguages);
202
+
203
+ return [...new Set(languages)].sort();
204
204
  } catch (error) {
205
205
  console.error('Error reading source directory:', error.message);
206
206
  return [];
@@ -712,7 +712,7 @@ try {
712
712
  throw new Error(t('analyze.failedToWriteReportFile') || 'Failed to write report file securely');
713
713
  }
714
714
 
715
- return reportPath;
715
+ return reportPath;
716
716
 
717
717
  } catch (error) {
718
718
  console.error(`Failed to save report for ${language}:`, error.message);
@@ -779,21 +779,21 @@ try {
779
779
  console.log(t('analyze.analyzing', { language }) || `\n🔄 Analyzing ${language}...`);
780
780
  }
781
781
 
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
- }
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
+ }
797
797
 
798
798
  results.push({
799
799
  language,
@@ -889,7 +889,7 @@ try {
889
889
  this.config = { ...baseConfig, ...this.config };
890
890
 
891
891
  const uiLanguage = this.config.uiLanguage || 'en';
892
- loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
892
+ loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
893
893
 
894
894
  this.sourceDir = this.config.sourceDir;
895
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 {