translomatic-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +216 -0
  2. package/dist/commands/analyze.d.ts +11 -0
  3. package/dist/commands/analyze.d.ts.map +1 -0
  4. package/dist/commands/analyze.js +108 -0
  5. package/dist/commands/analyze.js.map +1 -0
  6. package/dist/commands/init.d.ts +12 -0
  7. package/dist/commands/init.d.ts.map +1 -0
  8. package/dist/commands/init.js +100 -0
  9. package/dist/commands/init.js.map +1 -0
  10. package/dist/commands/status.d.ts +10 -0
  11. package/dist/commands/status.d.ts.map +1 -0
  12. package/dist/commands/status.js +116 -0
  13. package/dist/commands/status.js.map +1 -0
  14. package/dist/commands/translate.d.ts +15 -0
  15. package/dist/commands/translate.d.ts.map +1 -0
  16. package/dist/commands/translate.js +58 -0
  17. package/dist/commands/translate.js.map +1 -0
  18. package/dist/config.d.ts +19 -0
  19. package/dist/config.d.ts.map +1 -0
  20. package/dist/config.js +59 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/index.d.ts +3 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +50 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/logger.d.ts +25 -0
  27. package/dist/logger.d.ts.map +1 -0
  28. package/dist/logger.js +122 -0
  29. package/dist/logger.js.map +1 -0
  30. package/dist/scanner/detector.d.ts +6 -0
  31. package/dist/scanner/detector.d.ts.map +1 -0
  32. package/dist/scanner/detector.js +236 -0
  33. package/dist/scanner/detector.js.map +1 -0
  34. package/dist/scanner/extractor.d.ts +43 -0
  35. package/dist/scanner/extractor.d.ts.map +1 -0
  36. package/dist/scanner/extractor.js +107 -0
  37. package/dist/scanner/extractor.js.map +1 -0
  38. package/dist/translator.d.ts +34 -0
  39. package/dist/translator.d.ts.map +1 -0
  40. package/dist/translator.js +138 -0
  41. package/dist/translator.js.map +1 -0
  42. package/dist/types.d.ts +92 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +2 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +46 -0
