gtx-cli 2.4.15 → 2.5.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/collectUserEditDiffs.d.ts +2 -7
- package/dist/api/collectUserEditDiffs.js +33 -78
- package/dist/api/downloadFileBatch.d.ts +11 -10
- package/dist/api/downloadFileBatch.js +120 -127
- package/dist/api/saveLocalEdits.js +18 -15
- package/dist/cli/base.js +1 -1
- package/dist/cli/commands/stage.d.ts +8 -2
- package/dist/cli/commands/stage.js +25 -7
- package/dist/cli/commands/translate.d.ts +4 -2
- package/dist/cli/commands/translate.js +5 -6
- package/dist/cli/flags.js +4 -1
- package/dist/config/generateSettings.js +10 -0
- package/dist/console/logging.d.ts +1 -1
- package/dist/console/logging.js +3 -4
- package/dist/formats/files/translate.d.ts +2 -2
- package/dist/formats/files/translate.js +12 -7
- package/dist/fs/config/downloadedVersions.d.ts +10 -3
- package/dist/fs/config/downloadedVersions.js +8 -0
- package/dist/fs/config/updateVersions.d.ts +2 -1
- package/dist/git/branches.d.ts +7 -0
- package/dist/git/branches.js +88 -0
- package/dist/types/branch.d.ts +14 -0
- package/dist/types/branch.js +1 -0
- package/dist/types/data.d.ts +1 -1
- package/dist/types/files.d.ts +7 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/utils/SpinnerManager.d.ts +30 -0
- package/dist/utils/SpinnerManager.js +73 -0
- package/dist/utils/gitDiff.js +18 -16
- package/dist/workflow/BranchStep.d.ts +13 -0
- package/dist/workflow/BranchStep.js +131 -0
- package/dist/workflow/DownloadStep.d.ts +19 -0
- package/dist/workflow/DownloadStep.js +127 -0
- package/dist/workflow/EnqueueStep.d.ts +15 -0
- package/dist/workflow/EnqueueStep.js +33 -0
- package/dist/workflow/PollJobsStep.d.ts +31 -0
- package/dist/workflow/PollJobsStep.js +284 -0
- package/dist/workflow/SetupStep.d.ts +16 -0
- package/dist/workflow/SetupStep.js +71 -0
- package/dist/workflow/UploadStep.d.ts +21 -0
- package/dist/workflow/UploadStep.js +72 -0
- package/dist/workflow/UserEditDiffsStep.d.ts +11 -0
- package/dist/workflow/UserEditDiffsStep.js +30 -0
- package/dist/workflow/Workflow.d.ts +4 -0
- package/dist/workflow/Workflow.js +2 -0
- package/dist/workflow/download.d.ts +22 -0
- package/dist/workflow/download.js +104 -0
- package/dist/workflow/stage.d.ts +14 -0
- package/dist/workflow/stage.js +76 -0
- package/package.json +4 -5
- package/dist/api/checkFileTranslations.d.ts +0 -23
- package/dist/api/checkFileTranslations.js +0 -281
- package/dist/api/sendFiles.d.ts +0 -17
- package/dist/api/sendFiles.js +0 -127
- package/dist/api/sendUserEdits.d.ts +0 -19
- package/dist/api/sendUserEdits.js +0 -15
- package/dist/cli/commands/edits.d.ts +0 -8
- package/dist/cli/commands/edits.js +0 -32
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { WorkflowStep } from './Workflow.js';
|
|
2
|
+
import { createSpinner } from '../console/logging.js';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
export class SetupStep extends WorkflowStep {
|
|
5
|
+
gt;
|
|
6
|
+
settings;
|
|
7
|
+
timeoutMs;
|
|
8
|
+
spinner = createSpinner('dots');
|
|
9
|
+
setupJobId = null;
|
|
10
|
+
files = null;
|
|
11
|
+
completed = false;
|
|
12
|
+
constructor(gt, settings, timeoutMs) {
|
|
13
|
+
super();
|
|
14
|
+
this.gt = gt;
|
|
15
|
+
this.settings = settings;
|
|
16
|
+
this.timeoutMs = timeoutMs;
|
|
17
|
+
}
|
|
18
|
+
async run(files) {
|
|
19
|
+
this.files = files;
|
|
20
|
+
this.spinner.start('Setting up project...');
|
|
21
|
+
if (files.length === 0) {
|
|
22
|
+
this.completed = true;
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
const result = await this.gt.setupProject(files, {
|
|
26
|
+
locales: this.settings.locales,
|
|
27
|
+
});
|
|
28
|
+
if (result.status === 'completed') {
|
|
29
|
+
this.completed = true;
|
|
30
|
+
return files;
|
|
31
|
+
}
|
|
32
|
+
if (result.status === 'queued') {
|
|
33
|
+
this.setupJobId = result.setupJobId;
|
|
34
|
+
return files;
|
|
35
|
+
}
|
|
36
|
+
// Unknown status
|
|
37
|
+
this.completed = true;
|
|
38
|
+
return files;
|
|
39
|
+
}
|
|
40
|
+
async wait() {
|
|
41
|
+
if (this.completed) {
|
|
42
|
+
this.spinner.stop(chalk.green('Setup successfully completed'));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (!this.setupJobId) {
|
|
46
|
+
this.spinner.stop(chalk.yellow('Setup status unknown — proceeding without setup'));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Poll for completion
|
|
50
|
+
const start = Date.now();
|
|
51
|
+
const pollInterval = 5000; // 5 seconds
|
|
52
|
+
while (Date.now() - start < this.timeoutMs) {
|
|
53
|
+
const status = await this.gt.checkJobStatus([this.setupJobId]);
|
|
54
|
+
if (!status[0]) {
|
|
55
|
+
this.spinner.stop(chalk.yellow('Setup status unknown — proceeding without setup'));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (status[0].status === 'completed') {
|
|
59
|
+
this.spinner.stop(chalk.green('Setup successfully completed'));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (status[0].status === 'failed') {
|
|
63
|
+
this.spinner.stop(chalk.yellow(`Setup failed: ${status[0].error?.message || 'Unknown error'} — proceeding without setup`));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
await new Promise((r) => setTimeout(r, pollInterval));
|
|
67
|
+
}
|
|
68
|
+
// Timeout
|
|
69
|
+
this.spinner.stop(chalk.yellow('Setup timed out — proceeding without setup'));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FileToUpload } from 'generaltranslation/types';
|
|
2
|
+
import { WorkflowStep } from './Workflow.js';
|
|
3
|
+
import { GT } from 'generaltranslation';
|
|
4
|
+
import { Settings } from '../types/index.js';
|
|
5
|
+
import { BranchData } from '../types/branch.js';
|
|
6
|
+
import type { FileReference } from 'generaltranslation/types';
|
|
7
|
+
export declare class UploadStep extends WorkflowStep<{
|
|
8
|
+
files: FileToUpload[];
|
|
9
|
+
branchData: BranchData;
|
|
10
|
+
}, FileReference[]> {
|
|
11
|
+
private gt;
|
|
12
|
+
private settings;
|
|
13
|
+
private spinner;
|
|
14
|
+
private result;
|
|
15
|
+
constructor(gt: GT, settings: Settings);
|
|
16
|
+
run({ files, branchData, }: {
|
|
17
|
+
files: FileToUpload[];
|
|
18
|
+
branchData: BranchData;
|
|
19
|
+
}): Promise<FileReference[]>;
|
|
20
|
+
wait(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { WorkflowStep } from './Workflow.js';
|
|
2
|
+
import { createSpinner, logInfo } from '../console/logging.js';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
export class UploadStep extends WorkflowStep {
|
|
5
|
+
gt;
|
|
6
|
+
settings;
|
|
7
|
+
spinner = createSpinner('dots');
|
|
8
|
+
result = null;
|
|
9
|
+
constructor(gt, settings) {
|
|
10
|
+
super();
|
|
11
|
+
this.gt = gt;
|
|
12
|
+
this.settings = settings;
|
|
13
|
+
}
|
|
14
|
+
async run({ files, branchData, }) {
|
|
15
|
+
if (files.length === 0) {
|
|
16
|
+
logInfo('No files to upload found... skipping upload step');
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
this.spinner.start(`Syncing ${files.length} file${files.length !== 1 ? 's' : ''} with General Translation API...`);
|
|
20
|
+
// First, figure out which files need to be uploaded
|
|
21
|
+
const fileData = await this.gt.queryFileData({
|
|
22
|
+
sourceFiles: files.map((f) => ({
|
|
23
|
+
fileId: f.fileId,
|
|
24
|
+
versionId: f.versionId,
|
|
25
|
+
branchId: f.branchId ?? branchData.currentBranch.id,
|
|
26
|
+
})),
|
|
27
|
+
});
|
|
28
|
+
// build a map of branch:fileId:versionId to fileData
|
|
29
|
+
const fileDataMap = new Map();
|
|
30
|
+
fileData.sourceFiles?.forEach((f) => {
|
|
31
|
+
fileDataMap.set(`${f.branchId}:${f.fileId}:${f.versionId}`, f);
|
|
32
|
+
});
|
|
33
|
+
// Build a list of files that need to be uploaded
|
|
34
|
+
const filesToUpload = [];
|
|
35
|
+
const filesToSkipUpload = [];
|
|
36
|
+
files.forEach((f) => {
|
|
37
|
+
if (fileDataMap.has(`${f.branchId ?? branchData.currentBranch.id}:${f.fileId}:${f.versionId}`)) {
|
|
38
|
+
filesToSkipUpload.push(f);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
filesToUpload.push(f);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
const response = await this.gt.uploadSourceFiles(filesToUpload.map((f) => ({
|
|
45
|
+
source: {
|
|
46
|
+
...f,
|
|
47
|
+
branchId: f.branchId ?? branchData.currentBranch.id,
|
|
48
|
+
locale: this.settings.defaultLocale,
|
|
49
|
+
incomingBranchId: branchData.incomingBranch?.id,
|
|
50
|
+
checkedOutBranchId: branchData.checkedOutBranch?.id,
|
|
51
|
+
},
|
|
52
|
+
})), {
|
|
53
|
+
sourceLocale: this.settings.defaultLocale,
|
|
54
|
+
modelProvider: this.settings.modelProvider,
|
|
55
|
+
});
|
|
56
|
+
this.result = response.uploadedFiles;
|
|
57
|
+
// Merge files that were already uploaded into the result
|
|
58
|
+
this.result.push(...filesToSkipUpload.map((f) => ({
|
|
59
|
+
fileId: f.fileId,
|
|
60
|
+
versionId: f.versionId,
|
|
61
|
+
branchId: f.branchId ?? branchData.currentBranch.id,
|
|
62
|
+
fileName: f.fileName,
|
|
63
|
+
fileFormat: f.fileFormat,
|
|
64
|
+
dataFormat: f.dataFormat,
|
|
65
|
+
})));
|
|
66
|
+
this.spinner.stop(chalk.green('Files uploaded successfully'));
|
|
67
|
+
return this.result;
|
|
68
|
+
}
|
|
69
|
+
async wait() {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FileReference } from 'generaltranslation/types';
|
|
2
|
+
import { WorkflowStep } from './Workflow.js';
|
|
3
|
+
import { Settings } from '../types/index.js';
|
|
4
|
+
export declare class UserEditDiffsStep extends WorkflowStep<FileReference[], FileReference[]> {
|
|
5
|
+
private settings;
|
|
6
|
+
private spinner;
|
|
7
|
+
private completed;
|
|
8
|
+
constructor(settings: Settings);
|
|
9
|
+
run(files: FileReference[]): Promise<FileReference[]>;
|
|
10
|
+
wait(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { WorkflowStep } from './Workflow.js';
|
|
2
|
+
import { createSpinner } from '../console/logging.js';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { collectAndSendUserEditDiffs } from '../api/collectUserEditDiffs.js';
|
|
5
|
+
export class UserEditDiffsStep extends WorkflowStep {
|
|
6
|
+
settings;
|
|
7
|
+
spinner = createSpinner('dots');
|
|
8
|
+
completed = false;
|
|
9
|
+
constructor(settings) {
|
|
10
|
+
super();
|
|
11
|
+
this.settings = settings;
|
|
12
|
+
}
|
|
13
|
+
async run(files) {
|
|
14
|
+
this.spinner.start('Updating translations...');
|
|
15
|
+
try {
|
|
16
|
+
await collectAndSendUserEditDiffs(files, this.settings);
|
|
17
|
+
this.completed = true;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// Non-fatal; keep going to enqueue
|
|
21
|
+
this.completed = true;
|
|
22
|
+
}
|
|
23
|
+
return files;
|
|
24
|
+
}
|
|
25
|
+
async wait() {
|
|
26
|
+
if (this.completed) {
|
|
27
|
+
this.spinner.stop(chalk.green('Updated translations'));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Settings } from '../types/index.js';
|
|
2
|
+
import { EnqueueFilesResult } from 'generaltranslation/types';
|
|
3
|
+
import { BranchData } from '../types/branch.js';
|
|
4
|
+
export type FileTranslationData = {
|
|
5
|
+
[fileId: string]: {
|
|
6
|
+
versionId: string;
|
|
7
|
+
fileName: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Checks the status of translations and downloads them using a workflow pattern
|
|
12
|
+
* @param fileVersionData - Mapping of file IDs to their version and name information
|
|
13
|
+
* @param jobData - Optional job data from enqueue operation
|
|
14
|
+
* @param locales - The locales to wait for
|
|
15
|
+
* @param timeoutDuration - The timeout duration for the wait in seconds
|
|
16
|
+
* @param resolveOutputPath - Function to resolve the output path for a given source path and locale
|
|
17
|
+
* @param options - Settings configuration
|
|
18
|
+
* @param forceRetranslation - Whether to force retranslation
|
|
19
|
+
* @param forceDownload - Whether to force download even if file exists
|
|
20
|
+
* @returns True if all translations are downloaded successfully, false otherwise
|
|
21
|
+
*/
|
|
22
|
+
export declare function downloadTranslations(fileVersionData: FileTranslationData, jobData: EnqueueFilesResult | undefined, branchData: BranchData | undefined, locales: string[], timeoutDuration: number, resolveOutputPath: (sourcePath: string, locale: string) => string | null, options: Settings, forceRetranslation?: boolean, forceDownload?: boolean): Promise<boolean>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { gt } from '../utils/gt.js';
|
|
3
|
+
import { clearLocaleDirs } from '../fs/clearLocaleDirs.js';
|
|
4
|
+
import { PollTranslationJobsStep } from './PollJobsStep.js';
|
|
5
|
+
import { DownloadTranslationsStep } from './DownloadStep.js';
|
|
6
|
+
import { logErrorAndExit } from '../console/logging.js';
|
|
7
|
+
import { BranchStep } from './BranchStep.js';
|
|
8
|
+
/**
|
|
9
|
+
* Checks the status of translations and downloads them using a workflow pattern
|
|
10
|
+
* @param fileVersionData - Mapping of file IDs to their version and name information
|
|
11
|
+
* @param jobData - Optional job data from enqueue operation
|
|
12
|
+
* @param locales - The locales to wait for
|
|
13
|
+
* @param timeoutDuration - The timeout duration for the wait in seconds
|
|
14
|
+
* @param resolveOutputPath - Function to resolve the output path for a given source path and locale
|
|
15
|
+
* @param options - Settings configuration
|
|
16
|
+
* @param forceRetranslation - Whether to force retranslation
|
|
17
|
+
* @param forceDownload - Whether to force download even if file exists
|
|
18
|
+
* @returns True if all translations are downloaded successfully, false otherwise
|
|
19
|
+
*/
|
|
20
|
+
export async function downloadTranslations(fileVersionData, jobData, branchData, locales, timeoutDuration, resolveOutputPath, options, forceRetranslation, forceDownload) {
|
|
21
|
+
if (!branchData) {
|
|
22
|
+
// Run the branch step
|
|
23
|
+
const branchStep = new BranchStep(gt, options);
|
|
24
|
+
const branchResult = await branchStep.run();
|
|
25
|
+
await branchStep.wait();
|
|
26
|
+
if (!branchResult) {
|
|
27
|
+
logErrorAndExit('Failed to resolve git branch information.');
|
|
28
|
+
}
|
|
29
|
+
branchData = branchResult;
|
|
30
|
+
}
|
|
31
|
+
// Prepare the query data
|
|
32
|
+
const fileQueryData = prepareFileQueryData(fileVersionData, locales, branchData);
|
|
33
|
+
// Clear translated files before any downloads (if enabled)
|
|
34
|
+
if (options.options?.experimentalClearLocaleDirs === true &&
|
|
35
|
+
fileQueryData.length > 0) {
|
|
36
|
+
const translatedFiles = new Set(fileQueryData
|
|
37
|
+
.map((file) => {
|
|
38
|
+
const outputPath = resolveOutputPath(file.fileName, file.locale);
|
|
39
|
+
// Only clear if the output path is different from the source (i.e., there's a transform)
|
|
40
|
+
return outputPath !== null && outputPath !== file.fileName
|
|
41
|
+
? outputPath
|
|
42
|
+
: null;
|
|
43
|
+
})
|
|
44
|
+
.filter((path) => path !== null));
|
|
45
|
+
// Derive cwd from config path
|
|
46
|
+
const cwd = path.dirname(options.config);
|
|
47
|
+
await clearLocaleDirs(translatedFiles, locales, options.options?.clearLocaleDirsExclude, cwd);
|
|
48
|
+
}
|
|
49
|
+
// Initialize download status
|
|
50
|
+
const fileTracker = {
|
|
51
|
+
completed: new Map(),
|
|
52
|
+
inProgress: new Map(),
|
|
53
|
+
failed: new Map(),
|
|
54
|
+
skipped: new Map(),
|
|
55
|
+
};
|
|
56
|
+
// Step 1: Poll translation jobs if jobData exists
|
|
57
|
+
if (jobData) {
|
|
58
|
+
const pollStep = new PollTranslationJobsStep(gt);
|
|
59
|
+
const pollResult = await pollStep.run({
|
|
60
|
+
fileTracker,
|
|
61
|
+
fileQueryData,
|
|
62
|
+
jobData,
|
|
63
|
+
timeoutDuration,
|
|
64
|
+
forceRetranslation,
|
|
65
|
+
});
|
|
66
|
+
await pollStep.wait();
|
|
67
|
+
if (!pollResult.success) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
for (const file of fileQueryData) {
|
|
73
|
+
// Staging - assume all files are completed
|
|
74
|
+
fileTracker.completed.set(`${file.branchId}:${file.fileId}:${file.versionId}:${file.locale}`, file);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Step 2: Download translations
|
|
78
|
+
const downloadStep = new DownloadTranslationsStep(gt, options);
|
|
79
|
+
const downloadResult = await downloadStep.run({
|
|
80
|
+
fileTracker,
|
|
81
|
+
resolveOutputPath,
|
|
82
|
+
forceDownload,
|
|
83
|
+
});
|
|
84
|
+
await downloadStep.wait();
|
|
85
|
+
return downloadResult;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Prepares the file query data from input data and locales
|
|
89
|
+
*/
|
|
90
|
+
function prepareFileQueryData(fileVersionData, locales, branchData) {
|
|
91
|
+
const fileQueryData = [];
|
|
92
|
+
for (const fileId in fileVersionData) {
|
|
93
|
+
for (const locale of locales) {
|
|
94
|
+
fileQueryData.push({
|
|
95
|
+
versionId: fileVersionData[fileId].versionId,
|
|
96
|
+
fileName: fileVersionData[fileId].fileName,
|
|
97
|
+
fileId,
|
|
98
|
+
locale,
|
|
99
|
+
branchId: branchData.currentBranch.id,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return fileQueryData;
|
|
104
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Settings, TranslateFlags } from '../types/index.js';
|
|
2
|
+
import { EnqueueFilesResult, FileToUpload } from 'generaltranslation/types';
|
|
3
|
+
import { BranchData } from '../types/branch.js';
|
|
4
|
+
/**
|
|
5
|
+
* Sends multiple files for translation to the API using a workflow pattern
|
|
6
|
+
* @param files - Array of file objects to translate
|
|
7
|
+
* @param options - The options for the API call
|
|
8
|
+
* @param settings - Settings configuration
|
|
9
|
+
* @returns The translated content or version ID
|
|
10
|
+
*/
|
|
11
|
+
export declare function stageFiles(files: FileToUpload[], options: TranslateFlags, settings: Settings): Promise<{
|
|
12
|
+
branchData: BranchData;
|
|
13
|
+
enqueueResult: EnqueueFilesResult;
|
|
14
|
+
}>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { logErrorAndExit, logMessage } from '../console/logging.js';
|
|
3
|
+
import { gt } from '../utils/gt.js';
|
|
4
|
+
import { TEMPLATE_FILE_NAME } from '../cli/commands/stage.js';
|
|
5
|
+
import { UploadStep } from './UploadStep.js';
|
|
6
|
+
import { SetupStep } from './SetupStep.js';
|
|
7
|
+
import { EnqueueStep } from './EnqueueStep.js';
|
|
8
|
+
import { BranchStep } from './BranchStep.js';
|
|
9
|
+
import { UserEditDiffsStep } from './UserEditDiffsStep.js';
|
|
10
|
+
/**
|
|
11
|
+
* Helper: Calculate timeout with validation
|
|
12
|
+
*/
|
|
13
|
+
function calculateTimeout(timeout) {
|
|
14
|
+
const value = timeout !== undefined ? Number(timeout) : 600;
|
|
15
|
+
return (Number.isFinite(value) ? value : 600) * 1000;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Helper: Log files to be translated
|
|
19
|
+
*/
|
|
20
|
+
function logFilesToTranslate(files) {
|
|
21
|
+
logMessage(chalk.cyan('Files found in project:') +
|
|
22
|
+
'\n' +
|
|
23
|
+
files
|
|
24
|
+
.map((file) => {
|
|
25
|
+
if (file.fileName === TEMPLATE_FILE_NAME) {
|
|
26
|
+
return `- <React Elements>`;
|
|
27
|
+
}
|
|
28
|
+
return `- ${file.fileName}`;
|
|
29
|
+
})
|
|
30
|
+
.join('\n'));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Sends multiple files for translation to the API using a workflow pattern
|
|
34
|
+
* @param files - Array of file objects to translate
|
|
35
|
+
* @param options - The options for the API call
|
|
36
|
+
* @param settings - Settings configuration
|
|
37
|
+
* @returns The translated content or version ID
|
|
38
|
+
*/
|
|
39
|
+
export async function stageFiles(files, options, settings) {
|
|
40
|
+
try {
|
|
41
|
+
// Log files to be translated
|
|
42
|
+
logFilesToTranslate(files);
|
|
43
|
+
// Calculate timeout for setup step
|
|
44
|
+
const timeoutMs = calculateTimeout(options.timeout);
|
|
45
|
+
// Create workflow with steps
|
|
46
|
+
const branchStep = new BranchStep(gt, settings);
|
|
47
|
+
const uploadStep = new UploadStep(gt, settings);
|
|
48
|
+
const userEditDiffsStep = new UserEditDiffsStep(settings);
|
|
49
|
+
const setupStep = new SetupStep(gt, settings, timeoutMs);
|
|
50
|
+
const enqueueStep = new EnqueueStep(gt, settings, options.force);
|
|
51
|
+
// first run the branch step
|
|
52
|
+
const branchData = await branchStep.run();
|
|
53
|
+
await branchStep.wait();
|
|
54
|
+
if (!branchData) {
|
|
55
|
+
logErrorAndExit('Failed to resolve git branch information.');
|
|
56
|
+
}
|
|
57
|
+
// then run the upload step
|
|
58
|
+
const uploadedFiles = await uploadStep.run({ files, branchData });
|
|
59
|
+
await uploadStep.wait();
|
|
60
|
+
// optionally run the user edit diffs step
|
|
61
|
+
if (options?.saveLocal) {
|
|
62
|
+
await userEditDiffsStep.run(uploadedFiles);
|
|
63
|
+
await userEditDiffsStep.wait();
|
|
64
|
+
}
|
|
65
|
+
// then run the setup step
|
|
66
|
+
await setupStep.run(uploadedFiles);
|
|
67
|
+
await setupStep.wait();
|
|
68
|
+
// then run the enqueue step
|
|
69
|
+
const enqueueResult = await enqueueStep.run(uploadedFiles);
|
|
70
|
+
await enqueueStep.wait();
|
|
71
|
+
return { branchData, enqueueResult };
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
logErrorAndExit('Failed to send files for translation. ' + error);
|
|
75
|
+
}
|
|
76
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gtx-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0-alpha.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": "dist/main.js",
|
|
6
6
|
"files": [
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"@babel/parser": "^7.25.7",
|
|
68
68
|
"@babel/plugin-transform-react-jsx": "^7.25.9",
|
|
69
69
|
"@babel/traverse": "^7.25.7",
|
|
70
|
-
"@clack/prompts": "^1.0.0-alpha.
|
|
70
|
+
"@clack/prompts": "^1.0.0-alpha.6",
|
|
71
71
|
"@formatjs/icu-messageformat-parser": "^2.11.4",
|
|
72
72
|
"chalk": "^5.4.1",
|
|
73
73
|
"commander": "^12.1.0",
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
"fast-glob": "^3.3.3",
|
|
78
78
|
"fast-json-stable-stringify": "^2.1.0",
|
|
79
79
|
"form-data": "^4.0.4",
|
|
80
|
+
"generaltranslation": "8.0.0-alpha.1",
|
|
80
81
|
"gt-remark": "^1.0.1",
|
|
81
82
|
"json-pointer": "^0.6.2",
|
|
82
83
|
"jsonpath-plus": "^10.3.0",
|
|
@@ -84,7 +85,6 @@
|
|
|
84
85
|
"mdast-util-find-and-replace": "^3.0.2",
|
|
85
86
|
"micromatch": "^4.0.8",
|
|
86
87
|
"open": "^10.1.1",
|
|
87
|
-
"ora": "^8.2.0",
|
|
88
88
|
"remark-frontmatter": "^5.0.0",
|
|
89
89
|
"remark-mdx": "^3.1.0",
|
|
90
90
|
"remark-parse": "^11.0.0",
|
|
@@ -93,8 +93,7 @@
|
|
|
93
93
|
"tsconfig-paths": "^4.2.0",
|
|
94
94
|
"unified": "^11.0.5",
|
|
95
95
|
"unist-util-visit": "^5.0.0",
|
|
96
|
-
"yaml": "^2.8.0"
|
|
97
|
-
"generaltranslation": "7.9.1"
|
|
96
|
+
"yaml": "^2.8.0"
|
|
98
97
|
},
|
|
99
98
|
"devDependencies": {
|
|
100
99
|
"@babel/types": "^7.28.4",
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Settings } from '../types/index.js';
|
|
2
|
-
export type CheckFileTranslationData = {
|
|
3
|
-
[key: string]: {
|
|
4
|
-
versionId: string;
|
|
5
|
-
fileName: string;
|
|
6
|
-
};
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Checks the status of translations for a given version ID
|
|
10
|
-
* @param apiKey - The API key for the General Translation API
|
|
11
|
-
* @param baseUrl - The base URL for the General Translation API
|
|
12
|
-
* @param versionId - The version ID of the project
|
|
13
|
-
* @param locales - The locales to wait for
|
|
14
|
-
* @param startTime - The start time of the wait
|
|
15
|
-
* @param timeoutDuration - The timeout duration for the wait in seconds
|
|
16
|
-
* @returns True if all translations are deployed, false otherwise
|
|
17
|
-
*/
|
|
18
|
-
export declare function checkFileTranslations(data: {
|
|
19
|
-
[key: string]: {
|
|
20
|
-
versionId: string;
|
|
21
|
-
fileName: string;
|
|
22
|
-
};
|
|
23
|
-
}, locales: string[], timeoutDuration: number, resolveOutputPath: (sourcePath: string, locale: string) => string | null, options: Settings, forceRetranslation?: boolean, forceDownload?: boolean): Promise<boolean>;
|