gtx-cli 1.2.15 → 1.2.16
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/checkFileTranslations.d.ts +19 -0
- package/dist/api/checkFileTranslations.js +244 -0
- package/dist/api/downloadFile.d.ts +1 -0
- package/dist/api/downloadFile.js +83 -0
- package/dist/api/downloadFileBatch.d.ts +16 -0
- package/dist/api/downloadFileBatch.js +127 -0
- package/dist/api/fetchTranslations.d.ts +10 -0
- package/dist/api/fetchTranslations.js +35 -0
- package/dist/api/sendFiles.d.ts +24 -0
- package/dist/api/sendFiles.js +63 -0
- package/dist/api/sendUpdates.d.ts +19 -0
- package/dist/api/sendUpdates.js +75 -0
- package/dist/api/waitForUpdates.d.ts +11 -0
- package/dist/api/waitForUpdates.js +96 -0
- package/dist/cli/base.d.ts +28 -0
- package/dist/cli/base.js +322 -0
- package/dist/cli/next.d.ts +10 -0
- package/dist/cli/next.js +27 -0
- package/dist/cli/react.d.ts +18 -0
- package/dist/cli/react.js +305 -0
- package/dist/config/generateSettings.d.ts +7 -0
- package/dist/config/generateSettings.js +94 -0
- package/dist/config/utils.d.ts +2 -0
- package/dist/config/utils.js +7 -0
- package/dist/config/validateSettings.d.ts +2 -0
- package/dist/config/validateSettings.js +23 -0
- package/dist/console/colors.d.ts +5 -0
- package/dist/console/colors.js +26 -0
- package/dist/console/console.d.ts +1 -0
- package/dist/console/console.js +20 -0
- package/dist/console/errors.d.ts +1 -0
- package/dist/console/errors.js +20 -0
- package/dist/console/index.d.ts +19 -0
- package/dist/console/index.js +48 -0
- package/dist/console/logging.d.ts +55 -0
- package/dist/console/logging.js +207 -0
- package/dist/console/warnings.d.ts +1 -0
- package/dist/console/warnings.js +20 -0
- package/dist/formats/files/save.d.ts +5 -0
- package/dist/formats/files/save.js +23 -0
- package/dist/formats/files/supportedFiles.d.ts +8 -0
- package/dist/formats/files/supportedFiles.js +17 -0
- package/dist/formats/files/translate.d.ts +14 -0
- package/dist/formats/files/translate.js +218 -0
- package/dist/formats/gt/save.d.ts +10 -0
- package/dist/formats/gt/save.js +34 -0
- package/dist/fs/config/loadConfig.d.ts +1 -0
- package/dist/fs/config/loadConfig.js +15 -0
- package/dist/fs/config/parseFilesConfig.d.ts +23 -0
- package/dist/fs/config/parseFilesConfig.js +128 -0
- package/dist/fs/config/setupConfig.d.ts +15 -0
- package/dist/fs/config/setupConfig.js +51 -0
- package/dist/fs/config/updateConfig.d.ts +11 -0
- package/dist/fs/config/updateConfig.js +41 -0
- package/dist/fs/determineFramework.d.ts +5 -0
- package/dist/fs/determineFramework.js +52 -0
- package/dist/fs/findFilepath.d.ts +36 -0
- package/dist/fs/findFilepath.js +101 -0
- package/dist/fs/findJsxFilepath.d.ts +7 -0
- package/dist/fs/findJsxFilepath.js +36 -0
- package/dist/fs/index.d.ts +1 -0
- package/dist/fs/index.js +2 -0
- package/dist/fs/loadJSON.d.ts +6 -0
- package/dist/fs/loadJSON.js +23 -0
- package/dist/fs/saveJSON.d.ts +1 -0
- package/dist/fs/saveJSON.js +13 -0
- package/dist/fs/utils.d.ts +1 -0
- package/dist/fs/utils.js +19 -0
- package/dist/hooks/postProcess.d.ts +4 -0
- package/dist/hooks/postProcess.js +118 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +24 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +12 -0
- package/dist/next/config/parseNextConfig.d.ts +10 -0
- package/dist/next/config/parseNextConfig.js +59 -0
- package/dist/next/jsx/utils.d.ts +7 -0
- package/dist/next/jsx/utils.js +82 -0
- package/dist/next/parse/handleInitGT.d.ts +1 -0
- package/dist/next/parse/handleInitGT.js +153 -0
- package/dist/next/parse/wrapContent.d.ts +11 -0
- package/dist/next/parse/wrapContent.js +181 -0
- package/dist/react/config/createESBuildConfig.d.ts +2 -0
- package/dist/react/config/createESBuildConfig.js +125 -0
- package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.d.ts +1 -0
- package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.js +87 -0
- package/dist/react/jsx/evaluateJsx.d.ts +17 -0
- package/dist/react/jsx/evaluateJsx.js +133 -0
- package/dist/react/jsx/parse/parseStringFunction.d.ts +12 -0
- package/dist/react/jsx/parse/parseStringFunction.js +118 -0
- package/dist/react/jsx/trimJsxStringChildren.d.ts +7 -0
- package/dist/react/jsx/trimJsxStringChildren.js +100 -0
- package/dist/react/jsx/utils/parseAst.d.ts +30 -0
- package/dist/react/jsx/utils/parseAst.js +319 -0
- package/dist/react/jsx/utils/parseJsx.d.ts +13 -0
- package/dist/react/jsx/utils/parseJsx.js +250 -0
- package/dist/react/jsx/utils/parseStringFunction.d.ts +12 -0
- package/dist/react/jsx/utils/parseStringFunction.js +121 -0
- package/dist/react/jsx/wrapJsx.d.ts +51 -0
- package/dist/react/jsx/wrapJsx.js +411 -0
- package/dist/react/parse/createDictionaryUpdates.d.ts +3 -0
- package/dist/react/parse/createDictionaryUpdates.js +78 -0
- package/dist/react/parse/createInlineUpdates.d.ts +5 -0
- package/dist/react/parse/createInlineUpdates.js +135 -0
- package/dist/react/parse/wrapContent.d.ts +11 -0
- package/dist/react/parse/wrapContent.js +197 -0
- package/dist/react/utils/flattenDictionary.d.ts +20 -0
- package/dist/react/utils/flattenDictionary.js +79 -0
- package/dist/react/utils/getEntryAndMetadata.d.ts +5 -0
- package/dist/react/utils/getEntryAndMetadata.js +14 -0
- package/dist/react/utils/getVariableName.d.ts +2 -0
- package/dist/react/utils/getVariableName.js +17 -0
- package/dist/setup/userInput.d.ts +4 -0
- package/dist/setup/userInput.js +35 -0
- package/dist/setup/wizard.d.ts +2 -0
- package/dist/setup/wizard.js +171 -0
- package/dist/translation/parse.d.ts +14 -0
- package/dist/translation/parse.js +82 -0
- package/dist/translation/stage.d.ts +5 -0
- package/dist/translation/stage.js +80 -0
- package/dist/translation/translate.d.ts +2 -0
- package/dist/translation/translate.js +21 -0
- package/dist/types/api.d.ts +6 -0
- package/dist/types/api.js +2 -0
- package/dist/types/data.d.ts +31 -0
- package/dist/types/data.js +2 -0
- package/dist/types/index.d.ts +101 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.js +4 -0
- package/dist/utils/credentials.d.ts +12 -0
- package/dist/utils/credentials.js +128 -0
- package/dist/utils/installPackage.d.ts +2 -0
- package/dist/utils/installPackage.js +45 -0
- package/dist/utils/packageJson.d.ts +5 -0
- package/dist/utils/packageJson.js +78 -0
- package/dist/utils/packageManager.d.ts +23 -0
- package/dist/utils/packageManager.js +261 -0
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks the status of translations for a given version ID
|
|
3
|
+
* @param apiKey - The API key for the General Translation API
|
|
4
|
+
* @param baseUrl - The base URL for the General Translation API
|
|
5
|
+
* @param versionId - The version ID of the project
|
|
6
|
+
* @param locales - The locales to wait for
|
|
7
|
+
* @param startTime - The start time of the wait
|
|
8
|
+
* @param timeoutDuration - The timeout duration for the wait in seconds
|
|
9
|
+
* @returns True if all translations are deployed, false otherwise
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkFileTranslations(apiKey: string, baseUrl: string, data: {
|
|
12
|
+
[key: string]: {
|
|
13
|
+
versionId: string;
|
|
14
|
+
fileName: string;
|
|
15
|
+
};
|
|
16
|
+
}, locales: string[], timeoutDuration: number, resolveOutputPath: (sourcePath: string, locale: string) => string, downloadStatus: {
|
|
17
|
+
downloaded: Set<string>;
|
|
18
|
+
failed: Set<string>;
|
|
19
|
+
}): Promise<boolean>;
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.checkFileTranslations = checkFileTranslations;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const console_1 = require("../console");
|
|
9
|
+
const generaltranslation_1 = require("generaltranslation");
|
|
10
|
+
const downloadFile_1 = require("./downloadFile");
|
|
11
|
+
const downloadFileBatch_1 = require("./downloadFileBatch");
|
|
12
|
+
/**
|
|
13
|
+
* Checks the status of translations for a given version ID
|
|
14
|
+
* @param apiKey - The API key for the General Translation API
|
|
15
|
+
* @param baseUrl - The base URL for the General Translation API
|
|
16
|
+
* @param versionId - The version ID of the project
|
|
17
|
+
* @param locales - The locales to wait for
|
|
18
|
+
* @param startTime - The start time of the wait
|
|
19
|
+
* @param timeoutDuration - The timeout duration for the wait in seconds
|
|
20
|
+
* @returns True if all translations are deployed, false otherwise
|
|
21
|
+
*/
|
|
22
|
+
async function checkFileTranslations(apiKey, baseUrl, data, locales, timeoutDuration, resolveOutputPath, downloadStatus) {
|
|
23
|
+
const startTime = Date.now();
|
|
24
|
+
console.log();
|
|
25
|
+
const spinner = await (0, console_1.createOraSpinner)();
|
|
26
|
+
spinner.start('Waiting for translation...');
|
|
27
|
+
// Initialize the query data
|
|
28
|
+
const fileQueryData = prepareFileQueryData(data, locales);
|
|
29
|
+
// Do first check immediately
|
|
30
|
+
const initialCheck = await checkTranslationDeployment(baseUrl, apiKey, fileQueryData, downloadStatus, spinner, resolveOutputPath);
|
|
31
|
+
if (initialCheck) {
|
|
32
|
+
spinner.succeed(chalk_1.default.green('Files translated!'));
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
// Calculate time until next 5-second interval since startTime
|
|
36
|
+
const msUntilNextInterval = Math.max(0, 5000 - ((Date.now() - startTime) % 5000));
|
|
37
|
+
return new Promise((resolve) => {
|
|
38
|
+
let intervalCheck;
|
|
39
|
+
// Start the interval aligned with the original request time
|
|
40
|
+
setTimeout(() => {
|
|
41
|
+
intervalCheck = setInterval(async () => {
|
|
42
|
+
const isDeployed = await checkTranslationDeployment(baseUrl, apiKey, fileQueryData, downloadStatus, spinner, resolveOutputPath);
|
|
43
|
+
const elapsed = Date.now() - startTime;
|
|
44
|
+
if (isDeployed || elapsed >= timeoutDuration * 1000) {
|
|
45
|
+
clearInterval(intervalCheck);
|
|
46
|
+
if (isDeployed) {
|
|
47
|
+
spinner.succeed(chalk_1.default.green('All files translated!'));
|
|
48
|
+
resolve(true);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
spinner.fail(chalk_1.default.red('Timed out waiting for translations'));
|
|
52
|
+
resolve(false);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}, 5000);
|
|
56
|
+
}, msUntilNextInterval);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Prepares the file query data from input data and locales
|
|
61
|
+
*/
|
|
62
|
+
function prepareFileQueryData(data, locales) {
|
|
63
|
+
const fileQueryData = [];
|
|
64
|
+
for (const file in data) {
|
|
65
|
+
for (const locale of locales) {
|
|
66
|
+
fileQueryData.push({
|
|
67
|
+
versionId: data[file].versionId,
|
|
68
|
+
fileName: data[file].fileName,
|
|
69
|
+
locale,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return fileQueryData;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Generates a formatted status text showing translation progress
|
|
77
|
+
* @param downloadedFiles - Set of downloaded file+locale combinations
|
|
78
|
+
* @param fileQueryData - Array of file query data objects
|
|
79
|
+
* @returns Formatted status text
|
|
80
|
+
*/
|
|
81
|
+
function generateStatusSuffixText(downloadStatus, fileQueryData) {
|
|
82
|
+
// Simple progress indicator
|
|
83
|
+
const progressText = chalk_1.default.green(`[${downloadStatus.downloaded.size + downloadStatus.failed.size}/${fileQueryData.length}]`) + ` translations completed`;
|
|
84
|
+
// Get terminal height to adapt our output
|
|
85
|
+
const terminalHeight = process.stdout.rows || 24; // Default to 24 if undefined
|
|
86
|
+
// If terminal is very small, just show the basic progress
|
|
87
|
+
if (terminalHeight < 6) {
|
|
88
|
+
return `${progressText}`;
|
|
89
|
+
}
|
|
90
|
+
const newSuffixText = [`${progressText}`];
|
|
91
|
+
// Organize data by filename
|
|
92
|
+
const fileStatus = new Map();
|
|
93
|
+
// Initialize with all files and locales from fileQueryData
|
|
94
|
+
for (const item of fileQueryData) {
|
|
95
|
+
if (!fileStatus.has(item.fileName)) {
|
|
96
|
+
fileStatus.set(item.fileName, {
|
|
97
|
+
completed: new Set(),
|
|
98
|
+
pending: new Set([item.locale]),
|
|
99
|
+
failed: new Set(),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
fileStatus.get(item.fileName)?.pending.add(item.locale);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Mark which ones are completed or failed
|
|
107
|
+
for (const fileLocale of downloadStatus.downloaded) {
|
|
108
|
+
const [fileName, locale] = fileLocale.split(':');
|
|
109
|
+
const status = fileStatus.get(fileName);
|
|
110
|
+
if (status) {
|
|
111
|
+
status.pending.delete(locale);
|
|
112
|
+
status.completed.add(locale);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
for (const fileLocale of downloadStatus.failed) {
|
|
116
|
+
const [fileName, locale] = fileLocale.split(':');
|
|
117
|
+
const status = fileStatus.get(fileName);
|
|
118
|
+
if (status) {
|
|
119
|
+
status.pending.delete(locale);
|
|
120
|
+
status.failed.add(locale);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Calculate how many files we can show based on terminal height
|
|
124
|
+
const filesArray = Array.from(fileStatus.entries());
|
|
125
|
+
const maxFilesToShow = Math.min(filesArray.length, terminalHeight - 3 // Header + progress + buffer
|
|
126
|
+
);
|
|
127
|
+
// Display each file with its status on a single line
|
|
128
|
+
for (let i = 0; i < maxFilesToShow; i++) {
|
|
129
|
+
const [fileName, status] = filesArray[i];
|
|
130
|
+
// Create condensed locale status
|
|
131
|
+
const localeStatuses = [];
|
|
132
|
+
// Add completed locales
|
|
133
|
+
if (status.completed.size > 0) {
|
|
134
|
+
const completedCodes = Array.from(status.completed)
|
|
135
|
+
.map((locale) => (0, generaltranslation_1.getLocaleProperties)(locale).code)
|
|
136
|
+
.join(', ');
|
|
137
|
+
localeStatuses.push(chalk_1.default.green(`${completedCodes}`));
|
|
138
|
+
}
|
|
139
|
+
// Add failed locales
|
|
140
|
+
if (status.failed.size > 0) {
|
|
141
|
+
const failedCodes = Array.from(status.failed)
|
|
142
|
+
.map((locale) => (0, generaltranslation_1.getLocaleProperties)(locale).code)
|
|
143
|
+
.join(', ');
|
|
144
|
+
localeStatuses.push(chalk_1.default.red(`${failedCodes}`));
|
|
145
|
+
}
|
|
146
|
+
// Add pending locales
|
|
147
|
+
if (status.pending.size > 0) {
|
|
148
|
+
const pendingCodes = Array.from(status.pending)
|
|
149
|
+
.map((locale) => (0, generaltranslation_1.getLocaleProperties)(locale).code)
|
|
150
|
+
.join(', ');
|
|
151
|
+
localeStatuses.push(chalk_1.default.yellow(`${pendingCodes}`));
|
|
152
|
+
}
|
|
153
|
+
// Format the line
|
|
154
|
+
newSuffixText.push(`${chalk_1.default.bold(fileName)} [${localeStatuses.join(', ')}]`);
|
|
155
|
+
}
|
|
156
|
+
// If we couldn't show all files, add an indicator
|
|
157
|
+
if (filesArray.length > maxFilesToShow) {
|
|
158
|
+
newSuffixText.push(`... and ${filesArray.length - maxFilesToShow} more files`);
|
|
159
|
+
}
|
|
160
|
+
return newSuffixText.join('\n');
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Checks translation status and downloads ready files
|
|
164
|
+
*/
|
|
165
|
+
async function checkTranslationDeployment(baseUrl, apiKey, fileQueryData, downloadStatus, spinner, resolveOutputPath) {
|
|
166
|
+
try {
|
|
167
|
+
// Only query for files that haven't been downloaded yet
|
|
168
|
+
const currentQueryData = fileQueryData.filter((item) => !downloadStatus.downloaded.has(`${item.fileName}:${item.locale}`) &&
|
|
169
|
+
!downloadStatus.failed.has(`${item.fileName}:${item.locale}`));
|
|
170
|
+
// If all files have been downloaded, we're done
|
|
171
|
+
if (currentQueryData.length === 0) {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
const response = await fetch(`${baseUrl}/v1/project/translations/files/retrieve`, {
|
|
175
|
+
method: 'POST',
|
|
176
|
+
headers: {
|
|
177
|
+
'Content-Type': 'application/json',
|
|
178
|
+
...(apiKey && { 'x-gt-api-key': apiKey }),
|
|
179
|
+
},
|
|
180
|
+
body: JSON.stringify({ files: currentQueryData }),
|
|
181
|
+
});
|
|
182
|
+
if (response.ok) {
|
|
183
|
+
const responseData = await response.json();
|
|
184
|
+
const translations = responseData.translations || [];
|
|
185
|
+
// Filter for ready translations
|
|
186
|
+
const readyTranslations = translations.filter((translation) => translation.isReady && translation.fileName);
|
|
187
|
+
if (readyTranslations.length > 0) {
|
|
188
|
+
// Prepare batch download data
|
|
189
|
+
const batchFiles = readyTranslations.map((translation) => {
|
|
190
|
+
const locale = translation.locale;
|
|
191
|
+
const fileName = translation.fileName;
|
|
192
|
+
const translationId = translation.id;
|
|
193
|
+
const outputPath = resolveOutputPath(fileName, locale);
|
|
194
|
+
return {
|
|
195
|
+
translationId,
|
|
196
|
+
outputPath,
|
|
197
|
+
fileLocale: `${fileName}:${locale}`,
|
|
198
|
+
};
|
|
199
|
+
});
|
|
200
|
+
// Use batch download if there are multiple files
|
|
201
|
+
if (batchFiles.length > 1) {
|
|
202
|
+
const batchResult = await (0, downloadFileBatch_1.downloadFileBatch)(baseUrl, apiKey, batchFiles.map(({ translationId, outputPath }) => ({
|
|
203
|
+
translationId,
|
|
204
|
+
outputPath,
|
|
205
|
+
})));
|
|
206
|
+
// Process results
|
|
207
|
+
batchFiles.forEach((file) => {
|
|
208
|
+
const { translationId, fileLocale } = file;
|
|
209
|
+
if (batchResult.successful.includes(translationId)) {
|
|
210
|
+
downloadStatus.downloaded.add(fileLocale);
|
|
211
|
+
}
|
|
212
|
+
else if (batchResult.failed.includes(translationId)) {
|
|
213
|
+
downloadStatus.failed.add(fileLocale);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
else if (batchFiles.length === 1) {
|
|
218
|
+
// For a single file, use the original downloadFile method
|
|
219
|
+
const file = batchFiles[0];
|
|
220
|
+
const result = await (0, downloadFile_1.downloadFile)(baseUrl, apiKey, file.translationId, file.outputPath);
|
|
221
|
+
if (result) {
|
|
222
|
+
downloadStatus.downloaded.add(file.fileLocale);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
downloadStatus.failed.add(file.fileLocale);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Force a refresh of the spinner display
|
|
230
|
+
const statusText = generateStatusSuffixText(downloadStatus, fileQueryData);
|
|
231
|
+
// Clear and reapply the suffix to force a refresh
|
|
232
|
+
spinner.text = statusText;
|
|
233
|
+
}
|
|
234
|
+
if (downloadStatus.downloaded.size + downloadStatus.failed.size ===
|
|
235
|
+
fileQueryData.length) {
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
(0, console_1.logError)(chalk_1.default.red('Error checking translation status: ') + error);
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function downloadFile(baseUrl: string, apiKey: string, translationId: string, outputPath: string, maxRetries?: number, retryDelay?: number): Promise<boolean>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.downloadFile = downloadFile;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const console_1 = require("../console/console");
|
|
40
|
+
// Helper function to download a file
|
|
41
|
+
async function downloadFile(baseUrl, apiKey, translationId, outputPath, maxRetries = 3, retryDelay = 1000) {
|
|
42
|
+
let retries = 0;
|
|
43
|
+
while (retries <= maxRetries) {
|
|
44
|
+
try {
|
|
45
|
+
const downloadResponse = await fetch(`${baseUrl}/v1/project/translations/files/${translationId}/download`, {
|
|
46
|
+
method: 'GET',
|
|
47
|
+
headers: {
|
|
48
|
+
...(apiKey && { 'x-gt-api-key': apiKey }),
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
if (downloadResponse.ok) {
|
|
52
|
+
// Ensure the directory exists
|
|
53
|
+
const dir = path.dirname(outputPath);
|
|
54
|
+
if (!fs.existsSync(dir)) {
|
|
55
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
// Get the file data as an ArrayBuffer
|
|
58
|
+
const fileData = await downloadResponse.arrayBuffer();
|
|
59
|
+
// Write the file to disk
|
|
60
|
+
await fs.promises.writeFile(outputPath, Buffer.from(fileData));
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
// If we get here, the response was not OK
|
|
64
|
+
if (retries >= maxRetries) {
|
|
65
|
+
(0, console_1.logError)(`Failed to download file ${outputPath}. Status: ${downloadResponse.status} after ${maxRetries + 1} attempts.`);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
// Increment retry counter and wait before next attempt
|
|
69
|
+
retries++;
|
|
70
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (retries >= maxRetries) {
|
|
74
|
+
(0, console_1.logError)(`Error downloading file ${outputPath} after ${maxRetries + 1} attempts: ` +
|
|
75
|
+
error);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
retries++;
|
|
79
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Downloads multiple translation files in a single batch request
|
|
3
|
+
* @param baseUrl - The base URL for the General Translation API
|
|
4
|
+
* @param apiKey - The API key for the General Translation API
|
|
5
|
+
* @param files - Array of files to download with their output paths
|
|
6
|
+
* @param maxRetries - Maximum number of retry attempts
|
|
7
|
+
* @param retryDelay - Delay between retries in milliseconds
|
|
8
|
+
* @returns Object containing successful and failed file IDs
|
|
9
|
+
*/
|
|
10
|
+
export declare function downloadFileBatch(baseUrl: string, apiKey: string, files: Array<{
|
|
11
|
+
translationId: string;
|
|
12
|
+
outputPath: string;
|
|
13
|
+
}>, maxRetries?: number, retryDelay?: number): Promise<{
|
|
14
|
+
successful: string[];
|
|
15
|
+
failed: string[];
|
|
16
|
+
}>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.downloadFileBatch = downloadFileBatch;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const console_1 = require("../console/console");
|
|
40
|
+
/**
|
|
41
|
+
* Downloads multiple translation files in a single batch request
|
|
42
|
+
* @param baseUrl - The base URL for the General Translation API
|
|
43
|
+
* @param apiKey - The API key for the General Translation API
|
|
44
|
+
* @param files - Array of files to download with their output paths
|
|
45
|
+
* @param maxRetries - Maximum number of retry attempts
|
|
46
|
+
* @param retryDelay - Delay between retries in milliseconds
|
|
47
|
+
* @returns Object containing successful and failed file IDs
|
|
48
|
+
*/
|
|
49
|
+
async function downloadFileBatch(baseUrl, apiKey, files, maxRetries = 3, retryDelay = 1000) {
|
|
50
|
+
let retries = 0;
|
|
51
|
+
const fileIds = files.map((file) => file.translationId);
|
|
52
|
+
const result = { successful: [], failed: [] };
|
|
53
|
+
// Create a map of translationId to outputPath for easier lookup
|
|
54
|
+
const outputPathMap = new Map(files.map((file) => [file.translationId, file.outputPath]));
|
|
55
|
+
while (retries <= maxRetries) {
|
|
56
|
+
try {
|
|
57
|
+
const response = await fetch(`${baseUrl}/v1/project/translations/files/batch-download`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: {
|
|
60
|
+
'Content-Type': 'application/json',
|
|
61
|
+
...(apiKey && { 'x-gt-api-key': apiKey }),
|
|
62
|
+
},
|
|
63
|
+
body: JSON.stringify({ fileIds }),
|
|
64
|
+
});
|
|
65
|
+
if (response.ok) {
|
|
66
|
+
const responseData = await response.json();
|
|
67
|
+
const downloadedFiles = responseData.files || [];
|
|
68
|
+
// Process each file in the response
|
|
69
|
+
for (const file of downloadedFiles) {
|
|
70
|
+
try {
|
|
71
|
+
const translationId = file.id;
|
|
72
|
+
const outputPath = outputPathMap.get(translationId);
|
|
73
|
+
if (!outputPath) {
|
|
74
|
+
(0, console_1.logWarning)(`No output path found for file: ${translationId}`);
|
|
75
|
+
result.failed.push(translationId);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
// Ensure the directory exists
|
|
79
|
+
const dir = path.dirname(outputPath);
|
|
80
|
+
if (!fs.existsSync(dir)) {
|
|
81
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
82
|
+
}
|
|
83
|
+
// Write the file to disk
|
|
84
|
+
await fs.promises.writeFile(outputPath, file.data);
|
|
85
|
+
result.successful.push(translationId);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
(0, console_1.logError)(`Error saving file ${file.id}: ` + error);
|
|
89
|
+
result.failed.push(file.id);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Add any files that weren't in the response to the failed list
|
|
93
|
+
const downloadedIds = new Set(downloadedFiles.map((file) => file.id));
|
|
94
|
+
for (const fileId of fileIds) {
|
|
95
|
+
if (!downloadedIds.has(fileId) && !result.failed.includes(fileId)) {
|
|
96
|
+
result.failed.push(fileId);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
// If we get here, the response was not OK
|
|
102
|
+
if (retries >= maxRetries) {
|
|
103
|
+
(0, console_1.logError)(`Failed to download files in batch. Status: ${response.status} after ${maxRetries + 1} attempts.`);
|
|
104
|
+
// Mark all files as failed
|
|
105
|
+
result.failed = [...fileIds];
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
// Increment retry counter and wait before next attempt
|
|
109
|
+
retries++;
|
|
110
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
if (retries >= maxRetries) {
|
|
114
|
+
(0, console_1.logError)(`Error downloading files in batch after ${maxRetries + 1} attempts: ` +
|
|
115
|
+
error);
|
|
116
|
+
// Mark all files as failed
|
|
117
|
+
result.failed = [...fileIds];
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
retries++;
|
|
121
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Mark all files as failed if we get here
|
|
125
|
+
result.failed = [...fileIds];
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RetrievedTranslations } from '../types/api';
|
|
2
|
+
/**
|
|
3
|
+
* Fetches translations from the API and saves them to a local directory
|
|
4
|
+
* @param baseUrl - The base URL for the API
|
|
5
|
+
* @param apiKey - The API key for the API
|
|
6
|
+
* @param versionId - The version ID of the project
|
|
7
|
+
* @param translationsDir - The directory to save the translations to
|
|
8
|
+
* @param fileType - The file type to save the translations as (file extension)
|
|
9
|
+
*/
|
|
10
|
+
export declare function fetchTranslations(baseUrl: string, apiKey: string, versionId: string): Promise<RetrievedTranslations>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.fetchTranslations = fetchTranslations;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const errors_1 = require("../console/errors");
|
|
9
|
+
/**
|
|
10
|
+
* Fetches translations from the API and saves them to a local directory
|
|
11
|
+
* @param baseUrl - The base URL for the API
|
|
12
|
+
* @param apiKey - The API key for the API
|
|
13
|
+
* @param versionId - The version ID of the project
|
|
14
|
+
* @param translationsDir - The directory to save the translations to
|
|
15
|
+
* @param fileType - The file type to save the translations as (file extension)
|
|
16
|
+
*/
|
|
17
|
+
async function fetchTranslations(baseUrl, apiKey, versionId) {
|
|
18
|
+
// First fetch the translations from the API
|
|
19
|
+
const response = await fetch(`${baseUrl}/v1/project/translations/info/${encodeURIComponent(versionId)}`, {
|
|
20
|
+
method: 'GET',
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
...(apiKey && { 'x-gt-api-key': apiKey }),
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
if (response.ok) {
|
|
27
|
+
const data = await response.json();
|
|
28
|
+
const translations = data.translations;
|
|
29
|
+
return translations;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
(0, errors_1.logError)(chalk_1.default.red('Failed to fetch translations'));
|
|
33
|
+
}
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Settings } from '../types';
|
|
2
|
+
import { FileFormats, DataFormat } from '../types/data';
|
|
3
|
+
export interface FileToTranslate {
|
|
4
|
+
content: string;
|
|
5
|
+
fileName: string;
|
|
6
|
+
fileFormat: FileFormats;
|
|
7
|
+
dataFormat: DataFormat;
|
|
8
|
+
}
|
|
9
|
+
type ApiOptions = Settings & {
|
|
10
|
+
publish: boolean;
|
|
11
|
+
wait: boolean;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Sends multiple files for translation to the API
|
|
15
|
+
* @param files - Array of file objects to translate
|
|
16
|
+
* @param options - The options for the API call
|
|
17
|
+
* @returns The translated content or version ID
|
|
18
|
+
*/
|
|
19
|
+
export declare function sendFiles(files: FileToTranslate[], options: ApiOptions): Promise<{
|
|
20
|
+
data: any;
|
|
21
|
+
locales: any;
|
|
22
|
+
translations: any;
|
|
23
|
+
}>;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.sendFiles = sendFiles;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const console_1 = require("../console");
|
|
9
|
+
/**
|
|
10
|
+
* Sends multiple files for translation to the API
|
|
11
|
+
* @param files - Array of file objects to translate
|
|
12
|
+
* @param options - The options for the API call
|
|
13
|
+
* @returns The translated content or version ID
|
|
14
|
+
*/
|
|
15
|
+
async function sendFiles(files, options) {
|
|
16
|
+
const { apiKey } = options;
|
|
17
|
+
(0, console_1.logMessage)(chalk_1.default.cyan('Files to translate:') +
|
|
18
|
+
'\n' +
|
|
19
|
+
files.map((file) => ` - ${chalk_1.default.bold(file.fileName)}`).join('\n'));
|
|
20
|
+
const spinner = (0, console_1.createSpinner)('dots');
|
|
21
|
+
spinner.start(`Sending ${files.length} file${files.length > 1 ? 's' : ''} to General Translation API...`);
|
|
22
|
+
try {
|
|
23
|
+
// Create form data
|
|
24
|
+
const formData = new FormData();
|
|
25
|
+
// Add each file to the form data
|
|
26
|
+
files.forEach((file, index) => {
|
|
27
|
+
formData.append(`file${index}`, new Blob([file.content]), file.fileName);
|
|
28
|
+
formData.append(`fileFormat${index}`, file.fileFormat);
|
|
29
|
+
formData.append(`fileDataFormat${index}`, file.dataFormat); // Only used when translating JSON files
|
|
30
|
+
formData.append(`fileName${index}`, file.fileName);
|
|
31
|
+
});
|
|
32
|
+
// Add number of files
|
|
33
|
+
formData.append('fileCount', String(files.length));
|
|
34
|
+
// Add other metadata
|
|
35
|
+
formData.append('sourceLocale', options.defaultLocale);
|
|
36
|
+
formData.append('targetLocales', JSON.stringify(options.locales));
|
|
37
|
+
formData.append('projectId', options.projectId);
|
|
38
|
+
formData.append('publish', String(options.publish));
|
|
39
|
+
formData.append('versionId', options._versionId || '');
|
|
40
|
+
formData.append('description', options.description || '');
|
|
41
|
+
const response = await fetch(`${options.baseUrl}/v1/project/translations/files/upload`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: {
|
|
44
|
+
...(apiKey && { 'x-gt-api-key': apiKey }),
|
|
45
|
+
},
|
|
46
|
+
body: formData,
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
spinner.stop(chalk_1.default.red(await response.text()));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const responseData = await response.json();
|
|
53
|
+
// Handle version ID response (for async processing)
|
|
54
|
+
const { data, message, locales, translations } = responseData;
|
|
55
|
+
spinner.stop(chalk_1.default.green('Files for translation uploaded successfully'));
|
|
56
|
+
(0, console_1.logSuccess)(message);
|
|
57
|
+
return { data, locales, translations };
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
spinner.stop(chalk_1.default.red('Failed to send files for translation'));
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Settings, SupportedLibraries, Updates } from '../types';
|
|
2
|
+
import { DataFormat } from '../types/data';
|
|
3
|
+
type ApiOptions = Settings & {
|
|
4
|
+
timeout: string;
|
|
5
|
+
dataFormat: DataFormat;
|
|
6
|
+
description?: string;
|
|
7
|
+
requireApproval?: boolean;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Sends updates to the API
|
|
11
|
+
* @param updates - The updates to send
|
|
12
|
+
* @param options - The options for the API call
|
|
13
|
+
* @returns The versionId of the updated project
|
|
14
|
+
*/
|
|
15
|
+
export declare function sendUpdates(updates: Updates, options: ApiOptions, library: SupportedLibraries): Promise<{
|
|
16
|
+
versionId: string;
|
|
17
|
+
locales: string[];
|
|
18
|
+
}>;
|
|
19
|
+
export {};
|