gtx-cli 2.1.5-alpha.3 → 2.1.5-alpha.5
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 +4 -1
- package/dist/api/checkFileTranslations.js +35 -32
- package/dist/api/downloadFile.d.ts +9 -0
- package/dist/api/downloadFile.js +74 -0
- package/dist/api/downloadFileBatch.d.ts +0 -1
- package/dist/api/fetchTranslations.d.ts +7 -0
- package/dist/api/fetchTranslations.js +18 -0
- package/dist/api/sendFiles.d.ts +13 -2
- package/dist/api/sendFiles.js +8 -15
- package/dist/api/sendUpdates.d.ts +19 -0
- package/dist/api/sendUpdates.js +48 -0
- package/dist/api/waitForUpdates.d.ts +9 -0
- package/dist/api/waitForUpdates.js +89 -0
- package/dist/cli/base.d.ts +17 -5
- package/dist/cli/base.js +75 -48
- package/dist/cli/next.js +1 -0
- package/dist/cli/react.d.ts +5 -2
- package/dist/cli/react.js +153 -13
- package/dist/config/generateSettings.js +6 -11
- package/dist/console/index.d.ts +0 -1
- package/dist/console/index.js +0 -1
- package/dist/console/logging.d.ts +0 -1
- package/dist/console/logging.js +0 -3
- package/dist/formats/files/fileMapping.d.ts +1 -2
- package/dist/formats/files/fileMapping.js +0 -6
- package/dist/formats/files/translate.d.ts +13 -4
- package/dist/formats/files/translate.js +142 -30
- package/dist/formats/files/upload.js +75 -1
- package/dist/formats/gt/save.d.ts +2 -1
- package/dist/formats/gt/save.js +5 -2
- package/dist/fs/config/setupConfig.d.ts +0 -1
- package/dist/fs/config/setupConfig.js +0 -1
- package/dist/fs/config/updateConfig.d.ts +2 -1
- package/dist/fs/config/updateConfig.js +1 -1
- package/dist/fs/copyFile.d.ts +2 -1
- package/dist/translation/parse.d.ts +2 -2
- package/dist/translation/parse.js +6 -4
- package/dist/translation/stage.d.ts +5 -2
- package/dist/translation/stage.js +55 -13
- package/dist/translation/translate.d.ts +2 -0
- package/dist/translation/translate.js +18 -0
- package/dist/types/index.d.ts +4 -27
- package/dist/utils/flattenJsonFiles.d.ts +2 -2
- package/dist/utils/localizeStaticImports.d.ts +2 -2
- package/dist/utils/localizeStaticUrls.d.ts +6 -2
- package/dist/utils/localizeStaticUrls.js +119 -96
- package/package.json +2 -2
- package/dist/cli/commands/stage.d.ts +0 -5
- package/dist/cli/commands/stage.js +0 -100
- package/dist/cli/commands/translate.d.ts +0 -6
- package/dist/cli/commands/translate.js +0 -54
- package/dist/cli/flags.d.ts +0 -3
- package/dist/cli/flags.js +0 -37
- package/dist/fs/config/updateVersions.d.ts +0 -10
- package/dist/fs/config/updateVersions.js +0 -30
- package/dist/types/files.d.ts +0 -1
- package/dist/types/files.js +0 -1
- package/dist/utils/hash.d.ts +0 -6
- package/dist/utils/hash.js +0 -11
|
@@ -20,4 +20,7 @@ export declare function checkFileTranslations(data: {
|
|
|
20
20
|
versionId: string;
|
|
21
21
|
fileName: string;
|
|
22
22
|
};
|
|
23
|
-
}, locales: string[], timeoutDuration: number, resolveOutputPath: (sourcePath: string, locale: string) => string
|
|
23
|
+
}, locales: string[], timeoutDuration: number, resolveOutputPath: (sourcePath: string, locale: string) => string, downloadStatus: {
|
|
24
|
+
downloaded: Set<string>;
|
|
25
|
+
failed: Set<string>;
|
|
26
|
+
}, options: Settings): Promise<boolean>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { createOraSpinner, logError } from '../console/logging.js';
|
|
3
3
|
import { getLocaleProperties } from 'generaltranslation';
|
|
4
|
+
import { downloadFile } from './downloadFile.js';
|
|
4
5
|
import { downloadFileBatch } from './downloadFileBatch.js';
|
|
5
6
|
import { gt } from '../utils/gt.js';
|
|
6
|
-
import { TEMPLATE_FILE_NAME } from '../cli/commands/stage.js';
|
|
7
7
|
/**
|
|
8
8
|
* Checks the status of translations for a given version ID
|
|
9
9
|
* @param apiKey - The API key for the General Translation API
|
|
@@ -14,18 +14,13 @@ import { TEMPLATE_FILE_NAME } from '../cli/commands/stage.js';
|
|
|
14
14
|
* @param timeoutDuration - The timeout duration for the wait in seconds
|
|
15
15
|
* @returns True if all translations are deployed, false otherwise
|
|
16
16
|
*/
|
|
17
|
-
export async function checkFileTranslations(data, locales, timeoutDuration, resolveOutputPath, options) {
|
|
17
|
+
export async function checkFileTranslations(data, locales, timeoutDuration, resolveOutputPath, downloadStatus, options) {
|
|
18
18
|
const startTime = Date.now();
|
|
19
19
|
console.log();
|
|
20
20
|
const spinner = await createOraSpinner();
|
|
21
21
|
spinner.start('Waiting for translation...');
|
|
22
22
|
// Initialize the query data
|
|
23
23
|
const fileQueryData = prepareFileQueryData(data, locales);
|
|
24
|
-
const downloadStatus = {
|
|
25
|
-
downloaded: new Set(),
|
|
26
|
-
failed: new Set(),
|
|
27
|
-
skipped: new Set(),
|
|
28
|
-
};
|
|
29
24
|
// Do first check immediately
|
|
30
25
|
const initialCheck = await checkTranslationDeployment(fileQueryData, downloadStatus, spinner, resolveOutputPath, options);
|
|
31
26
|
if (initialCheck) {
|
|
@@ -151,8 +146,7 @@ function generateStatusSuffixText(downloadStatus, fileQueryData) {
|
|
|
151
146
|
localeStatuses.push(chalk.yellow(`${pendingCodes}`));
|
|
152
147
|
}
|
|
153
148
|
// Format the line
|
|
154
|
-
|
|
155
|
-
newSuffixText.push(`${chalk.bold(prettyFileName)} [${localeStatuses.join(', ')}]`);
|
|
149
|
+
newSuffixText.push(`${chalk.bold(fileName)} [${localeStatuses.join(', ')}]`);
|
|
156
150
|
}
|
|
157
151
|
// If we couldn't show all files, add an indicator
|
|
158
152
|
if (filesArray.length > maxFilesToShow) {
|
|
@@ -167,8 +161,7 @@ async function checkTranslationDeployment(fileQueryData, downloadStatus, spinner
|
|
|
167
161
|
try {
|
|
168
162
|
// Only query for files that haven't been downloaded yet
|
|
169
163
|
const currentQueryData = fileQueryData.filter((item) => !downloadStatus.downloaded.has(`${item.fileName}:${item.locale}`) &&
|
|
170
|
-
!downloadStatus.failed.has(`${item.fileName}:${item.locale}`)
|
|
171
|
-
!downloadStatus.skipped.has(`${item.fileName}:${item.locale}`));
|
|
164
|
+
!downloadStatus.failed.has(`${item.fileName}:${item.locale}`));
|
|
172
165
|
// If all files have been downloaded, we're done
|
|
173
166
|
if (currentQueryData.length === 0) {
|
|
174
167
|
return true;
|
|
@@ -180,17 +173,11 @@ async function checkTranslationDeployment(fileQueryData, downloadStatus, spinner
|
|
|
180
173
|
const readyTranslations = translations.filter((translation) => translation.isReady && translation.fileName);
|
|
181
174
|
if (readyTranslations.length > 0) {
|
|
182
175
|
// Prepare batch download data
|
|
183
|
-
const batchFiles = readyTranslations
|
|
184
|
-
.map((translation) => {
|
|
176
|
+
const batchFiles = readyTranslations.map((translation) => {
|
|
185
177
|
const locale = translation.locale;
|
|
186
178
|
const fileName = translation.fileName;
|
|
187
179
|
const translationId = translation.id;
|
|
188
180
|
const outputPath = resolveOutputPath(fileName, locale);
|
|
189
|
-
// Skip downloading GTJSON files that are not in the files configuration
|
|
190
|
-
if (outputPath === null) {
|
|
191
|
-
downloadStatus.skipped.add(`${fileName}:${locale}`);
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
181
|
return {
|
|
195
182
|
translationId,
|
|
196
183
|
inputPath: fileName,
|
|
@@ -198,28 +185,44 @@ async function checkTranslationDeployment(fileQueryData, downloadStatus, spinner
|
|
|
198
185
|
locale,
|
|
199
186
|
fileLocale: `${fileName}:${locale}`,
|
|
200
187
|
};
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
188
|
+
});
|
|
189
|
+
// Use batch download if there are multiple files
|
|
190
|
+
if (batchFiles.length > 1) {
|
|
191
|
+
const batchResult = await downloadFileBatch(batchFiles.map(({ translationId, outputPath, inputPath, locale }) => ({
|
|
192
|
+
translationId,
|
|
193
|
+
outputPath,
|
|
194
|
+
inputPath,
|
|
195
|
+
locale,
|
|
196
|
+
})), options);
|
|
197
|
+
// Process results
|
|
198
|
+
batchFiles.forEach((file) => {
|
|
199
|
+
const { translationId, fileLocale } = file;
|
|
200
|
+
if (batchResult.successful.includes(translationId)) {
|
|
201
|
+
downloadStatus.downloaded.add(fileLocale);
|
|
202
|
+
}
|
|
203
|
+
else if (batchResult.failed.includes(translationId)) {
|
|
204
|
+
downloadStatus.failed.add(fileLocale);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
else if (batchFiles.length === 1) {
|
|
209
|
+
// For a single file, use the original downloadFile method
|
|
210
|
+
const file = batchFiles[0];
|
|
211
|
+
const result = await downloadFile(file.translationId, file.outputPath, file.inputPath, file.locale, options);
|
|
212
|
+
if (result) {
|
|
213
|
+
downloadStatus.downloaded.add(file.fileLocale);
|
|
209
214
|
}
|
|
210
|
-
else
|
|
211
|
-
downloadStatus.failed.add(fileLocale);
|
|
215
|
+
else {
|
|
216
|
+
downloadStatus.failed.add(file.fileLocale);
|
|
212
217
|
}
|
|
213
|
-
}
|
|
218
|
+
}
|
|
214
219
|
}
|
|
215
220
|
// Force a refresh of the spinner display
|
|
216
221
|
const statusText = generateStatusSuffixText(downloadStatus, fileQueryData);
|
|
217
222
|
// Clear and reapply the suffix to force a refresh
|
|
218
223
|
spinner.text = statusText;
|
|
219
224
|
// If all files have been downloaded, we're done
|
|
220
|
-
if (downloadStatus.downloaded.size +
|
|
221
|
-
downloadStatus.failed.size +
|
|
222
|
-
downloadStatus.skipped.size ===
|
|
225
|
+
if (downloadStatus.downloaded.size + downloadStatus.failed.size ===
|
|
223
226
|
fileQueryData.length) {
|
|
224
227
|
return true;
|
|
225
228
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Settings } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Downloads a file from the API and saves it to a local directory
|
|
4
|
+
* @param translationId - The ID of the translation to download
|
|
5
|
+
* @param outputPath - The path to save the file to
|
|
6
|
+
* @param maxRetries - The maximum number of retries to attempt
|
|
7
|
+
* @param retryDelay - The delay between retries in milliseconds
|
|
8
|
+
*/
|
|
9
|
+
export declare function downloadFile(translationId: string, outputPath: string, inputPath: string, locale: string, options: Settings, maxRetries?: number, retryDelay?: number): Promise<boolean>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { logError } from '../console/logging.js';
|
|
4
|
+
import { gt } from '../utils/gt.js';
|
|
5
|
+
import { validateJsonSchema } from '../formats/json/utils.js';
|
|
6
|
+
import { mergeJson } from '../formats/json/mergeJson.js';
|
|
7
|
+
import { TextDecoder } from 'node:util';
|
|
8
|
+
import mergeYaml from '../formats/yaml/mergeYaml.js';
|
|
9
|
+
import { validateYamlSchema } from '../formats/yaml/utils.js';
|
|
10
|
+
/**
|
|
11
|
+
* Downloads a file from the API and saves it to a local directory
|
|
12
|
+
* @param translationId - The ID of the translation to download
|
|
13
|
+
* @param outputPath - The path to save the file to
|
|
14
|
+
* @param maxRetries - The maximum number of retries to attempt
|
|
15
|
+
* @param retryDelay - The delay between retries in milliseconds
|
|
16
|
+
*/
|
|
17
|
+
export async function downloadFile(translationId, outputPath, inputPath, locale, options, maxRetries = 3, retryDelay = 1000) {
|
|
18
|
+
let retries = 0;
|
|
19
|
+
while (retries <= maxRetries) {
|
|
20
|
+
try {
|
|
21
|
+
// Get the file data as an ArrayBuffer
|
|
22
|
+
const fileData = await gt.downloadFile(translationId);
|
|
23
|
+
// Ensure the directory exists
|
|
24
|
+
const dir = path.dirname(outputPath);
|
|
25
|
+
if (!fs.existsSync(dir)) {
|
|
26
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
let data = new TextDecoder().decode(fileData);
|
|
29
|
+
if (options.options?.jsonSchema && locale) {
|
|
30
|
+
const jsonSchema = validateJsonSchema(options.options, inputPath);
|
|
31
|
+
if (jsonSchema) {
|
|
32
|
+
const originalContent = fs.readFileSync(inputPath, 'utf8');
|
|
33
|
+
if (originalContent) {
|
|
34
|
+
data = mergeJson(originalContent, inputPath, options.options, [
|
|
35
|
+
{
|
|
36
|
+
translatedContent: data,
|
|
37
|
+
targetLocale: locale,
|
|
38
|
+
},
|
|
39
|
+
], options.defaultLocale)[0];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (options.options?.yamlSchema && locale) {
|
|
44
|
+
const yamlSchema = validateYamlSchema(options.options, inputPath);
|
|
45
|
+
if (yamlSchema) {
|
|
46
|
+
const originalContent = fs.readFileSync(inputPath, 'utf8');
|
|
47
|
+
if (originalContent) {
|
|
48
|
+
data = mergeYaml(originalContent, inputPath, options.options, [
|
|
49
|
+
{
|
|
50
|
+
translatedContent: data,
|
|
51
|
+
targetLocale: locale,
|
|
52
|
+
},
|
|
53
|
+
])[0];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Write the file to disk
|
|
58
|
+
await fs.promises.writeFile(outputPath, data);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// If we've retried too many times, log an error and return false
|
|
63
|
+
if (retries >= maxRetries) {
|
|
64
|
+
logError(`Error downloading file ${outputPath} after ${maxRetries + 1} attempts: ` +
|
|
65
|
+
error);
|
|
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
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { RetrievedTranslations } from 'generaltranslation/types';
|
|
2
|
+
/**
|
|
3
|
+
* Fetches translations from the API and saves them to a local directory
|
|
4
|
+
* @param translationsDir - The directory to save the translations to
|
|
5
|
+
* @param fileType - The file type to save the translations as (file extension)
|
|
6
|
+
*/
|
|
7
|
+
export declare function fetchTranslations(versionId: string): Promise<RetrievedTranslations>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { logError } from '../console/logging.js';
|
|
3
|
+
import { gt } from '../utils/gt.js';
|
|
4
|
+
/**
|
|
5
|
+
* Fetches translations from the API and saves them to a local directory
|
|
6
|
+
* @param translationsDir - The directory to save the translations to
|
|
7
|
+
* @param fileType - The file type to save the translations as (file extension)
|
|
8
|
+
*/
|
|
9
|
+
export async function fetchTranslations(versionId) {
|
|
10
|
+
try {
|
|
11
|
+
const result = await gt.fetchTranslations(versionId);
|
|
12
|
+
return result.translations;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
logError(chalk.red('Failed to fetch translations'));
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
}
|
package/dist/api/sendFiles.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import { Settings
|
|
1
|
+
import { Settings } from '../types/index.js';
|
|
2
2
|
import { CompletedFileTranslationData, FileToTranslate } from 'generaltranslation/types';
|
|
3
|
+
export type ApiOptions = Settings & {
|
|
4
|
+
publish: boolean;
|
|
5
|
+
wait: boolean;
|
|
6
|
+
};
|
|
3
7
|
export type SendFilesResult = {
|
|
4
8
|
data: Record<string, {
|
|
5
9
|
fileName: string;
|
|
@@ -14,4 +18,11 @@ export type SendFilesResult = {
|
|
|
14
18
|
* @param options - The options for the API call
|
|
15
19
|
* @returns The translated content or version ID
|
|
16
20
|
*/
|
|
17
|
-
export declare function sendFiles(files: FileToTranslate[], options:
|
|
21
|
+
export declare function sendFiles(files: FileToTranslate[], options: ApiOptions): Promise<{
|
|
22
|
+
data: Record<string, {
|
|
23
|
+
fileName: string;
|
|
24
|
+
versionId: string;
|
|
25
|
+
}>;
|
|
26
|
+
locales: string[];
|
|
27
|
+
translations: CompletedFileTranslationData[];
|
|
28
|
+
}>;
|
package/dist/api/sendFiles.js
CHANGED
|
@@ -1,34 +1,27 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { createSpinner, logMessage, logSuccess } from '../console/logging.js';
|
|
3
3
|
import { gt } from '../utils/gt.js';
|
|
4
|
-
import { TEMPLATE_FILE_NAME } from '../cli/commands/stage.js';
|
|
5
4
|
/**
|
|
6
5
|
* Sends multiple files for translation to the API
|
|
7
6
|
* @param files - Array of file objects to translate
|
|
8
7
|
* @param options - The options for the API call
|
|
9
8
|
* @returns The translated content or version ID
|
|
10
9
|
*/
|
|
11
|
-
export async function sendFiles(files, options
|
|
10
|
+
export async function sendFiles(files, options) {
|
|
12
11
|
logMessage(chalk.cyan('Files to translate:') +
|
|
13
12
|
'\n' +
|
|
14
|
-
files
|
|
15
|
-
.map((file) => {
|
|
16
|
-
if (file.fileName === TEMPLATE_FILE_NAME) {
|
|
17
|
-
return `- <React Elements>`;
|
|
18
|
-
}
|
|
19
|
-
return `- ${file.fileName}`;
|
|
20
|
-
})
|
|
21
|
-
.join('\n'));
|
|
13
|
+
files.map((file) => ` - ${chalk.bold(file.fileName)}`).join('\n'));
|
|
22
14
|
const spinner = createSpinner('dots');
|
|
23
15
|
spinner.start(`Sending ${files.length} file${files.length !== 1 ? 's' : ''} to General Translation API...`);
|
|
24
16
|
try {
|
|
25
17
|
// Send the files to the API
|
|
26
18
|
const responseData = await gt.enqueueFiles(files, {
|
|
27
|
-
publish:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
publish: options.publish,
|
|
20
|
+
description: options.description,
|
|
21
|
+
sourceLocale: options.defaultLocale,
|
|
22
|
+
targetLocales: options.locales,
|
|
23
|
+
_versionId: options._versionId,
|
|
24
|
+
modelProvider: options.modelProvider,
|
|
32
25
|
});
|
|
33
26
|
// Handle version ID response (for async processing)
|
|
34
27
|
const { data, message, locales, translations } = responseData;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Settings, SupportedLibraries, Updates } from '../types/index.js';
|
|
2
|
+
import { DataFormat } from '../types/data.js';
|
|
3
|
+
export type ApiOptions = Settings & {
|
|
4
|
+
timeout: string;
|
|
5
|
+
dataFormat: DataFormat;
|
|
6
|
+
description?: string;
|
|
7
|
+
requireApproval?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type SendUpdatesResult = {
|
|
10
|
+
versionId: string;
|
|
11
|
+
locales: string[];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Sends updates to the API
|
|
15
|
+
* @param updates - The updates to send
|
|
16
|
+
* @param options - The options for the API call
|
|
17
|
+
* @returns The versionId of the updated project
|
|
18
|
+
*/
|
|
19
|
+
export declare function sendUpdates(updates: Updates, options: ApiOptions, library: SupportedLibraries): Promise<SendUpdatesResult>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { createSpinner, logSuccess, logWarning, } from '../console/logging.js';
|
|
3
|
+
import updateConfig from '../fs/config/updateConfig.js';
|
|
4
|
+
import { isUsingLocalTranslations } from '../config/utils.js';
|
|
5
|
+
import { gt } from '../utils/gt.js';
|
|
6
|
+
/**
|
|
7
|
+
* Sends updates to the API
|
|
8
|
+
* @param updates - The updates to send
|
|
9
|
+
* @param options - The options for the API call
|
|
10
|
+
* @returns The versionId of the updated project
|
|
11
|
+
*/
|
|
12
|
+
export async function sendUpdates(updates, options, library) {
|
|
13
|
+
const spinner = createSpinner('dots');
|
|
14
|
+
spinner.start(`Sending ${library} updates to General Translation API...`);
|
|
15
|
+
try {
|
|
16
|
+
const responseData = await gt.enqueueEntries(updates, {
|
|
17
|
+
sourceLocale: options.defaultLocale,
|
|
18
|
+
targetLocales: options.locales,
|
|
19
|
+
dataFormat: options.dataFormat,
|
|
20
|
+
version: options.version,
|
|
21
|
+
description: options.description,
|
|
22
|
+
requireApproval: options.requireApproval,
|
|
23
|
+
modelProvider: options.modelProvider,
|
|
24
|
+
});
|
|
25
|
+
const { versionId, message, locales, projectSettings } = responseData;
|
|
26
|
+
spinner.stop(chalk.green('Sent updates'));
|
|
27
|
+
logSuccess(message);
|
|
28
|
+
if (isUsingLocalTranslations(options) && projectSettings.cdnEnabled) {
|
|
29
|
+
logWarning(chalk.yellow('Your project is configured to use the CDN, but you are also using local translations. Please disable one or the other.'));
|
|
30
|
+
}
|
|
31
|
+
else if (!isUsingLocalTranslations(options) &&
|
|
32
|
+
!projectSettings.cdnEnabled) {
|
|
33
|
+
logWarning(chalk.yellow('Your project is not using the CDN, nor are you using local translations. Please enable one or the other.'));
|
|
34
|
+
}
|
|
35
|
+
if (options.config) {
|
|
36
|
+
await updateConfig({
|
|
37
|
+
configFilepath: options.config,
|
|
38
|
+
_versionId: versionId,
|
|
39
|
+
locales,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return { versionId, locales };
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
spinner.stop(chalk.red('Failed to send updates'));
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Waits for translations to be deployed to the General Translation API
|
|
3
|
+
* @param versionId - The version ID of the project
|
|
4
|
+
* @param locales - The locales to wait for
|
|
5
|
+
* @param startTime - The start time of the wait
|
|
6
|
+
* @param timeoutDuration - The timeout duration for the wait
|
|
7
|
+
* @returns True if all translations are deployed, false otherwise
|
|
8
|
+
*/
|
|
9
|
+
export declare const waitForUpdates: (versionId: string, startTime: number, timeoutDuration: number) => Promise<boolean>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { createOraSpinner, logErrorAndExit, } from '../console/logging.js';
|
|
3
|
+
import { getLocaleProperties } from 'generaltranslation';
|
|
4
|
+
import { gt } from '../utils/gt.js';
|
|
5
|
+
/**
|
|
6
|
+
* Waits for translations to be deployed to the General Translation API
|
|
7
|
+
* @param versionId - The version ID of the project
|
|
8
|
+
* @param locales - The locales to wait for
|
|
9
|
+
* @param startTime - The start time of the wait
|
|
10
|
+
* @param timeoutDuration - The timeout duration for the wait
|
|
11
|
+
* @returns True if all translations are deployed, false otherwise
|
|
12
|
+
*/
|
|
13
|
+
export const waitForUpdates = async (versionId, startTime, timeoutDuration) => {
|
|
14
|
+
console.log();
|
|
15
|
+
const spinner = await createOraSpinner();
|
|
16
|
+
spinner.start('Waiting for translation...');
|
|
17
|
+
const checkDeployment = async () => {
|
|
18
|
+
let data;
|
|
19
|
+
try {
|
|
20
|
+
// get translation status
|
|
21
|
+
data = await gt.checkTranslationStatus(versionId);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
// check if any locales are waiting for approval
|
|
27
|
+
const { availableLocales, locales, localesWaitingForApproval } = data;
|
|
28
|
+
if (localesWaitingForApproval.length > 0) {
|
|
29
|
+
spinner.stop();
|
|
30
|
+
logErrorAndExit(`Error! ${localesWaitingForApproval.length} translations are waiting for approval:\n${localesWaitingForApproval
|
|
31
|
+
.map((locale) => {
|
|
32
|
+
const localeProperties = getLocaleProperties(locale);
|
|
33
|
+
return `${localeProperties.name} (${localeProperties.code})`;
|
|
34
|
+
})
|
|
35
|
+
.join('\n')}\nPlease approve these locales in the General Translation dashboard, then re-run the command.`);
|
|
36
|
+
}
|
|
37
|
+
// check if all locales are available
|
|
38
|
+
if (availableLocales) {
|
|
39
|
+
availableLocales.forEach((locale) => {
|
|
40
|
+
if (!availableLocales.includes(locale)) {
|
|
41
|
+
availableLocales.push(locale);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
const newSuffixText = [
|
|
45
|
+
chalk.green(`[${availableLocales.length}/${locales.length}]`) +
|
|
46
|
+
` translations completed`,
|
|
47
|
+
...availableLocales.map((locale) => {
|
|
48
|
+
const localeProperties = getLocaleProperties(locale);
|
|
49
|
+
return `Translation completed for ${chalk.green(localeProperties.name)} (${chalk.green(localeProperties.code)})`;
|
|
50
|
+
}),
|
|
51
|
+
];
|
|
52
|
+
spinner.text = newSuffixText.join('\n');
|
|
53
|
+
}
|
|
54
|
+
// check if all locales are available
|
|
55
|
+
if (locales.every((locale) => availableLocales.includes(locale))) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
};
|
|
60
|
+
// Calculate time until next 5-second interval since startTime
|
|
61
|
+
const msUntilNextInterval = Math.max(0, 5000 - ((Date.now() - startTime) % 5000));
|
|
62
|
+
// Do first check immediately
|
|
63
|
+
const initialCheck = await checkDeployment();
|
|
64
|
+
if (initialCheck) {
|
|
65
|
+
spinner.succeed(chalk.green('All translations are live!'));
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
return new Promise((resolve) => {
|
|
69
|
+
let intervalCheck;
|
|
70
|
+
// Start the interval aligned with the original request time
|
|
71
|
+
setTimeout(() => {
|
|
72
|
+
intervalCheck = setInterval(async () => {
|
|
73
|
+
const isDeployed = await checkDeployment();
|
|
74
|
+
const elapsed = Date.now() - startTime;
|
|
75
|
+
if (isDeployed || elapsed >= timeoutDuration) {
|
|
76
|
+
clearInterval(intervalCheck);
|
|
77
|
+
if (isDeployed) {
|
|
78
|
+
spinner.succeed(chalk.green('All translations are live!'));
|
|
79
|
+
resolve(true);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
spinner.fail(chalk.red('Timed out waiting for translations'));
|
|
83
|
+
resolve(false);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}, 5000);
|
|
87
|
+
}, msUntilNextInterval);
|
|
88
|
+
});
|
|
89
|
+
};
|
package/dist/cli/base.d.ts
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { Settings, SupportedLibraries, SetupOptions
|
|
2
|
+
import { Settings, SupportedLibraries, SetupOptions } from '../types/index.js';
|
|
3
3
|
export type UploadOptions = {
|
|
4
4
|
config?: string;
|
|
5
5
|
apiKey?: string;
|
|
6
6
|
projectId?: string;
|
|
7
7
|
defaultLocale?: string;
|
|
8
8
|
};
|
|
9
|
+
export type TranslateOptions = {
|
|
10
|
+
config?: string;
|
|
11
|
+
defaultLocale?: string;
|
|
12
|
+
locales?: string[];
|
|
13
|
+
apiKey?: string;
|
|
14
|
+
projectId?: string;
|
|
15
|
+
dryRun: boolean;
|
|
16
|
+
experimentalLocalizeStaticUrls?: boolean;
|
|
17
|
+
experimentalHideDefaultLocale?: boolean;
|
|
18
|
+
experimentalFlattenJsonFiles?: boolean;
|
|
19
|
+
experimentalLocalizeStaticImports?: boolean;
|
|
20
|
+
excludeStaticUrls?: string[];
|
|
21
|
+
excludeStaticImports?: string[];
|
|
22
|
+
};
|
|
9
23
|
export type LoginOptions = {
|
|
10
24
|
keyType?: 'development' | 'production';
|
|
11
25
|
};
|
|
@@ -16,16 +30,14 @@ export declare class BaseCLI {
|
|
|
16
30
|
constructor(program: Command, library: SupportedLibraries, additionalModules?: SupportedLibraries[]);
|
|
17
31
|
init(): void;
|
|
18
32
|
execute(): void;
|
|
19
|
-
protected
|
|
20
|
-
protected setupTranslateCommand(): void;
|
|
21
|
-
protected handleStage(initOptions: TranslateFlags): Promise<void>;
|
|
22
|
-
protected handleTranslate(initOptions: TranslateFlags): Promise<void>;
|
|
33
|
+
protected setupGTCommand(): void;
|
|
23
34
|
protected setupUploadCommand(): void;
|
|
24
35
|
protected setupLoginCommand(): void;
|
|
25
36
|
protected setupInitCommand(): void;
|
|
26
37
|
protected setupConfigureCommand(): void;
|
|
27
38
|
protected setupSetupCommand(): void;
|
|
28
39
|
protected handleUploadCommand(settings: Settings & UploadOptions): Promise<void>;
|
|
40
|
+
protected handleGenericTranslate(settings: Settings & TranslateOptions): Promise<void>;
|
|
29
41
|
protected handleSetupReactCommand(options: SetupOptions): Promise<void>;
|
|
30
42
|
protected handleInitCommand(ranReactSetup: boolean): Promise<void>;
|
|
31
43
|
protected handleLoginCommand(options: LoginOptions): Promise<void>;
|