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.
- package/dist/commands/audit.d.ts +3 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +180 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/backup.d.ts +6 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +85 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/check.d.ts +3 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +151 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +235 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/debug-patterns.d.ts +3 -0
- package/dist/commands/debug-patterns.d.ts.map +1 -0
- package/dist/commands/debug-patterns.js +192 -0
- package/dist/commands/debug-patterns.js.map +1 -0
- package/dist/commands/debug-patterns.test.d.ts +2 -0
- package/dist/commands/debug-patterns.test.d.ts.map +1 -0
- package/dist/commands/debug-patterns.test.js +109 -0
- package/dist/commands/debug-patterns.test.js.map +1 -0
- package/dist/commands/diagnose.d.ts +3 -0
- package/dist/commands/diagnose.d.ts.map +1 -0
- package/dist/commands/diagnose.js +117 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +450 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/init.test.d.ts +2 -0
- package/dist/commands/init.test.d.ts.map +1 -0
- package/dist/commands/init.test.js +74 -0
- package/dist/commands/init.test.js.map +1 -0
- package/dist/commands/install-hooks.d.ts +3 -0
- package/dist/commands/install-hooks.d.ts.map +1 -0
- package/dist/commands/install-hooks.js +52 -0
- package/dist/commands/install-hooks.js.map +1 -0
- package/dist/commands/preflight.d.ts +7 -0
- package/dist/commands/preflight.d.ts.map +1 -0
- package/dist/commands/preflight.js +417 -0
- package/dist/commands/preflight.js.map +1 -0
- package/dist/commands/preflight.test.d.ts +5 -0
- package/dist/commands/preflight.test.d.ts.map +1 -0
- package/dist/commands/preflight.test.js +108 -0
- package/dist/commands/preflight.test.js.map +1 -0
- package/dist/commands/rename.d.ts +6 -0
- package/dist/commands/rename.d.ts.map +1 -0
- package/dist/commands/rename.js +204 -0
- package/dist/commands/rename.js.map +1 -0
- package/dist/commands/scaffold-adapter.d.ts +3 -0
- package/dist/commands/scaffold-adapter.d.ts.map +1 -0
- package/dist/commands/scaffold-adapter.js +204 -0
- package/dist/commands/scaffold-adapter.js.map +1 -0
- package/dist/commands/scaffold-adapter.test.d.ts +2 -0
- package/dist/commands/scaffold-adapter.test.d.ts.map +1 -0
- package/dist/commands/scaffold-adapter.test.js +102 -0
- package/dist/commands/scaffold-adapter.test.js.map +1 -0
- package/dist/commands/scan.d.ts +3 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +93 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/sync-seed.test.d.ts +2 -0
- package/dist/commands/sync-seed.test.d.ts.map +1 -0
- package/dist/commands/sync-seed.test.js +86 -0
- package/dist/commands/sync-seed.test.js.map +1 -0
- package/dist/commands/sync.d.ts +3 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +590 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/transform.d.ts +3 -0
- package/dist/commands/transform.d.ts.map +1 -0
- package/dist/commands/transform.js +114 -0
- package/dist/commands/transform.js.map +1 -0
- package/dist/commands/translate/csv-handler.d.ts +21 -0
- package/dist/commands/translate/csv-handler.d.ts.map +1 -0
- package/dist/commands/translate/csv-handler.js +270 -0
- package/dist/commands/translate/csv-handler.js.map +1 -0
- package/dist/commands/translate/executor.d.ts +31 -0
- package/dist/commands/translate/executor.d.ts.map +1 -0
- package/dist/commands/translate/executor.js +117 -0
- package/dist/commands/translate/executor.js.map +1 -0
- package/dist/commands/translate/index.d.ts +10 -0
- package/dist/commands/translate/index.d.ts.map +1 -0
- package/dist/commands/translate/index.js +170 -0
- package/dist/commands/translate/index.js.map +1 -0
- package/dist/commands/translate/reporter.d.ts +29 -0
- package/dist/commands/translate/reporter.d.ts.map +1 -0
- package/dist/commands/translate/reporter.js +103 -0
- package/dist/commands/translate/reporter.js.map +1 -0
- package/dist/commands/translate/types.d.ts +50 -0
- package/dist/commands/translate/types.d.ts.map +1 -0
- package/dist/commands/translate/types.js +5 -0
- package/dist/commands/translate/types.js.map +1 -0
- package/dist/commands/translate.d.ts +7 -0
- package/dist/commands/translate.d.ts.map +1 -0
- package/dist/commands/translate.js +7 -0
- package/dist/commands/translate.js.map +1 -0
- package/dist/commands/translate.test.d.ts +2 -0
- package/dist/commands/translate.test.d.ts.map +1 -0
- package/dist/commands/translate.test.js +118 -0
- package/dist/commands/translate.test.js.map +1 -0
- package/dist/e2e.test.d.ts +6 -0
- package/dist/e2e.test.d.ts.map +1 -0
- package/dist/e2e.test.js +376 -0
- package/dist/e2e.test.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/integration.test.d.ts +6 -0
- package/dist/integration.test.d.ts.map +1 -0
- package/dist/integration.test.js +320 -0
- package/dist/integration.test.js.map +1 -0
- package/dist/utils/diagnostics-exit.d.ts +12 -0
- package/dist/utils/diagnostics-exit.d.ts.map +1 -0
- package/dist/utils/diagnostics-exit.js +49 -0
- package/dist/utils/diagnostics-exit.js.map +1 -0
- package/dist/utils/diagnostics-exit.test.d.ts +2 -0
- package/dist/utils/diagnostics-exit.test.d.ts.map +1 -0
- package/dist/utils/diagnostics-exit.test.js +40 -0
- package/dist/utils/diagnostics-exit.test.js.map +1 -0
- package/dist/utils/diff-utils.d.ts +4 -0
- package/dist/utils/diff-utils.d.ts.map +1 -0
- package/dist/utils/diff-utils.js +30 -0
- package/dist/utils/diff-utils.js.map +1 -0
- package/dist/utils/diff-utils.test.d.ts +2 -0
- package/dist/utils/diff-utils.test.d.ts.map +1 -0
- package/dist/utils/diff-utils.test.js +30 -0
- package/dist/utils/diff-utils.test.js.map +1 -0
- package/dist/utils/exit-codes.d.ts +142 -0
- package/dist/utils/exit-codes.d.ts.map +1 -0
- package/dist/utils/exit-codes.js +168 -0
- package/dist/utils/exit-codes.js.map +1 -0
- package/dist/utils/package-manager.d.ts +4 -0
- package/dist/utils/package-manager.d.ts.map +1 -0
- package/dist/utils/package-manager.js +40 -0
- package/dist/utils/package-manager.js.map +1 -0
- package/dist/utils/pkg.d.ts +3 -0
- package/dist/utils/pkg.d.ts.map +1 -0
- package/dist/utils/pkg.js +24 -0
- package/dist/utils/pkg.js.map +1 -0
- package/dist/utils/provider-injector.d.ts +36 -0
- package/dist/utils/provider-injector.d.ts.map +1 -0
- package/dist/utils/provider-injector.js +223 -0
- package/dist/utils/provider-injector.js.map +1 -0
- package/dist/utils/provider-injector.test.d.ts +2 -0
- package/dist/utils/provider-injector.test.d.ts.map +1 -0
- package/dist/utils/provider-injector.test.js +67 -0
- package/dist/utils/provider-injector.test.js.map +1 -0
- package/dist/utils/scaffold.d.ts +20 -0
- package/dist/utils/scaffold.d.ts.map +1 -0
- package/dist/utils/scaffold.js +197 -0
- package/dist/utils/scaffold.js.map +1 -0
- package/package.json +35 -0
- package/src/commands/audit.ts +234 -0
- package/src/commands/backup.ts +96 -0
- package/src/commands/check.ts +191 -0
- package/src/commands/config.ts +263 -0
- package/src/commands/debug-patterns.test.ts +134 -0
- package/src/commands/debug-patterns.ts +257 -0
- package/src/commands/diagnose.ts +136 -0
- package/src/commands/init.test.ts +82 -0
- package/src/commands/init.ts +536 -0
- package/src/commands/install-hooks.ts +66 -0
- package/src/commands/preflight.test.ts +139 -0
- package/src/commands/preflight.ts +488 -0
- package/src/commands/rename.ts +264 -0
- package/src/commands/scaffold-adapter.test.ts +110 -0
- package/src/commands/scaffold-adapter.ts +250 -0
- package/src/commands/scan.ts +125 -0
- package/src/commands/sync-seed.test.ts +116 -0
- package/src/commands/sync.ts +736 -0
- package/src/commands/transform.ts +151 -0
- package/src/commands/translate/README.md +75 -0
- package/src/commands/translate/csv-handler.ts +301 -0
- package/src/commands/translate/executor.ts +188 -0
- package/src/commands/translate/index.ts +220 -0
- package/src/commands/translate/reporter.ts +138 -0
- package/src/commands/translate/types.ts +56 -0
- package/src/commands/translate.test.ts +173 -0
- package/src/commands/translate.ts +6 -0
- package/src/e2e.test.ts +479 -0
- package/src/fixtures/README.md +61 -0
- package/src/fixtures/basic-react/i18n.config.json +15 -0
- package/src/fixtures/basic-react/locales/de.json +8 -0
- package/src/fixtures/basic-react/locales/en.json +8 -0
- package/src/fixtures/basic-react/locales/fr.json +8 -0
- package/src/fixtures/basic-react/src/App.tsx +15 -0
- package/src/fixtures/basic-react/src/Messages.tsx +12 -0
- package/src/fixtures/nested-locales/i18n.config.json +9 -0
- package/src/fixtures/nested-locales/locales/en.json +23 -0
- package/src/fixtures/nested-locales/locales/fr.json +23 -0
- package/src/fixtures/nested-locales/src/HomePage.tsx +13 -0
- package/src/fixtures/suspicious-keys/i18n.config.json +9 -0
- package/src/fixtures/suspicious-keys/locales/en.json +11 -0
- package/src/fixtures/suspicious-keys/locales/fr.json +11 -0
- package/src/fixtures/suspicious-keys/src/BadKeys.tsx +19 -0
- package/src/index.ts +43 -0
- package/src/integration.test.ts +438 -0
- package/src/utils/diagnostics-exit.test.ts +47 -0
- package/src/utils/diagnostics-exit.ts +63 -0
- package/src/utils/diff-utils.test.ts +36 -0
- package/src/utils/diff-utils.ts +42 -0
- package/src/utils/exit-codes.ts +201 -0
- package/src/utils/package-manager.ts +44 -0
- package/src/utils/pkg.ts +23 -0
- package/src/utils/provider-injector.test.ts +79 -0
- package/src/utils/provider-injector.ts +315 -0
- package/src/utils/scaffold.ts +240 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { loadConfigWithMeta } from '@i18nsmith/core';
|
|
5
|
+
import { Transformer } from '@i18nsmith/transformer';
|
|
6
|
+
import { printLocaleDiffs, writeLocaleDiffPatches } from '../utils/diff-utils.js';
|
|
7
|
+
const collectTargetPatterns = (value, previous) => {
|
|
8
|
+
const list = Array.isArray(value) ? value : [value];
|
|
9
|
+
const tokens = list
|
|
10
|
+
.flatMap((entry) => entry.split(','))
|
|
11
|
+
.map((token) => token.trim())
|
|
12
|
+
.filter(Boolean);
|
|
13
|
+
return [...previous, ...tokens];
|
|
14
|
+
};
|
|
15
|
+
function printTransformSummary(summary) {
|
|
16
|
+
console.log(chalk.green(`Scanned ${summary.filesScanned} file${summary.filesScanned === 1 ? '' : 's'}; ` +
|
|
17
|
+
`${summary.candidates.length} candidate${summary.candidates.length === 1 ? '' : 's'} processed.`));
|
|
18
|
+
const preview = summary.candidates.slice(0, 50).map((candidate) => ({
|
|
19
|
+
File: candidate.filePath,
|
|
20
|
+
Line: candidate.position.line,
|
|
21
|
+
Kind: candidate.kind,
|
|
22
|
+
Status: candidate.status,
|
|
23
|
+
Key: candidate.suggestedKey,
|
|
24
|
+
Preview: candidate.text.length > 40
|
|
25
|
+
? `${candidate.text.slice(0, 37)}...`
|
|
26
|
+
: candidate.text,
|
|
27
|
+
}));
|
|
28
|
+
console.table(preview);
|
|
29
|
+
if (summary.filesChanged.length) {
|
|
30
|
+
console.log(chalk.blue(`Files changed (${summary.filesChanged.length}):`));
|
|
31
|
+
summary.filesChanged.forEach((file) => console.log(` • ${file}`));
|
|
32
|
+
}
|
|
33
|
+
if (summary.localeStats.length) {
|
|
34
|
+
console.log(chalk.blue('Locale updates:'));
|
|
35
|
+
summary.localeStats.forEach((stat) => {
|
|
36
|
+
console.log(` • ${stat.locale}: ${stat.added.length} added, ${stat.updated.length} updated, ${stat.removed.length} removed (total ${stat.totalKeys})`);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (summary.skippedFiles.length) {
|
|
40
|
+
console.log(chalk.yellow('Skipped items:'));
|
|
41
|
+
summary.skippedFiles.forEach((item) => console.log(` • ${item.filePath}: ${item.reason}`));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function registerTransform(program) {
|
|
45
|
+
program
|
|
46
|
+
.command('transform')
|
|
47
|
+
.description('Scan project and apply i18n transformations')
|
|
48
|
+
.option('-c, --config <path>', 'Path to i18nsmith config file', 'i18n.config.json')
|
|
49
|
+
.option('--json', 'Print raw JSON results', false)
|
|
50
|
+
.option('--report <path>', 'Write JSON summary to a file (for CI or editors)')
|
|
51
|
+
.option('--write', 'Write changes to disk (defaults to dry-run)', false)
|
|
52
|
+
.option('--check', 'Exit with error code if changes are needed', false)
|
|
53
|
+
.option('--diff', 'Display unified diffs for locale files that would change', false)
|
|
54
|
+
.option('--patch-dir <path>', 'Write locale diffs to .patch files in the specified directory')
|
|
55
|
+
.option('--target <pattern...>', 'Limit scanning to specific files or glob patterns', collectTargetPatterns, [])
|
|
56
|
+
.option('--migrate-text-keys', 'Migrate existing t("Text") calls to structured keys')
|
|
57
|
+
.action(async (options) => {
|
|
58
|
+
const diffEnabled = Boolean(options.diff || options.patchDir);
|
|
59
|
+
console.log(chalk.blue(options.write ? 'Running transform (write mode)...' : 'Planning transform (dry-run)...'));
|
|
60
|
+
try {
|
|
61
|
+
const { config, projectRoot, configPath } = await loadConfigWithMeta(options.config);
|
|
62
|
+
// Inform user if config was found in a parent directory
|
|
63
|
+
const cwd = process.cwd();
|
|
64
|
+
if (projectRoot !== cwd) {
|
|
65
|
+
console.log(chalk.gray(`Config found at ${path.relative(cwd, configPath)}`));
|
|
66
|
+
console.log(chalk.gray(`Using project root: ${projectRoot}\n`));
|
|
67
|
+
}
|
|
68
|
+
const transformer = new Transformer(config, { workspaceRoot: projectRoot });
|
|
69
|
+
const summary = await transformer.run({
|
|
70
|
+
write: options.write,
|
|
71
|
+
targets: options.target,
|
|
72
|
+
diff: diffEnabled,
|
|
73
|
+
migrateTextKeys: options.migrateTextKeys,
|
|
74
|
+
});
|
|
75
|
+
if (options.report) {
|
|
76
|
+
const outputPath = path.resolve(process.cwd(), options.report);
|
|
77
|
+
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
|
78
|
+
await fs.writeFile(outputPath, JSON.stringify(summary, null, 2));
|
|
79
|
+
console.log(chalk.green(`Transform report written to ${outputPath}`));
|
|
80
|
+
}
|
|
81
|
+
if (options.json) {
|
|
82
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
printTransformSummary(summary);
|
|
86
|
+
if (diffEnabled) {
|
|
87
|
+
printLocaleDiffs(summary.diffs);
|
|
88
|
+
}
|
|
89
|
+
if (options.patchDir) {
|
|
90
|
+
await writeLocaleDiffPatches(summary.diffs, options.patchDir);
|
|
91
|
+
}
|
|
92
|
+
if (options.check && summary.candidates.some((candidate) => candidate.status === 'pending')) {
|
|
93
|
+
console.error(chalk.red('\nCheck failed: Pending translations found. Run with --write to fix.'));
|
|
94
|
+
process.exitCode = 1;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!options.write && summary.candidates.some((candidate) => candidate.status === 'pending')) {
|
|
98
|
+
console.log(chalk.cyan('\n📋 DRY RUN - No files were modified'));
|
|
99
|
+
console.log(chalk.yellow('Run again with --write to apply these changes.'));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
const errorMessage = error.message;
|
|
104
|
+
if (options.json) {
|
|
105
|
+
console.log(JSON.stringify({ ok: false, error: { message: errorMessage } }, null, 2));
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
console.error(chalk.red('Transform failed:'), errorMessage);
|
|
109
|
+
}
|
|
110
|
+
process.exitCode = 1;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../src/commands/transform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSV export/import utilities for translator handoff
|
|
3
|
+
*/
|
|
4
|
+
import type { TranslateCommandOptions } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Escape a field for CSV output
|
|
7
|
+
*/
|
|
8
|
+
export declare function escapeCsvField(field: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Parse a CSV line into fields (handles quoted fields with commas and escaped quotes)
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseCsvLine(line: string): string[];
|
|
13
|
+
/**
|
|
14
|
+
* Export missing translations to a CSV file for external translation
|
|
15
|
+
*/
|
|
16
|
+
export declare function handleCsvExport(options: TranslateCommandOptions): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Import translations from a CSV file and merge into locale files
|
|
19
|
+
*/
|
|
20
|
+
export declare function handleCsvImport(options: TranslateCommandOptions): Promise<void>;
|
|
21
|
+
//# sourceMappingURL=csv-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv-handler.d.ts","sourceRoot":"","sources":["../../../src/commands/translate/csv-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,OAAO,KAAK,EAAE,uBAAuB,EAAU,MAAM,YAAY,CAAC;AAElE;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAqCnD;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DrF;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsKrF"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSV export/import utilities for translator handoff
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { DEFAULT_PLACEHOLDER_FORMATS, PlaceholderValidator, loadConfig, TranslationService, } from '@i18nsmith/core';
|
|
8
|
+
/**
|
|
9
|
+
* Escape a field for CSV output
|
|
10
|
+
*/
|
|
11
|
+
export function escapeCsvField(field) {
|
|
12
|
+
if (field.includes(',') || field.includes('"') || field.includes('\n') || field.includes('\r')) {
|
|
13
|
+
return `"${field.replace(/"/g, '""')}"`;
|
|
14
|
+
}
|
|
15
|
+
return field;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse a CSV line into fields (handles quoted fields with commas and escaped quotes)
|
|
19
|
+
*/
|
|
20
|
+
export function parseCsvLine(line) {
|
|
21
|
+
const fields = [];
|
|
22
|
+
let current = '';
|
|
23
|
+
let inQuotes = false;
|
|
24
|
+
let i = 0;
|
|
25
|
+
while (i < line.length) {
|
|
26
|
+
const char = line[i];
|
|
27
|
+
if (inQuotes) {
|
|
28
|
+
if (char === '"') {
|
|
29
|
+
if (line[i + 1] === '"') {
|
|
30
|
+
current += '"';
|
|
31
|
+
i += 2;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
inQuotes = false;
|
|
35
|
+
i++;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
current += char;
|
|
40
|
+
i++;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
if (char === '"') {
|
|
45
|
+
inQuotes = true;
|
|
46
|
+
i++;
|
|
47
|
+
}
|
|
48
|
+
else if (char === ',') {
|
|
49
|
+
fields.push(current);
|
|
50
|
+
current = '';
|
|
51
|
+
i++;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
current += char;
|
|
55
|
+
i++;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
fields.push(current);
|
|
60
|
+
return fields;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Export missing translations to a CSV file for external translation
|
|
64
|
+
*/
|
|
65
|
+
export async function handleCsvExport(options) {
|
|
66
|
+
const exportPath = options.export;
|
|
67
|
+
console.log(chalk.blue(`Exporting missing translations to ${exportPath}...`));
|
|
68
|
+
try {
|
|
69
|
+
const config = await loadConfig(options.config);
|
|
70
|
+
const translationService = new TranslationService(config);
|
|
71
|
+
const plan = await translationService.buildPlan({
|
|
72
|
+
locales: options.locales,
|
|
73
|
+
force: options.force,
|
|
74
|
+
});
|
|
75
|
+
if (!plan.totalTasks) {
|
|
76
|
+
console.log(chalk.green('✓ No missing translations to export.'));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// Build CSV rows
|
|
80
|
+
const rows = [];
|
|
81
|
+
for (const localePlan of plan.locales) {
|
|
82
|
+
for (const task of localePlan.tasks) {
|
|
83
|
+
rows.push({
|
|
84
|
+
key: task.key,
|
|
85
|
+
sourceLocale: plan.sourceLocale,
|
|
86
|
+
sourceValue: task.sourceValue,
|
|
87
|
+
targetLocale: localePlan.locale,
|
|
88
|
+
targetValue: '',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Generate CSV content
|
|
93
|
+
const header = 'key,sourceLocale,sourceValue,targetLocale,translatedValue';
|
|
94
|
+
const csvLines = [header];
|
|
95
|
+
for (const row of rows) {
|
|
96
|
+
csvLines.push([
|
|
97
|
+
escapeCsvField(row.key),
|
|
98
|
+
escapeCsvField(row.sourceLocale),
|
|
99
|
+
escapeCsvField(row.sourceValue),
|
|
100
|
+
escapeCsvField(row.targetLocale),
|
|
101
|
+
escapeCsvField(row.targetValue),
|
|
102
|
+
].join(','));
|
|
103
|
+
}
|
|
104
|
+
const csvContent = csvLines.join('\n') + '\n';
|
|
105
|
+
// Write CSV file
|
|
106
|
+
const resolvedPath = path.resolve(process.cwd(), exportPath);
|
|
107
|
+
await fs.mkdir(path.dirname(resolvedPath), { recursive: true });
|
|
108
|
+
await fs.writeFile(resolvedPath, csvContent, 'utf8');
|
|
109
|
+
console.log(chalk.green(`✓ Exported ${rows.length} missing translation(s) to ${exportPath}`));
|
|
110
|
+
console.log(chalk.gray(` Source locale: ${plan.sourceLocale}`));
|
|
111
|
+
console.log(chalk.gray(` Target locales: ${plan.locales.map(l => l.locale).join(', ')}`));
|
|
112
|
+
console.log(chalk.gray('\nFill in the "translatedValue" column and import with:'));
|
|
113
|
+
console.log(chalk.cyan(` i18nsmith translate --import ${exportPath} --write`));
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error(chalk.red('Export failed:'), error.message);
|
|
117
|
+
process.exitCode = 1;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Import translations from a CSV file and merge into locale files
|
|
122
|
+
*/
|
|
123
|
+
export async function handleCsvImport(options) {
|
|
124
|
+
const importPath = options.import;
|
|
125
|
+
const dryRun = !options.write;
|
|
126
|
+
console.log(chalk.blue(`${dryRun ? 'Previewing' : 'Importing'} translations from ${importPath}...`));
|
|
127
|
+
try {
|
|
128
|
+
const config = await loadConfig(options.config);
|
|
129
|
+
const translationService = new TranslationService(config);
|
|
130
|
+
const placeholderValidator = new PlaceholderValidator(config.sync?.placeholderFormats?.length ? config.sync.placeholderFormats : DEFAULT_PLACEHOLDER_FORMATS);
|
|
131
|
+
// Read and parse CSV
|
|
132
|
+
const resolvedPath = path.resolve(process.cwd(), importPath);
|
|
133
|
+
let csvContent;
|
|
134
|
+
try {
|
|
135
|
+
csvContent = await fs.readFile(resolvedPath, 'utf8');
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
const error = err;
|
|
139
|
+
if (error.code === 'ENOENT') {
|
|
140
|
+
throw new Error(`CSV file not found: ${resolvedPath}`);
|
|
141
|
+
}
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
const lines = csvContent.split(/\r?\n/).filter(line => line.trim().length > 0);
|
|
145
|
+
if (lines.length < 2) {
|
|
146
|
+
throw new Error('CSV file is empty or has no data rows.');
|
|
147
|
+
}
|
|
148
|
+
// Parse header
|
|
149
|
+
const headerFields = parseCsvLine(lines[0]);
|
|
150
|
+
const keyIdx = headerFields.indexOf('key');
|
|
151
|
+
const sourceLocaleIdx = headerFields.indexOf('sourceLocale');
|
|
152
|
+
const sourceValueIdx = headerFields.indexOf('sourceValue');
|
|
153
|
+
const targetLocaleIdx = headerFields.indexOf('targetLocale');
|
|
154
|
+
const translatedValueIdx = headerFields.indexOf('translatedValue');
|
|
155
|
+
if (keyIdx === -1 || targetLocaleIdx === -1 || translatedValueIdx === -1) {
|
|
156
|
+
throw new Error('CSV must have columns: key, targetLocale, translatedValue');
|
|
157
|
+
}
|
|
158
|
+
// Parse data rows
|
|
159
|
+
const updates = new Map();
|
|
160
|
+
const placeholderIssues = [];
|
|
161
|
+
let skipped = 0;
|
|
162
|
+
let total = 0;
|
|
163
|
+
for (let i = 1; i < lines.length; i++) {
|
|
164
|
+
const fields = parseCsvLine(lines[i]);
|
|
165
|
+
const key = fields[keyIdx]?.trim();
|
|
166
|
+
const targetLocale = fields[targetLocaleIdx]?.trim();
|
|
167
|
+
const translatedValue = fields[translatedValueIdx]?.trim();
|
|
168
|
+
const sourceValue = sourceValueIdx >= 0 ? fields[sourceValueIdx]?.trim() : undefined;
|
|
169
|
+
if (!key || !targetLocale) {
|
|
170
|
+
skipped++;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
total++;
|
|
174
|
+
if (!translatedValue) {
|
|
175
|
+
skipped++;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
// Validate placeholders if we have source value
|
|
179
|
+
if (sourceValue) {
|
|
180
|
+
const comparison = placeholderValidator.compare(sourceValue, translatedValue);
|
|
181
|
+
if (comparison.missing.length > 0) {
|
|
182
|
+
placeholderIssues.push({
|
|
183
|
+
key,
|
|
184
|
+
locale: targetLocale,
|
|
185
|
+
issue: `Missing placeholders: ${comparison.missing.join(', ')}`,
|
|
186
|
+
});
|
|
187
|
+
if (options.strictPlaceholders) {
|
|
188
|
+
skipped++;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (comparison.extra.length > 0) {
|
|
193
|
+
placeholderIssues.push({
|
|
194
|
+
key,
|
|
195
|
+
locale: targetLocale,
|
|
196
|
+
issue: `Extra placeholders: ${comparison.extra.join(', ')}`,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (!updates.has(targetLocale)) {
|
|
201
|
+
updates.set(targetLocale, []);
|
|
202
|
+
}
|
|
203
|
+
updates.get(targetLocale).push({ key, value: translatedValue });
|
|
204
|
+
}
|
|
205
|
+
// Print summary
|
|
206
|
+
const totalUpdates = Array.from(updates.values()).reduce((sum, arr) => sum + arr.length, 0);
|
|
207
|
+
console.log(chalk.green(`Parsed ${total} row(s): ${totalUpdates} with translations, ${skipped} skipped (empty)`));
|
|
208
|
+
if (placeholderIssues.length > 0) {
|
|
209
|
+
console.log(chalk.yellow(`\n⚠️ ${placeholderIssues.length} placeholder issue(s):`));
|
|
210
|
+
for (const issue of placeholderIssues.slice(0, 10)) {
|
|
211
|
+
console.log(chalk.yellow(` • ${issue.key} (${issue.locale}): ${issue.issue}`));
|
|
212
|
+
}
|
|
213
|
+
if (placeholderIssues.length > 10) {
|
|
214
|
+
console.log(chalk.gray(` ... and ${placeholderIssues.length - 10} more`));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (options.strictPlaceholders && placeholderIssues.length > 0) {
|
|
218
|
+
console.error(chalk.red('\n✗ Aborting due to placeholder issues (--strict-placeholders mode)'));
|
|
219
|
+
process.exitCode = 1;
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (totalUpdates === 0) {
|
|
223
|
+
console.log(chalk.yellow('No translations to import. Fill in the "translatedValue" column.'));
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
// Apply updates
|
|
227
|
+
if (dryRun) {
|
|
228
|
+
console.log(chalk.blue('\nDry-run preview:'));
|
|
229
|
+
for (const [locale, localeUpdates] of updates) {
|
|
230
|
+
console.log(` • ${locale}: ${localeUpdates.length} translation(s)`);
|
|
231
|
+
}
|
|
232
|
+
console.log(chalk.cyan('\n📋 DRY RUN - No files were modified'));
|
|
233
|
+
console.log(chalk.yellow('Run again with --write to apply changes.'));
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
for (const [locale, localeUpdates] of updates) {
|
|
237
|
+
const result = await translationService.writeTranslations(locale, localeUpdates, {
|
|
238
|
+
overwrite: options.force ?? false,
|
|
239
|
+
skipEmpty: options.skipEmpty !== false,
|
|
240
|
+
});
|
|
241
|
+
console.log(` • ${locale}: ${result.written} written, ${result.skipped} skipped`);
|
|
242
|
+
}
|
|
243
|
+
const stats = await translationService.flush();
|
|
244
|
+
console.log(chalk.green(`\n✓ Imported translations from ${importPath}`));
|
|
245
|
+
for (const stat of stats) {
|
|
246
|
+
console.log(chalk.gray(` ${stat.locale}: ${stat.added.length} added, ${stat.updated.length} updated`));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// Write report if requested
|
|
250
|
+
if (options.report) {
|
|
251
|
+
const report = {
|
|
252
|
+
source: importPath,
|
|
253
|
+
dryRun,
|
|
254
|
+
totalRows: total,
|
|
255
|
+
skipped,
|
|
256
|
+
updates: Object.fromEntries(Array.from(updates.entries()).map(([locale, arr]) => [locale, arr.length])),
|
|
257
|
+
placeholderIssues,
|
|
258
|
+
};
|
|
259
|
+
const outputPath = path.resolve(process.cwd(), options.report);
|
|
260
|
+
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
|
261
|
+
await fs.writeFile(outputPath, JSON.stringify(report, null, 2));
|
|
262
|
+
console.log(chalk.green(`Import report written to ${options.report}`));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
console.error(chalk.red('Import failed:'), error.message);
|
|
267
|
+
process.exitCode = 1;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=csv-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv-handler.js","sourceRoot":"","sources":["../../../src/commands/translate/csv-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translation execution logic with retry, batching, and placeholder validation
|
|
3
|
+
*/
|
|
4
|
+
import type { PlaceholderValidator, TranslationPlan, TranslationService } from '@i18nsmith/core';
|
|
5
|
+
import { type TranslatorLoadOptions } from '@i18nsmith/translation';
|
|
6
|
+
import type { TranslateLocaleResult } from './types.js';
|
|
7
|
+
export interface ExecuteTranslationsInput {
|
|
8
|
+
plan: TranslationPlan;
|
|
9
|
+
translationService: TranslationService;
|
|
10
|
+
provider: {
|
|
11
|
+
name: string;
|
|
12
|
+
loaderOptions: TranslatorLoadOptions;
|
|
13
|
+
};
|
|
14
|
+
overwrite: boolean;
|
|
15
|
+
skipEmpty: boolean;
|
|
16
|
+
placeholderValidator: PlaceholderValidator;
|
|
17
|
+
strictPlaceholders: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface ExecuteTranslationsResult {
|
|
20
|
+
results: TranslateLocaleResult[];
|
|
21
|
+
stats: Awaited<ReturnType<TranslationService['flush']>>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Execute translations for all locales in the plan
|
|
25
|
+
*/
|
|
26
|
+
export declare function executeTranslations(input: ExecuteTranslationsInput): Promise<ExecuteTranslationsResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Split an array into chunks of a given size
|
|
29
|
+
*/
|
|
30
|
+
export declare function chunkTasks<T>(items: T[], size: number): T[][];
|
|
31
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/commands/translate/executor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,kBAAkB,EAAyB,MAAM,iBAAiB,CAAC;AACxH,OAAO,EAAmC,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACrG,OAAO,KAAK,EAAE,qBAAqB,EAAoB,MAAM,YAAY,CAAC;AAE1E,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,eAAe,CAAC;IACtB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,qBAAqB,CAAC;KACtC,CAAC;IACF,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;CACzD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,yBAAyB,CAAC,CAyCpC;AAoGD;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,CAS7D"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translation execution logic with retry, batching, and placeholder validation
|
|
3
|
+
*/
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import pLimit from 'p-limit';
|
|
6
|
+
import pRetry from 'p-retry';
|
|
7
|
+
import { loadTranslator } from '@i18nsmith/translation';
|
|
8
|
+
/**
|
|
9
|
+
* Execute translations for all locales in the plan
|
|
10
|
+
*/
|
|
11
|
+
export async function executeTranslations(input) {
|
|
12
|
+
const translator = await loadTranslator(input.provider.loaderOptions);
|
|
13
|
+
const results = [];
|
|
14
|
+
const limit = pLimit(input.provider.loaderOptions.concurrency ?? 4);
|
|
15
|
+
try {
|
|
16
|
+
const translationPromises = input.plan.locales.map((localePlan) => limit(async () => {
|
|
17
|
+
const { updates, placeholderIssues } = await translateLocalePlan(translator, localePlan, input.plan.sourceLocale, input.provider.loaderOptions.batchSize ?? 25, input.placeholderValidator, input.strictPlaceholders);
|
|
18
|
+
const writeSummary = await input.translationService.writeTranslations(localePlan.locale, updates, {
|
|
19
|
+
overwrite: input.overwrite,
|
|
20
|
+
skipEmpty: input.skipEmpty,
|
|
21
|
+
});
|
|
22
|
+
results.push({
|
|
23
|
+
...writeSummary,
|
|
24
|
+
characters: localePlan.totalCharacters,
|
|
25
|
+
placeholderIssues,
|
|
26
|
+
});
|
|
27
|
+
}));
|
|
28
|
+
await Promise.all(translationPromises);
|
|
29
|
+
const stats = await input.translationService.flush();
|
|
30
|
+
// Sort results to match the plan's locale order for consistent output
|
|
31
|
+
results.sort((a, b) => {
|
|
32
|
+
const aIndex = input.plan.locales.findIndex((p) => p.locale === a.locale);
|
|
33
|
+
const bIndex = input.plan.locales.findIndex((p) => p.locale === b.locale);
|
|
34
|
+
return aIndex - bIndex;
|
|
35
|
+
});
|
|
36
|
+
return { results, stats };
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
await translator.dispose?.();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Translate a single locale plan with batching and retry logic
|
|
44
|
+
*/
|
|
45
|
+
async function translateLocalePlan(translator, localePlan, sourceLocale, batchSize, placeholderValidator, strictPlaceholders) {
|
|
46
|
+
const updates = [];
|
|
47
|
+
const placeholderIssues = [];
|
|
48
|
+
for (const chunk of chunkTasks(localePlan.tasks, batchSize)) {
|
|
49
|
+
const translationMap = new Map();
|
|
50
|
+
// Pre-fill with reused values
|
|
51
|
+
chunk.forEach((task) => {
|
|
52
|
+
if (task.reusedValue) {
|
|
53
|
+
translationMap.set(task.key, task.reusedValue.value);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const tasksRequiringTranslation = chunk.filter((task) => !task.reusedValue);
|
|
57
|
+
if (tasksRequiringTranslation.length > 0) {
|
|
58
|
+
const sourceTexts = tasksRequiringTranslation.map((task) => task.sourceValue);
|
|
59
|
+
const translated = await pRetry(() => translator.translate(sourceTexts, sourceLocale, localePlan.locale), {
|
|
60
|
+
retries: 3,
|
|
61
|
+
onFailedAttempt: (error) => {
|
|
62
|
+
console.log(chalk.yellow(`Attempt ${error.attemptNumber} failed translating ${localePlan.locale}. There are ${error.retriesLeft} retries left.`));
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
if (!Array.isArray(translated) || translated.length !== sourceTexts.length) {
|
|
66
|
+
throw new Error(`Translator returned ${translated.length} result(s) for ${sourceTexts.length} input(s) while translating ${localePlan.locale}.`);
|
|
67
|
+
}
|
|
68
|
+
tasksRequiringTranslation.forEach((task, index) => {
|
|
69
|
+
const candidate = translated[index] ?? '';
|
|
70
|
+
const comparison = placeholderValidator.compare(task.sourceValue, candidate ?? '');
|
|
71
|
+
if (task.placeholders.length && comparison.missing.length) {
|
|
72
|
+
placeholderIssues.push({
|
|
73
|
+
key: task.key,
|
|
74
|
+
locale: localePlan.locale,
|
|
75
|
+
type: 'missing',
|
|
76
|
+
placeholders: comparison.missing,
|
|
77
|
+
});
|
|
78
|
+
if (!strictPlaceholders) {
|
|
79
|
+
console.log(chalk.yellow(`Translator output for ${task.key} (${localePlan.locale}) is missing placeholder${comparison.missing.length === 1 ? '' : 's'}: ${comparison.missing.join(', ')}. Falling back to source text.`));
|
|
80
|
+
}
|
|
81
|
+
translationMap.set(task.key, task.sourceValue);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (comparison.extra.length) {
|
|
85
|
+
placeholderIssues.push({
|
|
86
|
+
key: task.key,
|
|
87
|
+
locale: localePlan.locale,
|
|
88
|
+
type: 'extra',
|
|
89
|
+
placeholders: comparison.extra,
|
|
90
|
+
});
|
|
91
|
+
if (!strictPlaceholders) {
|
|
92
|
+
console.log(chalk.yellow(`Translator output for ${task.key} (${localePlan.locale}) introduced unexpected placeholder${comparison.extra.length === 1 ? '' : 's'}: ${comparison.extra.join(', ')}`));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
translationMap.set(task.key, candidate ?? '');
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
chunk.forEach((task) => {
|
|
99
|
+
updates.push({ key: task.key, value: translationMap.get(task.key) ?? '' });
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return { updates, placeholderIssues };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Split an array into chunks of a given size
|
|
106
|
+
*/
|
|
107
|
+
export function chunkTasks(items, size) {
|
|
108
|
+
if (size <= 0) {
|
|
109
|
+
return [items];
|
|
110
|
+
}
|
|
111
|
+
const result = [];
|
|
112
|
+
for (let i = 0; i < items.length; i += size) {
|
|
113
|
+
result.push(items.slice(i, i + size));
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../src/commands/translate/executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate command - fill missing locale entries via translation adapters
|
|
3
|
+
*/
|
|
4
|
+
import type { Command } from 'commander';
|
|
5
|
+
export * from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Register the translate command
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerTranslate(program: Command): void;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/translate/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBzC,cAAc,YAAY,CAAC;AAyD3B;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwIxD"}
|