i18nsmith 0.1.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 (213) hide show
  1. package/dist/commands/audit.d.ts +3 -0
  2. package/dist/commands/audit.d.ts.map +1 -0
  3. package/dist/commands/audit.js +180 -0
  4. package/dist/commands/audit.js.map +1 -0
  5. package/dist/commands/backup.d.ts +6 -0
  6. package/dist/commands/backup.d.ts.map +1 -0
  7. package/dist/commands/backup.js +85 -0
  8. package/dist/commands/backup.js.map +1 -0
  9. package/dist/commands/check.d.ts +3 -0
  10. package/dist/commands/check.d.ts.map +1 -0
  11. package/dist/commands/check.js +151 -0
  12. package/dist/commands/check.js.map +1 -0
  13. package/dist/commands/config.d.ts +3 -0
  14. package/dist/commands/config.d.ts.map +1 -0
  15. package/dist/commands/config.js +235 -0
  16. package/dist/commands/config.js.map +1 -0
  17. package/dist/commands/debug-patterns.d.ts +3 -0
  18. package/dist/commands/debug-patterns.d.ts.map +1 -0
  19. package/dist/commands/debug-patterns.js +192 -0
  20. package/dist/commands/debug-patterns.js.map +1 -0
  21. package/dist/commands/debug-patterns.test.d.ts +2 -0
  22. package/dist/commands/debug-patterns.test.d.ts.map +1 -0
  23. package/dist/commands/debug-patterns.test.js +109 -0
  24. package/dist/commands/debug-patterns.test.js.map +1 -0
  25. package/dist/commands/diagnose.d.ts +3 -0
  26. package/dist/commands/diagnose.d.ts.map +1 -0
  27. package/dist/commands/diagnose.js +117 -0
  28. package/dist/commands/diagnose.js.map +1 -0
  29. package/dist/commands/init.d.ts +8 -0
  30. package/dist/commands/init.d.ts.map +1 -0
  31. package/dist/commands/init.js +450 -0
  32. package/dist/commands/init.js.map +1 -0
  33. package/dist/commands/init.test.d.ts +2 -0
  34. package/dist/commands/init.test.d.ts.map +1 -0
  35. package/dist/commands/init.test.js +74 -0
  36. package/dist/commands/init.test.js.map +1 -0
  37. package/dist/commands/install-hooks.d.ts +3 -0
  38. package/dist/commands/install-hooks.d.ts.map +1 -0
  39. package/dist/commands/install-hooks.js +52 -0
  40. package/dist/commands/install-hooks.js.map +1 -0
  41. package/dist/commands/preflight.d.ts +7 -0
  42. package/dist/commands/preflight.d.ts.map +1 -0
  43. package/dist/commands/preflight.js +417 -0
  44. package/dist/commands/preflight.js.map +1 -0
  45. package/dist/commands/preflight.test.d.ts +5 -0
  46. package/dist/commands/preflight.test.d.ts.map +1 -0
  47. package/dist/commands/preflight.test.js +108 -0
  48. package/dist/commands/preflight.test.js.map +1 -0
  49. package/dist/commands/rename.d.ts +6 -0
  50. package/dist/commands/rename.d.ts.map +1 -0
  51. package/dist/commands/rename.js +204 -0
  52. package/dist/commands/rename.js.map +1 -0
  53. package/dist/commands/scaffold-adapter.d.ts +3 -0
  54. package/dist/commands/scaffold-adapter.d.ts.map +1 -0
  55. package/dist/commands/scaffold-adapter.js +204 -0
  56. package/dist/commands/scaffold-adapter.js.map +1 -0
  57. package/dist/commands/scaffold-adapter.test.d.ts +2 -0
  58. package/dist/commands/scaffold-adapter.test.d.ts.map +1 -0
  59. package/dist/commands/scaffold-adapter.test.js +102 -0
  60. package/dist/commands/scaffold-adapter.test.js.map +1 -0
  61. package/dist/commands/scan.d.ts +3 -0
  62. package/dist/commands/scan.d.ts.map +1 -0
  63. package/dist/commands/scan.js +93 -0
  64. package/dist/commands/scan.js.map +1 -0
  65. package/dist/commands/sync-seed.test.d.ts +2 -0
  66. package/dist/commands/sync-seed.test.d.ts.map +1 -0
  67. package/dist/commands/sync-seed.test.js +86 -0
  68. package/dist/commands/sync-seed.test.js.map +1 -0
  69. package/dist/commands/sync.d.ts +3 -0
  70. package/dist/commands/sync.d.ts.map +1 -0
  71. package/dist/commands/sync.js +590 -0
  72. package/dist/commands/sync.js.map +1 -0
  73. package/dist/commands/transform.d.ts +3 -0
  74. package/dist/commands/transform.d.ts.map +1 -0
  75. package/dist/commands/transform.js +114 -0
  76. package/dist/commands/transform.js.map +1 -0
  77. package/dist/commands/translate/csv-handler.d.ts +21 -0
  78. package/dist/commands/translate/csv-handler.d.ts.map +1 -0
  79. package/dist/commands/translate/csv-handler.js +270 -0
  80. package/dist/commands/translate/csv-handler.js.map +1 -0
  81. package/dist/commands/translate/executor.d.ts +31 -0
  82. package/dist/commands/translate/executor.d.ts.map +1 -0
  83. package/dist/commands/translate/executor.js +117 -0
  84. package/dist/commands/translate/executor.js.map +1 -0
  85. package/dist/commands/translate/index.d.ts +10 -0
  86. package/dist/commands/translate/index.d.ts.map +1 -0
  87. package/dist/commands/translate/index.js +170 -0
  88. package/dist/commands/translate/index.js.map +1 -0
  89. package/dist/commands/translate/reporter.d.ts +29 -0
  90. package/dist/commands/translate/reporter.d.ts.map +1 -0
  91. package/dist/commands/translate/reporter.js +103 -0
  92. package/dist/commands/translate/reporter.js.map +1 -0
  93. package/dist/commands/translate/types.d.ts +50 -0
  94. package/dist/commands/translate/types.d.ts.map +1 -0
  95. package/dist/commands/translate/types.js +5 -0
  96. package/dist/commands/translate/types.js.map +1 -0
  97. package/dist/commands/translate.d.ts +7 -0
  98. package/dist/commands/translate.d.ts.map +1 -0
  99. package/dist/commands/translate.js +7 -0
  100. package/dist/commands/translate.js.map +1 -0
  101. package/dist/commands/translate.test.d.ts +2 -0
  102. package/dist/commands/translate.test.d.ts.map +1 -0
  103. package/dist/commands/translate.test.js +118 -0
  104. package/dist/commands/translate.test.js.map +1 -0
  105. package/dist/e2e.test.d.ts +6 -0
  106. package/dist/e2e.test.d.ts.map +1 -0
  107. package/dist/e2e.test.js +376 -0
  108. package/dist/e2e.test.js.map +1 -0
  109. package/dist/index.d.ts +4 -0
  110. package/dist/index.d.ts.map +1 -0
  111. package/dist/index.js +39 -0
  112. package/dist/index.js.map +1 -0
  113. package/dist/integration.test.d.ts +6 -0
  114. package/dist/integration.test.d.ts.map +1 -0
  115. package/dist/integration.test.js +320 -0
  116. package/dist/integration.test.js.map +1 -0
  117. package/dist/utils/diagnostics-exit.d.ts +12 -0
  118. package/dist/utils/diagnostics-exit.d.ts.map +1 -0
  119. package/dist/utils/diagnostics-exit.js +49 -0
  120. package/dist/utils/diagnostics-exit.js.map +1 -0
  121. package/dist/utils/diagnostics-exit.test.d.ts +2 -0
  122. package/dist/utils/diagnostics-exit.test.d.ts.map +1 -0
  123. package/dist/utils/diagnostics-exit.test.js +40 -0
  124. package/dist/utils/diagnostics-exit.test.js.map +1 -0
  125. package/dist/utils/diff-utils.d.ts +4 -0
  126. package/dist/utils/diff-utils.d.ts.map +1 -0
  127. package/dist/utils/diff-utils.js +30 -0
  128. package/dist/utils/diff-utils.js.map +1 -0
  129. package/dist/utils/diff-utils.test.d.ts +2 -0
  130. package/dist/utils/diff-utils.test.d.ts.map +1 -0
  131. package/dist/utils/diff-utils.test.js +30 -0
  132. package/dist/utils/diff-utils.test.js.map +1 -0
  133. package/dist/utils/exit-codes.d.ts +142 -0
  134. package/dist/utils/exit-codes.d.ts.map +1 -0
  135. package/dist/utils/exit-codes.js +168 -0
  136. package/dist/utils/exit-codes.js.map +1 -0
  137. package/dist/utils/package-manager.d.ts +4 -0
  138. package/dist/utils/package-manager.d.ts.map +1 -0
  139. package/dist/utils/package-manager.js +40 -0
  140. package/dist/utils/package-manager.js.map +1 -0
  141. package/dist/utils/pkg.d.ts +3 -0
  142. package/dist/utils/pkg.d.ts.map +1 -0
  143. package/dist/utils/pkg.js +24 -0
  144. package/dist/utils/pkg.js.map +1 -0
  145. package/dist/utils/provider-injector.d.ts +36 -0
  146. package/dist/utils/provider-injector.d.ts.map +1 -0
  147. package/dist/utils/provider-injector.js +223 -0
  148. package/dist/utils/provider-injector.js.map +1 -0
  149. package/dist/utils/provider-injector.test.d.ts +2 -0
  150. package/dist/utils/provider-injector.test.d.ts.map +1 -0
  151. package/dist/utils/provider-injector.test.js +67 -0
  152. package/dist/utils/provider-injector.test.js.map +1 -0
  153. package/dist/utils/scaffold.d.ts +20 -0
  154. package/dist/utils/scaffold.d.ts.map +1 -0
  155. package/dist/utils/scaffold.js +197 -0
  156. package/dist/utils/scaffold.js.map +1 -0
  157. package/package.json +35 -0
  158. package/src/commands/audit.ts +234 -0
  159. package/src/commands/backup.ts +96 -0
  160. package/src/commands/check.ts +191 -0
  161. package/src/commands/config.ts +263 -0
  162. package/src/commands/debug-patterns.test.ts +134 -0
  163. package/src/commands/debug-patterns.ts +257 -0
  164. package/src/commands/diagnose.ts +136 -0
  165. package/src/commands/init.test.ts +82 -0
  166. package/src/commands/init.ts +536 -0
  167. package/src/commands/install-hooks.ts +66 -0
  168. package/src/commands/preflight.test.ts +139 -0
  169. package/src/commands/preflight.ts +488 -0
  170. package/src/commands/rename.ts +264 -0
  171. package/src/commands/scaffold-adapter.test.ts +110 -0
  172. package/src/commands/scaffold-adapter.ts +250 -0
  173. package/src/commands/scan.ts +125 -0
  174. package/src/commands/sync-seed.test.ts +116 -0
  175. package/src/commands/sync.ts +736 -0
  176. package/src/commands/transform.ts +151 -0
  177. package/src/commands/translate/README.md +75 -0
  178. package/src/commands/translate/csv-handler.ts +301 -0
  179. package/src/commands/translate/executor.ts +188 -0
  180. package/src/commands/translate/index.ts +220 -0
  181. package/src/commands/translate/reporter.ts +138 -0
  182. package/src/commands/translate/types.ts +56 -0
  183. package/src/commands/translate.test.ts +173 -0
  184. package/src/commands/translate.ts +6 -0
  185. package/src/e2e.test.ts +479 -0
  186. package/src/fixtures/README.md +61 -0
  187. package/src/fixtures/basic-react/i18n.config.json +15 -0
  188. package/src/fixtures/basic-react/locales/de.json +8 -0
  189. package/src/fixtures/basic-react/locales/en.json +8 -0
  190. package/src/fixtures/basic-react/locales/fr.json +8 -0
  191. package/src/fixtures/basic-react/src/App.tsx +15 -0
  192. package/src/fixtures/basic-react/src/Messages.tsx +12 -0
  193. package/src/fixtures/nested-locales/i18n.config.json +9 -0
  194. package/src/fixtures/nested-locales/locales/en.json +23 -0
  195. package/src/fixtures/nested-locales/locales/fr.json +23 -0
  196. package/src/fixtures/nested-locales/src/HomePage.tsx +13 -0
  197. package/src/fixtures/suspicious-keys/i18n.config.json +9 -0
  198. package/src/fixtures/suspicious-keys/locales/en.json +11 -0
  199. package/src/fixtures/suspicious-keys/locales/fr.json +11 -0
  200. package/src/fixtures/suspicious-keys/src/BadKeys.tsx +19 -0
  201. package/src/index.ts +43 -0
  202. package/src/integration.test.ts +438 -0
  203. package/src/utils/diagnostics-exit.test.ts +47 -0
  204. package/src/utils/diagnostics-exit.ts +63 -0
  205. package/src/utils/diff-utils.test.ts +36 -0
  206. package/src/utils/diff-utils.ts +42 -0
  207. package/src/utils/exit-codes.ts +201 -0
  208. package/src/utils/package-manager.ts +44 -0
  209. package/src/utils/pkg.ts +23 -0
  210. package/src/utils/provider-injector.test.ts +79 -0
  211. package/src/utils/provider-injector.ts +315 -0
  212. package/src/utils/scaffold.ts +240 -0
  213. package/tsconfig.json +17 -0
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Translate command - fill missing locale entries via translation adapters
3
+ */
4
+ import chalk from 'chalk';
5
+ import inquirer from 'inquirer';
6
+ import { DEFAULT_PLACEHOLDER_FORMATS, PlaceholderValidator, loadConfig, TranslationService, } from '@i18nsmith/core';
7
+ import { TranslatorLoadError } from '@i18nsmith/translation';
8
+ import { emitTranslateOutput, maybePrintEstimate } from './reporter.js';
9
+ import { handleCsvExport, handleCsvImport } from './csv-handler.js';
10
+ import { executeTranslations } from './executor.js';
11
+ // Re-export types for external use
12
+ export * from './types.js';
13
+ /**
14
+ * Parse comma-separated locale values
15
+ */
16
+ function collectLocales(value, previous) {
17
+ const tokens = (Array.isArray(value) ? value : value.split(','))
18
+ .map((entry) => entry.trim())
19
+ .filter(Boolean);
20
+ return [...previous, ...tokens];
21
+ }
22
+ /**
23
+ * Resolve provider settings from config and options
24
+ */
25
+ function resolveProviderSettings(translationConfig, override) {
26
+ const providerName = (override ?? translationConfig?.provider ?? 'manual').trim();
27
+ const moduleSpecifier = translationConfig?.module;
28
+ let secret;
29
+ if (translationConfig?.secretEnvVar) {
30
+ secret = process.env[translationConfig.secretEnvVar];
31
+ }
32
+ const loaderOptions = {
33
+ provider: providerName,
34
+ module: moduleSpecifier,
35
+ apiKey: translationConfig?.apiKey,
36
+ secret,
37
+ concurrency: translationConfig?.concurrency,
38
+ batchSize: translationConfig?.batchSize,
39
+ config: translationConfig ? { ...translationConfig } : undefined,
40
+ };
41
+ return {
42
+ name: providerName,
43
+ loaderOptions,
44
+ };
45
+ }
46
+ /**
47
+ * Prompt for translation confirmation
48
+ */
49
+ async function confirmTranslate(plan, providerName) {
50
+ const { proceed } = await inquirer.prompt([
51
+ {
52
+ type: 'confirm',
53
+ name: 'proceed',
54
+ default: false,
55
+ message: `Translate ${plan.totalTasks} key${plan.totalTasks === 1 ? '' : 's'} (${plan.totalCharacters} chars) across ${plan.locales.length} locale${plan.locales.length === 1 ? '' : 's'} via ${providerName}?`,
56
+ },
57
+ ]);
58
+ return proceed;
59
+ }
60
+ /**
61
+ * Register the translate command
62
+ */
63
+ export function registerTranslate(program) {
64
+ program
65
+ .command('translate')
66
+ .description('Fill missing locale entries by invoking configured translation adapters')
67
+ .option('-c, --config <path>', 'Path to i18nsmith config file', 'i18n.config.json')
68
+ .option('--json', 'Print raw JSON results', false)
69
+ .option('--report <path>', 'Write JSON summary to a file')
70
+ .option('--write', 'Write translated values to locale files (defaults to dry-run)', false)
71
+ .option('--locales <codes...>', 'Comma-separated list of locale codes to translate', collectLocales, [])
72
+ .option('--provider <name>', 'Override the translation provider configured in i18n.config.json')
73
+ .option('--force', 'Retranslate keys even if a locale already has a value', false)
74
+ .option('--estimate', 'Attempt to estimate cost when running in dry-run mode', false)
75
+ .option('--no-skip-empty', 'Allow writing empty translator results (default skips them)')
76
+ .option('-y, --yes', 'Skip interactive confirmation when applying translations', false)
77
+ .option('--strict-placeholders', 'Fail if translated output has placeholder mismatches (for CI)', false)
78
+ .option('--export <path>', 'Export missing translations to a CSV file for external translation')
79
+ .option('--import <path>', 'Import translations from a CSV file and merge into locale files')
80
+ .action(async (options) => {
81
+ // Handle CSV export mode
82
+ if (options.export) {
83
+ await handleCsvExport(options);
84
+ return;
85
+ }
86
+ // Handle CSV import mode
87
+ if (options.import) {
88
+ await handleCsvImport(options);
89
+ return;
90
+ }
91
+ console.log(chalk.blue(options.write ? 'Translating locale files...' : 'Planning translations (dry-run)...'));
92
+ try {
93
+ const config = await loadConfig(options.config);
94
+ const translationService = new TranslationService(config);
95
+ const plan = await translationService.buildPlan({
96
+ locales: options.locales,
97
+ force: options.force,
98
+ });
99
+ const placeholderValidator = new PlaceholderValidator(config.sync?.placeholderFormats?.length ? config.sync.placeholderFormats : DEFAULT_PLACEHOLDER_FORMATS);
100
+ if (!plan.totalTasks) {
101
+ console.log(chalk.green('✓ No missing translations detected.'));
102
+ return;
103
+ }
104
+ const providerSettings = resolveProviderSettings(config.translation, options.provider);
105
+ const summary = {
106
+ provider: providerSettings.name,
107
+ dryRun: !options.write,
108
+ plan,
109
+ locales: [],
110
+ localeStats: [],
111
+ totalCharacters: plan.totalCharacters,
112
+ };
113
+ if (!options.write) {
114
+ if (options.estimate && providerSettings.name !== 'manual') {
115
+ await maybePrintEstimate(plan, providerSettings);
116
+ }
117
+ await emitTranslateOutput(summary, options);
118
+ return;
119
+ }
120
+ if (providerSettings.name === 'manual') {
121
+ throw new Error('No translation provider configured. Update "translation.provider" in i18n.config.json or pass --provider.');
122
+ }
123
+ if (options.write && !options.yes) {
124
+ if (!process.stdout.isTTY) {
125
+ throw new Error('Interactive confirmation required in non-TTY environment. Re-run with --yes to proceed.');
126
+ }
127
+ const confirmed = await confirmTranslate(plan, providerSettings.name);
128
+ if (!confirmed) {
129
+ console.log(chalk.yellow('Translation aborted by user.'));
130
+ return;
131
+ }
132
+ }
133
+ const skipEmpty = options.skipEmpty !== false;
134
+ const strictPlaceholders = options.strictPlaceholders ?? false;
135
+ const localeResults = await executeTranslations({
136
+ plan,
137
+ translationService,
138
+ provider: providerSettings,
139
+ overwrite: options.force ?? false,
140
+ skipEmpty,
141
+ placeholderValidator,
142
+ strictPlaceholders,
143
+ });
144
+ summary.locales = localeResults.results;
145
+ summary.localeStats = localeResults.stats;
146
+ // Check for placeholder issues in strict mode
147
+ const allPlaceholderIssues = localeResults.results.flatMap((r) => r.placeholderIssues);
148
+ if (strictPlaceholders && allPlaceholderIssues.length > 0) {
149
+ console.error(chalk.red(`\n✗ ${allPlaceholderIssues.length} placeholder issue(s) detected in translated output:`));
150
+ allPlaceholderIssues.slice(0, 10).forEach((issue) => {
151
+ console.error(chalk.red(` • ${issue.key} (${issue.locale}): ${issue.type} placeholder${issue.placeholders.length === 1 ? '' : 's'} ${issue.placeholders.join(', ')}`));
152
+ });
153
+ if (allPlaceholderIssues.length > 10) {
154
+ console.error(chalk.red(` ... and ${allPlaceholderIssues.length - 10} more issues`));
155
+ }
156
+ process.exitCode = 1;
157
+ }
158
+ await emitTranslateOutput(summary, options);
159
+ }
160
+ catch (error) {
161
+ const translatorError = error instanceof TranslatorLoadError ? error : undefined;
162
+ const normalizedError = error instanceof Error
163
+ ? error
164
+ : new Error(typeof error === 'string' ? error : JSON.stringify(error));
165
+ console.error(chalk.red('Translate failed:'), translatorError?.message ?? normalizedError.message);
166
+ process.exitCode = 1;
167
+ }
168
+ });
169
+ }
170
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/translate/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Output formatting and reporting utilities for the translate command
3
+ */
4
+ import type { TranslationPlan } from '@i18nsmith/core';
5
+ import { type TranslatorLoadOptions } from '@i18nsmith/translation';
6
+ import type { TranslateSummary, TranslateLocaleResult, TranslateCommandOptions, ProviderSettings } from './types.js';
7
+ /**
8
+ * Emit the translation output (report file, JSON, or console)
9
+ */
10
+ export declare function emitTranslateOutput(summary: TranslateSummary, options: TranslateCommandOptions): Promise<void>;
11
+ /**
12
+ * Print a summary of the translation plan
13
+ */
14
+ export declare function printPlanSummary(plan: TranslationPlan): void;
15
+ /**
16
+ * Print the execution summary after translations are applied
17
+ */
18
+ export declare function printExecutionSummary(results: TranslateLocaleResult[]): void;
19
+ /**
20
+ * Print cost estimation if available
21
+ */
22
+ export declare function maybePrintEstimate(plan: TranslationPlan, provider: ProviderSettings & {
23
+ loaderOptions: TranslatorLoadOptions;
24
+ }): Promise<void>;
25
+ /**
26
+ * Print a generic cost estimate based on common cloud provider rates
27
+ */
28
+ export declare function printGenericEstimate(plan: TranslationPlan): void;
29
+ //# sourceMappingURL=reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../../../src/commands/translate/reporter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAkB,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,KAAK,EACV,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAqB5D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,EAAE,GAAG,IAAI,CAY5E;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,eAAe,EACrB,QAAQ,EAAE,gBAAgB,GAAG;IAAE,aAAa,EAAE,qBAAqB,CAAA;CAAE,GACpE,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAShE"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Output formatting and reporting utilities for the translate command
3
+ */
4
+ import fs from 'fs/promises';
5
+ import path from 'path';
6
+ import chalk from 'chalk';
7
+ import { loadTranslator } from '@i18nsmith/translation';
8
+ /**
9
+ * Emit the translation output (report file, JSON, or console)
10
+ */
11
+ export async function emitTranslateOutput(summary, options) {
12
+ if (options.report) {
13
+ const outputPath = path.resolve(process.cwd(), options.report);
14
+ await fs.mkdir(path.dirname(outputPath), { recursive: true });
15
+ await fs.writeFile(outputPath, JSON.stringify(summary, null, 2));
16
+ console.log(chalk.green(`Translate report written to ${outputPath}`));
17
+ }
18
+ if (options.json) {
19
+ console.log(JSON.stringify(summary, null, 2));
20
+ return;
21
+ }
22
+ printPlanSummary(summary.plan);
23
+ if (!summary.dryRun) {
24
+ printExecutionSummary(summary.locales);
25
+ const mutations = summary.localeStats.reduce((total, stat) => total + stat.added.length + stat.updated.length, 0);
26
+ if (mutations === 0) {
27
+ console.log(chalk.yellow('No locale files were updated. Translator may have skipped all entries.'));
28
+ }
29
+ }
30
+ else {
31
+ console.log(chalk.yellow('Run again with --write to apply translations.'));
32
+ }
33
+ }
34
+ /**
35
+ * Print a summary of the translation plan
36
+ */
37
+ export function printPlanSummary(plan) {
38
+ console.log(chalk.green(`Source locale ${plan.sourceLocale}; ${plan.totalTasks} missing entr${plan.totalTasks === 1 ? 'y' : 'ies'} across ${plan.locales.length} locale${plan.locales.length === 1 ? '' : 's'}.`));
39
+ if (!plan.locales.length) {
40
+ console.log(chalk.green('All configured locales are up to date.'));
41
+ return;
42
+ }
43
+ plan.locales.forEach((localePlan) => {
44
+ const reuseCount = localePlan.tasks.filter((task) => task.reusedValue).length;
45
+ const reuseMessage = reuseCount > 0 ? chalk.gray(` (${reuseCount} reusable)`) : '';
46
+ console.log(` • ${localePlan.locale}: ${localePlan.tasks.length} key${localePlan.tasks.length === 1 ? '' : 's'} (${localePlan.totalCharacters} chars)${reuseMessage}`);
47
+ });
48
+ }
49
+ /**
50
+ * Print the execution summary after translations are applied
51
+ */
52
+ export function printExecutionSummary(results) {
53
+ if (!results.length) {
54
+ console.log(chalk.yellow('No translations were written.'));
55
+ return;
56
+ }
57
+ console.log(chalk.blue('\nTranslation results:'));
58
+ results.forEach((result) => {
59
+ console.log(` • ${result.locale}: ${result.written} written, ${result.skipped} skipped, ${result.emptySkipped} empty (${result.characters} chars)`);
60
+ });
61
+ }
62
+ /**
63
+ * Print cost estimation if available
64
+ */
65
+ export async function maybePrintEstimate(plan, provider) {
66
+ console.log(chalk.blue('\n📊 Cost Estimation:'));
67
+ console.log(chalk.gray(` Provider: ${provider.name}`));
68
+ console.log(chalk.gray(` Total characters: ${plan.totalCharacters.toLocaleString()}`));
69
+ console.log(chalk.gray(` Locales: ${plan.locales.length}`));
70
+ try {
71
+ const translator = await loadTranslator(provider.loaderOptions);
72
+ if (typeof translator.estimateCost === 'function') {
73
+ const estimate = await translator.estimateCost(plan.totalCharacters, { localeCount: plan.locales.length });
74
+ const formattedCost = typeof estimate === 'number'
75
+ ? `$${estimate.toFixed(4)}`
76
+ : String(estimate);
77
+ console.log(chalk.green(` Estimated cost: ${formattedCost}`));
78
+ }
79
+ else {
80
+ console.log(chalk.yellow(' Provider does not expose cost estimation.'));
81
+ printGenericEstimate(plan);
82
+ }
83
+ await translator.dispose?.();
84
+ }
85
+ catch (error) {
86
+ console.log(chalk.yellow(` Unable to estimate via provider: ${error.message}`));
87
+ printGenericEstimate(plan);
88
+ }
89
+ }
90
+ /**
91
+ * Print a generic cost estimate based on common cloud provider rates
92
+ */
93
+ export function printGenericEstimate(plan) {
94
+ // Generic estimation based on common cloud provider rates (rough average)
95
+ // Google/AWS/Azure typically charge ~$20 per million characters
96
+ const ratePerMillion = 20;
97
+ const charsByLocale = plan.totalCharacters;
98
+ const totalChars = charsByLocale * plan.locales.length;
99
+ const estimated = (totalChars / 1000000) * ratePerMillion;
100
+ console.log(chalk.gray(` Generic estimate (at ~$20/M chars): $${estimated.toFixed(4)}`));
101
+ console.log(chalk.gray(' (Actual costs vary by provider and tier)'));
102
+ }
103
+ //# sourceMappingURL=reporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../../src/commands/translate/reporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Type definitions for the translate command
3
+ */
4
+ import type { TranslationWriteSummary, TranslationPlan } from '@i18nsmith/core';
5
+ import type { TranslationService } from '@i18nsmith/core';
6
+ export interface TranslateCommandOptions {
7
+ config?: string;
8
+ json?: boolean;
9
+ report?: string;
10
+ write?: boolean;
11
+ locales?: string[];
12
+ provider?: string;
13
+ force?: boolean;
14
+ estimate?: boolean;
15
+ skipEmpty?: boolean;
16
+ yes?: boolean;
17
+ strictPlaceholders?: boolean;
18
+ export?: string;
19
+ import?: string;
20
+ }
21
+ export interface TranslateLocaleResult extends TranslationWriteSummary {
22
+ characters: number;
23
+ placeholderIssues: PlaceholderIssue[];
24
+ }
25
+ export interface PlaceholderIssue {
26
+ key: string;
27
+ locale: string;
28
+ type: 'missing' | 'extra';
29
+ placeholders: string[];
30
+ }
31
+ export interface TranslateSummary {
32
+ provider: string;
33
+ dryRun: boolean;
34
+ plan: TranslationPlan;
35
+ locales: TranslateLocaleResult[];
36
+ localeStats: Awaited<ReturnType<TranslationService['flush']>>;
37
+ totalCharacters: number;
38
+ }
39
+ export interface ProviderSettings {
40
+ name: string;
41
+ options?: Record<string, unknown>;
42
+ }
43
+ export interface CsvRow {
44
+ key: string;
45
+ sourceLocale: string;
46
+ sourceValue: string;
47
+ targetLocale: string;
48
+ targetValue: string;
49
+ }
50
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/translate/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAsB,SAAQ,uBAAuB;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9D,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Type definitions for the translate command
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/commands/translate/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Translate command - re-exports from translate module
3
+ * @deprecated Import from './translate/index.js' instead
4
+ */
5
+ export { registerTranslate } from './translate/index.js';
6
+ export * from './translate/types.js';
7
+ //# sourceMappingURL=translate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/commands/translate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Translate command - re-exports from translate module
3
+ * @deprecated Import from './translate/index.js' instead
4
+ */
5
+ export { registerTranslate } from './translate/index.js';
6
+ export * from './translate/types.js';
7
+ //# sourceMappingURL=translate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/commands/translate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=translate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate.test.d.ts","sourceRoot":"","sources":["../../src/commands/translate.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,118 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import fs from 'fs/promises';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import { execSync } from 'child_process';
6
+ describe('translate command', () => {
7
+ let tempDir;
8
+ beforeEach(async () => {
9
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'i18nsmith-translate-test-'));
10
+ // Create basic project structure
11
+ await fs.mkdir(path.join(tempDir, 'src'), { recursive: true });
12
+ await fs.mkdir(path.join(tempDir, 'locales'), { recursive: true });
13
+ // Create source file with translation calls
14
+ await fs.writeFile(path.join(tempDir, 'src', 'App.tsx'), `import { useTranslation } from 'react-i18next';
15
+ export function App() {
16
+ const { t } = useTranslation();
17
+ return <div>{t('greeting')}{t('farewell')}</div>;
18
+ }
19
+ `);
20
+ // Create source locale
21
+ await fs.writeFile(path.join(tempDir, 'locales', 'en.json'), JSON.stringify({ greeting: 'Hello', farewell: 'Goodbye' }, null, 2));
22
+ // Create target locale with one missing key
23
+ await fs.writeFile(path.join(tempDir, 'locales', 'fr.json'), JSON.stringify({ greeting: 'Bonjour' }, null, 2));
24
+ // Create config
25
+ await fs.writeFile(path.join(tempDir, 'i18n.config.json'), JSON.stringify({
26
+ version: 1,
27
+ sourceLanguage: 'en',
28
+ targetLanguages: ['fr'],
29
+ localesDir: 'locales',
30
+ include: ['src/**/*.{ts,tsx}'],
31
+ }, null, 2));
32
+ });
33
+ afterEach(async () => {
34
+ await fs.rm(tempDir, { recursive: true, force: true });
35
+ });
36
+ const runCli = (args) => {
37
+ const cliPath = path.resolve(__dirname, '..', '..', 'dist', 'index.js');
38
+ try {
39
+ return execSync(`node ${cliPath} ${args}`, {
40
+ cwd: tempDir,
41
+ encoding: 'utf8',
42
+ stdio: ['pipe', 'pipe', 'pipe'],
43
+ });
44
+ }
45
+ catch (error) {
46
+ const err = error;
47
+ return (err.stdout ?? '') + (err.stderr ?? '');
48
+ }
49
+ };
50
+ describe('--export', () => {
51
+ it('exports missing translations to CSV', async () => {
52
+ const csvPath = path.join(tempDir, 'missing.csv');
53
+ const output = runCli(`translate --export ${csvPath}`);
54
+ expect(output).toContain('Exported');
55
+ const csvContent = await fs.readFile(csvPath, 'utf8');
56
+ expect(csvContent).toContain('key,sourceLocale,sourceValue,targetLocale,translatedValue');
57
+ expect(csvContent).toContain('farewell');
58
+ expect(csvContent).toContain('Goodbye');
59
+ expect(csvContent).toContain('fr');
60
+ });
61
+ it('handles empty values correctly', async () => {
62
+ // All translations are present
63
+ await fs.writeFile(path.join(tempDir, 'locales', 'fr.json'), JSON.stringify({ greeting: 'Bonjour', farewell: 'Au revoir' }, null, 2));
64
+ const output = runCli('translate --export output.csv');
65
+ expect(output).toContain('No missing translations');
66
+ });
67
+ });
68
+ describe('--import', () => {
69
+ it('imports translations from CSV', async () => {
70
+ const csvPath = path.join(tempDir, 'translations.csv');
71
+ await fs.writeFile(csvPath, `key,sourceLocale,sourceValue,targetLocale,translatedValue
72
+ farewell,en,Goodbye,fr,Au revoir
73
+ `);
74
+ const output = runCli(`translate --import ${csvPath} --write`);
75
+ expect(output).toContain('1 row');
76
+ const frContent = await fs.readFile(path.join(tempDir, 'locales', 'fr.json'), 'utf8');
77
+ const frData = JSON.parse(frContent);
78
+ expect(frData.farewell).toBe('Au revoir');
79
+ });
80
+ it('skips rows with empty translatedValue', async () => {
81
+ const csvPath = path.join(tempDir, 'translations.csv');
82
+ await fs.writeFile(csvPath, `key,sourceLocale,sourceValue,targetLocale,translatedValue
83
+ farewell,en,Goodbye,fr,
84
+ `);
85
+ const output = runCli(`translate --import ${csvPath}`);
86
+ expect(output).toContain('skipped');
87
+ });
88
+ it('handles quoted CSV fields with commas', async () => {
89
+ // Add a source key with comma
90
+ await fs.writeFile(path.join(tempDir, 'locales', 'en.json'), JSON.stringify({
91
+ greeting: 'Hello',
92
+ farewell: 'Goodbye',
93
+ message: 'Hello, world!'
94
+ }, null, 2));
95
+ const csvPath = path.join(tempDir, 'translations.csv');
96
+ await fs.writeFile(csvPath, `key,sourceLocale,sourceValue,targetLocale,translatedValue
97
+ message,en,"Hello, world!",fr,"Bonjour, le monde!"
98
+ `);
99
+ const output = runCli(`translate --import ${csvPath} --write`);
100
+ expect(output).toContain('1 row');
101
+ const frContent = await fs.readFile(path.join(tempDir, 'locales', 'fr.json'), 'utf8');
102
+ const frData = JSON.parse(frContent);
103
+ expect(frData.message).toBe('Bonjour, le monde!');
104
+ });
105
+ it('dry-run mode does not write files', async () => {
106
+ const csvPath = path.join(tempDir, 'translations.csv');
107
+ await fs.writeFile(csvPath, `key,sourceLocale,sourceValue,targetLocale,translatedValue
108
+ farewell,en,Goodbye,fr,Au revoir
109
+ `);
110
+ const originalContent = await fs.readFile(path.join(tempDir, 'locales', 'fr.json'), 'utf8');
111
+ const output = runCli(`translate --import ${csvPath}`);
112
+ expect(output).toContain('DRY RUN');
113
+ const newContent = await fs.readFile(path.join(tempDir, 'locales', 'fr.json'), 'utf8');
114
+ expect(newContent).toBe(originalContent);
115
+ });
116
+ });
117
+ });
118
+ //# sourceMappingURL=translate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate.test.js","sourceRoot":"","sources":["../../src/commands/translate.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * E2E Tests using fixture projects
3
+ * These tests run against pre-configured fixture projects to test real-world scenarios
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=e2e.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"e2e.test.d.ts","sourceRoot":"","sources":["../src/e2e.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}