gtx-cli 1.2.30-alpha.35 → 1.2.31-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -18
- package/dist/api/sendFiles.d.ts +2 -9
- package/dist/api/sendFiles.js +2 -2
- package/dist/cli/base.js +14 -14
- package/dist/cli/react.js +8 -21
- package/dist/config/generateSettings.d.ts +0 -1
- package/dist/config/generateSettings.js +21 -31
- package/dist/console/index.d.ts +2 -1
- package/dist/console/index.js +2 -1
- package/dist/formats/files/supportedFiles.d.ts +1 -1
- package/dist/formats/files/supportedFiles.js +1 -1
- package/dist/formats/files/translate.d.ts +1 -4
- package/dist/formats/files/translate.js +7 -8
- package/dist/fs/config/loadConfig.d.ts +1 -1
- package/dist/fs/config/loadConfig.js +1 -1
- package/dist/fs/config/parseFilesConfig.js +12 -13
- package/dist/fs/config/setupConfig.d.ts +0 -1
- package/dist/fs/config/setupConfig.js +0 -1
- package/dist/fs/findJsxFilepath.d.ts +7 -0
- package/dist/fs/findJsxFilepath.js +30 -0
- package/dist/next/parse/wrapContent.js +4 -4
- package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.d.ts +1 -8
- package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.js +63 -90
- package/dist/react/jsx/parse/parseStringFunction.d.ts +12 -0
- package/dist/react/jsx/parse/parseStringFunction.js +80 -0
- package/dist/react/jsx/utils/constants.d.ts +0 -2
- package/dist/react/jsx/utils/constants.js +0 -8
- package/dist/react/jsx/utils/parseJsx.d.ts +1 -8
- package/dist/react/jsx/utils/parseJsx.js +14 -26
- package/dist/react/jsx/utils/parseStringFunction.d.ts +1 -0
- package/dist/react/jsx/utils/parseStringFunction.js +8 -7
- package/dist/react/parse/createDictionaryUpdates.d.ts +2 -2
- package/dist/react/parse/createDictionaryUpdates.js +13 -112
- package/dist/react/parse/createInlineUpdates.js +34 -7
- package/dist/react/parse/wrapContent.js +4 -5
- package/dist/react/utils/getVariableName.d.ts +1 -24
- package/dist/react/utils/getVariableName.js +7 -31
- package/dist/translation/parse.js +2 -2
- package/dist/translation/stage.js +1 -1
- package/dist/types/data.d.ts +1 -1
- package/dist/types/index.d.ts +4 -7
- package/package.json +2 -2
- package/dist/config/resolveConfig.d.ts +0 -4
- package/dist/config/resolveConfig.js +0 -19
- package/dist/fs/matchFiles.d.ts +0 -2
- package/dist/fs/matchFiles.js +0 -10
- package/dist/utils/flattenJsonFiles.d.ts +0 -2
- package/dist/utils/flattenJsonFiles.js +0 -36
- package/dist/utils/localizeStaticUrls.d.ts +0 -15
- package/dist/utils/localizeStaticUrls.js +0 -78
- package/dist/utils/sanitizeFileContent.d.ts +0 -6
- package/dist/utils/sanitizeFileContent.js +0 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,23 +1,5 @@
|
|
|
1
1
|
# gtx-cli
|
|
2
2
|
|
|
3
|
-
## 1.2.34
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- [#428](https://github.com/generaltranslation/gt/pull/428) [`54036f5`](https://github.com/generaltranslation/gt/commit/54036f54308bdb9f9e6dcec93871e004dcf1be4c) Thanks [@ErnestM1234](https://github.com/ErnestM1234)! - feat: add experimental options to translate
|
|
8
|
-
|
|
9
|
-
## 1.2.33
|
|
10
|
-
|
|
11
|
-
### Patch Changes
|
|
12
|
-
|
|
13
|
-
- [#426](https://github.com/generaltranslation/gt/pull/426) [`ce57545`](https://github.com/generaltranslation/gt/commit/ce575454301185c663cfb93345d3058c9ceb25dd) Thanks [@brian-lou](https://github.com/brian-lou)! - Improve file pattern matching
|
|
14
|
-
|
|
15
|
-
## 1.2.31
|
|
16
|
-
|
|
17
|
-
### Patch Changes
|
|
18
|
-
|
|
19
|
-
- [#423](https://github.com/generaltranslation/gt/pull/423) [`0ed08c7`](https://github.com/generaltranslation/gt/commit/0ed08c7bb1e63c99296b74138e4d44b718681fc8) Thanks [@brian-lou](https://github.com/brian-lou)! - Add setting configuration options
|
|
20
|
-
|
|
21
3
|
## 1.2.30
|
|
22
4
|
|
|
23
5
|
### Patch Changes
|
package/dist/api/sendFiles.d.ts
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
import { Settings } from '../types/index.js';
|
|
2
|
-
import {
|
|
3
|
-
/**
|
|
4
|
-
* File object structure
|
|
5
|
-
* @param content - The content of the file
|
|
6
|
-
* @param fileName - The name of the file
|
|
7
|
-
* @param fileExtension - The format of the file (JSON, MDX, MD, etc.)
|
|
8
|
-
* @param dataFormat - The format of the data within the file
|
|
9
|
-
*/
|
|
2
|
+
import { FileFormats, DataFormat } from '../types/data.js';
|
|
10
3
|
export interface FileToTranslate {
|
|
11
4
|
content: string;
|
|
12
5
|
fileName: string;
|
|
13
|
-
|
|
6
|
+
fileFormat: FileFormats;
|
|
14
7
|
dataFormat: DataFormat;
|
|
15
8
|
}
|
|
16
9
|
type ApiOptions = Settings & {
|
package/dist/api/sendFiles.js
CHANGED
|
@@ -19,8 +19,8 @@ export async function sendFiles(files, options) {
|
|
|
19
19
|
// Add each file to the form data
|
|
20
20
|
files.forEach((file, index) => {
|
|
21
21
|
formData.append(`file${index}`, new Blob([file.content]), file.fileName);
|
|
22
|
-
formData.append(`
|
|
23
|
-
formData.append(`
|
|
22
|
+
formData.append(`fileFormat${index}`, file.fileFormat);
|
|
23
|
+
formData.append(`fileDataFormat${index}`, file.dataFormat); // Only used when translating JSON files
|
|
24
24
|
formData.append(`fileName${index}`, file.fileName);
|
|
25
25
|
});
|
|
26
26
|
// Add number of files
|
package/dist/cli/base.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createOrUpdateConfig } from '../fs/config/setupConfig.js';
|
|
2
|
-
import findFilepath from '../fs/findFilepath.js';
|
|
2
|
+
import findFilepath, { findFilepaths } from '../fs/findFilepath.js';
|
|
3
3
|
import { displayHeader, promptText, logErrorAndExit, endCommand, promptConfirm, promptMultiSelect, logSuccess, logInfo, startCommand, createSpinner, logMessage, } from '../console/logging.js';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import { generateSettings } from '../config/generateSettings.js';
|
|
7
7
|
import chalk from 'chalk';
|
|
8
8
|
import { translateFiles } from '../formats/files/translate.js';
|
|
9
|
-
import {
|
|
9
|
+
import { FILE_EXT_TO_FORMAT } from '../formats/files/supportedFiles.js';
|
|
10
10
|
import { handleSetupReactCommand } from '../setup/wizard.js';
|
|
11
11
|
import { isPackageInstalled, searchForPackageJson, } from '../utils/packageJson.js';
|
|
12
12
|
import { getDesiredLocales } from '../setup/userInput.js';
|
|
@@ -94,7 +94,7 @@ export class BaseCLI {
|
|
|
94
94
|
this.program
|
|
95
95
|
.command('init')
|
|
96
96
|
.description('Run the setup wizard to configure your project for General Translation')
|
|
97
|
-
.option('--src <paths...>', "
|
|
97
|
+
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components", findFilepaths(['./src', './app', './pages', './components']))
|
|
98
98
|
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', findFilepath(['gt.config.json']))
|
|
99
99
|
.action(async (options) => {
|
|
100
100
|
displayHeader('Running setup wizard...');
|
|
@@ -139,7 +139,7 @@ See the docs for more information: https://generaltranslation.com/docs/react/tut
|
|
|
139
139
|
this.program
|
|
140
140
|
.command('setup')
|
|
141
141
|
.description('Run the setup to configure your Next.js or React project for General Translation')
|
|
142
|
-
.option('--src <paths...>', "
|
|
142
|
+
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components", findFilepaths(['./src', './app', './pages', './components']))
|
|
143
143
|
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', findFilepath(['gt.config.json']))
|
|
144
144
|
.action(async (options) => {
|
|
145
145
|
displayHeader('Running React setup wizard...');
|
|
@@ -210,24 +210,24 @@ See the docs for more information: https://generaltranslation.com/docs/react/tut
|
|
|
210
210
|
const message = !isUsingGT
|
|
211
211
|
? 'What is the format of your language resource files? Select as many as applicable.\nAdditionally, you can translate any other files you have in your project.'
|
|
212
212
|
: `${chalk.dim('(Optional)')} Do you have any separate files you would like to translate? For example, extra Markdown files for docs.`;
|
|
213
|
-
const
|
|
213
|
+
const dataFormats = await promptMultiSelect({
|
|
214
214
|
message,
|
|
215
215
|
options: [
|
|
216
|
-
{ value: 'json', label:
|
|
217
|
-
{ value: 'md', label:
|
|
218
|
-
{ value: 'mdx', label:
|
|
219
|
-
{ value: 'ts', label:
|
|
220
|
-
{ value: 'js', label:
|
|
216
|
+
{ value: 'json', label: 'JSON' },
|
|
217
|
+
{ value: 'md', label: 'Markdown' },
|
|
218
|
+
{ value: 'mdx', label: 'MDX' },
|
|
219
|
+
{ value: 'ts', label: 'TypeScript' },
|
|
220
|
+
{ value: 'js', label: 'JavaScript' },
|
|
221
221
|
],
|
|
222
222
|
required: !isUsingGT,
|
|
223
223
|
});
|
|
224
224
|
const files = {};
|
|
225
|
-
for (const
|
|
225
|
+
for (const dataFormat of dataFormats) {
|
|
226
226
|
const paths = await promptText({
|
|
227
|
-
message: `${chalk.cyan(
|
|
228
|
-
defaultValue: `./**/[locale]/*.${
|
|
227
|
+
message: `${chalk.cyan(FILE_EXT_TO_FORMAT[dataFormat])}: Please enter a space-separated list of glob patterns matching the location of the ${FILE_EXT_TO_FORMAT[dataFormat]} files you would like to translate.\nMake sure to include [locale] in the patterns.\nSee https://generaltranslation.com/docs/cli/reference/config#include for more information.`,
|
|
228
|
+
defaultValue: `./**/[locale]/*.${dataFormat}`,
|
|
229
229
|
});
|
|
230
|
-
files[
|
|
230
|
+
files[dataFormat] = {
|
|
231
231
|
include: paths.split(' '),
|
|
232
232
|
};
|
|
233
233
|
}
|
package/dist/cli/react.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { displayHeader, endCommand, logError, logErrorAndExit, logStep, logSuccess, logWarning, promptConfirm, } from '../console/logging.js';
|
|
2
2
|
import loadJSON from '../fs/loadJSON.js';
|
|
3
|
-
import findFilepath from '../fs/findFilepath.js';
|
|
3
|
+
import findFilepath, { findFilepaths } from '../fs/findFilepath.js';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import { formatFiles } from '../hooks/postProcess.js';
|
|
6
6
|
import { BaseCLI } from './base.js';
|
|
@@ -16,8 +16,6 @@ import updateConfig from '../fs/config/updateConfig.js';
|
|
|
16
16
|
import { validateConfigExists } from '../config/validateSettings.js';
|
|
17
17
|
import { validateProject } from '../translation/validate.js';
|
|
18
18
|
import { intro } from '@clack/prompts';
|
|
19
|
-
import localizeStaticUrls from '../utils/localizeStaticUrls.js';
|
|
20
|
-
import flattenJsonFiles from '../utils/flattenJsonFiles.js';
|
|
21
19
|
const DEFAULT_TIMEOUT = 600;
|
|
22
20
|
const pkg = 'gt-react';
|
|
23
21
|
export class ReactCLI extends BaseCLI {
|
|
@@ -47,7 +45,7 @@ export class ReactCLI extends BaseCLI {
|
|
|
47
45
|
.option('--version-id <id>', 'Version ID for the translation service')
|
|
48
46
|
.option('--tsconfig, --jsconfig <path>', 'Path to jsconfig or tsconfig file', findFilepath(['./tsconfig.json', './jsconfig.json']))
|
|
49
47
|
.option('--dictionary <path>', 'Path to dictionary file')
|
|
50
|
-
.option('--src <paths...>', "
|
|
48
|
+
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components")
|
|
51
49
|
.option('--default-language, --default-locale <locale>', 'Default locale (e.g., en)')
|
|
52
50
|
.option('--new, --locales <locales...>', 'Space-separated list of locales (e.g., en fr es)')
|
|
53
51
|
.option('--inline', 'Include inline <T> tags in addition to dictionary file', true)
|
|
@@ -70,16 +68,13 @@ export class ReactCLI extends BaseCLI {
|
|
|
70
68
|
.option('--version-id <id>', 'Version ID for the translation service')
|
|
71
69
|
.option('--tsconfig, --jsconfig <path>', 'Path to jsconfig or tsconfig file', findFilepath(['./tsconfig.json', './jsconfig.json']))
|
|
72
70
|
.option('--dictionary <path>', 'Path to dictionary file')
|
|
73
|
-
.option('--src <paths...>', "
|
|
71
|
+
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components")
|
|
74
72
|
.option('--default-language, --default-locale <locale>', 'Default locale (e.g., en)')
|
|
75
73
|
.option('--new, --locales <locales...>', 'Space-separated list of locales (e.g., en fr es)')
|
|
76
74
|
.option('--inline', 'Include inline <T> tags in addition to dictionary file', true)
|
|
77
75
|
.option('--ignore-errors', 'Ignore errors encountered while scanning for <T> tags', false)
|
|
78
76
|
.option('--dry-run', 'Dry run, does not send updates to General Translation API', false)
|
|
79
77
|
.option('--timeout <seconds>', 'Timeout in seconds for waiting for updates to be deployed to the CDN', DEFAULT_TIMEOUT.toString())
|
|
80
|
-
.option('--experimental-localize-static-urls', 'Triggering this will run a script after the cli tool that localizes all urls in content files. Currently only supported for md and mdx files.', false)
|
|
81
|
-
.option('--experimental-hide-default-locale', 'When localizing static locales, hide the default locale from the path', false)
|
|
82
|
-
.option('--experimental-flatten-json-files', 'Triggering this will flatten the json files into a single file. This is useful for projects that have a lot of json files.', false)
|
|
83
78
|
.action(async (options) => {
|
|
84
79
|
displayHeader('Translating project...');
|
|
85
80
|
await this.handleTranslate(options);
|
|
@@ -93,7 +88,7 @@ export class ReactCLI extends BaseCLI {
|
|
|
93
88
|
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', findFilepath(['gt.config.json']))
|
|
94
89
|
.option('--tsconfig, --jsconfig <path>', 'Path to jsconfig or tsconfig file', findFilepath(['./tsconfig.json', './jsconfig.json']))
|
|
95
90
|
.option('--dictionary <path>', 'Path to dictionary file')
|
|
96
|
-
.option('--src <paths...>', "
|
|
91
|
+
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components")
|
|
97
92
|
.option('--inline', 'Include inline <T> tags in addition to dictionary file', true)
|
|
98
93
|
.action(async (options) => {
|
|
99
94
|
// intro here since we don't want to show the ascii title
|
|
@@ -106,7 +101,7 @@ export class ReactCLI extends BaseCLI {
|
|
|
106
101
|
this.program
|
|
107
102
|
.command('generate')
|
|
108
103
|
.description('Generate a translation file for the source locale. The -t flag must be provided. This command should be used if you are handling your own translations.')
|
|
109
|
-
.option('--src <paths...>', "
|
|
104
|
+
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components")
|
|
110
105
|
.option('--tsconfig, --jsconfig <path>', 'Path to jsconfig or tsconfig file', findFilepath(['./tsconfig.json', './jsconfig.json']))
|
|
111
106
|
.option('--dictionary <path>', 'Path to dictionary file')
|
|
112
107
|
.option('--default-language, --default-locale <locale>', 'Source locale (e.g., en)')
|
|
@@ -123,7 +118,7 @@ export class ReactCLI extends BaseCLI {
|
|
|
123
118
|
this.program
|
|
124
119
|
.command('scan')
|
|
125
120
|
.description('Scans the project and wraps all JSX elements in the src directory with a <T> tag, with unique ids')
|
|
126
|
-
.option('--src <paths...>', "
|
|
121
|
+
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components", findFilepaths(['./src', './app', './pages', './components']))
|
|
127
122
|
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', findFilepath(['gt.config.json']))
|
|
128
123
|
.option('--disable-ids', 'Disable id generation for the <T> tags', false)
|
|
129
124
|
.option('--disable-formatting', 'Disable formatting of edited files', false)
|
|
@@ -158,7 +153,7 @@ export class ReactCLI extends BaseCLI {
|
|
|
158
153
|
.join('\n')));
|
|
159
154
|
}
|
|
160
155
|
else {
|
|
161
|
-
logErrorAndExit(chalk.red(`CLI tool encountered errors while scanning for translatable content. ${chalk.
|
|
156
|
+
logErrorAndExit(chalk.red(`CLI tool encountered errors while scanning for translatable content. ${chalk.dim('To ignore these errors, re-run with --ignore-errors')}\n` +
|
|
162
157
|
errors
|
|
163
158
|
.map((error) => chalk.red('• Error: ') + chalk.white(error))
|
|
164
159
|
.join('\n')));
|
|
@@ -267,7 +262,7 @@ export class ReactCLI extends BaseCLI {
|
|
|
267
262
|
await super.handleGenericTranslate(options);
|
|
268
263
|
// If the base class's handleTranslate completes successfully, continue with ReactCLI-specific code
|
|
269
264
|
}
|
|
270
|
-
catch {
|
|
265
|
+
catch (error) {
|
|
271
266
|
// Continue with ReactCLI-specific code even if base handleTranslate failed
|
|
272
267
|
}
|
|
273
268
|
if (!settings.stageTranslations) {
|
|
@@ -285,14 +280,6 @@ export class ReactCLI extends BaseCLI {
|
|
|
285
280
|
}
|
|
286
281
|
await translate(options, settings._versionId);
|
|
287
282
|
}
|
|
288
|
-
// Localize static urls (/docs -> /[locale]/docs)
|
|
289
|
-
if (options.experimentalLocalizeStaticUrls) {
|
|
290
|
-
await localizeStaticUrls(options);
|
|
291
|
-
}
|
|
292
|
-
// Flatten json files into a single file
|
|
293
|
-
if (options.experimentalFlattenJsonFiles) {
|
|
294
|
-
await flattenJsonFiles(options);
|
|
295
|
-
}
|
|
296
283
|
}
|
|
297
284
|
async handleValidate(initOptions) {
|
|
298
285
|
validateConfigExists();
|
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
import { displayProjectId,
|
|
2
|
-
import
|
|
1
|
+
import { displayProjectId, warnApiKeyInConfig } from '../console/logging.js';
|
|
2
|
+
import loadConfig from '../fs/config/loadConfig.js';
|
|
3
3
|
import { defaultBaseUrl, libraryDefaultLocale, } from 'generaltranslation/internal';
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import { createOrUpdateConfig } from '../fs/config/setupConfig.js';
|
|
6
6
|
import { resolveFiles } from '../fs/config/parseFilesConfig.js';
|
|
7
|
+
import { findFilepaths } from '../fs/findFilepath.js';
|
|
7
8
|
import { validateSettings } from './validateSettings.js';
|
|
8
9
|
import { GT_DASHBOARD_URL } from '../utils/constants.js';
|
|
9
10
|
import { resolveProjectId } from '../fs/utils.js';
|
|
10
11
|
import path from 'node:path';
|
|
11
|
-
import chalk from 'chalk';
|
|
12
|
-
import { resolveConfig } from './resolveConfig.js';
|
|
13
|
-
export const DEFAULT_SRC_PATTERNS = [
|
|
14
|
-
'src/**/*.{js,jsx,ts,tsx}',
|
|
15
|
-
'app/**/*.{js,jsx,ts,tsx}',
|
|
16
|
-
'pages/**/*.{js,jsx,ts,tsx}',
|
|
17
|
-
'components/**/*.{js,jsx,ts,tsx}',
|
|
18
|
-
];
|
|
19
12
|
/**
|
|
20
13
|
* Generates settings from any
|
|
21
14
|
* @param options - The options to generate settings from
|
|
@@ -31,33 +24,23 @@ export async function generateSettings(options, cwd = process.cwd()) {
|
|
|
31
24
|
if (options.config) {
|
|
32
25
|
gtConfig = loadConfig(options.config);
|
|
33
26
|
}
|
|
27
|
+
else if (fs.existsSync(path.join(cwd, 'gt.config.json'))) {
|
|
28
|
+
options.config = path.join(cwd, 'gt.config.json');
|
|
29
|
+
gtConfig = loadConfig(options.config);
|
|
30
|
+
}
|
|
31
|
+
else if (fs.existsSync(path.join(cwd, 'src/gt.config.json'))) {
|
|
32
|
+
options.config = path.join(cwd, 'src/gt.config.json');
|
|
33
|
+
gtConfig = loadConfig(options.config);
|
|
34
|
+
}
|
|
34
35
|
else {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
gtConfig = config.config;
|
|
38
|
-
options.config = config.path;
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
gtConfig = {};
|
|
42
|
-
}
|
|
36
|
+
// If neither config exists, use empty config
|
|
37
|
+
gtConfig = {};
|
|
43
38
|
}
|
|
44
39
|
// Warn if apiKey is present in gt.config.json
|
|
45
40
|
if (gtConfig.apiKey) {
|
|
46
41
|
warnApiKeyInConfig(options.config);
|
|
47
42
|
process.exit(1);
|
|
48
43
|
}
|
|
49
|
-
const projectIdEnv = resolveProjectId();
|
|
50
|
-
// Resolve mismatched projectIds
|
|
51
|
-
if (gtConfig.projectId &&
|
|
52
|
-
options.projectId &&
|
|
53
|
-
gtConfig.projectId !== options.projectId) {
|
|
54
|
-
logErrorAndExit(`Project ID mismatch between ${chalk.green(gtConfig.projectId)} and ${chalk.green(options.projectId)}! Please use the same projectId in all configs.`);
|
|
55
|
-
}
|
|
56
|
-
else if (gtConfig.projectId &&
|
|
57
|
-
projectIdEnv &&
|
|
58
|
-
gtConfig.projectId !== projectIdEnv) {
|
|
59
|
-
logErrorAndExit(`Project ID mismatch between ${chalk.green(gtConfig.projectId)} and ${chalk.green(projectIdEnv)}! Please use the same projectId in all configs.`);
|
|
60
|
-
}
|
|
61
44
|
// merge options
|
|
62
45
|
const mergedOptions = { ...gtConfig, ...options };
|
|
63
46
|
// merge locales
|
|
@@ -85,7 +68,14 @@ export async function generateSettings(options, cwd = process.cwd()) {
|
|
|
85
68
|
// For human review, always stage the project
|
|
86
69
|
mergedOptions.stageTranslations = mergedOptions.stageTranslations ?? false;
|
|
87
70
|
// Populate src if not provided
|
|
88
|
-
mergedOptions.src =
|
|
71
|
+
mergedOptions.src =
|
|
72
|
+
mergedOptions.src ||
|
|
73
|
+
findFilepaths([
|
|
74
|
+
path.join(cwd, './src'),
|
|
75
|
+
path.join(cwd, './app'),
|
|
76
|
+
path.join(cwd, './pages'),
|
|
77
|
+
path.join(cwd, './components'),
|
|
78
|
+
]);
|
|
89
79
|
// Resolve all glob patterns in the files object
|
|
90
80
|
mergedOptions.files = mergedOptions.files
|
|
91
81
|
? resolveFiles(mergedOptions.files, mergedOptions.defaultLocale, cwd)
|
package/dist/console/index.d.ts
CHANGED
|
@@ -13,7 +13,8 @@ export declare const noLocalesError = "No locales found! Please provide a list o
|
|
|
13
13
|
export declare const noDefaultLocaleError = "No default locale found! Please provide a default locale, or specify it in your gt.config.json file.";
|
|
14
14
|
export declare const noFilesError = "Incorrect or missing files configuration! Please make sure your files are configured correctly in your gt.config.json file.";
|
|
15
15
|
export declare const noSourceFileError = "No source file found! Please double check your translations directory and default locale.";
|
|
16
|
-
export declare const
|
|
16
|
+
export declare const noDataFormatError = "No data format found! Please make sure your translationsDir parameter ends with a supported file extension.";
|
|
17
|
+
export declare const noSupportedDataFormatError = "Unsupported data format! Please make sure your translationsDir parameter ends with a supported file extension.";
|
|
17
18
|
export declare const noApiKeyError = "No API key found! Please provide an API key using the --api-key flag or set the GT_API_KEY environment variable.";
|
|
18
19
|
export declare const devApiKeyError = "You are using a development API key. Please use a production API key to use the General Translation API.\nYou can generate a production API key with the command: npx gtx-cli auth -t production";
|
|
19
20
|
export declare const noProjectIdError = "No project ID found! Please provide a project ID using the --project-id flag, specify it in your gt.config.json file, or set the GT_PROJECT_ID environment variable.";
|
package/dist/console/index.js
CHANGED
|
@@ -16,7 +16,8 @@ export const noLocalesError = `No locales found! Please provide a list of locale
|
|
|
16
16
|
export const noDefaultLocaleError = `No default locale found! Please provide a default locale, or specify it in your gt.config.json file.`;
|
|
17
17
|
export const noFilesError = `Incorrect or missing files configuration! Please make sure your files are configured correctly in your gt.config.json file.`;
|
|
18
18
|
export const noSourceFileError = `No source file found! Please double check your translations directory and default locale.`;
|
|
19
|
-
export const
|
|
19
|
+
export const noDataFormatError = `No data format found! Please make sure your translationsDir parameter ends with a supported file extension.`;
|
|
20
|
+
export const noSupportedDataFormatError = `Unsupported data format! Please make sure your translationsDir parameter ends with a supported file extension.`;
|
|
20
21
|
export const noApiKeyError = `No API key found! Please provide an API key using the --api-key flag or set the GT_API_KEY environment variable.`;
|
|
21
22
|
export const devApiKeyError = `You are using a development API key. Please use a production API key to use the General Translation API.\nYou can generate a production API key with the command: npx gtx-cli auth -t production`;
|
|
22
23
|
export const noProjectIdError = `No project ID found! Please provide a project ID using the --project-id flag, specify it in your gt.config.json file, or set the GT_PROJECT_ID environment variable.`;
|
|
@@ -6,12 +6,9 @@ import { TranslateOptions } from '../../cli/base.js';
|
|
|
6
6
|
* @param filePaths - Resolved file paths for different file types
|
|
7
7
|
* @param placeholderPaths - Placeholder paths for translated files
|
|
8
8
|
* @param transformPaths - Transform paths for file naming
|
|
9
|
+
* @param fileFormat - Format of the files
|
|
9
10
|
* @param dataFormat - Format of the data within the files
|
|
10
11
|
* @param options - Translation options including API settings
|
|
11
12
|
* @returns Promise that resolves when translation is complete
|
|
12
13
|
*/
|
|
13
14
|
export declare function translateFiles(filePaths: ResolvedFiles, placeholderPaths: ResolvedFiles, transformPaths: TransformFiles, dataFormat: DataFormat | undefined, options: Settings & TranslateOptions): Promise<void>;
|
|
14
|
-
/**
|
|
15
|
-
* Creates a mapping between source files and their translated counterparts for each locale
|
|
16
|
-
*/
|
|
17
|
-
export declare function createFileMapping(filePaths: ResolvedFiles, placeholderPaths: ResolvedFiles, transformPaths: TransformFiles, locales: string[]): Record<string, Record<string, string>>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { checkFileTranslations } from '../../api/checkFileTranslations.js';
|
|
2
2
|
import { sendFiles } from '../../api/sendFiles.js';
|
|
3
|
-
import {
|
|
3
|
+
import { noSupportedDataFormatError, noLocalesError, noDefaultLocaleError, noApiKeyError, noProjectIdError, devApiKeyError, } from '../../console/index.js';
|
|
4
4
|
import { logErrorAndExit, createSpinner, logError, logSuccess, } from '../../console/logging.js';
|
|
5
5
|
import { resolveLocaleFiles } from '../../fs/config/parseFilesConfig.js';
|
|
6
6
|
import { getRelative, readFile } from '../../fs/findFilepath.js';
|
|
@@ -10,13 +10,13 @@ import chalk from 'chalk';
|
|
|
10
10
|
import { downloadFile } from '../../api/downloadFile.js';
|
|
11
11
|
import { downloadFileBatch } from '../../api/downloadFileBatch.js';
|
|
12
12
|
import { SUPPORTED_FILE_EXTENSIONS } from './supportedFiles.js';
|
|
13
|
-
import sanitizeFileContent from '../../utils/sanitizeFileContent.js';
|
|
14
13
|
const SUPPORTED_DATA_FORMATS = ['JSX', 'ICU', 'I18NEXT'];
|
|
15
14
|
/**
|
|
16
15
|
* Sends multiple files to the API for translation
|
|
17
16
|
* @param filePaths - Resolved file paths for different file types
|
|
18
17
|
* @param placeholderPaths - Placeholder paths for translated files
|
|
19
18
|
* @param transformPaths - Transform paths for file naming
|
|
19
|
+
* @param fileFormat - Format of the files
|
|
20
20
|
* @param dataFormat - Format of the data within the files
|
|
21
21
|
* @param options - Translation options including API settings
|
|
22
22
|
* @returns Promise that resolves when translation is complete
|
|
@@ -27,7 +27,7 @@ export async function translateFiles(filePaths, placeholderPaths, transformPaths
|
|
|
27
27
|
// Process JSON files
|
|
28
28
|
if (filePaths.json) {
|
|
29
29
|
if (!SUPPORTED_DATA_FORMATS.includes(dataFormat)) {
|
|
30
|
-
logErrorAndExit(
|
|
30
|
+
logErrorAndExit(noSupportedDataFormatError);
|
|
31
31
|
}
|
|
32
32
|
const jsonFiles = filePaths.json.map((filePath) => {
|
|
33
33
|
const content = readFile(filePath);
|
|
@@ -38,7 +38,7 @@ export async function translateFiles(filePaths, placeholderPaths, transformPaths
|
|
|
38
38
|
return {
|
|
39
39
|
content,
|
|
40
40
|
fileName: relativePath,
|
|
41
|
-
|
|
41
|
+
fileFormat: 'JSON',
|
|
42
42
|
dataFormat,
|
|
43
43
|
};
|
|
44
44
|
});
|
|
@@ -50,12 +50,11 @@ export async function translateFiles(filePaths, placeholderPaths, transformPaths
|
|
|
50
50
|
if (filePaths[fileType]) {
|
|
51
51
|
const files = filePaths[fileType].map((filePath) => {
|
|
52
52
|
const content = readFile(filePath);
|
|
53
|
-
const sanitizedContent = sanitizeFileContent(content);
|
|
54
53
|
const relativePath = getRelative(filePath);
|
|
55
54
|
return {
|
|
56
|
-
content
|
|
55
|
+
content,
|
|
57
56
|
fileName: relativePath,
|
|
58
|
-
|
|
57
|
+
fileFormat: fileType.toUpperCase(),
|
|
59
58
|
dataFormat,
|
|
60
59
|
};
|
|
61
60
|
});
|
|
@@ -110,7 +109,7 @@ export async function translateFiles(filePaths, placeholderPaths, transformPaths
|
|
|
110
109
|
/**
|
|
111
110
|
* Creates a mapping between source files and their translated counterparts for each locale
|
|
112
111
|
*/
|
|
113
|
-
|
|
112
|
+
function createFileMapping(filePaths, placeholderPaths, transformPaths, locales) {
|
|
114
113
|
const fileMapping = {};
|
|
115
114
|
for (const locale of locales) {
|
|
116
115
|
const translatedPaths = resolveLocaleFiles(placeholderPaths, locale);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export default function loadConfig(filepath: string): Record<string, any>;
|
|
@@ -92,30 +92,29 @@ function expandGlobPatterns(cwd, includePatterns, excludePatterns, locale, trans
|
|
|
92
92
|
resolvedPaths.push(...matches);
|
|
93
93
|
// For each match, create a version with [locale] in the correct positions
|
|
94
94
|
matches.forEach((match) => {
|
|
95
|
-
// Convert to
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
// Convert to relative path to make replacement easier
|
|
96
|
+
const relativePath = path.relative(cwd, match);
|
|
97
|
+
let originalRelativePath = relativePath;
|
|
98
|
+
// Replace locale with [locale] at each tracked position
|
|
99
99
|
if (localePositions.length > 0) {
|
|
100
|
-
//
|
|
100
|
+
// We need to account for path resolution differences
|
|
101
|
+
// This is a simplified approach - we'll replace all instances of the locale
|
|
101
102
|
// but only in path segments where we expect it based on the original pattern
|
|
102
|
-
const pathParts =
|
|
103
|
-
const patternParts =
|
|
103
|
+
const pathParts = relativePath.split(path.sep);
|
|
104
|
+
const patternParts = pattern.split(/[\/\\]/); // Handle both slash types
|
|
104
105
|
for (let i = 0; i < pathParts.length; i++) {
|
|
105
106
|
if (i < patternParts.length) {
|
|
106
107
|
if (patternParts[i].includes(localeTag)) {
|
|
107
108
|
// This segment should have the locale replaced
|
|
108
|
-
|
|
109
|
-
const regexPattern = patternParts[i].replace(/\[locale\]/g, `(${locale.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`);
|
|
110
|
-
const regex = new RegExp(regexPattern);
|
|
111
|
-
pathParts[i] = pathParts[i].replace(regex, patternParts[i].replace(/\[locale\]/g, localeTag));
|
|
109
|
+
pathParts[i] = pathParts[i].replace(locale, localeTag);
|
|
112
110
|
}
|
|
113
111
|
}
|
|
114
112
|
}
|
|
115
|
-
|
|
113
|
+
originalRelativePath = pathParts.join(path.sep);
|
|
116
114
|
}
|
|
117
115
|
// Convert back to absolute path
|
|
118
|
-
|
|
116
|
+
const originalPath = path.resolve(cwd, originalRelativePath);
|
|
117
|
+
placeholderPaths.push(originalPath);
|
|
119
118
|
});
|
|
120
119
|
}
|
|
121
120
|
return { resolvedPaths, placeholderPaths };
|
|
@@ -15,7 +15,6 @@ export async function createOrUpdateConfig(configFilepath, options) {
|
|
|
15
15
|
...(options.defaultLocale && { defaultLocale: options.defaultLocale }),
|
|
16
16
|
...(options.files && { files: options.files }),
|
|
17
17
|
...(options.framework && { framework: options.framework }),
|
|
18
|
-
...(options.baseUrl && { baseUrl: options.baseUrl }),
|
|
19
18
|
};
|
|
20
19
|
try {
|
|
21
20
|
// if file exists
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively scan the directory and collect all files with the specified extensions,
|
|
3
|
+
* excluding files or directories that start with a dot (.)
|
|
4
|
+
* @param dir - The directory to scan
|
|
5
|
+
* @returns An array of file paths
|
|
6
|
+
*/
|
|
7
|
+
export declare function getFiles(dir: string): string[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
// Define the file extensions to look for
|
|
4
|
+
const extensions = ['.js', '.jsx', '.tsx'];
|
|
5
|
+
/**
|
|
6
|
+
* Recursively scan the directory and collect all files with the specified extensions,
|
|
7
|
+
* excluding files or directories that start with a dot (.)
|
|
8
|
+
* @param dir - The directory to scan
|
|
9
|
+
* @returns An array of file paths
|
|
10
|
+
*/
|
|
11
|
+
export function getFiles(dir) {
|
|
12
|
+
let files = [];
|
|
13
|
+
const items = fs.readdirSync(dir);
|
|
14
|
+
for (const item of items) {
|
|
15
|
+
// Skip hidden files and directories
|
|
16
|
+
if (item.startsWith('.'))
|
|
17
|
+
continue;
|
|
18
|
+
const fullPath = path.join(dir, item);
|
|
19
|
+
const stat = fs.statSync(fullPath);
|
|
20
|
+
if (stat.isDirectory()) {
|
|
21
|
+
// Recursively scan subdirectories
|
|
22
|
+
files = files.concat(getFiles(fullPath));
|
|
23
|
+
}
|
|
24
|
+
else if (extensions.includes(path.extname(item))) {
|
|
25
|
+
// Add files with the specified extensions
|
|
26
|
+
files.push(fullPath);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return files;
|
|
30
|
+
}
|
|
@@ -6,13 +6,12 @@ import generateModule from '@babel/generator';
|
|
|
6
6
|
// Handle CommonJS/ESM interop
|
|
7
7
|
const traverse = traverseModule.default || traverseModule;
|
|
8
8
|
const generate = generateModule.default || generateModule;
|
|
9
|
+
import { getFiles } from '../../fs/findJsxFilepath.js';
|
|
9
10
|
import { isMeaningful } from '../../react/jsx/evaluateJsx.js';
|
|
10
11
|
import { handleJsxElement } from '../../react/jsx/wrapJsx.js';
|
|
11
12
|
import { getRelativePath } from '../../fs/findFilepath.js';
|
|
12
13
|
import { isHtmlElement, isBodyElement, hasGTProviderChild, addDynamicLangAttribute, makeParentFunctionAsync, } from '../jsx/utils.js';
|
|
13
14
|
import { generateImportMap, createImports, } from '../../react/jsx/utils/parseAst.js';
|
|
14
|
-
import { matchFiles } from '../../fs/matchFiles.js';
|
|
15
|
-
import { DEFAULT_SRC_PATTERNS } from '../../config/generateSettings.js';
|
|
16
15
|
const IMPORT_MAP = {
|
|
17
16
|
T: { name: 'T', source: 'gt-next' },
|
|
18
17
|
Var: { name: 'Var', source: 'gt-next' },
|
|
@@ -29,12 +28,13 @@ const IMPORT_MAP = {
|
|
|
29
28
|
* @returns An object containing the updates and errors
|
|
30
29
|
*/
|
|
31
30
|
export async function wrapContentNext(options, pkg, errors, warnings) {
|
|
32
|
-
const
|
|
31
|
+
const srcDirectory = options.src || ['./'];
|
|
32
|
+
const files = srcDirectory.flatMap((dir) => getFiles(dir));
|
|
33
33
|
const filesUpdated = [];
|
|
34
34
|
for (const file of files) {
|
|
35
35
|
const code = await fs.promises.readFile(file, 'utf8');
|
|
36
36
|
// Create relative path from src directory and remove extension
|
|
37
|
-
const relativePath = getRelativePath(file,
|
|
37
|
+
const relativePath = getRelativePath(file, srcDirectory[0]);
|
|
38
38
|
let ast;
|
|
39
39
|
try {
|
|
40
40
|
ast = parse(code, {
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Add GT Identifier and minify the tree (recreates addGTIdentifier and writeChildrenAsObjects)
|
|
4
|
-
* @param tree - The tree to add GT identifiers to
|
|
5
|
-
* @param startingIndex - The starting index for GT IDs
|
|
6
|
-
* @returns The tree with GT identifiers added
|
|
7
|
-
*/
|
|
8
|
-
export default function addGTIdentifierToSyntaxTree(tree: any, startingIndex?: number): JsxChildren;
|
|
1
|
+
export default function addGTIdentifierToSyntaxTree(tree: any, startingIndex?: number): any;
|