i18ntk 1.7.0 → 1.7.1
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.
- package/README.md +17 -55
- package/main/i18ntk-analyze.js +2 -2
- package/main/i18ntk-autorun.js +1 -1
- package/main/i18ntk-complete.js +1 -1
- package/main/i18ntk-init.js +25 -10
- package/main/i18ntk-manage.js +214 -40
- package/main/i18ntk-sizing.js +2 -2
- package/main/i18ntk-summary.js +2 -2
- package/main/i18ntk-ui.js +6 -0
- package/main/i18ntk-usage.js +2 -2
- package/main/i18ntk-validate.js +47 -11
- package/package.json +7 -8
- package/scripts/admin-auth.test.js +21 -0
- package/settings/.i18n-admin-config.json +2 -2
- package/settings/i18ntk-config.json +0 -1
- package/settings/initialization.json +7 -0
- package/settings/settings-cli.js +1 -1
- package/ui-locales/de.json +2 -0
- package/ui-locales/en.json +2 -0
- package/ui-locales/es.json +2 -0
- package/ui-locales/fr.json +2 -0
- package/ui-locales/ja.json +2 -0
- package/ui-locales/ru.json +35 -33
- package/ui-locales/zh.json +2 -0
- package/utils/admin-auth.js +86 -18
- package/utils/admin-cli.js +15 -3
- package/utils/admin-pin.js +519 -526
- package/utils/cli-helper.js +84 -11
- package/utils/config-helper.js +55 -2
- package/utils/config.js +41 -0
- package/utils/i18n-helper.js +2 -1
- package/utils/promptPin.js +76 -0
- package/utils/security-check.js +6 -2
package/README.md
CHANGED
|
@@ -2,19 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
**Version:** 1.7.
|
|
5
|
+
**Version:** 1.7.1
|
|
6
6
|
**Last Updated:** 2025-08-10
|
|
7
7
|
**GitHub Repository:** [vladnoskv/i18ntk](https://github.com/vladnoskv/i18ntk)
|
|
8
8
|
|
|
9
|
-
[](https://www.npmjs.com/package/i18ntk) [](https://badge.fury.io/js/i18ntk) [](https://nodejs.org/) [](https://www.npmjs.com/package/i18ntk) [](https://github.com/vladnoskv/i18ntk)
|
|
9
|
+
[](https://www.npmjs.com/package/i18ntk) [](https://badge.fury.io/js/i18ntk) [](https://nodejs.org/) [](https://www.npmjs.com/package/i18ntk) [](https://github.com/vladnoskv/i18ntk)
|
|
10
|
+
[](https://socket.dev/npm/package/i18ntk/overview/1.7.1)
|
|
10
11
|
|
|
11
12
|
**🚀 The fastest way to manage translations across any framework or vanilla JavaScript projects**
|
|
12
13
|
|
|
13
|
-
**Framework Support:** Auto-detects popular libraries (React i18next, Vue i18n, i18next, Nuxt i18n, Svelte i18n) or works without a framework. i18ntk manages translation files and validation—it does NOT implement
|
|
14
|
+
**Framework Support:** Auto-detects popular libraries (React i18next, Vue i18n, i18next, Nuxt i18n, Svelte i18n) or works without a framework. i18ntk manages translation files and validation—it does NOT implement translation logic like i18next or Vue i18n.
|
|
14
15
|
|
|
15
|
-
> **
|
|
16
|
-
|
|
17
|
-
> **v1.7.0** – 97% speed improvement (**15.38ms** for 200k keys), new watch helper, and a lite English-only UI locale framework; up to 86% package size reduction, zero runtime dependencies, enhanced security with PIN protection, and comprehensive edge case handling.
|
|
16
|
+
> **v1.7.1** – Enhanced security logging, flexible 4-6 digit PIN authentication, configuration stability improvements, and CI/CD silent mode support; maintains 97% speed improvement (**15.38ms** for 200k keys up to 5/M keys per second).
|
|
18
17
|
|
|
19
18
|
## 🚀 Quick Start
|
|
20
19
|
|
|
@@ -88,7 +87,7 @@ Configuration is managed through the `settings/i18ntk-config.json` file:
|
|
|
88
87
|
|
|
89
88
|
```json
|
|
90
89
|
{
|
|
91
|
-
"version": "1.7.
|
|
90
|
+
"version": "1.7.1",
|
|
92
91
|
"sourceDir": "./locales",
|
|
93
92
|
"outputDir": "./i18ntk-reports",
|
|
94
93
|
"defaultLanguage": "en",
|
|
@@ -176,6 +175,7 @@ const i18n = createI18n({ locale: 'en', messages: translations });
|
|
|
176
175
|
- **Encrypted Backups**: AES-256 encrypted backup storage
|
|
177
176
|
|
|
178
177
|
### 🎯 **NEW INTERACTIVE LOCALE OPTIMIZER** - up to 86% Package Size Reduction
|
|
178
|
+
|
|
179
179
|
- **Package Size**: 830.4KB → 115.3KB (86% reduction for English only)
|
|
180
180
|
- **Smart Management**: Interactive selection with automatic backups
|
|
181
181
|
- **Zero Breaking Changes**: Safe restoration from backups
|
|
@@ -199,51 +199,10 @@ your-project/
|
|
|
199
199
|
|
|
200
200
|
- **Locale files are backed up automatically** before optimization
|
|
201
201
|
- **Use interactive optimizer** for safe locale management
|
|
202
|
-
- **Zero breaking changes** from v1.6.x to v1.7.
|
|
203
|
-
- **All versions prior to 1.7.
|
|
202
|
+
- **Zero breaking changes** from v1.6.x to v1.7.1
|
|
203
|
+
- **All versions prior to 1.7.1 are deprecated**
|
|
204
204
|
- **All improvements applied automatically** on update
|
|
205
205
|
|
|
206
|
-
## 📞 Support
|
|
207
|
-
|
|
208
|
-
- **Issues**: [GitHub Issues](https://github.com/vladnoskv/i18ntk/issues)
|
|
209
|
-
- **Documentation**: [Complete docs](./docs)
|
|
210
|
-
- **Performance**: [Benchmark results](./benchmarks/results)
|
|
211
|
-
- **Version**: `i18ntk --version`
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
**Made for the global development community** ❤️
|
|
216
|
-
|
|
217
|
-
## Migration Guide
|
|
218
|
-
|
|
219
|
-
### Upgrading from Deprecated Versions
|
|
220
|
-
|
|
221
|
-
#### From any version < 1.7.0 (DEPRECATED - use latest version)
|
|
222
|
-
1. **Backup your current configuration**:
|
|
223
|
-
```bash
|
|
224
|
-
cp -r ./.i18ntk ./.i18ntk-backup-$(date +%Y%m%d)
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
2. **Install the latest version**:
|
|
228
|
-
```bash
|
|
229
|
-
npm install i18ntk@1.7.0
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
3. **Verify installation**:
|
|
233
|
-
```bash
|
|
234
|
-
i18ntk --version
|
|
235
|
-
i18ntk doctor
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
3. **Run configuration migration**:
|
|
239
|
-
```bash
|
|
240
|
-
npx i18ntk@1.6.3 --migrate
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
4. **Verify installation**:
|
|
244
|
-
```bash
|
|
245
|
-
npx i18ntk@1.6.3--validate
|
|
246
|
-
```
|
|
247
206
|
|
|
248
207
|
#### Preserved Features from 1.6.3
|
|
249
208
|
- ✅ Ultra-extreme performance improvements
|
|
@@ -256,9 +215,12 @@ your-project/
|
|
|
256
215
|
#### Breaking Changes
|
|
257
216
|
- **None** - 1.6.3 is fully backward compatible
|
|
258
217
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
218
|
+
## 📞 Support
|
|
219
|
+
|
|
220
|
+
- **Issues**: [GitHub Issues](https://github.com/vladnoskv/i18ntk/issues)
|
|
221
|
+
- **Documentation**: [Complete docs](./docs)
|
|
222
|
+
- **Performance**: [Benchmark results](./benchmarks/results)
|
|
223
|
+
- **Version**: `i18ntk --version`
|
|
224
|
+
---
|
|
264
225
|
|
|
226
|
+
**Made for the global development community** ❤️
|
package/main/i18ntk-analyze.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* I18N TRANSLATION ANALYSIS SCRIPT
|
|
4
4
|
*
|
|
@@ -11,7 +11,7 @@ const fs = require('fs');
|
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const cliHelper = require('../utils/cli-helper');
|
|
13
13
|
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
14
|
-
loadTranslations(process.env.I18NTK_LANG
|
|
14
|
+
loadTranslations(process.env.I18NTK_LANG);
|
|
15
15
|
const { getUnifiedConfig, parseCommonArgs, displayHelp } = require('../utils/config-helper');
|
|
16
16
|
const SecurityUtils = require('../utils/security');
|
|
17
17
|
const AdminCLI = require('../utils/admin-cli');
|
package/main/i18ntk-autorun.js
CHANGED
|
@@ -14,7 +14,7 @@ const fs = require('fs');
|
|
|
14
14
|
const path = require('path');
|
|
15
15
|
const { spawnSync } = require('child_process');
|
|
16
16
|
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
17
|
-
loadTranslations(process.env.I18NTK_LANG
|
|
17
|
+
loadTranslations(process.env.I18NTK_LANG);
|
|
18
18
|
const { getUnifiedConfig, parseCommonArgs, displayHelp, ensureInitialized } = require('../utils/config-helper');
|
|
19
19
|
const SecurityUtils = require('../utils/security');
|
|
20
20
|
const configManager = require('../utils/config-manager');
|
package/main/i18ntk-complete.js
CHANGED
|
@@ -17,7 +17,7 @@ const { execSync } = require('child_process');
|
|
|
17
17
|
const SecurityUtils = require('../utils/security');
|
|
18
18
|
const { getUnifiedConfig, parseCommonArgs, displayHelp } = require('../utils/config-helper');
|
|
19
19
|
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
20
|
-
loadTranslations(process.env.I18NTK_LANG
|
|
20
|
+
loadTranslations(process.env.I18NTK_LANG);
|
|
21
21
|
const { getGlobalReadline, closeGlobalReadline } = require('../utils/cli');
|
|
22
22
|
|
|
23
23
|
|
package/main/i18ntk-init.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* I18N INITIALIZATION SCRIPT
|
|
4
4
|
*
|
|
@@ -20,7 +20,7 @@ const AdminAuth = require('../utils/admin-auth');
|
|
|
20
20
|
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
21
21
|
// Ensure UIi18n is available for this initializer class
|
|
22
22
|
const UIi18n = require('./i18ntk-ui');
|
|
23
|
-
loadTranslations(process.env.I18NTK_LANG
|
|
23
|
+
loadTranslations(process.env.I18NTK_LANG);
|
|
24
24
|
const { getUnifiedConfig, parseCommonArgs, displayHelp } = require('../utils/config-helper');
|
|
25
25
|
const { showFrameworkWarningOnce } = require('../utils/cli-helper');
|
|
26
26
|
|
|
@@ -66,15 +66,16 @@ class I18nInitializer {
|
|
|
66
66
|
// No longer create readline interface here - use CLI helpers
|
|
67
67
|
this.rl = null;
|
|
68
68
|
this.shouldCloseRL = false;
|
|
69
|
+
this.announcedExistingDir = false;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
//
|
|
72
|
+
// Updated checkI18nDependencies method that uses configuration
|
|
72
73
|
async checkI18nDependencies(noPrompt = false) {
|
|
73
74
|
const packageJsonPath = path.resolve('./package.json');
|
|
74
75
|
|
|
75
76
|
if (!fs.existsSync(packageJsonPath)) {
|
|
76
77
|
console.log(t('init.noPackageJson'));
|
|
77
|
-
return
|
|
78
|
+
return true; // Allow to continue without framework
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
try {
|
|
@@ -102,12 +103,13 @@ class I18nInitializer {
|
|
|
102
103
|
console.log(t('init.detectedI18nFrameworks', { frameworks: installedFrameworks.join(', ') }));
|
|
103
104
|
return true;
|
|
104
105
|
} else {
|
|
105
|
-
|
|
106
|
-
|
|
106
|
+
// Framework detection is now handled by maybePromptFramework in i18ntk-manage.js
|
|
107
|
+
// Skip prompting here to avoid double prompts
|
|
108
|
+
return true;
|
|
107
109
|
}
|
|
108
110
|
} catch (error) {
|
|
109
111
|
console.log(t('init.errors.packageJsonRead'));
|
|
110
|
-
return
|
|
112
|
+
return true; // Allow to continue on error
|
|
111
113
|
}
|
|
112
114
|
}
|
|
113
115
|
|
|
@@ -239,7 +241,10 @@ class I18nInitializer {
|
|
|
239
241
|
|
|
240
242
|
if (selectedIndex >= 0 && selectedIndex < existingLocations.length) {
|
|
241
243
|
const selectedDir = existingLocations[selectedIndex];
|
|
242
|
-
|
|
244
|
+
if (!this.announcedExistingDir) {
|
|
245
|
+
console.log(t('init.usingExistingDirectory', { dir: selectedDir }));
|
|
246
|
+
this.announcedExistingDir = true;
|
|
247
|
+
}
|
|
243
248
|
|
|
244
249
|
this.config.sourceDir = selectedDir;
|
|
245
250
|
this.sourceDir = path.resolve(selectedDir);
|
|
@@ -733,7 +738,10 @@ class I18nInitializer {
|
|
|
733
738
|
this.config.sourceDir = selectedDir;
|
|
734
739
|
this.sourceDir = path.resolve(selectedDir);
|
|
735
740
|
this.sourceLanguageDir = path.join(this.sourceDir, this.config.sourceLanguage);
|
|
736
|
-
|
|
741
|
+
if (!this.announcedExistingDir) {
|
|
742
|
+
console.log(t('init.usingExistingDirectory', { dir: selectedDir }));
|
|
743
|
+
this.announcedExistingDir = true;
|
|
744
|
+
}
|
|
737
745
|
} else {
|
|
738
746
|
await this.setupInitialStructure(args.noPrompt);
|
|
739
747
|
}
|
|
@@ -907,7 +915,14 @@ class I18nInitializer {
|
|
|
907
915
|
try {
|
|
908
916
|
// Parse command line arguments
|
|
909
917
|
const args = this.parseArgs();
|
|
910
|
-
|
|
918
|
+
|
|
919
|
+
// On first run, prompt user for preferred UI language
|
|
920
|
+
if (!fs.existsSync(configManager.CONFIG_PATH)) {
|
|
921
|
+
const { getGlobalReadline } = require('../utils/cli');
|
|
922
|
+
getGlobalReadline();
|
|
923
|
+
const selectedLang = await this.ui.selectLanguage();
|
|
924
|
+
loadTranslations(selectedLang);
|
|
925
|
+
}
|
|
911
926
|
// Initialize configuration properly when called from menu
|
|
912
927
|
if (fromMenu && !this.sourceDir) {
|
|
913
928
|
const baseConfig = await getUnifiedConfig('init', args);
|
package/main/i18ntk-manage.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* I18N MANAGEMENT TOOLKIT - MAIN MANAGER
|
|
4
4
|
*
|
|
@@ -34,9 +34,168 @@ const I18nSizingAnalyzer = require('./i18ntk-sizing');
|
|
|
34
34
|
const SettingsCLI = require('../settings/settings-cli');
|
|
35
35
|
const I18nDebugger = require('../scripts/debug/debugger');
|
|
36
36
|
|
|
37
|
-
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
38
|
-
loadTranslations(process.env.I18NTK_LANG || 'en');
|
|
37
|
+
const { loadTranslations, t, refreshLanguageFromSettings} = require('../utils/i18n-helper');
|
|
39
38
|
const cliHelper = require('../utils/cli-helper');
|
|
39
|
+
const { loadConfig, saveConfig, ensureConfigDefaults } = require('../utils/config');
|
|
40
|
+
const pkg = require('../package.json');
|
|
41
|
+
|
|
42
|
+
async function runInitFlow(rl) {
|
|
43
|
+
const initializer = new I18nInitializer();
|
|
44
|
+
await initializer.run({ fromMenu: true });
|
|
45
|
+
const settings = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
46
|
+
return { i18nDir: settings.i18nDir, sourceDir: settings.sourceDir };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function askYesNo(rl, prompt) {
|
|
50
|
+
return new Promise(res => {
|
|
51
|
+
rl.question(prompt, a => res(/^y(es)?$/i.test(a.trim())));
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function ensureInitializedOrExit(rl) {
|
|
56
|
+
const path = require('path');
|
|
57
|
+
const fs = require('fs');
|
|
58
|
+
const { ensureDirectory } = require('../utils/config-helper');
|
|
59
|
+
const settingsManager = require('../settings/settings-manager');
|
|
60
|
+
|
|
61
|
+
// Get configuration from settings manager
|
|
62
|
+
const settings = settingsManager.getAllSettings();
|
|
63
|
+
|
|
64
|
+
const cfg = {
|
|
65
|
+
sourceDir: path.resolve(settings.sourceDir || './locales'),
|
|
66
|
+
sourceLanguage: settings.sourceLanguage || 'en',
|
|
67
|
+
projectRoot: path.resolve('.'),
|
|
68
|
+
framework: settings.framework || { detected: false, prompt: 'always' }
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Check if already initialized using new tracking system
|
|
72
|
+
const initFilePath = path.join(process.cwd(), 'settings', 'initialization.json');
|
|
73
|
+
|
|
74
|
+
let isInitialized = false;
|
|
75
|
+
if (fs.existsSync(initFilePath)) {
|
|
76
|
+
try {
|
|
77
|
+
const initStatus = JSON.parse(fs.readFileSync(initFilePath, 'utf8'));
|
|
78
|
+
isInitialized = initStatus.initialized && initStatus.version === '1.7.1';
|
|
79
|
+
} catch (e) {
|
|
80
|
+
// Invalid init file, proceed with check
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (isInitialized) {
|
|
85
|
+
return cfg;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Check if source language files exist
|
|
89
|
+
const langDir = path.join(cfg.sourceDir, cfg.sourceLanguage);
|
|
90
|
+
|
|
91
|
+
const hasLanguageFiles = fs.existsSync(langDir) &&
|
|
92
|
+
fs.readdirSync(langDir).some(f => f.endsWith('.json'));
|
|
93
|
+
|
|
94
|
+
// If language files exist, mark as initialized
|
|
95
|
+
if (hasLanguageFiles) {
|
|
96
|
+
const initDir = path.dirname(initFilePath);
|
|
97
|
+
ensureDirectory(initDir);
|
|
98
|
+
fs.writeFileSync(initFilePath, JSON.stringify({
|
|
99
|
+
initialized: true,
|
|
100
|
+
version: '1.7.1',
|
|
101
|
+
timestamp: new Date().toISOString(),
|
|
102
|
+
sourceDir: cfg.sourceDir,
|
|
103
|
+
sourceLanguage: cfg.sourceLanguage
|
|
104
|
+
}, null, 2));
|
|
105
|
+
return cfg;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const answer = await askYesNo(rl, 'Initialization Required\nThis project must be initialized before running this command.\nWould you like to run initialization now? (y/N): ');
|
|
109
|
+
if (!answer) {
|
|
110
|
+
console.log('Operation cancelled.');
|
|
111
|
+
process.exit(0);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const result = await runInitFlow(rl);
|
|
115
|
+
|
|
116
|
+
// Mark as initialized after successful init
|
|
117
|
+
const initDir = path.dirname(initFilePath);
|
|
118
|
+
ensureDirectory(initDir);
|
|
119
|
+
fs.writeFileSync(initFilePath, JSON.stringify({
|
|
120
|
+
initialized: true,
|
|
121
|
+
version: '1.7.1',
|
|
122
|
+
timestamp: new Date().toISOString(),
|
|
123
|
+
sourceDir: result.sourceDir || cfg.sourceDir,
|
|
124
|
+
sourceLanguage: cfg.sourceLanguage
|
|
125
|
+
}, null, 2));
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
...cfg,
|
|
129
|
+
sourceDir: result.sourceDir || cfg.sourceDir,
|
|
130
|
+
i18nDir: result.i18nDir || cfg.i18nDir
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function maybePromptFramework(rl, cfg, currentVersion) {
|
|
135
|
+
// Load current settings to check framework configuration
|
|
136
|
+
const settings = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
137
|
+
|
|
138
|
+
// Ensure framework configuration exists
|
|
139
|
+
if (!settings.framework) {
|
|
140
|
+
settings.framework = {
|
|
141
|
+
detected: false,
|
|
142
|
+
preference: null,
|
|
143
|
+
prompt: 'always',
|
|
144
|
+
lastPromptedVersion: null
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Check if framework is already detected or preference is set to none
|
|
149
|
+
if (settings.framework.detected || settings.framework.preference === 'none') {
|
|
150
|
+
return cfg;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Check if dnr (do not remind) is active for this version
|
|
154
|
+
if (settings.framework.prompt === 'suppress' && settings.framework.lastPromptedVersion === currentVersion) {
|
|
155
|
+
return cfg;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Reset suppress if version changed
|
|
159
|
+
if (settings.framework.prompt === 'suppress' && settings.framework.lastPromptedVersion !== currentVersion) {
|
|
160
|
+
settings.framework.prompt = 'always';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (settings.framework.prompt === 'always') {
|
|
164
|
+
const ans = await new Promise(res =>
|
|
165
|
+
rl.question([
|
|
166
|
+
t('init.suggestions.noFramework'),
|
|
167
|
+
t('init.frameworks.react'),
|
|
168
|
+
t('init.frameworks.vue'),
|
|
169
|
+
t('init.frameworks.i18next'),
|
|
170
|
+
t('init.frameworks.nuxt'),
|
|
171
|
+
t('init.frameworks.svelte'),
|
|
172
|
+
'',
|
|
173
|
+
t('init.continueWithoutI18nPrompt') + ' (y/N/dnr = do not remind until next update): '
|
|
174
|
+
].join('\n'), a => res(a.trim().toLowerCase()))
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
if (ans === 'y' || ans === 'yes') {
|
|
178
|
+
settings.framework.preference = 'none';
|
|
179
|
+
settings.framework.prompt = 'always'; // Keep asking until explicitly suppressed
|
|
180
|
+
} else if (ans === 'dnr') {
|
|
181
|
+
settings.framework.preference = 'none';
|
|
182
|
+
settings.framework.prompt = 'suppress';
|
|
183
|
+
settings.framework.lastPromptedVersion = currentVersion;
|
|
184
|
+
} else {
|
|
185
|
+
console.log('Operation cancelled.');
|
|
186
|
+
process.exit(0);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Save configuration using settings manager
|
|
190
|
+
if (configManager.saveSettings) {
|
|
191
|
+
configManager.saveSettings(settings);
|
|
192
|
+
} else if (configManager.saveConfig) {
|
|
193
|
+
configManager.saveConfig(settings);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return cfg;
|
|
198
|
+
}
|
|
40
199
|
|
|
41
200
|
// Use unified configuration system
|
|
42
201
|
const { getUnifiedConfig, ensureInitialized, validateSourceDir } = require('../utils/config-helper');
|
|
@@ -48,7 +207,7 @@ class I18nManager {
|
|
|
48
207
|
this.isReadlineClosed = false;
|
|
49
208
|
this.isAuthenticated = false;
|
|
50
209
|
this.ui = null;
|
|
51
|
-
this.adminAuth =
|
|
210
|
+
this.adminAuth = new AdminAuth();
|
|
52
211
|
|
|
53
212
|
// No longer create readline interface here - use CLI helpers
|
|
54
213
|
}
|
|
@@ -62,34 +221,29 @@ class I18nManager {
|
|
|
62
221
|
// Initialize configuration using unified system
|
|
63
222
|
async initialize() {
|
|
64
223
|
try {
|
|
224
|
+
// Parse args here for other initialization needs (but language is already loaded)
|
|
65
225
|
const args = this.parseArgs();
|
|
66
226
|
if (args.help) {
|
|
67
227
|
this.showHelp();
|
|
68
228
|
process.exit(0);
|
|
69
229
|
}
|
|
70
230
|
|
|
71
|
-
|
|
72
|
-
this.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
this.adminAuth = new AdminAuth();
|
|
79
|
-
|
|
80
|
-
// Load language from saved configuration, not just CLI args
|
|
81
|
-
const settings = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
82
|
-
const uiLanguage = settings.uiLanguage || settings.language || this.config.uiLanguage || 'en';
|
|
83
|
-
this.ui.loadLanguage(uiLanguage);
|
|
231
|
+
// Ensure UI is initialized (it should already be loaded in run())
|
|
232
|
+
if (!this.ui) {
|
|
233
|
+
const settings = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
234
|
+
const uiLanguage = args.uiLanguage || settings.uiLanguage || settings.language || this.config.uiLanguage || 'en';
|
|
235
|
+
this.ui.loadLanguage(uiLanguage);
|
|
236
|
+
loadTranslations(uiLanguage);
|
|
237
|
+
}
|
|
84
238
|
|
|
85
239
|
// Validate source directory exists
|
|
86
240
|
const {validateSourceDir, displayPaths} = require('../utils/config-helper');
|
|
87
241
|
try {
|
|
88
242
|
validateSourceDir(this.config.sourceDir, 'i18ntk-manage');
|
|
89
243
|
} catch (err) {
|
|
90
|
-
console.log(t('init.requiredTitle'));
|
|
91
|
-
console.log(t('init.requiredBody'));
|
|
92
|
-
const answer = await cliHelper.prompt(t('init.promptRunNow'));
|
|
244
|
+
console.log(this.ui.t('init.requiredTitle'));
|
|
245
|
+
console.log(this.ui.t('init.requiredBody'));
|
|
246
|
+
const answer = await cliHelper.prompt(this.ui.t('init.promptRunNow'));
|
|
93
247
|
if (answer.trim().toLowerCase() === 'y') {
|
|
94
248
|
const initializer = new I18nInitializer(this.config);
|
|
95
249
|
await initializer.run({ fromMenu: true });
|
|
@@ -99,13 +253,14 @@ class I18nManager {
|
|
|
99
253
|
}
|
|
100
254
|
|
|
101
255
|
} catch (error) {
|
|
102
|
-
|
|
256
|
+
|
|
103
257
|
throw error;
|
|
104
258
|
}
|
|
105
259
|
}
|
|
106
260
|
|
|
107
261
|
// Auto-detect i18n directory from common locations only if not configured in settings
|
|
108
262
|
detectI18nDirectory() {
|
|
263
|
+
|
|
109
264
|
const settings = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
110
265
|
const projectRoot = path.resolve(settings.projectRoot || this.config.projectRoot || '.');
|
|
111
266
|
|
|
@@ -156,13 +311,13 @@ class I18nManager {
|
|
|
156
311
|
}
|
|
157
312
|
}
|
|
158
313
|
|
|
159
|
-
// Check if i18n framework is installed
|
|
314
|
+
// Check if i18n framework is installed - configuration-based check without prompts
|
|
160
315
|
async checkI18nDependencies() {
|
|
161
316
|
const packageJsonPath = path.resolve('./package.json');
|
|
162
317
|
|
|
163
318
|
if (!fs.existsSync(packageJsonPath)) {
|
|
164
|
-
console.log(t('init.noPackageJson'));
|
|
165
|
-
return
|
|
319
|
+
console.log(this.ui ? this.ui.t('init.noPackageJson') : 'No package.json found');
|
|
320
|
+
return true; // Allow to continue without framework
|
|
166
321
|
}
|
|
167
322
|
|
|
168
323
|
try {
|
|
@@ -187,20 +342,27 @@ class I18nManager {
|
|
|
187
342
|
const installedFrameworks = i18nFrameworks.filter(framework => dependencies[framework]);
|
|
188
343
|
|
|
189
344
|
if (installedFrameworks.length > 0) {
|
|
190
|
-
|
|
345
|
+
if (this.ui && this.ui.t) {
|
|
346
|
+
console.log(this.ui.t('init.detectedFrameworks', { frameworks: installedFrameworks.join(', ') }));
|
|
347
|
+
} else {
|
|
348
|
+
console.log(`Detected frameworks: ${installedFrameworks.join(', ')}`);
|
|
349
|
+
}
|
|
191
350
|
return true;
|
|
192
351
|
} else {
|
|
352
|
+
// Check configuration for framework preference
|
|
193
353
|
const cfg = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
194
|
-
|
|
354
|
+
|
|
355
|
+
// If framework preference is already set to 'none', skip warning
|
|
356
|
+
if (cfg.framework === 'none' || (cfg.framework && cfg.framework.preference === 'none')) {
|
|
195
357
|
return true;
|
|
196
358
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return
|
|
359
|
+
|
|
360
|
+
// Framework detection is handled by maybePromptFramework, so just return true here
|
|
361
|
+
return true;
|
|
200
362
|
}
|
|
201
363
|
} catch (error) {
|
|
202
364
|
console.log(t('init.errors.packageJsonRead'));
|
|
203
|
-
return
|
|
365
|
+
return true; // Allow to continue on error
|
|
204
366
|
}
|
|
205
367
|
}
|
|
206
368
|
|
|
@@ -208,7 +370,8 @@ class I18nManager {
|
|
|
208
370
|
* Prompt user to continue without i18n framework
|
|
209
371
|
*/
|
|
210
372
|
async promptContinueWithoutI18n() {
|
|
211
|
-
const
|
|
373
|
+
const promptText = this.ui && this.ui.t ? this.ui.t('init.continueWithoutI18nPrompt') : 'Do you want to continue without one? (y/N)';
|
|
374
|
+
const answer = await this.prompt('\n' + promptText);
|
|
212
375
|
return answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
|
|
213
376
|
}
|
|
214
377
|
|
|
@@ -259,11 +422,27 @@ class I18nManager {
|
|
|
259
422
|
// Add this run method after the checkI18nDependencies method
|
|
260
423
|
async run() {
|
|
261
424
|
try {
|
|
425
|
+
// Parse command line arguments first
|
|
426
|
+
const args = this.parseArgs();
|
|
427
|
+
|
|
428
|
+
// Load settings to get language preference BEFORE any messages
|
|
429
|
+
const settings = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
430
|
+
|
|
431
|
+
// Initialize UI localization system with language from settings
|
|
432
|
+
this.ui = new UIi18n();
|
|
433
|
+
const uiLanguage = args.uiLanguage || settings.uiLanguage || settings.language || this.config.uiLanguage || 'en';
|
|
434
|
+
this.ui.loadLanguage(uiLanguage);
|
|
435
|
+
|
|
436
|
+
const rl = cliHelper.getInterface();
|
|
437
|
+
const cfgAfterInitCheck = await ensureInitializedOrExit(rl);
|
|
438
|
+
await maybePromptFramework(rl, cfgAfterInitCheck, pkg.version);
|
|
439
|
+
|
|
440
|
+
// Update this.config with the configuration from ensureInitializedOrExit
|
|
441
|
+
this.config = { ...this.config, ...cfgAfterInitCheck };
|
|
442
|
+
|
|
262
443
|
// Initialize configuration using unified system
|
|
263
444
|
await this.initialize();
|
|
264
445
|
|
|
265
|
-
// Parse command line arguments
|
|
266
|
-
const args = this.parseArgs();
|
|
267
446
|
const rawArgs = process.argv.slice(2); // Preserve original CLI args array for positional checks
|
|
268
447
|
let commandToExecute = null;
|
|
269
448
|
|
|
@@ -301,13 +480,8 @@ class I18nManager {
|
|
|
301
480
|
return;
|
|
302
481
|
}
|
|
303
482
|
|
|
304
|
-
//
|
|
305
|
-
|
|
306
|
-
if (!shouldContinue) {
|
|
307
|
-
console.log(t('init.errorsNoFramework'));
|
|
308
|
-
console.log(t('init.suggestions.installFramework'));
|
|
309
|
-
process.exit(0);
|
|
310
|
-
}
|
|
483
|
+
// Framework detection is now handled by maybePromptFramework above
|
|
484
|
+
// Skip the redundant checkI18nDependencies prompt
|
|
311
485
|
|
|
312
486
|
// Interactive mode - showInteractiveMenu will handle the title
|
|
313
487
|
await this.showInteractiveMenu();
|
package/main/i18ntk-sizing.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* I18n Sizing Analyzer
|
|
@@ -35,7 +35,7 @@ const fs = require('fs');
|
|
|
35
35
|
const path = require('path');
|
|
36
36
|
const { performance } = require('perf_hooks');
|
|
37
37
|
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
38
|
-
loadTranslations(process.env.I18NTK_LANG
|
|
38
|
+
loadTranslations(process.env.I18NTK_LANG);
|
|
39
39
|
const configManager = require('../settings/settings-manager');
|
|
40
40
|
const SecurityUtils = require('../utils/security');
|
|
41
41
|
const { getUnifiedConfig } = require('../utils/config-helper');
|
package/main/i18ntk-summary.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
6
|
-
loadTranslations(process.env.I18NTK_LANG
|
|
6
|
+
loadTranslations(process.env.I18NTK_LANG);
|
|
7
7
|
const { getUnifiedConfig, parseCommonArgs, displayHelp } = require('../utils/config-helper');
|
|
8
8
|
const SecurityUtils = require('../utils/security');
|
|
9
9
|
const AdminCLI = require('../utils/admin-cli');
|
package/main/i18ntk-ui.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
const path = require('path');
|
|
8
8
|
const SettingsManager = require('../settings/settings-manager');
|
|
9
|
+
const legacyConfigManager = require('../utils/config-manager');
|
|
9
10
|
const configManager = SettingsManager;
|
|
10
11
|
|
|
11
12
|
class UIi18n {
|
|
@@ -223,6 +224,11 @@ this.translations = {};
|
|
|
223
224
|
await configManager.updateConfig(settings);
|
|
224
225
|
}
|
|
225
226
|
}
|
|
227
|
+
|
|
228
|
+
// Keep legacy config-manager in sync for modules using it directly
|
|
229
|
+
if (legacyConfigManager && legacyConfigManager.updateConfig) {
|
|
230
|
+
await legacyConfigManager.updateConfig({ language, uiLanguage: language });
|
|
231
|
+
}
|
|
226
232
|
} catch (error) {
|
|
227
233
|
console.error(`Error saving language preference: ${error.message}`);
|
|
228
234
|
}
|
package/main/i18ntk-usage.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* I18N USAGE ANALYSIS TOOLKIT - Version 1.6.3
|
|
4
4
|
*
|
|
@@ -25,7 +25,7 @@ const fs = require('fs');
|
|
|
25
25
|
const path = require('path');
|
|
26
26
|
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
27
27
|
const { getGlobalReadline, closeGlobalReadline, askHidden } = require('../utils/cli');
|
|
28
|
-
loadTranslations(process.env.I18NTK_LANG
|
|
28
|
+
loadTranslations(process.env.I18NTK_LANG);
|
|
29
29
|
const configManager = require('../utils/config-manager');
|
|
30
30
|
const SecurityUtils = require('../utils/security');
|
|
31
31
|
const AdminCLI = require('../utils/admin-cli');
|