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.
- package/README.md +10 -6
- package/main/i18ntk-analyze.js +63 -63
- package/main/i18ntk-complete.js +75 -74
- package/main/i18ntk-fixer.js +3 -3
- package/main/i18ntk-init.js +5 -5
- package/main/i18ntk-scanner.js +2 -2
- package/main/i18ntk-sizing.js +35 -35
- package/main/i18ntk-summary.js +4 -4
- package/main/i18ntk-ui.js +95 -96
- package/main/i18ntk-usage.js +14 -14
- package/main/i18ntk-validate.js +6 -5
- package/main/manage/commands/AnalyzeCommand.js +67 -67
- package/main/manage/commands/FixerCommand.js +2 -2
- package/main/manage/commands/ScannerCommand.js +2 -2
- package/main/manage/commands/ValidateCommand.js +9 -9
- package/main/manage/index.js +7 -4
- package/main/manage/managers/LanguageMenu.js +7 -2
- package/main/manage/services/UsageService.js +7 -7
- package/package.json +20 -41
- package/settings/settings-cli.js +3 -3
- package/ui-locales/de.json +12 -11
- package/ui-locales/en.json +12 -11
- package/ui-locales/es.json +12 -11
- package/ui-locales/fr.json +12 -11
- package/ui-locales/ja.json +12 -11
- package/ui-locales/ru.json +12 -11
- package/ui-locales/zh.json +12 -11
- package/utils/i18n-helper.js +161 -166
- package/{scripts → utils}/locale-optimizer.js +61 -60
- package/main/i18ntk-go.js +0 -283
- package/main/i18ntk-java.js +0 -380
- package/main/i18ntk-js.js +0 -512
- package/main/i18ntk-manage.js +0 -1694
- package/main/i18ntk-php.js +0 -462
- package/main/i18ntk-py.js +0 -379
- package/main/i18ntk-settings.js +0 -23
- package/main/manage/index-fixed.js +0 -1447
- package/scripts/build-lite.js +0 -279
- package/scripts/deprecate-versions.js +0 -317
- package/scripts/export-translations.js +0 -84
- package/scripts/fix-all-i18n.js +0 -236
- package/scripts/fix-and-purify-i18n.js +0 -233
- package/scripts/fix-locale-control-chars.js +0 -110
- package/scripts/lint-locales.js +0 -80
- package/scripts/prepublish-dev.js +0 -221
- package/scripts/prepublish.js +0 -362
- package/scripts/security-check.js +0 -117
- package/scripts/sync-translations.js +0 -151
- package/scripts/sync-ui-locales.js +0 -20
- package/scripts/validate-all-translations.js +0 -195
- package/scripts/verify-deprecations.js +0 -157
- package/scripts/verify-translations.js +0 -63
- package/utils/security-fixed.js +0 -609
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# i18ntk v2.
|
|
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
|
[](https://nodejs.org)
|
|
10
10
|
[](https://www.npmjs.com/package/i18ntk)
|
|
11
11
|
[](LICENSE)
|
|
12
|
-
[](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.
|
|
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.
|
|
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
|
package/main/i18ntk-analyze.js
CHANGED
|
@@ -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(
|
|
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, '..', '
|
|
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, '..', '
|
|
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);
|
package/main/i18ntk-complete.js
CHANGED
|
@@ -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, '..', '
|
|
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;
|
package/main/i18ntk-fixer.js
CHANGED
|
@@ -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, '..', '
|
|
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, '..', '
|
|
54
|
+
loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
|
|
55
55
|
|
|
56
56
|
this.sourceDir = this.config.sourceDir;
|
|
57
57
|
this.outputDir = this.config.outputDir;
|
package/main/i18ntk-init.js
CHANGED
|
@@ -1122,7 +1122,7 @@ class I18nInitializer {
|
|
|
1122
1122
|
|
|
1123
1123
|
try {
|
|
1124
1124
|
// Import locale optimizer directly
|
|
1125
|
-
const LocaleOptimizer = require('../
|
|
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
|
|
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
|
|
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, '..', '
|
|
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, '..', '
|
|
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...');
|
package/main/i18ntk-scanner.js
CHANGED
|
@@ -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, '..', '
|
|
50
|
+
const uiLocalesDir = path.join(__dirname, '..', 'ui-locales');
|
|
51
51
|
const localeFile = path.join(uiLocalesDir, 'en.json');
|
|
52
52
|
|
|
53
53
|
try {
|