i18ntk 4.2.2 → 4.3.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/CHANGELOG.md +13 -1
- package/README.md +17 -8
- package/main/i18ntk-fixer.js +16 -11
- package/main/i18ntk-go.js +283 -0
- package/main/i18ntk-java.js +380 -0
- package/main/i18ntk-js.js +512 -0
- package/main/i18ntk-php.js +462 -0
- package/main/i18ntk-py.js +379 -0
- package/main/i18ntk-translate.js +29 -3
- package/main/manage/commands/CommandRouter.js +7 -4
- package/main/manage/commands/FixerCommand.js +144 -55
- package/main/manage/commands/TranslateCommand.js +36 -24
- package/package.json +16 -6
- package/utils/english-placeholder-checker.js +162 -0
- package/utils/mini-commander.js +179 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,10 +5,22 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [4.
|
|
8
|
+
## [4.3.1] - 2026-05-31
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Published tarball now includes `utils/english-placeholder-checker.js`, resolving `MODULE_NOT_FOUND` at startup for `i18ntk-fixer --check-placeholders` and manager option 7.
|
|
12
|
+
- Language-specific CLI entry points (`main/i18ntk-go.js`, `main/i18ntk-java.js`, `main/i18ntk-js.js`, `main/i18ntk-php.js`, `main/i18ntk-py.js`) and their shared `utils/mini-commander.js` dependency are now included in the published package.
|
|
13
|
+
- Removed inconsistent `.js` extension suffixes from require paths in `main/i18ntk-js.js`.
|
|
14
|
+
|
|
15
|
+
## [4.3.0] - 2026-05-31
|
|
9
16
|
|
|
10
17
|
### Fixed
|
|
11
18
|
- Auto Translate now treats single-word uppercase target-language placeholders such as `[AR] Email` and `[AR] Password` as untranslated target values, matching the existing multi-word `[AR] What We Offer` detection.
|
|
19
|
+
- Auto Translate now treats bracketed target-language placeholders case-insensitively, so `[zh] Email` and `[TR] Password` are both retried for the matching target language.
|
|
20
|
+
- Managed Auto Translate now checks every selected source file for a target language before reporting leftover failures, instead of stopping after the first failed file.
|
|
21
|
+
- Auto Translate no longer fails a run when a provider legitimately returns a short all-caps acronym or code unchanged, such as `XP`.
|
|
22
|
+
- Manager option 7 and `i18ntk-fixer --check-placeholders` now run an English source placeholder audit, reporting any `[LANG] ...` values left in English locale files; a clean project reports `0` placeholders.
|
|
23
|
+
- The management command router no longer prints a generic operation-success message when a command returns `{ success: false }`.
|
|
12
24
|
|
|
13
25
|
## [4.2.1] - 2026-05-31
|
|
14
26
|
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# i18ntk v4.
|
|
1
|
+
# i18ntk v4.3.1
|
|
2
2
|
|
|
3
3
|
A i18n toolkit - A zero-dependency internationalization toolkit for setup, scanning, analysis, validation, usage tracking, translation completion, automatic JSON locale translation, reporting, and runtime translation loading.
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ A i18n toolkit - A zero-dependency internationalization toolkit for setup, scann
|
|
|
9
9
|
[](https://nodejs.org)
|
|
10
10
|
[](https://www.npmjs.com/package/i18ntk)
|
|
11
11
|
[](LICENSE)
|
|
12
|
-
[](https://socket.dev/npm/package/i18ntk/overview/4.3.1)
|
|
13
13
|
|
|
14
14
|
## Install
|
|
15
15
|
|
|
@@ -30,14 +30,23 @@ Requirements:
|
|
|
30
30
|
- npm `>=8.0.0`
|
|
31
31
|
- No runtime dependencies
|
|
32
32
|
|
|
33
|
-
## What's New in 4.
|
|
33
|
+
## What's New in 4.3.1
|
|
34
34
|
|
|
35
|
-
- **
|
|
35
|
+
- **FIX**: Published tarball now includes `utils/english-placeholder-checker.js`, resolving `MODULE_NOT_FOUND` at startup for `i18ntk-fixer --check-placeholders` and manager option 7.
|
|
36
|
+
- **FIX**: Language-specific CLI entry points (`i18ntk-go`, `i18ntk-java`, `i18ntk-js`, `i18ntk-php`, `i18ntk-py`) and their shared `utils/mini-commander.js` dependency are now included in the published package.
|
|
37
|
+
- **FIX**: Removed inconsistent `.js` extension suffixes from require paths in `main/i18ntk-js.js`.
|
|
38
|
+
|
|
39
|
+
## What's New in 4.3.0
|
|
40
|
+
|
|
41
|
+
- **AUTO TRANSLATE**: Existing target values like `[AR] What We Offer`, `[AR] Email`, `[zh] Email`, and `[TR] Password` are now treated as untranslated placeholders for the matching target language and are translated from the source text.
|
|
36
42
|
- **AUTO TRANSLATE**: Before writing each output file, Auto Translate now performs a final leftover check and retries any placeholder-prefixed or source-copy values once.
|
|
37
43
|
- **AUTO TRANSLATE**: If leftovers remain after the final retry, the command warns, includes them in the report, recommends rerunning Auto Translate, and exits with validation failure instead of reporting a clean completion.
|
|
44
|
+
- **AUTO TRANSLATE**: Managed Auto Translate now checks every selected source file for a target language before reporting leftovers, so one failed file does not prevent the rest from being audited.
|
|
45
|
+
- **AUTO TRANSLATE**: Short all-caps acronyms and codes such as `XP` are allowed to remain unchanged instead of failing the final leftover check.
|
|
46
|
+
- **FIX PLACEHOLDERS**: Menu option 7 now runs an English source placeholder audit and reports how many `[LANG] ...` values remain in English locale files. A clean project reports `0`.
|
|
38
47
|
- **SIZING/USAGE**: Usage analysis no longer writes its inferred app source fallback back into the shared locale config, so running usage before sizing no longer makes sizing analyze the wrong directory.
|
|
39
48
|
- **VALIDATION REPORTS**: Validation summary files now include warning and error details, including English-content warning payloads, instead of only totals.
|
|
40
|
-
- **DOCS**: Versioned docs and migration guidance now reflect the current 4.
|
|
49
|
+
- **DOCS**: Versioned docs and migration guidance now reflect the current 4.3.1 command surface.
|
|
41
50
|
|
|
42
51
|
## What's New in 4.1.0
|
|
43
52
|
|
|
@@ -144,7 +153,7 @@ Note: manager route `i18ntk --command=backup` is disabled in current builds. Use
|
|
|
144
153
|
| `i18ntk --command=translate` / `i18ntk-translate` | Auto-translates locale JSON using configured provider behavior. | Missing, empty, untranslated-marker, source-copy, likely-English, or visibly corrupt target values by default. | Target locale JSON files and translation reports. Existing translated values are kept unless `--translate-all` is used. |
|
|
145
154
|
| `i18ntk --command=sizing` / `i18ntk-sizing` | Estimates translated string length expansion and layout risk. | Text length, expansion ratios, placeholder-bearing strings. | Sizing report. Does not edit locale files. |
|
|
146
155
|
| `i18ntk --command=summary` / `i18ntk-summary` | Shows project translation status. | Configured locales, reports, completeness status. | Console/report output only. |
|
|
147
|
-
| `i18ntk-fixer` | Fixes placeholder and missing-marker issues
|
|
156
|
+
| `i18ntk-fixer` | Fixes placeholder and missing-marker issues, and can audit English source files with `--check-placeholders`. | Placeholder corruption, missing translation markers, configured language files, `[LANG] ...` leftovers in English locales. | Locale JSON files when fixes are applied. Use dry-run options where available before bulk edits. |
|
|
148
157
|
| `i18ntk-backup` | Creates, verifies, restores, and cleans locale backups. | Locale JSON files and backup manifests. | Backup archives/manifests, or restored locale files when using restore. |
|
|
149
158
|
|
|
150
159
|
## Common Options
|
|
@@ -503,7 +512,7 @@ Example:
|
|
|
503
512
|
|
|
504
513
|
```json
|
|
505
514
|
{
|
|
506
|
-
"version": "4.
|
|
515
|
+
"version": "4.3.1",
|
|
507
516
|
"sourceDir": "./locales",
|
|
508
517
|
"i18nDir": "./locales",
|
|
509
518
|
"outputDir": "./i18ntk-reports",
|
|
@@ -565,7 +574,7 @@ The public package manifest includes `readmeFilename: "README.md"`, and the rele
|
|
|
565
574
|
- [Auto Translate Guide](./docs/auto-translate.md)
|
|
566
575
|
- [Scanner Guide](./docs/scanner-guide.md)
|
|
567
576
|
- [Environment Variables](./docs/environment-variables.md)
|
|
568
|
-
- [Migration Guide v4.
|
|
577
|
+
- [Migration Guide v4.3.1](./docs/migration-guide-v4.3.1.md)
|
|
569
578
|
|
|
570
579
|
## Security
|
|
571
580
|
|
package/main/i18ntk-fixer.js
CHANGED
|
@@ -13,9 +13,10 @@ const fs = require('fs');
|
|
|
13
13
|
const SecurityUtils = require('../utils/security');
|
|
14
14
|
const cliHelper = require('../utils/cli-helper');
|
|
15
15
|
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
16
|
-
const { getUnifiedConfig, parseCommonArgs, displayHelp } = require('../utils/config-helper');
|
|
17
|
-
const JsonOutput = require('../utils/json-output');
|
|
18
|
-
const SetupEnforcer = require('../utils/setup-enforcer');
|
|
16
|
+
const { getUnifiedConfig, parseCommonArgs, displayHelp } = require('../utils/config-helper');
|
|
17
|
+
const JsonOutput = require('../utils/json-output');
|
|
18
|
+
const SetupEnforcer = require('../utils/setup-enforcer');
|
|
19
|
+
const FixerCommand = require('./manage/commands/FixerCommand');
|
|
19
20
|
|
|
20
21
|
// Ensure setup is complete before running
|
|
21
22
|
(async () => {
|
|
@@ -94,13 +95,17 @@ class I18nFixer {
|
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
async run() {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
98
|
+
async run(options = {}) {
|
|
99
|
+
const command = new FixerCommand(this.config, null);
|
|
100
|
+
const result = await command.execute(options);
|
|
101
|
+
|
|
102
|
+
if (result && result.success === false) {
|
|
103
|
+
throw new Error(result.error || 'Fixer command failed');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
104
109
|
|
|
105
110
|
module.exports = I18nFixer;
|
|
106
111
|
|
|
@@ -110,4 +115,4 @@ if (require.main === module) {
|
|
|
110
115
|
console.error('I18n Fixer failed:', error);
|
|
111
116
|
process.exit(1);
|
|
112
117
|
});
|
|
113
|
-
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* i18ntk-go.js - Go Language I18n Management Command
|
|
5
|
+
*
|
|
6
|
+
* Supports:
|
|
7
|
+
* - Standard Go i18n patterns
|
|
8
|
+
* - go-i18n library
|
|
9
|
+
* - Custom Go i18n implementations
|
|
10
|
+
* - Resource file (.json, .toml) management
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const SecurityUtils = require('../utils/security');
|
|
16
|
+
const { getConfig, saveConfig } = require('../utils/config-helper');
|
|
17
|
+
const I18nHelper = require('../utils/i18n-helper');
|
|
18
|
+
const SetupEnforcer = require('../utils/setup-enforcer');
|
|
19
|
+
const { program } = require('../utils/mini-commander');
|
|
20
|
+
|
|
21
|
+
(async () => {
|
|
22
|
+
try {
|
|
23
|
+
await SetupEnforcer.checkSetupCompleteAsync();
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error('Setup check failed:', error.message);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
})();
|
|
29
|
+
|
|
30
|
+
class GoI18nManager {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.supportedPatterns = [
|
|
33
|
+
'T("key")',
|
|
34
|
+
'Localize("key")',
|
|
35
|
+
'i18n.T("key")',
|
|
36
|
+
'tr("key")',
|
|
37
|
+
'message.Printer.Printf',
|
|
38
|
+
'i18n.MustLocalize'
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
this.fileExtensions = ['.go', '.mod', '.sum'];
|
|
42
|
+
this.resourceFormats = ['.json', '.toml', '.yaml', '.yml'];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async detectFramework(sourceDir) {
|
|
46
|
+
const goModPath = path.join(sourceDir, 'go.mod');
|
|
47
|
+
if (SecurityUtils.safeExistsSync(goModPath)) {
|
|
48
|
+
const content = SecurityUtils.safeReadFileSync(goModPath, sourceDir, 'utf8') || '';
|
|
49
|
+
|
|
50
|
+
if (content.includes('go-i18n')) return 'go-i18n-v2';
|
|
51
|
+
if (/x\/text\b/.test(content)) return 'golang-text';
|
|
52
|
+
|
|
53
|
+
return 'standard-go';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check for Go files
|
|
57
|
+
const goFiles = this.findFiles(sourceDir, '.go');
|
|
58
|
+
if (goFiles.length > 0) {
|
|
59
|
+
return 'standard-go';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return 'generic';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async extractTranslations(sourceDir, options = {}) {
|
|
66
|
+
const framework = await this.detectFramework(sourceDir);
|
|
67
|
+
const translations = new Set();
|
|
68
|
+
|
|
69
|
+
const goFiles = this.findFiles(sourceDir, '.go');
|
|
70
|
+
|
|
71
|
+
for (const file of goFiles) {
|
|
72
|
+
const content = SecurityUtils.safeReadFileSync(file, path.dirname(file), 'utf8') || '';
|
|
73
|
+
|
|
74
|
+
// Extract Go i18n patterns
|
|
75
|
+
const patterns = [
|
|
76
|
+
/T\("([^"]+)"\)/g,
|
|
77
|
+
/Localize\("([^"]+)"\)/g,
|
|
78
|
+
/i18n\.T\("([^"]+)"\)/g,
|
|
79
|
+
/tr\("([^"]+)"\)/g,
|
|
80
|
+
/message\.Printer\.Printf\("([^"]+)"/g,
|
|
81
|
+
/i18n\.MustLocalize\(&i18n\.LocalizeConfig\{MessageID:\s*"([^"]+)"/g
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
for (const pattern of patterns) {
|
|
85
|
+
let match;
|
|
86
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
87
|
+
translations.add(match[1]);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
framework,
|
|
94
|
+
translations: Array.from(translations),
|
|
95
|
+
files: goFiles.length,
|
|
96
|
+
patterns: this.supportedPatterns
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async createLocaleStructure(outputDir, languages = ['en']) {
|
|
101
|
+
const localesDir = path.join(outputDir, 'locales');
|
|
102
|
+
|
|
103
|
+
for (const lang of languages) {
|
|
104
|
+
const langDir = path.join(localesDir, lang);
|
|
105
|
+
fs.mkdirSync(langDir, { recursive: true });
|
|
106
|
+
|
|
107
|
+
// Create Go i18n format files
|
|
108
|
+
SecurityUtils.safeWriteFileSync(path.join(langDir, 'active.en.toml'), `# Go i18n translations for ${lang}
|
|
109
|
+
[hello]
|
|
110
|
+
other = "Hello, World!"
|
|
111
|
+
|
|
112
|
+
[items]
|
|
113
|
+
one = "{{.Count}} item"
|
|
114
|
+
other = "{{.Count}} items"
|
|
115
|
+
`);
|
|
116
|
+
|
|
117
|
+
SecurityUtils.safeWriteFileSync(path.join(langDir, 'active.en.json'), JSON.stringify({
|
|
118
|
+
hello: "Hello, World!",
|
|
119
|
+
items: {
|
|
120
|
+
one: "{{.Count}} item",
|
|
121
|
+
other: "{{.Count}} items"
|
|
122
|
+
}
|
|
123
|
+
}, null, 2));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return localesDir;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
findFiles(dir, extension) {
|
|
130
|
+
const files = [];
|
|
131
|
+
|
|
132
|
+
function traverse(currentDir) {
|
|
133
|
+
const items = fs.readdirSync(currentDir);
|
|
134
|
+
|
|
135
|
+
for (const item of items) {
|
|
136
|
+
const fullPath = path.join(currentDir, item);
|
|
137
|
+
const stat = fs.statSync(fullPath);
|
|
138
|
+
|
|
139
|
+
if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') {
|
|
140
|
+
traverse(fullPath);
|
|
141
|
+
} else if (stat.isFile() && path.extname(item) === extension) {
|
|
142
|
+
files.push(fullPath);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
traverse(dir);
|
|
148
|
+
return files;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async generateReport(results, outputDir) {
|
|
152
|
+
const report = {
|
|
153
|
+
timestamp: new Date().toISOString(),
|
|
154
|
+
framework: results.framework,
|
|
155
|
+
totalTranslations: results.translations.length,
|
|
156
|
+
translations: results.translations,
|
|
157
|
+
filesProcessed: results.files,
|
|
158
|
+
patterns: results.patterns,
|
|
159
|
+
recommendations: this.getRecommendations(results)
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const reportPath = path.join(outputDir, 'i18ntk-go-report.json');
|
|
163
|
+
SecurityUtils.safeWriteFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
164
|
+
|
|
165
|
+
return reportPath;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
getRecommendations(results) {
|
|
169
|
+
const recommendations = [];
|
|
170
|
+
|
|
171
|
+
if (results.translations.length === 0) {
|
|
172
|
+
recommendations.push('No translations found. Check your Go i18n patterns');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (results.files === 0) {
|
|
176
|
+
recommendations.push('No Go files found in source directory');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (results.framework === 'generic') {
|
|
180
|
+
recommendations.push('Consider using go-i18n library for better i18n support');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return recommendations;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// CLI Implementation
|
|
188
|
+
program
|
|
189
|
+
.name('i18ntk-go')
|
|
190
|
+
.description('Go language i18n management tool')
|
|
191
|
+
.version('1.10.1');
|
|
192
|
+
|
|
193
|
+
program
|
|
194
|
+
.command('init')
|
|
195
|
+
.description('Initialize Go i18n structure')
|
|
196
|
+
.option('-s, --source-dir <dir>', 'Source directory', './')
|
|
197
|
+
.option('-o, --output-dir <dir>', 'Output directory', './i18ntk-reports')
|
|
198
|
+
.option('-l, --languages <langs>', 'Languages (comma-separated)', 'en')
|
|
199
|
+
.action(async (options) => {
|
|
200
|
+
try {
|
|
201
|
+
const manager = new GoI18nManager();
|
|
202
|
+
const languages = options.languages.split(',');
|
|
203
|
+
|
|
204
|
+
const localesDir = await manager.createLocaleStructure(options.outputDir, languages);
|
|
205
|
+
|
|
206
|
+
console.log(`✅ Go i18n structure initialized in: ${localesDir}`);
|
|
207
|
+
console.log(`📊 Languages: ${languages.join(', ')}`);
|
|
208
|
+
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('❌ Error initializing Go i18n:', error.message);
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
program
|
|
216
|
+
.command('analyze')
|
|
217
|
+
.description('Analyze Go i18n usage')
|
|
218
|
+
.option('-s, --source-dir <dir>', 'Source directory', './')
|
|
219
|
+
.option('-o, --output-dir <dir>', 'Output directory', './i18ntk-reports')
|
|
220
|
+
.option('--dry-run', 'Preview without making changes')
|
|
221
|
+
.action(async (options) => {
|
|
222
|
+
try {
|
|
223
|
+
SecurityUtils.validatePath(options.sourceDir);
|
|
224
|
+
|
|
225
|
+
const manager = new GoI18nManager();
|
|
226
|
+
const results = await manager.extractTranslations(options.sourceDir);
|
|
227
|
+
|
|
228
|
+
console.log(`🔍 Framework detected: ${results.framework}`);
|
|
229
|
+
console.log(`📊 Files processed: ${results.files}`);
|
|
230
|
+
console.log(`📝 Translations found: ${results.translations.length}`);
|
|
231
|
+
|
|
232
|
+
if (!options.dryRun) {
|
|
233
|
+
const reportPath = await manager.generateReport(results, options.outputDir);
|
|
234
|
+
console.log(`📄 Report saved: ${reportPath}`);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.error('❌ Error analyzing Go i18n:', error.message);
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
program
|
|
244
|
+
.command('extract')
|
|
245
|
+
.description('Extract Go translations')
|
|
246
|
+
.option('-s, --source-dir <dir>', 'Source directory', './')
|
|
247
|
+
.option('-o, --output-dir <dir>', 'Output directory', './locales')
|
|
248
|
+
.option('-l, --languages <langs>', 'Languages (comma-separated)', 'en')
|
|
249
|
+
.action(async (options) => {
|
|
250
|
+
try {
|
|
251
|
+
SecurityUtils.validatePath(options.sourceDir);
|
|
252
|
+
|
|
253
|
+
const manager = new GoI18nManager();
|
|
254
|
+
const results = await manager.extractTranslations(options.sourceDir);
|
|
255
|
+
|
|
256
|
+
await manager.createLocaleStructure(options.outputDir, options.languages.split(','));
|
|
257
|
+
|
|
258
|
+
console.log(`✅ Extracted ${results.translations.length} translations`);
|
|
259
|
+
console.log(`📁 Locale structure created in: ${options.outputDir}`);
|
|
260
|
+
|
|
261
|
+
} catch (error) {
|
|
262
|
+
console.error('❌ Error extracting Go translations:', error.message);
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Handle uncaught errors
|
|
268
|
+
process.on('uncaughtException', (error) => {
|
|
269
|
+
console.error('❌ Uncaught exception:', error.message);
|
|
270
|
+
process.exit(1);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
process.on('unhandledRejection', (reason) => {
|
|
274
|
+
console.error('❌ Unhandled rejection:', reason);
|
|
275
|
+
process.exit(1);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Export for programmatic use
|
|
279
|
+
module.exports = { GoI18nManager };
|
|
280
|
+
|
|
281
|
+
if (require.main === module) {
|
|
282
|
+
program.parse();
|
|
283
|
+
}
|