i18ntk 1.7.1 → 1.7.2
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 +5 -4
- package/main/i18ntk-init.js +19 -1
- package/main/i18ntk-manage.js +32 -10
- package/package.json +2 -2
- package/scripts/admin-auth.test.js +1 -1
- package/scripts/prepublish.js +1 -1
- package/settings/settings-manager.js +2 -2
- package/utils/admin-auth.js +2 -1
- package/utils/config-helper.js +10 -9
- package/utils/config-manager.js +2 -1
- package/utils/config.js +6 -6
- package/utils/security.js +1 -1
package/README.md
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
**Version:** 1.7.
|
|
5
|
+
**Version:** 1.7.2
|
|
6
6
|
**Last Updated:** 2025-08-10
|
|
7
7
|
**GitHub Repository:** [vladnoskv/i18ntk](https://github.com/vladnoskv/i18ntk)
|
|
8
8
|
|
|
9
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.
|
|
10
|
+
[](https://socket.dev/npm/package/i18ntk/overview/1.7.2)
|
|
11
11
|
|
|
12
12
|
**🚀 The fastest way to manage translations across any framework or vanilla JavaScript projects**
|
|
13
13
|
|
|
14
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.
|
|
15
15
|
|
|
16
|
-
> **v1.7.
|
|
16
|
+
> **v1.7.2** – Enhanced security logging, flexible 4-6 digit PIN authentication, configuration stability improvements, **fixed framework detection prompt**, and CI/CD silent mode support; maintains 97% speed improvement (**15.38ms** for 200k keys up to 5/M keys per second).
|
|
17
17
|
|
|
18
18
|
## 🚀 Quick Start
|
|
19
19
|
|
|
@@ -53,6 +53,7 @@ i18ntk validate --source ./locales
|
|
|
53
53
|
- **Framework Support**: Auto-detects React i18next, Vue i18n, Angular, Next i18next, Nuxt i18next, Svelte i18n
|
|
54
54
|
- **Memory Optimization**: 67% memory reduction with streaming processing
|
|
55
55
|
- **Scalability**: Linear scaling up to 5M keys with ultra-extreme settings
|
|
56
|
+
- **Smart Framework Detection**: Automatically skips unnecessary prompts when i18n frameworks are detected
|
|
56
57
|
|
|
57
58
|
### 📸 Screenshots
|
|
58
59
|
|
|
@@ -87,7 +88,7 @@ Configuration is managed through the `settings/i18ntk-config.json` file:
|
|
|
87
88
|
|
|
88
89
|
```json
|
|
89
90
|
{
|
|
90
|
-
"version": "1.7.
|
|
91
|
+
"version": "1.7.2",
|
|
91
92
|
"sourceDir": "./locales",
|
|
92
93
|
"outputDir": "./i18ntk-reports",
|
|
93
94
|
"defaultLanguage": "en",
|
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
|
*
|
|
@@ -101,8 +101,26 @@ class I18nInitializer {
|
|
|
101
101
|
|
|
102
102
|
if (installedFrameworks.length > 0) {
|
|
103
103
|
console.log(t('init.detectedI18nFrameworks', { frameworks: installedFrameworks.join(', ') }));
|
|
104
|
+
const cfg = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
105
|
+
cfg.framework = cfg.framework || {};
|
|
106
|
+
cfg.framework.detected = true;
|
|
107
|
+
cfg.framework.installed = installedFrameworks;
|
|
108
|
+
if (configManager.saveSettings) {
|
|
109
|
+
configManager.saveSettings(cfg);
|
|
110
|
+
} else if (configManager.saveConfig) {
|
|
111
|
+
configManager.saveConfig(cfg);
|
|
112
|
+
}
|
|
104
113
|
return true;
|
|
105
114
|
} else {
|
|
115
|
+
const cfg = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
116
|
+
if (cfg.framework) {
|
|
117
|
+
cfg.framework.detected = false;
|
|
118
|
+
if (configManager.saveSettings) {
|
|
119
|
+
configManager.saveSettings(cfg);
|
|
120
|
+
} else if (configManager.saveConfig) {
|
|
121
|
+
configManager.saveConfig(cfg);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
106
124
|
// Framework detection is now handled by maybePromptFramework in i18ntk-manage.js
|
|
107
125
|
// Skip prompting here to avoid double prompts
|
|
108
126
|
return true;
|
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
|
*
|
|
@@ -69,13 +69,13 @@ async function ensureInitializedOrExit(rl) {
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
// Check if already initialized using new tracking system
|
|
72
|
-
const initFilePath = path.join(
|
|
72
|
+
const initFilePath = path.join(settingsManager.configDir, 'initialization.json');
|
|
73
73
|
|
|
74
74
|
let isInitialized = false;
|
|
75
75
|
if (fs.existsSync(initFilePath)) {
|
|
76
76
|
try {
|
|
77
77
|
const initStatus = JSON.parse(fs.readFileSync(initFilePath, 'utf8'));
|
|
78
|
-
isInitialized = initStatus.initialized && initStatus.version === '1.7.
|
|
78
|
+
isInitialized = initStatus.initialized && initStatus.version === '1.7.2';
|
|
79
79
|
} catch (e) {
|
|
80
80
|
// Invalid init file, proceed with check
|
|
81
81
|
}
|
|
@@ -97,7 +97,7 @@ async function ensureInitializedOrExit(rl) {
|
|
|
97
97
|
ensureDirectory(initDir);
|
|
98
98
|
fs.writeFileSync(initFilePath, JSON.stringify({
|
|
99
99
|
initialized: true,
|
|
100
|
-
version: '1.7.
|
|
100
|
+
version: '1.7.2',
|
|
101
101
|
timestamp: new Date().toISOString(),
|
|
102
102
|
sourceDir: cfg.sourceDir,
|
|
103
103
|
sourceLanguage: cfg.sourceLanguage
|
|
@@ -118,7 +118,7 @@ async function ensureInitializedOrExit(rl) {
|
|
|
118
118
|
ensureDirectory(initDir);
|
|
119
119
|
fs.writeFileSync(initFilePath, JSON.stringify({
|
|
120
120
|
initialized: true,
|
|
121
|
-
version: '1.7.
|
|
121
|
+
version: '1.7.2',
|
|
122
122
|
timestamp: new Date().toISOString(),
|
|
123
123
|
sourceDir: result.sourceDir || cfg.sourceDir,
|
|
124
124
|
sourceLanguage: cfg.sourceLanguage
|
|
@@ -145,6 +145,12 @@ async function maybePromptFramework(rl, cfg, currentVersion) {
|
|
|
145
145
|
};
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
// Reload settings to ensure we have latest framework detection results
|
|
149
|
+
const freshSettings = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
150
|
+
if (freshSettings.framework) {
|
|
151
|
+
settings.framework = freshSettings.framework;
|
|
152
|
+
}
|
|
153
|
+
|
|
148
154
|
// Check if framework is already detected or preference is set to none
|
|
149
155
|
if (settings.framework.detected || settings.framework.preference === 'none') {
|
|
150
156
|
return cfg;
|
|
@@ -340,23 +346,38 @@ class I18nManager {
|
|
|
340
346
|
];
|
|
341
347
|
|
|
342
348
|
const installedFrameworks = i18nFrameworks.filter(framework => dependencies[framework]);
|
|
343
|
-
|
|
349
|
+
|
|
344
350
|
if (installedFrameworks.length > 0) {
|
|
345
351
|
if (this.ui && this.ui.t) {
|
|
346
352
|
console.log(this.ui.t('init.detectedFrameworks', { frameworks: installedFrameworks.join(', ') }));
|
|
347
353
|
} else {
|
|
348
354
|
console.log(`Detected frameworks: ${installedFrameworks.join(', ')}`);
|
|
349
355
|
}
|
|
356
|
+
const cfg = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
357
|
+
cfg.framework = cfg.framework || {};
|
|
358
|
+
cfg.framework.detected = true;
|
|
359
|
+
cfg.framework.installed = installedFrameworks;
|
|
360
|
+
if (configManager.saveSettings) {
|
|
361
|
+
configManager.saveSettings(cfg);
|
|
362
|
+
} else if (configManager.saveConfig) {
|
|
363
|
+
configManager.saveConfig(cfg);
|
|
364
|
+
}
|
|
350
365
|
return true;
|
|
351
366
|
} else {
|
|
352
|
-
// Check configuration for framework preference
|
|
353
367
|
const cfg = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
|
354
|
-
|
|
368
|
+
if (cfg.framework) {
|
|
369
|
+
cfg.framework.detected = false;
|
|
370
|
+
if (configManager.saveSettings) {
|
|
371
|
+
configManager.saveSettings(cfg);
|
|
372
|
+
} else if (configManager.saveConfig) {
|
|
373
|
+
configManager.saveConfig(cfg);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
355
376
|
// If framework preference is already set to 'none', skip warning
|
|
356
377
|
if (cfg.framework === 'none' || (cfg.framework && cfg.framework.preference === 'none')) {
|
|
357
378
|
return true;
|
|
358
379
|
}
|
|
359
|
-
|
|
380
|
+
|
|
360
381
|
// Framework detection is handled by maybePromptFramework, so just return true here
|
|
361
382
|
return true;
|
|
362
383
|
}
|
|
@@ -435,6 +456,7 @@ class I18nManager {
|
|
|
435
456
|
|
|
436
457
|
const rl = cliHelper.getInterface();
|
|
437
458
|
const cfgAfterInitCheck = await ensureInitializedOrExit(rl);
|
|
459
|
+
await this.checkI18nDependencies();
|
|
438
460
|
await maybePromptFramework(rl, cfgAfterInitCheck, pkg.version);
|
|
439
461
|
|
|
440
462
|
// Update this.config with the configuration from ensureInitializedOrExit
|
|
@@ -1065,7 +1087,7 @@ class I18nManager {
|
|
|
1065
1087
|
{ path: path.join(process.cwd(), 'reports', 'backups'), name: 'Reports Backups', type: 'backups' },
|
|
1066
1088
|
{ path: path.join(process.cwd(), 'scripts', 'debug', 'logs'), name: 'Debug Logs', type: 'logs' },
|
|
1067
1089
|
{ path: path.join(process.cwd(), 'scripts', 'debug', 'reports'), name: 'Debug Reports', type: 'reports' },
|
|
1068
|
-
{ path: path.join(
|
|
1090
|
+
{ path: path.join(configManager.configDir, 'backups'), name: 'Settings Backups', type: 'backups' },
|
|
1069
1091
|
{ path: path.join(process.cwd(), 'utils', 'i18ntk-reports'), name: 'Utils Reports', type: 'reports' }
|
|
1070
1092
|
];
|
|
1071
1093
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "i18ntk",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"description": "i18ntk (i18n Toolkit) - Ultra-extreme performance enterprise-grade internationalization management toolkit with 97% performance improvement (15.38ms for 200k keys), advanced security with PIN protection, comprehensive backup & recovery, and edge case handling for JavaScript/TypeScript projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
},
|
|
145
145
|
"preferGlobal": true,
|
|
146
146
|
"versionInfo": {
|
|
147
|
-
"version": "1.7.
|
|
147
|
+
"version": "1.7.2",
|
|
148
148
|
"releaseDate": "27/07/2025",
|
|
149
149
|
"lastUpdated": "10/08/2025",
|
|
150
150
|
"maintainer": "Vladimir Noskov",
|
|
@@ -4,7 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const AdminAuth = require('../utils/admin-auth');
|
|
5
5
|
|
|
6
6
|
(async () => {
|
|
7
|
-
const configPath = path.join(
|
|
7
|
+
const configPath = path.join(require('../settings/settings-manager').configDir, '.i18n-admin-config.json');
|
|
8
8
|
const auth = new AdminAuth();
|
|
9
9
|
|
|
10
10
|
try {
|
package/scripts/prepublish.js
CHANGED
|
@@ -316,7 +316,7 @@ class PrepublishCleaner {
|
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
async resetSecuritySettings() {
|
|
319
|
-
const configPath = path.join(
|
|
319
|
+
const configPath = path.join(require('../settings/settings-manager').configDir, '.i18n-admin-config.json');
|
|
320
320
|
|
|
321
321
|
if (fs.existsSync(configPath)) {
|
|
322
322
|
const defaultConfig = {
|
|
@@ -9,8 +9,8 @@ const path = require('path');
|
|
|
9
9
|
|
|
10
10
|
class SettingsManager {
|
|
11
11
|
constructor() {
|
|
12
|
-
const
|
|
13
|
-
this.configDir =
|
|
12
|
+
const packageDir = __dirname;
|
|
13
|
+
this.configDir = packageDir;
|
|
14
14
|
this.configFile = path.join(this.configDir, 'i18ntk-config.json');
|
|
15
15
|
this.lastBackupTime = 0;
|
|
16
16
|
this.backupDebounceMs = 5000; // 5 seconds debounce
|
package/utils/admin-auth.js
CHANGED
|
@@ -10,7 +10,8 @@ const configManager = require('./config-manager');
|
|
|
10
10
|
*/
|
|
11
11
|
class AdminAuth {
|
|
12
12
|
constructor() {
|
|
13
|
-
|
|
13
|
+
const settingsDir = require('../settings/settings-manager').configDir;
|
|
14
|
+
this.configPath = path.join(settingsDir, '.i18n-admin-config.json');
|
|
14
15
|
|
|
15
16
|
// Get settings from config manager
|
|
16
17
|
const settings = configManager.loadSettings ? configManager.loadSettings() : (configManager.getConfig ? configManager.getConfig() : {});
|
package/utils/config-helper.js
CHANGED
|
@@ -64,6 +64,7 @@ async function getUnifiedConfig(scriptName, cliArgs = {}) {
|
|
|
64
64
|
outputDir: configManager.toRelative(cfg.outputDir),
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
+
const settingsDir = settingsManager.configDir;
|
|
67
68
|
const config = {
|
|
68
69
|
...cfg,
|
|
69
70
|
sourceLanguage: cliArgs.sourceLanguage || cfg.sourceLanguage || 'en',
|
|
@@ -73,10 +74,10 @@ async function getUnifiedConfig(scriptName, cliArgs = {}) {
|
|
|
73
74
|
excludeFiles: cfg.excludeFiles || cfg.processing?.excludeFiles || ['.DS_Store', 'Thumbs.db'],
|
|
74
75
|
excludeDirs: cfg.excludeDirs || cfg.processing?.excludeDirs || ['node_modules', '.next', '.git', 'dist', 'build'],
|
|
75
76
|
strictMode: cliArgs.strictMode || cfg.strictMode || false,
|
|
76
|
-
backupDir: path.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
backupDir: path.join(settingsDir, 'backups'),
|
|
78
|
+
tempDir: path.join(settingsDir, 'temp'),
|
|
79
|
+
cacheDir: path.join(settingsDir, '.cache'),
|
|
80
|
+
configDir: settingsDir,
|
|
80
81
|
settings: {
|
|
81
82
|
defaultLanguages: cfg.defaultLanguages || ['de', 'es', 'fr', 'ru'],
|
|
82
83
|
processing: { ...cfg.processing },
|
|
@@ -268,14 +269,14 @@ function displayPaths(cfg = {}) {
|
|
|
268
269
|
async function ensureInitialized(cfg) {
|
|
269
270
|
try {
|
|
270
271
|
// Check if initialization has been marked as complete
|
|
271
|
-
const configPath = path.join(
|
|
272
|
+
const configPath = path.join(settingsManager.configDir, 'initialization.json');
|
|
272
273
|
let initStatus = { initialized: false, version: null, timestamp: null };
|
|
273
274
|
|
|
274
275
|
if (fs.existsSync(configPath)) {
|
|
275
276
|
try {
|
|
276
277
|
initStatus = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
277
278
|
// If initialized and version matches current, skip further checks
|
|
278
|
-
if (initStatus.initialized && initStatus.version === '1.7.
|
|
279
|
+
if (initStatus.initialized && initStatus.version === '1.7.2') {
|
|
279
280
|
return true;
|
|
280
281
|
}
|
|
281
282
|
} catch (e) {
|
|
@@ -296,7 +297,7 @@ async function ensureInitialized(cfg) {
|
|
|
296
297
|
ensureDirectory(initDir);
|
|
297
298
|
fs.writeFileSync(configPath, JSON.stringify({
|
|
298
299
|
initialized: true,
|
|
299
|
-
version: '1.7.
|
|
300
|
+
version: '1.7.2',
|
|
300
301
|
timestamp: new Date().toISOString(),
|
|
301
302
|
sourceDir: sourceDir,
|
|
302
303
|
sourceLanguage: sourceLanguage
|
|
@@ -316,7 +317,7 @@ async function ensureInitialized(cfg) {
|
|
|
316
317
|
ensureDirectory(initDir);
|
|
317
318
|
fs.writeFileSync(configPath, JSON.stringify({
|
|
318
319
|
initialized: true,
|
|
319
|
-
version: '1.7.
|
|
320
|
+
version: '1.7.2',
|
|
320
321
|
timestamp: new Date().toISOString(),
|
|
321
322
|
sourceDir: sourceDir,
|
|
322
323
|
sourceLanguage: sourceLanguage
|
|
@@ -337,7 +338,7 @@ async function ensureInitialized(cfg) {
|
|
|
337
338
|
ensureDirectory(initDir);
|
|
338
339
|
fs.writeFileSync(configPath, JSON.stringify({
|
|
339
340
|
initialized: true,
|
|
340
|
-
version: '1.7.
|
|
341
|
+
version: '1.7.2',
|
|
341
342
|
timestamp: new Date().toISOString(),
|
|
342
343
|
sourceDir: sourceDir,
|
|
343
344
|
sourceLanguage: sourceLanguage
|
package/utils/config-manager.js
CHANGED
|
@@ -3,7 +3,8 @@ const path = require('path');
|
|
|
3
3
|
|
|
4
4
|
// Project root is where commands are executed
|
|
5
5
|
const projectRoot = process.cwd();
|
|
6
|
-
const
|
|
6
|
+
const settingsManager = require('../settings/settings-manager');
|
|
7
|
+
const CONFIG_DIR = settingsManager.configDir;
|
|
7
8
|
const CONFIG_PATH = path.join(CONFIG_DIR, 'i18ntk-config.json');
|
|
8
9
|
|
|
9
10
|
// Default configuration values - comprehensive configuration
|
package/utils/config.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const settingsManager = require('../settings/settings-manager');
|
|
5
5
|
const CONFIG_FILE = 'i18ntk-config.json';
|
|
6
6
|
|
|
7
|
-
function getConfigPath(cwd =
|
|
8
|
-
return path.join(cwd,
|
|
7
|
+
function getConfigPath(cwd = settingsManager.configDir) {
|
|
8
|
+
return path.join(cwd, CONFIG_FILE);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
function loadConfig(cwd =
|
|
11
|
+
function loadConfig(cwd = settingsManager.configDir) {
|
|
12
12
|
const p = getConfigPath(cwd);
|
|
13
13
|
try {
|
|
14
14
|
const raw = fs.readFileSync(p, 'utf8');
|
|
@@ -18,8 +18,8 @@ function loadConfig(cwd = process.cwd()) {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
function saveConfig(cfg, cwd =
|
|
22
|
-
const dir =
|
|
21
|
+
function saveConfig(cfg, cwd = settingsManager.configDir) {
|
|
22
|
+
const dir = cwd;
|
|
23
23
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
24
24
|
fs.writeFileSync(path.join(dir, CONFIG_FILE), JSON.stringify(cfg, null, 2), 'utf8');
|
|
25
25
|
}
|
package/utils/security.js
CHANGED
|
@@ -356,7 +356,7 @@ class SecurityUtils {
|
|
|
356
356
|
static async saveEncryptedPin(pin) {
|
|
357
357
|
try {
|
|
358
358
|
const hash = crypto.createHash('sha256').update(pin).digest('hex');
|
|
359
|
-
const settingsDir =
|
|
359
|
+
const settingsDir = require('../settings/settings-manager').configDir;
|
|
360
360
|
const pinFile = path.join(settingsDir, 'admin-pin.hash');
|
|
361
361
|
await fs.promises.mkdir(settingsDir, { recursive: true });
|
|
362
362
|
await fs.promises.writeFile(pinFile, hash, 'utf8');
|