gtx-cli 2.1.5-alpha.2 → 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
|
@@ -1,42 +1,38 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { checkFileTranslations } from '../../api/checkFileTranslations.js';
|
|
2
|
+
import { sendFiles } from '../../api/sendFiles.js';
|
|
3
|
+
import { noSupportedFormatError, noLocalesError, noDefaultLocaleError, noApiKeyError, noProjectIdError, devApiKeyError, } from '../../console/index.js';
|
|
4
|
+
import { logErrorAndExit, createSpinner, logError, logSuccess, } from '../../console/logging.js';
|
|
2
5
|
import { getRelative, readFile } from '../../fs/findFilepath.js';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { downloadFile } from '../../api/downloadFile.js';
|
|
8
|
+
import { downloadFileBatch } from '../../api/downloadFileBatch.js';
|
|
3
9
|
import { SUPPORTED_FILE_EXTENSIONS } from './supportedFiles.js';
|
|
4
10
|
import sanitizeFileContent from '../../utils/sanitizeFileContent.js';
|
|
5
11
|
import { parseJson } from '../json/parseJson.js';
|
|
12
|
+
import { createFileMapping } from './fileMapping.js';
|
|
6
13
|
import parseYaml from '../yaml/parseYaml.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
const SUPPORTED_DATA_FORMATS = ['JSX', 'ICU', 'I18NEXT'];
|
|
15
|
+
/**
|
|
16
|
+
* Sends multiple files to the API for translation
|
|
17
|
+
* @param filePaths - Resolved file paths for different file types
|
|
18
|
+
* @param placeholderPaths - Placeholder paths for translated files
|
|
19
|
+
* @param transformPaths - Transform paths for file naming
|
|
20
|
+
* @param dataFormat - Format of the data within the files
|
|
21
|
+
* @param options - Translation options including API settings
|
|
22
|
+
* @returns Promise that resolves when translation is complete
|
|
23
|
+
*/
|
|
24
|
+
export async function translateFiles(filePaths, placeholderPaths, transformPaths, dataFormat = 'JSX', options) {
|
|
25
|
+
// Collect all files to translate
|
|
11
26
|
const allFiles = [];
|
|
12
|
-
|
|
13
|
-
(Object.keys(settings.files.placeholderPaths).length === 1 &&
|
|
14
|
-
settings.files.placeholderPaths.gt)) {
|
|
15
|
-
return allFiles;
|
|
16
|
-
}
|
|
17
|
-
const { resolvedPaths: filePaths } = settings.files;
|
|
27
|
+
const additionalOptions = options.options || {};
|
|
18
28
|
// Process JSON files
|
|
19
29
|
if (filePaths.json) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
let dataFormat;
|
|
23
|
-
if (library === 'next-intl') {
|
|
24
|
-
dataFormat = 'ICU';
|
|
25
|
-
}
|
|
26
|
-
else if (library === 'i18next') {
|
|
27
|
-
if (additionalModules.includes('i18next-icu')) {
|
|
28
|
-
dataFormat = 'ICU';
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
dataFormat = 'I18NEXT';
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
dataFormat = 'JSX';
|
|
30
|
+
if (!SUPPORTED_DATA_FORMATS.includes(dataFormat)) {
|
|
31
|
+
logErrorAndExit(noSupportedFormatError);
|
|
36
32
|
}
|
|
37
33
|
const jsonFiles = filePaths.json.map((filePath) => {
|
|
38
34
|
const content = readFile(filePath);
|
|
39
|
-
const parsedJson = parseJson(content, filePath,
|
|
35
|
+
const parsedJson = parseJson(content, filePath, additionalOptions, options.defaultLocale);
|
|
40
36
|
const relativePath = getRelative(filePath);
|
|
41
37
|
return {
|
|
42
38
|
content: parsedJson,
|
|
@@ -49,14 +45,18 @@ export async function aggregateFiles(settings) {
|
|
|
49
45
|
}
|
|
50
46
|
// Process YAML files
|
|
51
47
|
if (filePaths.yaml) {
|
|
48
|
+
if (!SUPPORTED_DATA_FORMATS.includes(dataFormat)) {
|
|
49
|
+
logErrorAndExit(noSupportedFormatError);
|
|
50
|
+
}
|
|
52
51
|
const yamlFiles = filePaths.yaml.map((filePath) => {
|
|
53
52
|
const content = readFile(filePath);
|
|
54
|
-
const { content: parsedYaml, fileFormat } = parseYaml(content, filePath,
|
|
53
|
+
const { content: parsedYaml, fileFormat } = parseYaml(content, filePath, additionalOptions);
|
|
55
54
|
const relativePath = getRelative(filePath);
|
|
56
55
|
return {
|
|
57
56
|
content: parsedYaml,
|
|
58
57
|
fileName: relativePath,
|
|
59
58
|
fileFormat,
|
|
59
|
+
dataFormat,
|
|
60
60
|
};
|
|
61
61
|
});
|
|
62
62
|
allFiles.push(...yamlFiles);
|
|
@@ -73,6 +73,7 @@ export async function aggregateFiles(settings) {
|
|
|
73
73
|
content: sanitizedContent,
|
|
74
74
|
fileName: relativePath,
|
|
75
75
|
fileFormat: fileType.toUpperCase(),
|
|
76
|
+
dataFormat,
|
|
76
77
|
};
|
|
77
78
|
});
|
|
78
79
|
allFiles.push(...files);
|
|
@@ -80,6 +81,117 @@ export async function aggregateFiles(settings) {
|
|
|
80
81
|
}
|
|
81
82
|
if (allFiles.length === 0) {
|
|
82
83
|
logError('No files to translate were found. Please check your configuration and try again.');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (options.dryRun) {
|
|
87
|
+
const fileNames = allFiles.map((file) => `- ${file.fileName}`).join('\n');
|
|
88
|
+
logSuccess(`Dry run: No files were sent to General Translation. Found files:\n${fileNames}`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Validate required settings are present
|
|
92
|
+
if (!options.locales) {
|
|
93
|
+
logErrorAndExit(noLocalesError);
|
|
94
|
+
}
|
|
95
|
+
if (!options.defaultLocale) {
|
|
96
|
+
logErrorAndExit(noDefaultLocaleError);
|
|
97
|
+
}
|
|
98
|
+
if (!options.apiKey) {
|
|
99
|
+
logErrorAndExit(noApiKeyError);
|
|
100
|
+
}
|
|
101
|
+
if (options.apiKey.startsWith('gtx-dev-')) {
|
|
102
|
+
logErrorAndExit(devApiKeyError);
|
|
103
|
+
}
|
|
104
|
+
if (!options.projectId) {
|
|
105
|
+
logErrorAndExit(noProjectIdError);
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
// Send all files in a single API call
|
|
109
|
+
const response = await sendFiles(allFiles, {
|
|
110
|
+
...options,
|
|
111
|
+
publish: false,
|
|
112
|
+
wait: true,
|
|
113
|
+
});
|
|
114
|
+
const { data, locales, translations } = response;
|
|
115
|
+
// Create file mapping for all file types
|
|
116
|
+
const fileMapping = createFileMapping(filePaths, placeholderPaths, transformPaths, locales, options.defaultLocale);
|
|
117
|
+
// Process any translations that were already completed and returned with the initial response
|
|
118
|
+
const downloadStatus = await processInitialTranslations(translations, fileMapping, options);
|
|
119
|
+
// Check for remaining translations
|
|
120
|
+
await checkFileTranslations(data, locales, 600, (sourcePath, locale) => fileMapping[locale][sourcePath], downloadStatus, // Pass the already downloaded files to avoid duplicate requests
|
|
121
|
+
options);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
logErrorAndExit(`Error translating files: ${error}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Processes translations that were already completed and returned with the initial API response
|
|
129
|
+
* @returns Set of downloaded file+locale combinations
|
|
130
|
+
*/
|
|
131
|
+
async function processInitialTranslations(translations = [], fileMapping, options) {
|
|
132
|
+
const downloadStatus = {
|
|
133
|
+
downloaded: new Set(),
|
|
134
|
+
failed: new Set(),
|
|
135
|
+
};
|
|
136
|
+
if (!translations || translations.length === 0) {
|
|
137
|
+
return downloadStatus;
|
|
138
|
+
}
|
|
139
|
+
// Filter for ready translations
|
|
140
|
+
const readyTranslations = translations.filter((translation) => translation.isReady && translation.fileName);
|
|
141
|
+
if (readyTranslations.length > 0) {
|
|
142
|
+
const spinner = createSpinner('dots');
|
|
143
|
+
spinner.start('Downloading translations...');
|
|
144
|
+
// Prepare batch download data
|
|
145
|
+
const batchFiles = readyTranslations
|
|
146
|
+
.map((translation) => {
|
|
147
|
+
const { locale, fileName, id } = translation;
|
|
148
|
+
const outputPath = fileMapping[locale][fileName];
|
|
149
|
+
if (!outputPath) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
translationId: id,
|
|
154
|
+
inputPath: fileName,
|
|
155
|
+
outputPath,
|
|
156
|
+
fileLocale: `${fileName}:${locale}`,
|
|
157
|
+
locale,
|
|
158
|
+
};
|
|
159
|
+
})
|
|
160
|
+
.filter(Boolean);
|
|
161
|
+
if (batchFiles.length === 0 || batchFiles[0] === null) {
|
|
162
|
+
return downloadStatus;
|
|
163
|
+
}
|
|
164
|
+
// Use batch download if there are multiple files
|
|
165
|
+
if (batchFiles.length > 1) {
|
|
166
|
+
const batchResult = await downloadFileBatch(batchFiles.map(({ translationId, outputPath, inputPath, locale }) => ({
|
|
167
|
+
translationId,
|
|
168
|
+
outputPath,
|
|
169
|
+
inputPath,
|
|
170
|
+
locale,
|
|
171
|
+
})), options);
|
|
172
|
+
// Process results
|
|
173
|
+
batchFiles.forEach((file) => {
|
|
174
|
+
const { translationId, fileLocale } = file;
|
|
175
|
+
if (batchResult.successful.includes(translationId)) {
|
|
176
|
+
downloadStatus.downloaded.add(fileLocale);
|
|
177
|
+
}
|
|
178
|
+
else if (batchResult.failed.includes(translationId)) {
|
|
179
|
+
downloadStatus.failed.add(fileLocale);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
else if (batchFiles.length === 1) {
|
|
184
|
+
// For a single file, use the original downloadFile method
|
|
185
|
+
const file = batchFiles[0];
|
|
186
|
+
const result = await downloadFile(file.translationId, file.outputPath, file.inputPath, file.locale, options);
|
|
187
|
+
if (result) {
|
|
188
|
+
downloadStatus.downloaded.add(file.fileLocale);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
downloadStatus.failed.add(file.fileLocale);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
spinner.stop(chalk.green('Downloaded cached translations'));
|
|
83
195
|
}
|
|
84
|
-
return
|
|
196
|
+
return downloadStatus;
|
|
85
197
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { noSupportedFormatError, noDefaultLocaleError, noApiKeyError, noProjectIdError, devApiKeyError, } from '../../console/index.js';
|
|
2
|
-
import { logErrorAndExit, logError } from '../../console/logging.js';
|
|
2
|
+
import { logErrorAndExit, createSpinner, logError, } from '../../console/logging.js';
|
|
3
3
|
import { getRelative, readFile } from '../../fs/findFilepath.js';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { downloadFile } from '../../api/downloadFile.js';
|
|
6
|
+
import { downloadFileBatch } from '../../api/downloadFileBatch.js';
|
|
4
7
|
import { SUPPORTED_FILE_EXTENSIONS } from './supportedFiles.js';
|
|
5
8
|
import sanitizeFileContent from '../../utils/sanitizeFileContent.js';
|
|
6
9
|
import { parseJson } from '../json/parseJson.js';
|
|
@@ -136,3 +139,74 @@ export async function upload(filePaths, placeholderPaths, transformPaths, dataFo
|
|
|
136
139
|
logErrorAndExit(`Error uploading files: ${error}`);
|
|
137
140
|
}
|
|
138
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Processes translations that were already completed and returned with the initial API response
|
|
144
|
+
* @returns Set of downloaded file+locale combinations
|
|
145
|
+
*/
|
|
146
|
+
async function processInitialTranslations(translations = [], fileMapping, options) {
|
|
147
|
+
const downloadStatus = {
|
|
148
|
+
downloaded: new Set(),
|
|
149
|
+
failed: new Set(),
|
|
150
|
+
};
|
|
151
|
+
if (!translations || translations.length === 0) {
|
|
152
|
+
return downloadStatus;
|
|
153
|
+
}
|
|
154
|
+
// Filter for ready translations
|
|
155
|
+
const readyTranslations = translations.filter((translation) => translation.isReady && translation.fileName);
|
|
156
|
+
if (readyTranslations.length > 0) {
|
|
157
|
+
const spinner = createSpinner('dots');
|
|
158
|
+
spinner.start('Downloading translations...');
|
|
159
|
+
// Prepare batch download data
|
|
160
|
+
const batchFiles = readyTranslations
|
|
161
|
+
.map((translation) => {
|
|
162
|
+
const { locale, fileName, id } = translation;
|
|
163
|
+
const outputPath = fileMapping[locale][fileName];
|
|
164
|
+
if (!outputPath) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
translationId: id,
|
|
169
|
+
outputPath,
|
|
170
|
+
inputPath: fileName,
|
|
171
|
+
fileLocale: `${fileName}:${locale}`,
|
|
172
|
+
locale,
|
|
173
|
+
};
|
|
174
|
+
})
|
|
175
|
+
.filter(Boolean);
|
|
176
|
+
if (batchFiles.length === 0 || batchFiles[0] === null) {
|
|
177
|
+
return downloadStatus;
|
|
178
|
+
}
|
|
179
|
+
// Use batch download if there are multiple files
|
|
180
|
+
if (batchFiles.length > 1) {
|
|
181
|
+
const batchResult = await downloadFileBatch(batchFiles.map(({ translationId, outputPath, inputPath, locale }) => ({
|
|
182
|
+
translationId,
|
|
183
|
+
outputPath,
|
|
184
|
+
inputPath,
|
|
185
|
+
locale,
|
|
186
|
+
})), options);
|
|
187
|
+
// Process results
|
|
188
|
+
batchFiles.forEach((file) => {
|
|
189
|
+
const { translationId, fileLocale } = file;
|
|
190
|
+
if (batchResult.successful.includes(translationId)) {
|
|
191
|
+
downloadStatus.downloaded.add(fileLocale);
|
|
192
|
+
}
|
|
193
|
+
else if (batchResult.failed.includes(translationId)) {
|
|
194
|
+
downloadStatus.failed.add(fileLocale);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
else if (batchFiles.length === 1) {
|
|
199
|
+
// For a single file, use the original downloadFile method
|
|
200
|
+
const file = batchFiles[0];
|
|
201
|
+
const result = await downloadFile(file.translationId, file.outputPath, file.inputPath, file.locale, options);
|
|
202
|
+
if (result) {
|
|
203
|
+
downloadStatus.downloaded.add(file.fileLocale);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
downloadStatus.failed.add(file.fileLocale);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
spinner.stop(chalk.green('Downloaded cached translations'));
|
|
210
|
+
}
|
|
211
|
+
return downloadStatus;
|
|
212
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { RetrievedTranslations } from 'generaltranslation/types';
|
|
2
2
|
import { ResolvedFiles } from '../../types/index.js';
|
|
3
|
+
import { DataFormat } from '../../types/data.js';
|
|
3
4
|
/**
|
|
4
5
|
* Saves translations to a local directory
|
|
5
6
|
* @param translations - The translations to save
|
|
6
7
|
* @param translationsDir - The directory to save the translations to
|
|
7
8
|
* @param fileType - The file type to save the translations as (file extension)
|
|
8
9
|
*/
|
|
9
|
-
export declare function saveTranslations(translations: RetrievedTranslations, placeholderPaths: ResolvedFiles): Promise<void>;
|
|
10
|
+
export declare function saveTranslations(translations: RetrievedTranslations, placeholderPaths: ResolvedFiles, dataFormat: DataFormat): Promise<void>;
|
package/dist/formats/gt/save.js
CHANGED
|
@@ -9,7 +9,7 @@ import { resolveLocaleFiles } from '../../fs/config/parseFilesConfig.js';
|
|
|
9
9
|
* @param translationsDir - The directory to save the translations to
|
|
10
10
|
* @param fileType - The file type to save the translations as (file extension)
|
|
11
11
|
*/
|
|
12
|
-
export async function saveTranslations(translations, placeholderPaths) {
|
|
12
|
+
export async function saveTranslations(translations, placeholderPaths, dataFormat) {
|
|
13
13
|
for (const translation of translations) {
|
|
14
14
|
const locale = translation.locale;
|
|
15
15
|
const translationFiles = resolveLocaleFiles(placeholderPaths, locale);
|
|
@@ -21,6 +21,9 @@ export async function saveTranslations(translations, placeholderPaths) {
|
|
|
21
21
|
const translationData = translation.translation;
|
|
22
22
|
// Ensure directory exists
|
|
23
23
|
await fs.promises.mkdir(path.dirname(filepath), { recursive: true });
|
|
24
|
-
|
|
24
|
+
// Handle different file types
|
|
25
|
+
if (dataFormat === 'JSX') {
|
|
26
|
+
await fs.promises.writeFile(filepath, JSON.stringify(translationData, null, 2));
|
|
27
|
+
}
|
|
25
28
|
}
|
|
26
29
|
}
|
|
@@ -17,7 +17,6 @@ export async function createOrUpdateConfig(configFilepath, options) {
|
|
|
17
17
|
...(options.files && { files: options.files }),
|
|
18
18
|
...(options.framework && { framework: options.framework }),
|
|
19
19
|
...(options.baseUrl && { baseUrl: options.baseUrl }),
|
|
20
|
-
...(options.publish && { publish: options.publish }),
|
|
21
20
|
};
|
|
22
21
|
try {
|
|
23
22
|
// if file exists
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Update the config file version id, locales, and projectId (if necessary)
|
|
3
3
|
* @param {Record<string, any>} configObject - The config object to write if the file does not exist.
|
|
4
4
|
*/
|
|
5
|
-
export default function updateConfig({ configFilepath, projectId, _versionId, stageTranslations, }: {
|
|
5
|
+
export default function updateConfig({ configFilepath, projectId, _versionId, locales, stageTranslations, }: {
|
|
6
6
|
configFilepath: string;
|
|
7
7
|
projectId?: string;
|
|
8
8
|
_versionId?: string;
|
|
9
|
+
locales?: string[];
|
|
9
10
|
stageTranslations?: boolean;
|
|
10
11
|
}): Promise<void>;
|
|
@@ -5,7 +5,7 @@ import { logError } from '../../console/logging.js';
|
|
|
5
5
|
* Update the config file version id, locales, and projectId (if necessary)
|
|
6
6
|
* @param {Record<string, any>} configObject - The config object to write if the file does not exist.
|
|
7
7
|
*/
|
|
8
|
-
export default async function updateConfig({ configFilepath, projectId, _versionId, stageTranslations, }) {
|
|
8
|
+
export default async function updateConfig({ configFilepath, projectId, _versionId, locales, stageTranslations, }) {
|
|
9
9
|
// Filter out empty string values from the config object
|
|
10
10
|
const newContent = {
|
|
11
11
|
...(projectId && { projectId }),
|
package/dist/fs/copyFile.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Settings } from '../types/index.js';
|
|
2
|
+
import { TranslateOptions } from '../cli/base.js';
|
|
2
3
|
/**
|
|
3
4
|
* Copy a file to target locale without translation
|
|
4
5
|
*
|
|
5
6
|
* This is a naive approach, does not allow for wild cards
|
|
6
7
|
*/
|
|
7
|
-
export default function copyFile(settings: Settings): Promise<void>;
|
|
8
|
+
export default function copyFile(settings: Settings & TranslateOptions): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Options, GenerateSourceOptions, Updates } from '../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Searches for gt-react or gt-next dictionary files and creates updates for them,
|
|
4
4
|
* as well as inline updates for <T> tags and useGT()/getGT() calls
|
|
@@ -8,7 +8,7 @@ import { Updates, TranslateFlags } from '../types/index.js';
|
|
|
8
8
|
* @param pkg - The package name
|
|
9
9
|
* @returns An object containing the updates and errors
|
|
10
10
|
*/
|
|
11
|
-
export declare function createUpdates(options:
|
|
11
|
+
export declare function createUpdates(options: Options | GenerateSourceOptions, sourceDictionary: string | undefined, pkg: 'gt-react' | 'gt-next', validate: boolean): Promise<{
|
|
12
12
|
updates: Updates;
|
|
13
13
|
errors: string[];
|
|
14
14
|
warnings: string[];
|
|
@@ -48,10 +48,12 @@ export async function createUpdates(options, sourceDictionary, pkg, validate) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
// Scan through project for <T> tags
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
if (options.inline) {
|
|
52
|
+
const { updates: newUpdates, errors: newErrors, warnings: newWarnings, } = await createInlineUpdates(pkg, validate, options.src);
|
|
53
|
+
errors = [...errors, ...newErrors];
|
|
54
|
+
warnings = [...warnings, ...newWarnings];
|
|
55
|
+
updates = [...updates, ...newUpdates];
|
|
56
|
+
}
|
|
55
57
|
// Metadata addition and validation
|
|
56
58
|
const idHashMap = new Map();
|
|
57
59
|
const duplicateIds = new Set();
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function
|
|
1
|
+
import { Options, Settings } from '../types/index.js';
|
|
2
|
+
export declare function stageProject(settings: Options & Settings, pkg: 'gt-react' | 'gt-next'): Promise<{
|
|
3
|
+
versionId: string;
|
|
4
|
+
locales: string[];
|
|
5
|
+
} | null>;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { devApiKeyError } from '../console/index.js';
|
|
1
2
|
import { logErrorAndExit } from '../console/logging.js';
|
|
2
3
|
import chalk from 'chalk';
|
|
3
4
|
import findFilepath from '../fs/findFilepath.js';
|
|
4
|
-
import { logWarning, logError } from '../console/logging.js';
|
|
5
|
+
import { logSuccess, logWarning, logError } from '../console/logging.js';
|
|
5
6
|
import { createUpdates } from './parse.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import { noLocalesError, noDefaultLocaleError, noProjectIdError, noApiKeyError, } from '../console/index.js';
|
|
8
|
+
import { sendUpdates } from '../api/sendUpdates.js';
|
|
9
|
+
export async function stageProject(settings, pkg) {
|
|
10
|
+
if (!settings.dictionary) {
|
|
11
|
+
settings.dictionary = findFilepath([
|
|
9
12
|
'./dictionary.js',
|
|
10
13
|
'./src/dictionary.js',
|
|
11
14
|
'./dictionary.json',
|
|
@@ -14,16 +17,29 @@ export async function aggregateReactTranslations(options, settings, library) {
|
|
|
14
17
|
'./src/dictionary.ts',
|
|
15
18
|
]);
|
|
16
19
|
}
|
|
20
|
+
// Separate defaultLocale from locales
|
|
21
|
+
settings.locales = settings.locales.filter((locale) => locale !== settings.defaultLocale);
|
|
22
|
+
// validate timeout
|
|
23
|
+
const timeout = parseInt(settings.timeout);
|
|
24
|
+
if (isNaN(timeout) || timeout < 0) {
|
|
25
|
+
logErrorAndExit(`Invalid timeout: ${settings.timeout}. Must be a positive integer.`);
|
|
26
|
+
}
|
|
27
|
+
settings.timeout = timeout.toString();
|
|
17
28
|
// ---- CREATING UPDATES ---- //
|
|
18
|
-
const { updates, errors, warnings } = await createUpdates(
|
|
29
|
+
const { updates, errors, warnings } = await createUpdates(settings, settings.dictionary, pkg, false);
|
|
19
30
|
if (warnings.length > 0) {
|
|
20
|
-
|
|
21
|
-
warnings
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
if (settings.suppressWarnings) {
|
|
32
|
+
logWarning(chalk.yellow(`CLI tool encountered ${warnings.length} warnings while scanning for translatable content. ${chalk.gray('To view these warnings, re-run without the --suppress-warnings flag')}`));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
logWarning(chalk.yellow(`CLI tool encountered ${warnings.length} warnings while scanning for translatable content. ${chalk.gray('To suppress these warnings, re-run with --suppress-warnings')}\n` +
|
|
36
|
+
warnings
|
|
37
|
+
.map((warning) => chalk.yellow('• Warning: ') + chalk.white(warning))
|
|
38
|
+
.join('\n')));
|
|
39
|
+
}
|
|
24
40
|
}
|
|
25
41
|
if (errors.length > 0) {
|
|
26
|
-
if (
|
|
42
|
+
if (settings.ignoreErrors) {
|
|
27
43
|
logWarning(chalk.yellow(`Warning: CLI tool encountered ${errors.length} syntax errors while scanning for translatable content. These components will not be translated.\n` +
|
|
28
44
|
errors
|
|
29
45
|
.map((error) => chalk.yellow('• ') + chalk.white(error) + '\n')
|
|
@@ -36,9 +52,35 @@ export async function aggregateReactTranslations(options, settings, library) {
|
|
|
36
52
|
.join('')));
|
|
37
53
|
}
|
|
38
54
|
}
|
|
55
|
+
if (settings.dryRun) {
|
|
56
|
+
logSuccess('Dry run: No translations were sent to General Translation.');
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
39
59
|
if (updates.length == 0) {
|
|
40
|
-
logError(chalk.red(`No in-line content or dictionaries were found for ${chalk.green(
|
|
41
|
-
return
|
|
60
|
+
logError(chalk.red(`No in-line content or dictionaries were found for ${chalk.green(pkg)}. Are you sure you're running this command in the right directory?`));
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
// Send updates to General Translation API
|
|
64
|
+
if (!settings.locales) {
|
|
65
|
+
logErrorAndExit(noLocalesError);
|
|
66
|
+
}
|
|
67
|
+
if (!settings.defaultLocale) {
|
|
68
|
+
logErrorAndExit(noDefaultLocaleError);
|
|
69
|
+
}
|
|
70
|
+
if (!settings.apiKey) {
|
|
71
|
+
logErrorAndExit(noApiKeyError);
|
|
72
|
+
}
|
|
73
|
+
if (settings.apiKey.startsWith('gtx-dev-')) {
|
|
74
|
+
logErrorAndExit(devApiKeyError);
|
|
75
|
+
}
|
|
76
|
+
if (!settings.projectId) {
|
|
77
|
+
logErrorAndExit(noProjectIdError);
|
|
42
78
|
}
|
|
43
|
-
|
|
79
|
+
const updateResponse = await sendUpdates(updates, {
|
|
80
|
+
...settings,
|
|
81
|
+
timeout: settings.timeout,
|
|
82
|
+
dataFormat: 'JSX',
|
|
83
|
+
}, pkg);
|
|
84
|
+
const { versionId, locales } = updateResponse;
|
|
85
|
+
return { versionId, locales };
|
|
44
86
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { fetchTranslations } from '../api/fetchTranslations.js';
|
|
2
|
+
import { waitForUpdates } from '../api/waitForUpdates.js';
|
|
3
|
+
import { saveTranslations } from '../formats/gt/save.js';
|
|
4
|
+
import { isUsingLocalTranslations } from '../config/utils.js';
|
|
5
|
+
export async function translate(settings, versionId) {
|
|
6
|
+
// timeout was validated earlier
|
|
7
|
+
const startTime = Date.now();
|
|
8
|
+
const timeout = parseInt(settings.timeout) * 1000;
|
|
9
|
+
const result = await waitForUpdates(versionId, startTime, timeout);
|
|
10
|
+
if (!result) {
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
const translations = await fetchTranslations(versionId);
|
|
14
|
+
// Save translations to local directory if files.gt.output is provided
|
|
15
|
+
if (settings.files && isUsingLocalTranslations(settings)) {
|
|
16
|
+
await saveTranslations(translations, settings.files.placeholderPaths, 'JSX');
|
|
17
|
+
}
|
|
18
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -15,35 +15,13 @@ export type Options = {
|
|
|
15
15
|
ignoreErrors: boolean;
|
|
16
16
|
suppressWarnings: boolean;
|
|
17
17
|
dryRun: boolean;
|
|
18
|
-
timeout:
|
|
18
|
+
timeout: string;
|
|
19
19
|
stageTranslations?: boolean;
|
|
20
20
|
experimentalLocalizeStaticUrls?: boolean;
|
|
21
21
|
experimentalHideDefaultLocale?: boolean;
|
|
22
22
|
experimentalFlattenJsonFiles?: boolean;
|
|
23
23
|
experimentalLocalizeStaticImports?: boolean;
|
|
24
24
|
};
|
|
25
|
-
export type TranslateFlags = {
|
|
26
|
-
config?: string;
|
|
27
|
-
apiKey?: string;
|
|
28
|
-
projectId?: string;
|
|
29
|
-
versionId?: string;
|
|
30
|
-
jsconfig?: string;
|
|
31
|
-
dictionary?: string;
|
|
32
|
-
defaultLocale?: string;
|
|
33
|
-
locales?: string[];
|
|
34
|
-
ignoreErrors?: boolean;
|
|
35
|
-
src?: string[];
|
|
36
|
-
timeout: number;
|
|
37
|
-
dryRun: boolean;
|
|
38
|
-
stageTranslations?: boolean;
|
|
39
|
-
publish?: boolean;
|
|
40
|
-
experimentalLocalizeStaticUrls?: boolean;
|
|
41
|
-
experimentalHideDefaultLocale?: boolean;
|
|
42
|
-
experimentalFlattenJsonFiles?: boolean;
|
|
43
|
-
experimentalLocalizeStaticImports?: boolean;
|
|
44
|
-
excludeStaticUrls?: string[];
|
|
45
|
-
excludeStaticImports?: string[];
|
|
46
|
-
};
|
|
47
25
|
export type WrapOptions = {
|
|
48
26
|
src?: string[];
|
|
49
27
|
config: string;
|
|
@@ -102,11 +80,10 @@ export type FilesOptions = {
|
|
|
102
80
|
};
|
|
103
81
|
export type Settings = {
|
|
104
82
|
config: string;
|
|
105
|
-
configDirectory: string;
|
|
106
83
|
baseUrl: string;
|
|
107
84
|
dashboardUrl: string;
|
|
108
|
-
apiKey
|
|
109
|
-
projectId
|
|
85
|
+
apiKey: string;
|
|
86
|
+
projectId: string;
|
|
110
87
|
defaultLocale: string;
|
|
111
88
|
locales: string[];
|
|
112
89
|
files: {
|
|
@@ -115,7 +92,6 @@ export type Settings = {
|
|
|
115
92
|
transformPaths: TransformFiles;
|
|
116
93
|
} | undefined;
|
|
117
94
|
stageTranslations: boolean;
|
|
118
|
-
publish: boolean;
|
|
119
95
|
_versionId?: string;
|
|
120
96
|
version?: string;
|
|
121
97
|
description?: string;
|
|
@@ -141,6 +117,7 @@ export type AdditionalOptions = {
|
|
|
141
117
|
experimentalLocalizeStaticUrls?: boolean;
|
|
142
118
|
experimentalHideDefaultLocale?: boolean;
|
|
143
119
|
experimentalFlattenJsonFiles?: boolean;
|
|
120
|
+
baseDomain?: string;
|
|
144
121
|
};
|
|
145
122
|
export type JsonSchema = {
|
|
146
123
|
preset?: 'mintlify';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Settings } from '../types/index.js';
|
|
2
|
-
export default function flattenJsonFiles(settings: Settings): Promise<void>;
|
|
1
|
+
import { Settings, Options } from '../types/index.js';
|
|
2
|
+
export default function flattenJsonFiles(settings: Omit<Settings & Options, 'ignoreErrors' | 'suppressWarnings' | 'timeout'>): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Settings } from '../types/index.js';
|
|
1
|
+
import { Options, Settings } from '../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Localizes static imports in content files.
|
|
4
4
|
* Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
|
|
@@ -12,4 +12,4 @@ import { Settings } from '../types/index.js';
|
|
|
12
12
|
* - Support more file types
|
|
13
13
|
* - Support more complex paths
|
|
14
14
|
*/
|
|
15
|
-
export default function localizeStaticImports(settings: Settings): Promise<void>;
|
|
15
|
+
export default function localizeStaticImports(settings: Omit<Settings & Options, 'ignoreErrors' | 'suppressWarnings' | 'timeout'>): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Settings } from '../types/index.js';
|
|
1
|
+
import { Options, Settings } from '../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Localizes static urls in content files.
|
|
4
4
|
* Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
|
|
@@ -12,4 +12,8 @@ import { Settings } from '../types/index.js';
|
|
|
12
12
|
* - Support more file types
|
|
13
13
|
* - Support more complex paths
|
|
14
14
|
*/
|
|
15
|
-
export default function localizeStaticUrls(settings: Settings): Promise<void>;
|
|
15
|
+
export default function localizeStaticUrls(settings: Omit<Settings & Options, 'ignoreErrors' | 'suppressWarnings' | 'timeout'>, targetLocales?: string[]): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Main URL transformation function that delegates to specific scenarios
|
|
18
|
+
*/
|
|
19
|
+
export declare function transformUrlPath(originalUrl: string, patternHead: string, targetLocale: string, defaultLocale: string, hideDefaultLocale: boolean): string | null;
|