package/README.md ADDED
@@ -0,0 +1,216 @@
1
+ # Translomatic CLI
2
+
3
+ Auto-scan and translate your entire project from the command line.
4
+
5
+ Works with **react-i18next**, **next-intl**, **vue-i18n**, **angular**, **svelte-i18n**, and any JSON-based i18n setup.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g translomatic-cli
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ # 1. Initialize — auto-detect your i18n setup
17
+ translomatic init
18
+
19
+ # 2. Set your API key
20
+ export TRANSLOMATIC_API_KEY=tr_live_YOUR_KEY
21
+
22
+ # 3. (Optional) Auto-analyze context for smarter translations
23
+ translomatic analyze
24
+
25
+ # 4. Translate all missing strings
26
+ translomatic translate
27
+
28
+ # 5. Check translation coverage
29
+ translomatic status
30
+ ```
31
+
32
+ ## Commands
33
+
34
+ ### `translomatic init`
35
+
36
+ Scans your project to auto-detect the i18n framework, locale directory, and existing languages. Creates a `.translomaticrc.json` config file.
37
+
38
+ ```bash
39
+ translomatic init # Scan and create config
40
+ translomatic init --force # Overwrite existing config
41
+ ```
42
+
43
+ **Auto-detects:**
44
+ - Framework: react-i18next, next-intl, vue-i18n, angular, svelte-i18n
45
+ - Locale directory: `locales/`, `messages/`, `src/locales/`, etc.
46
+ - File pattern: `{lang}.json` or `{lang}/{namespace}.json`
47
+ - Source language and existing translations
48
+
49
+ ### `translomatic translate`
50
+
51
+ Translates all missing strings in your project. Only translates new/changed strings by default — existing translations are preserved.
52
+
53
+ ```bash
54
+ translomatic translate # Translate all missing strings
55
+ translomatic translate --force # Re-translate everything
56
+ translomatic translate -l vi,ja # Only translate specific languages
57
+ translomatic translate -n common # Only translate specific namespaces
58
+ translomatic translate --dry-run # Preview without changes
59
+ translomatic translate -v # Verbose output
60
+ ```
61
+
62
+ **Features:**
63
+ - Smart batching (50 strings per API call)
64
+ - Progress bar with real-time updates
65
+ - Preserves existing translations (use `--force` to re-translate)
66
+ - Context-aware translation using AI models
67
+ - Per-language glossary support
68
+
69
+ ### `translomatic analyze`
70
+
71
+ Uses AI to analyze your source strings and auto-generate:
72
+ - **Context description**: What your app is about (e.g., "mobile app store")
73
+ - **Recommended model**: Best translation model for your domain
74
+ - **Per-language glossaries**: Term mappings for accurate translations
75
+
76
+ ```bash
77
+ translomatic analyze # Analyze and update config
78
+ translomatic analyze -v # Verbose output
79
+ ```
80
+
81
+ This solves the common problem of ambiguous translations:
82
+ - "Free" → "Miễn phí" (not "Tự do") for an app store
83
+ - "Home" → "Trang chủ" (not "Nhà") for a website
84
+
85
+ ### `translomatic status`
86
+
87
+ Shows translation coverage for all configured target languages.
88
+
89
+ ```bash
90
+ translomatic status # Show coverage table
91
+ translomatic status -v # Include namespace breakdown
92
+ ```
93
+
94
+ **Example output:**
95
+ ```
96
+ Translation Status
97
+ ────────────────────────────────────────
98
+ ℹ Source strings: 150
99
+
100
+ Lang Coverage Translated Missing
101
+ ─────────────────────────────────────────────
102
+ vi ████████░░ 80% 120/150 30
103
+ ja ██████████ 100% 150/150 0
104
+ ko ██████░░░░ 60% 90/150 60
105
+ fr ░░░░░░░░░░ 0% 0/150 150
106
+ ```
107
+
108
+ ## Config File
109
+
110
+ `.translomaticrc.json` — created by `translomatic init`, edit as needed:
111
+
112
+ ```json
113
+ {
114
+ "apiKey": "tr_live_YOUR_KEY",
115
+ "sourceLang": "en",
116
+ "targetLangs": ["vi", "ja", "ko", "fr", "es"],
117
+ "localesDir": "./locales",
118
+ "fileFormat": "nested-json",
119
+ "filePattern": "{lang}.json",
120
+ "framework": "react-i18next",
121
+ "namespaces": ["common", "home", "settings"],
122
+ "model": "transloai-pro",
123
+ "context": "This is a mobile app store website...",
124
+ "glossary": {
125
+ "vi": { "Free": "Miễn phí", "Home": "Trang chủ" },
126
+ "ja": { "Free": "無料", "Home": "ホーム" }
127
+ }
128
+ }
129
+ ```
130
+
131
+ | Field | Description |
132
+ |-------|-------------|
133
+ | `apiKey` | API key (or use `TRANSLOMATIC_API_KEY` env var) |
134
+ | `sourceLang` | Source language code (default: `"en"`) |
135
+ | `targetLangs` | Languages to translate to |
136
+ | `localesDir` | Path to locale files directory |
137
+ | `fileFormat` | `"json"` (flat) or `"nested-json"` (nested keys) |
138
+ | `filePattern` | File naming: `"{lang}.json"` or `"{lang}/{namespace}.json"` |
139
+ | `framework` | Detected i18n framework (informational) |
140
+ | `namespaces` | Namespace list for multi-file setups |
141
+ | `model` | Translation model (`"transloai-pro"` for context-aware) |
142
+ | `context` | Domain description for AI translation |
143
+ | `glossary` | Per-language forced term mappings |
144
+
145
+ ## Supported Frameworks
146
+
147
+ | Framework | Detection | Default Locale Dir |
148
+ |-----------|-----------|-------------------|
149
+ | react-i18next | `react-i18next` in deps | `locales/` or `public/locales/` |
150
+ | next-intl | `next-intl` in deps | `messages/` |
151
+ | vue-i18n | `vue-i18n` in deps | `locales/` or `src/locales/` |
152
+ | Angular i18n | `@angular/localize` in deps | `src/assets/i18n/` |
153
+ | svelte-i18n | `svelte-i18n` in deps | `src/locales/` |
154
+ | Generic | Any JSON locale files | Auto-detected |
155
+
156
+ ## Supported File Patterns
157
+
158
+ ### Single file per language
159
+ ```
160
+ locales/
161
+ ├── en.json ← source
162
+ ├── vi.json ← auto-generated
163
+ ├── ja.json ← auto-generated
164
+ └── ko.json ← auto-generated
165
+ ```
166
+ Config: `"filePattern": "{lang}.json"`
167
+
168
+ ### Namespace files per language
169
+ ```
170
+ locales/
171
+ ├── en/
172
+ │ ├── common.json
173
+ │ ├── home.json
174
+ │ └── settings.json
175
+ ├── vi/
176
+ │ ├── common.json ← auto-generated
177
+ │ ├── home.json ← auto-generated
178
+ │ └── settings.json ← auto-generated
179
+ ```
180
+ Config: `"filePattern": "{lang}/{namespace}.json"`
181
+
182
+ ## Nested JSON Support
183
+
184
+ The CLI handles nested JSON structures automatically:
185
+
186
+ ```json
187
+ {
188
+ "common": {
189
+ "buttons": {
190
+ "save": "Save",
191
+ "cancel": "Cancel"
192
+ }
193
+ },
194
+ "home": {
195
+ "title": "Welcome",
196
+ "subtitle": "Get started today"
197
+ }
198
+ }
199
+ ```
200
+
201
+ All leaf strings are extracted, translated, and written back preserving the nested structure.
202
+
203
+ ## Environment Variables
204
+
205
+ | Variable | Description |
206
+ |----------|-------------|
207
+ | `TRANSLOMATIC_API_KEY` | API key (alternative to config file) |
208
+
209
+ ## Requirements
210
+
211
+ - Node.js 18.17 or later
212
+ - A [Translomatic](https://translomatic.com) API key
213
+
214
+ ## License
215
+
216
+ MIT
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `translomatic analyze` command
3
+ *
4
+ * Reads sample strings from the source language file,
5
+ * sends them to the AI for context analysis, and updates
6
+ * the config with auto-generated context + glossary.
7
+ */
8
+ export declare function analyzeCommand(projectDir: string, options: {
9
+ verbose?: boolean;
10
+ }): Promise<void>;
11
+ //# sourceMappingURL=analyze.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,IAAI,CAAC,CA+Ff"}
@@ -0,0 +1,108 @@
1
+ import { Translomatic } from "translomatic";
2
+ import { loadConfig, saveConfig, resolveApiKey } from "../config.js";
3
+ import { readLocaleFile, resolveLocalePath, } from "../scanner/extractor.js";
4
+ import { Logger } from "../logger.js";
5
+ import { join } from "node:path";
6
+ /**
7
+ * `translomatic analyze` command
8
+ *
9
+ * Reads sample strings from the source language file,
10
+ * sends them to the AI for context analysis, and updates
11
+ * the config with auto-generated context + glossary.
12
+ */
13
+ export async function analyzeCommand(projectDir, options) {
14
+ const logger = new Logger(options.verbose);
15
+ logger.banner();
16
+ logger.section("Analyzing Project Context");
17
+ // Load config
18
+ const config = await loadConfig(projectDir);
19
+ const apiKey = resolveApiKey(config);
20
+ logger.info(`Source language: ${config.sourceLang}`);
21
+ logger.info(`Target languages: ${config.targetLangs.join(", ")}`);
22
+ if (config.targetLangs.length === 0) {
23
+ logger.error("No target languages configured. Edit .translomaticrc.json first.");
24
+ process.exit(1);
25
+ }
26
+ // Collect sample strings from source language files
27
+ logger.info("Collecting sample strings...");
28
+ const sampleTexts = [];
29
+ const hasNamespaces = config.filePattern.includes("{namespace}");
30
+ const namespacesToRead = hasNamespaces
31
+ ? config.namespaces || ["translation"]
32
+ : [undefined];
33
+ for (const ns of namespacesToRead) {
34
+ const sourcePath = resolveLocalePath(join(projectDir, config.localesDir), config.filePattern, config.sourceLang, ns);
35
+ const flat = await readLocaleFile(sourcePath);
36
+ const values = Object.values(flat);
37
+ sampleTexts.push(...values);
38
+ }
39
+ if (sampleTexts.length === 0) {
40
+ logger.error("No source strings found. Check your localesDir and filePattern settings.");
41
+ process.exit(1);
42
+ }
43
+ // Take a representative sample (max 100 strings)
44
+ const sample = sampleTexts.length > 100
45
+ ? pickRepresentativeSample(sampleTexts, 100)
46
+ : sampleTexts;
47
+ logger.info(`Found ${sampleTexts.length} strings, using ${sample.length} for analysis`);
48
+ // Call analyzeContext API
49
+ logger.info("Analyzing with AI...");
50
+ const client = new Translomatic({ apiKey });
51
+ try {
52
+ const analysis = await client.analyzeContext({
53
+ texts: sample,
54
+ targetLangs: config.targetLangs,
55
+ sourceLang: config.sourceLang,
56
+ });
57
+ logger.success(`Domain detected: ${analysis.domain}`);
58
+ logger.info(`Context: ${analysis.context.slice(0, 100)}${analysis.context.length > 100 ? "..." : ""}`);
59
+ logger.info(`Recommended model: ${analysis.recommendedModel}`);
60
+ // Build per-language glossary map
61
+ const glossary = {};
62
+ for (const g of analysis.glossaries) {
63
+ const termCount = Object.keys(g.glossary).length;
64
+ if (termCount > 0) {
65
+ glossary[g.lang] = g.glossary;
66
+ logger.info(`Glossary for ${g.lang}: ${termCount} terms`);
67
+ }
68
+ }
69
+ // Update config
70
+ config.model = analysis.recommendedModel;
71
+ config.context = analysis.context;
72
+ config.glossary = glossary;
73
+ const configPath = await saveConfig(projectDir, config);
74
+ logger.success(`Updated ${configPath}`);
75
+ logger.section("Analysis Complete");
76
+ logger.info("Your config has been updated with:");
77
+ logger.info(" • AI-detected context description");
78
+ logger.info(" • Recommended translation model");
79
+ logger.info(" • Per-language glossaries");
80
+ logger.info("");
81
+ logger.info("Run 'translomatic translate' to start translating!");
82
+ console.log();
83
+ }
84
+ catch (err) {
85
+ logger.error(`Analysis failed: ${err.message}`);
86
+ process.exit(1);
87
+ }
88
+ }
89
+ /**
90
+ * Pick a representative sample of strings.
91
+ * Prioritize diversity: short strings, medium strings, long strings.
92
+ */
93
+ function pickRepresentativeSample(texts, count) {
94
+ // Remove duplicates
95
+ const unique = [...new Set(texts)];
96
+ if (unique.length <= count)
97
+ return unique;
98
+ // Sort by length and pick evenly
99
+ const sorted = unique.sort((a, b) => a.length - b.length);
100
+ const result = [];
101
+ const step = sorted.length / count;
102
+ for (let i = 0; i < count; i++) {
103
+ const index = Math.min(Math.floor(i * step), sorted.length - 1);
104
+ result.push(sorted[index]);
105
+ }
106
+ return result;
107
+ }
108
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `translomatic init` command
3
+ *
4
+ * Scans the project directory to:
5
+ * 1. Detect i18n framework (react-i18next, vue-i18n, next-intl, etc.)
6
+ * 2. Find locale directory and existing language files
7
+ * 3. Create .translomaticrc.json config file
8
+ */
9
+ export declare function initCommand(projectDir: string, options: {
10
+ force?: boolean;
11
+ }): Promise<void>;
12
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAwGf"}
@@ -0,0 +1,100 @@
1
+ import { join } from "node:path";
2
+ import { configExists, saveConfig } from "../config.js";
3
+ import { detectFramework } from "../scanner/detector.js";
4
+ import { readLocaleFile } from "../scanner/extractor.js";
5
+ import { Logger } from "../logger.js";
6
+ /**
7
+ * `translomatic init` command
8
+ *
9
+ * Scans the project directory to:
10
+ * 1. Detect i18n framework (react-i18next, vue-i18n, next-intl, etc.)
11
+ * 2. Find locale directory and existing language files
12
+ * 3. Create .translomaticrc.json config file
13
+ */
14
+ export async function initCommand(projectDir, options) {
15
+ const logger = new Logger();
16
+ logger.banner();
17
+ logger.section("Initializing Translomatic CLI");
18
+ // Check existing config
19
+ if (!options.force && (await configExists(projectDir))) {
20
+ logger.warn("Config file .translomaticrc.json already exists.");
21
+ logger.info("Use --force to overwrite.");
22
+ return;
23
+ }
24
+ // Step 1: Detect i18n framework
25
+ logger.info("Scanning project structure...");
26
+ const framework = await detectFramework(projectDir);
27
+ if (!framework) {
28
+ logger.warn("Could not detect i18n framework or locale files.");
29
+ logger.info("Creating default config. Edit .translomaticrc.json manually.");
30
+ const defaultConfig = {
31
+ sourceLang: "en",
32
+ targetLangs: [],
33
+ localesDir: "./locales",
34
+ fileFormat: "nested-json",
35
+ filePattern: "{lang}.json",
36
+ };
37
+ const configPath = await saveConfig(projectDir, defaultConfig);
38
+ logger.success(`Created ${configPath}`);
39
+ logger.info("Edit the config file to set your API key and target languages.");
40
+ return;
41
+ }
42
+ // Step 2: Show detected info
43
+ logger.success(`Detected framework: ${framework.displayName}`);
44
+ logger.info(`Locales directory: ${framework.localesDir}`);
45
+ logger.info(`File pattern: ${framework.filePattern}`);
46
+ logger.info(`Source language: ${framework.sourceLang}`);
47
+ logger.info(`Existing languages: ${framework.existingLangs.join(", ")}`);
48
+ if (framework.namespaces && framework.namespaces.length > 0) {
49
+ logger.info(`Namespaces: ${framework.namespaces.join(", ")}`);
50
+ }
51
+ // Step 3: Count source strings
52
+ const isNamespaced = framework.filePattern.includes("{namespace}");
53
+ let totalKeys = 0;
54
+ if (isNamespaced && framework.namespaces) {
55
+ for (const ns of framework.namespaces) {
56
+ const filePath = join(projectDir, framework.localesDir, framework.filePattern
57
+ .replace("{lang}", framework.sourceLang)
58
+ .replace("{namespace}", ns));
59
+ const keys = await readLocaleFile(filePath);
60
+ totalKeys += Object.keys(keys).length;
61
+ }
62
+ }
63
+ else {
64
+ const filePath = join(projectDir, framework.localesDir, framework.filePattern.replace("{lang}", framework.sourceLang));
65
+ const keys = await readLocaleFile(filePath);
66
+ totalKeys = Object.keys(keys).length;
67
+ }
68
+ logger.info(`Source strings found: ${totalKeys}`);
69
+ // Step 4: Create config
70
+ const config = {
71
+ sourceLang: framework.sourceLang,
72
+ targetLangs: framework.existingLangs.filter((l) => l !== framework.sourceLang),
73
+ localesDir: `./${framework.localesDir}`,
74
+ fileFormat: "nested-json",
75
+ framework: framework.name,
76
+ filePattern: framework.filePattern,
77
+ namespaces: framework.namespaces,
78
+ model: "transloai-pro",
79
+ context: "",
80
+ glossary: {},
81
+ };
82
+ const configPath = await saveConfig(projectDir, config);
83
+ logger.success(`Created ${configPath}`);
84
+ // Step 5: Show next steps
85
+ logger.section("Next Steps");
86
+ logger.info("1. Set your API key:");
87
+ logger.info(" export TRANSLOMATIC_API_KEY=tr_live_YOUR_KEY");
88
+ logger.info(" (or add apiKey to .translomaticrc.json)");
89
+ logger.info("");
90
+ logger.info("2. Add target languages to .translomaticrc.json:");
91
+ logger.info(` "targetLangs": ["vi", "ja", "ko", "fr", "es"]`);
92
+ logger.info("");
93
+ logger.info("3. (Optional) Auto-analyze context for better translations:");
94
+ logger.info(" translomatic analyze");
95
+ logger.info("");
96
+ logger.info("4. Translate your project:");
97
+ logger.info(" translomatic translate");
98
+ console.log();
99
+ }
100
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `translomatic status` command
3
+ *
4
+ * Shows translation coverage for all configured target languages.
5
+ * Displays a table with coverage percentages and missing string counts.
6
+ */
7
+ export declare function statusCommand(projectDir: string, options: {
8
+ verbose?: boolean;
9
+ }): Promise<void>;
10
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,IAAI,CAAC,CA2If"}
@@ -0,0 +1,116 @@
1
+ import { join } from "node:path";
2
+ import { loadConfig } from "../config.js";
3
+ import { readLocaleFile, resolveLocalePath, findMissingKeys, } from "../scanner/extractor.js";
4
+ import { Logger } from "../logger.js";
5
+ /**
6
+ * `translomatic status` command
7
+ *
8
+ * Shows translation coverage for all configured target languages.
9
+ * Displays a table with coverage percentages and missing string counts.
10
+ */
11
+ export async function statusCommand(projectDir, options) {
12
+ const logger = new Logger(options.verbose);
13
+ logger.banner();
14
+ logger.section("Translation Status");
15
+ // Load config
16
+ const config = await loadConfig(projectDir);
17
+ logger.info(`Source language: ${config.sourceLang}`);
18
+ if (config.targetLangs.length === 0) {
19
+ logger.warn("No target languages configured.");
20
+ logger.info("Edit .translomaticrc.json to add targetLangs.");
21
+ return;
22
+ }
23
+ const hasNamespaces = config.filePattern.includes("{namespace}");
24
+ const namespacesToRead = hasNamespaces
25
+ ? config.namespaces || ["translation"]
26
+ : [undefined];
27
+ // Read all source strings
28
+ const sourceStrings = {};
29
+ let totalSourceKeys = 0;
30
+ for (const ns of namespacesToRead) {
31
+ const sourcePath = resolveLocalePath(join(projectDir, config.localesDir), config.filePattern, config.sourceLang, ns);
32
+ const flat = await readLocaleFile(sourcePath);
33
+ const nsKey = ns || "_default";
34
+ sourceStrings[nsKey] = flat;
35
+ totalSourceKeys += Object.keys(flat).length;
36
+ }
37
+ logger.info(`Source strings: ${totalSourceKeys}`);
38
+ console.log();
39
+ // Check each target language
40
+ const statuses = [];
41
+ for (const lang of config.targetLangs) {
42
+ if (lang === config.sourceLang)
43
+ continue;
44
+ let langTotal = 0;
45
+ let langTranslated = 0;
46
+ const nsStatuses = [];
47
+ for (const ns of namespacesToRead) {
48
+ const nsKey = ns || "_default";
49
+ const source = sourceStrings[nsKey];
50
+ const sourceKeyCount = Object.keys(source).length;
51
+ const targetPath = resolveLocalePath(join(projectDir, config.localesDir), config.filePattern, lang, ns);
52
+ const target = await readLocaleFile(targetPath);
53
+ const missing = findMissingKeys(source, target);
54
+ const missingCount = Object.keys(missing).length;
55
+ const translatedCount = sourceKeyCount - missingCount;
56
+ langTotal += sourceKeyCount;
57
+ langTranslated += translatedCount;
58
+ if (hasNamespaces && ns) {
59
+ nsStatuses.push({
60
+ namespace: ns,
61
+ totalKeys: sourceKeyCount,
62
+ translatedKeys: translatedCount,
63
+ missingKeys: missingCount,
64
+ coverage: sourceKeyCount > 0
65
+ ? Math.round((translatedCount / sourceKeyCount) * 100)
66
+ : 100,
67
+ });
68
+ }
69
+ }
70
+ statuses.push({
71
+ lang,
72
+ totalKeys: langTotal,
73
+ translatedKeys: langTranslated,
74
+ missingKeys: langTotal - langTranslated,
75
+ coverage: langTotal > 0
76
+ ? Math.round((langTranslated / langTotal) * 100)
77
+ : 100,
78
+ namespaces: nsStatuses.length > 0 ? nsStatuses : undefined,
79
+ });
80
+ }
81
+ // Display table
82
+ logger.statusTable(statuses.map((s) => ({
83
+ lang: s.lang,
84
+ coverage: s.coverage,
85
+ translated: s.translatedKeys,
86
+ total: s.totalKeys,
87
+ })));
88
+ // Show namespace details if verbose
89
+ if (options.verbose && hasNamespaces) {
90
+ for (const status of statuses) {
91
+ if (status.namespaces && status.namespaces.length > 1) {
92
+ console.log();
93
+ logger.info(`${status.lang} namespace details:`);
94
+ for (const ns of status.namespaces) {
95
+ const indicator = ns.coverage === 100 ? "✓" : ns.coverage >= 80 ? "~" : "✗";
96
+ logger.debug(` ${indicator} ${ns.namespace}: ${ns.coverage}% (${ns.translatedKeys}/${ns.totalKeys})`);
97
+ }
98
+ }
99
+ }
100
+ }
101
+ // Summary
102
+ const totalCoverage = statuses.length > 0
103
+ ? Math.round(statuses.reduce((sum, s) => sum + s.coverage, 0) / statuses.length)
104
+ : 0;
105
+ const totalMissing = statuses.reduce((sum, s) => sum + s.missingKeys, 0);
106
+ console.log();
107
+ if (totalMissing === 0) {
108
+ logger.success("All languages are fully translated!");
109
+ }
110
+ else {
111
+ logger.info(`Overall coverage: ${totalCoverage}% — ${totalMissing} strings missing across ${statuses.length} languages`);
112
+ logger.info('Run "translomatic translate" to fill in missing translations.');
113
+ }
114
+ console.log();
115
+ }
116
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `translomatic translate` command
3
+ *
4
+ * Translates all missing strings in the project.
5
+ * Reads source language file, finds missing keys in each target language,
6
+ * and batch-translates them using the Translomatic API.
7
+ */
8
+ export declare function translateCommand(projectDir: string, options: {
9
+ force?: boolean;
10
+ lang?: string;
11
+ namespace?: string;
12
+ dryRun?: boolean;
13
+ verbose?: boolean;
14
+ }): Promise<void>;
15
+ //# sourceMappingURL=translate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/commands/translate.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IACP,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GACA,OAAO,CAAC,IAAI,CAAC,CAyDf"}