gtx-cli 2.6.17 → 2.6.18
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 +10 -0
- package/dist/cli/base.d.ts +2 -0
- package/dist/cli/base.js +79 -14
- package/dist/cli/flags.d.ts +12 -1
- package/dist/cli/flags.js +24 -5
- package/dist/cli/inline.d.ts +16 -0
- package/dist/cli/inline.js +128 -0
- package/dist/cli/next.d.ts +0 -2
- package/dist/cli/next.js +0 -10
- package/dist/cli/node.d.ts +9 -0
- package/dist/cli/node.js +9 -0
- package/dist/cli/react.d.ts +3 -10
- package/dist/cli/react.js +5 -120
- package/dist/formats/files/collectFiles.js +5 -3
- package/dist/fs/determineFramework.js +3 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/index.js +4 -0
- package/dist/react/jsx/utils/constants.d.ts +9 -2
- package/dist/react/jsx/utils/constants.js +7 -2
- package/dist/react/jsx/utils/getPathsAndAliases.js +3 -4
- package/dist/react/jsx/utils/parseStringFunction.js +2 -2
- package/dist/react/parse/createInlineUpdates.js +22 -19
- package/dist/setup/agentInstructions.d.ts +24 -0
- package/dist/setup/agentInstructions.js +135 -0
- package/dist/setup/instructions/base.md +29 -0
- package/dist/setup/instructions/gt-next.md +107 -0
- package/dist/setup/instructions/gt-react.md +98 -0
- package/dist/translation/parse.d.ts +1 -1
- package/dist/translation/stage.d.ts +1 -1
- package/dist/translation/stage.js +1 -1
- package/dist/translation/validate.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# gtx-cli
|
|
2
2
|
|
|
3
|
+
## 2.6.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1009](https://github.com/generaltranslation/gt/pull/1009) [`ffd6995`](https://github.com/generaltranslation/gt/commit/ffd6995d57e5444157071696e533ee29abcc2df4) Thanks [@pie575](https://github.com/pie575)! - added ai instructions on how to use the gt library
|
|
8
|
+
|
|
9
|
+
- [#1013](https://github.com/generaltranslation/gt/pull/1013) [`d01b29c`](https://github.com/generaltranslation/gt/commit/d01b29c0f5a4442f49a1ab6d8d5ee72403c6fa17) Thanks [@pie575](https://github.com/pie575)! - added flag to update-instructions add comments to ai files even if they weren't there before
|
|
10
|
+
|
|
11
|
+
- [#1007](https://github.com/generaltranslation/gt/pull/1007) [`7aaac80`](https://github.com/generaltranslation/gt/commit/7aaac80b67f4f6ffa8d9ef9aa00f6fc669596003) Thanks [@ErnestM1234](https://github.com/ErnestM1234)! - chore: add gt-node support
|
|
12
|
+
|
|
3
13
|
## 2.6.17
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/dist/cli/base.d.ts
CHANGED
|
@@ -30,4 +30,6 @@ export declare class BaseCLI {
|
|
|
30
30
|
protected handleUploadCommand(settings: Settings & UploadOptions): Promise<void>;
|
|
31
31
|
protected handleInitCommand(ranReactSetup: boolean, useDefaults?: boolean): Promise<void>;
|
|
32
32
|
protected handleLoginCommand(options: LoginOptions): Promise<void>;
|
|
33
|
+
protected setupUpdateInstructionsCommand(): void;
|
|
34
|
+
protected promptAgentInstructions(useDefaults?: boolean): Promise<void>;
|
|
33
35
|
}
|
package/dist/cli/base.js
CHANGED
|
@@ -29,6 +29,8 @@ import processSharedStaticAssets, { mirrorAssetsToLocales, } from '../utils/shar
|
|
|
29
29
|
import { setupLocadex } from '../locadex/setupFlow.js';
|
|
30
30
|
import { detectFramework } from '../setup/detectFramework.js';
|
|
31
31
|
import { getFrameworkDisplayName, getReactFrameworkLibrary, } from '../setup/frameworkUtils.js';
|
|
32
|
+
import { findAgentFiles, findAgentFilesWithInstructions, hasCursorRulesDir, CURSOR_GT_RULES_FILE, getAgentInstructions, appendAgentInstructions, } from '../setup/agentInstructions.js';
|
|
33
|
+
import { determineLibrary } from '../fs/determineFramework.js';
|
|
32
34
|
export class BaseCLI {
|
|
33
35
|
library;
|
|
34
36
|
additionalModules;
|
|
@@ -43,6 +45,7 @@ export class BaseCLI {
|
|
|
43
45
|
this.setupUploadCommand();
|
|
44
46
|
this.setupLoginCommand();
|
|
45
47
|
this.setupSendDiffsCommand();
|
|
48
|
+
this.setupUpdateInstructionsCommand();
|
|
46
49
|
}
|
|
47
50
|
// Init is never called in a child class
|
|
48
51
|
init() {
|
|
@@ -158,13 +161,10 @@ export class BaseCLI {
|
|
|
158
161
|
displayHeader('Authenticating with General Translation...');
|
|
159
162
|
if (!options.keyType) {
|
|
160
163
|
const packageJson = await searchForPackageJson();
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
? isPackageInstalled('gt-react', packageJson)
|
|
166
|
-
: false;
|
|
167
|
-
if (isUsingGTNext || isUsingGTReact) {
|
|
164
|
+
if (packageJson &&
|
|
165
|
+
(isPackageInstalled('gt-next', packageJson) ||
|
|
166
|
+
isPackageInstalled('gt-react', packageJson) ||
|
|
167
|
+
isPackageInstalled('gt-node', packageJson))) {
|
|
168
168
|
options.keyType = 'development';
|
|
169
169
|
}
|
|
170
170
|
else {
|
|
@@ -209,6 +209,7 @@ export class BaseCLI {
|
|
|
209
209
|
})();
|
|
210
210
|
if (useAgent) {
|
|
211
211
|
await setupLocadex(settings);
|
|
212
|
+
await this.promptAgentInstructions();
|
|
212
213
|
logger.endCommand('Once installed, Locadex will open a PR to your repository. See the docs for more information: https://generaltranslation.com/docs/locadex');
|
|
213
214
|
}
|
|
214
215
|
else {
|
|
@@ -250,6 +251,7 @@ export class BaseCLI {
|
|
|
250
251
|
}
|
|
251
252
|
// Configure gt.config.json
|
|
252
253
|
await this.handleInitCommand(ranReactSetup, useDefaults);
|
|
254
|
+
await this.promptAgentInstructions(useDefaults);
|
|
253
255
|
logger.endCommand('Done! Check out our docs for more information on how to use General Translation: https://generaltranslation.com/docs');
|
|
254
256
|
}
|
|
255
257
|
});
|
|
@@ -294,14 +296,12 @@ export class BaseCLI {
|
|
|
294
296
|
async handleInitCommand(ranReactSetup, useDefaults = false) {
|
|
295
297
|
const { defaultLocale, locales } = await getDesiredLocales(); // Locales should still be asked for even if using defaults
|
|
296
298
|
const packageJson = await searchForPackageJson();
|
|
297
|
-
const isUsingGTNext = packageJson
|
|
298
|
-
? isPackageInstalled('gt-next', packageJson)
|
|
299
|
-
: false;
|
|
300
|
-
const isUsingGTReact = packageJson
|
|
301
|
-
? isPackageInstalled('gt-react', packageJson)
|
|
302
|
-
: false;
|
|
303
299
|
// Ask if using another i18n library
|
|
304
|
-
const
|
|
300
|
+
const gtInstalled = !!packageJson &&
|
|
301
|
+
(isPackageInstalled('gt-next', packageJson) ||
|
|
302
|
+
isPackageInstalled('gt-react', packageJson) ||
|
|
303
|
+
isPackageInstalled('gt-node', packageJson));
|
|
304
|
+
const isUsingGT = ranReactSetup || gtInstalled;
|
|
305
305
|
// Ask where the translations are stored
|
|
306
306
|
const usingCDN = await (async () => {
|
|
307
307
|
if (!isUsingGT)
|
|
@@ -414,4 +414,69 @@ See https://generaltranslation.com/en/docs/next/guides/local-tx`);
|
|
|
414
414
|
const credentials = await retrieveCredentials(settings, keyType);
|
|
415
415
|
await setCredentials(credentials, keyType, settings.framework);
|
|
416
416
|
}
|
|
417
|
+
setupUpdateInstructionsCommand() {
|
|
418
|
+
this.program
|
|
419
|
+
.command('update-instructions')
|
|
420
|
+
.description('Update GT usage instructions in AI agent files')
|
|
421
|
+
.option('--new', 'Add instructions to all agent files, even those without existing GT instructions')
|
|
422
|
+
.action(async (options) => {
|
|
423
|
+
const agentFiles = options.new
|
|
424
|
+
? findAgentFiles()
|
|
425
|
+
: findAgentFilesWithInstructions();
|
|
426
|
+
if (options.new &&
|
|
427
|
+
hasCursorRulesDir() &&
|
|
428
|
+
!agentFiles.includes(CURSOR_GT_RULES_FILE)) {
|
|
429
|
+
agentFiles.push(CURSOR_GT_RULES_FILE);
|
|
430
|
+
}
|
|
431
|
+
if (agentFiles.length === 0) {
|
|
432
|
+
logger.warn(options.new
|
|
433
|
+
? 'No agent files found. Create a CLAUDE.md or similar agent file first.'
|
|
434
|
+
: 'No agent files with GT instructions found. Use --new to add instructions to existing agent files.');
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const { library } = determineLibrary();
|
|
438
|
+
const instructions = getAgentInstructions(library);
|
|
439
|
+
let updatedCount = 0;
|
|
440
|
+
for (const file of agentFiles) {
|
|
441
|
+
if (appendAgentInstructions(file, instructions)) {
|
|
442
|
+
updatedCount++;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (updatedCount > 0) {
|
|
446
|
+
logger.success(`Updated GT instructions in ${updatedCount} file${updatedCount > 1 ? 's' : ''}.`);
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
logger.info('All agent instruction files are already up to date.');
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
async promptAgentInstructions(useDefaults = false) {
|
|
454
|
+
const agentFiles = findAgentFiles();
|
|
455
|
+
// Include .cursor/rules/gt-i18n.mdc if the directory exists but the file doesn't yet
|
|
456
|
+
if (hasCursorRulesDir() && !agentFiles.includes(CURSOR_GT_RULES_FILE)) {
|
|
457
|
+
agentFiles.push(CURSOR_GT_RULES_FILE);
|
|
458
|
+
}
|
|
459
|
+
if (agentFiles.length === 0)
|
|
460
|
+
return;
|
|
461
|
+
const addInstructions = useDefaults
|
|
462
|
+
? true
|
|
463
|
+
: await promptConfirm({
|
|
464
|
+
message: `Found AI agent instruction files (${agentFiles.map((f) => path.basename(f)).join(', ')}). Would you like to add GT usage instructions?`,
|
|
465
|
+
defaultValue: true,
|
|
466
|
+
});
|
|
467
|
+
if (addInstructions) {
|
|
468
|
+
// Re-detect library since packages may have been installed during init
|
|
469
|
+
const { library } = determineLibrary();
|
|
470
|
+
const instructions = getAgentInstructions(library);
|
|
471
|
+
let updatedCount = 0;
|
|
472
|
+
for (const file of agentFiles) {
|
|
473
|
+
if (appendAgentInstructions(file, instructions)) {
|
|
474
|
+
updatedCount++;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
if (updatedCount > 0) {
|
|
478
|
+
logger.success('Added GT instructions to agent files.');
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
417
482
|
}
|
package/dist/cli/flags.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
export declare function attachSharedFlags(command: Command): Command;
|
|
3
3
|
export declare function attachTranslateFlags(command: Command): Command;
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Attaches flags necessary for validating a project
|
|
6
|
+
* @param command
|
|
7
|
+
* @returns The command with the validate flags attached
|
|
8
|
+
*/
|
|
9
|
+
export declare function attachValidateFlags(command: Command): Command;
|
|
10
|
+
/**
|
|
11
|
+
* Attaches flags necessary for translating a project
|
|
12
|
+
* @param command
|
|
13
|
+
* @returns The command with the translate flags attached
|
|
14
|
+
*/
|
|
15
|
+
export declare function attachInlineTranslateFlags(command: Command): Command;
|
package/dist/cli/flags.js
CHANGED
|
@@ -40,12 +40,31 @@ export function attachTranslateFlags(command) {
|
|
|
40
40
|
.option('--remote-name <name>', 'Specify a custom remote name to use for branch detection', DEFAULT_GIT_REMOTE_NAME);
|
|
41
41
|
return command;
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Attaches flags necessary for parsing inline content
|
|
45
|
+
* @param command - The command to attach the flags to
|
|
46
|
+
* @returns The command with the inline content parsing flags attached
|
|
47
|
+
*/
|
|
48
|
+
function attachInlineContentParsingFlags(command) {
|
|
49
|
+
return command
|
|
45
50
|
.option('--tsconfig, --jsconfig <path>', 'Path to custom jsconfig or tsconfig file', findFilepath(['./tsconfig.json', './jsconfig.json']))
|
|
46
51
|
.option('--dictionary <path>', 'Path to dictionary file')
|
|
47
52
|
.option('--src <paths...>', "Space-separated list of glob patterns containing the app's source code, by default 'src/**/*.{js,jsx,ts,tsx}' 'app/**/*.{js,jsx,ts,tsx}' 'pages/**/*.{js,jsx,ts,tsx}' 'components/**/*.{js,jsx,ts,tsx}'")
|
|
48
|
-
.option('--inline', 'Include inline
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
.option('--inline', 'Include inline content in translations (e.g., inline jsx translations, inline string translations, etc.)', true);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Attaches flags necessary for validating a project
|
|
57
|
+
* @param command
|
|
58
|
+
* @returns The command with the validate flags attached
|
|
59
|
+
*/
|
|
60
|
+
export function attachValidateFlags(command) {
|
|
61
|
+
return attachInlineContentParsingFlags(command.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', findFilepath(['gt.config.json'])));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Attaches flags necessary for translating a project
|
|
65
|
+
* @param command
|
|
66
|
+
* @returns The command with the translate flags attached
|
|
67
|
+
*/
|
|
68
|
+
export function attachInlineTranslateFlags(command) {
|
|
69
|
+
return attachInlineContentParsingFlags(command.option('--ignore-errors', 'Ignore errors encountered while scanning for inline content', false));
|
|
51
70
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { BaseCLI } from './base.js';
|
|
3
|
+
import { SupportedLibraries, TranslateFlags, Options } from '../types/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Stand in for a CLI tool that does any sort of inline content translations
|
|
6
|
+
*/
|
|
7
|
+
export declare class InlineCLI extends BaseCLI {
|
|
8
|
+
constructor(command: Command, library: 'gt-react' | 'gt-next' | 'gt-node', additionalModules?: SupportedLibraries[]);
|
|
9
|
+
init(): void;
|
|
10
|
+
protected setupStageCommand(): void;
|
|
11
|
+
protected setupTranslateCommand(): void;
|
|
12
|
+
protected setupValidateCommand(): void;
|
|
13
|
+
protected setupGenerateSourceCommand(): void;
|
|
14
|
+
protected handleGenerateSourceCommand(initOptions: TranslateFlags): Promise<void>;
|
|
15
|
+
protected handleValidate(initOptions: Options, files?: string[]): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { BaseCLI } from './base.js';
|
|
2
|
+
import { attachInlineTranslateFlags, attachTranslateFlags, attachValidateFlags, } from './flags.js';
|
|
3
|
+
import { displayHeader, exitSync } from '../console/logging.js';
|
|
4
|
+
import { logger } from '../console/logger.js';
|
|
5
|
+
import { intro } from '@clack/prompts';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { resolveLocaleFiles } from '../fs/config/parseFilesConfig.js';
|
|
8
|
+
import { noFilesError } from '../console/index.js';
|
|
9
|
+
import { saveJSON } from '../fs/saveJSON.js';
|
|
10
|
+
import loadJSON from '../fs/loadJSON.js';
|
|
11
|
+
import { generateSettings } from '../config/generateSettings.js';
|
|
12
|
+
import { aggregateInlineTranslations } from '../translation/stage.js';
|
|
13
|
+
import { validateConfigExists } from '../config/validateSettings.js';
|
|
14
|
+
import { validateProject } from '../translation/validate.js';
|
|
15
|
+
/**
|
|
16
|
+
* Stand in for a CLI tool that does any sort of inline content translations
|
|
17
|
+
*/
|
|
18
|
+
export class InlineCLI extends BaseCLI {
|
|
19
|
+
constructor(command, library, additionalModules) {
|
|
20
|
+
super(command, library, additionalModules);
|
|
21
|
+
}
|
|
22
|
+
init() {
|
|
23
|
+
this.setupStageCommand();
|
|
24
|
+
this.setupTranslateCommand();
|
|
25
|
+
this.setupGenerateSourceCommand();
|
|
26
|
+
this.setupValidateCommand();
|
|
27
|
+
}
|
|
28
|
+
setupStageCommand() {
|
|
29
|
+
attachInlineTranslateFlags(attachTranslateFlags(this.program
|
|
30
|
+
.command('stage')
|
|
31
|
+
.description('Submits the project to the General Translation API for translation. Translations created using this command will require human approval.'))).action(async (options) => {
|
|
32
|
+
displayHeader('Staging project for translation with approval required...');
|
|
33
|
+
await this.handleStage(options);
|
|
34
|
+
logger.endCommand('Done!');
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
setupTranslateCommand() {
|
|
38
|
+
attachInlineTranslateFlags(attachTranslateFlags(this.program
|
|
39
|
+
.command('translate')
|
|
40
|
+
.description('Scans the project for a dictionary and inline translations and sends the updates to the General Translation API for translation.'))).action(async (options) => {
|
|
41
|
+
displayHeader('Translating project...');
|
|
42
|
+
await this.handleTranslate(options);
|
|
43
|
+
logger.endCommand('Done!');
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
setupValidateCommand() {
|
|
47
|
+
attachValidateFlags(this.program
|
|
48
|
+
.command('validate [files...]')
|
|
49
|
+
.description('Scans the project for a dictionary and/or inline content and validates the project for errors.')).action(async (files, options) => {
|
|
50
|
+
// intro here since we don't want to show the ascii title
|
|
51
|
+
intro(chalk.cyan('Validating project...'));
|
|
52
|
+
await this.handleValidate(options, files);
|
|
53
|
+
logger.endCommand('Done!');
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
setupGenerateSourceCommand() {
|
|
57
|
+
attachInlineTranslateFlags(attachTranslateFlags(this.program
|
|
58
|
+
.command('generate')
|
|
59
|
+
.description('Generate a translation file for the source locale. This command should be used if you are handling your own translations.'))).action(async (initOptions) => {
|
|
60
|
+
displayHeader('Generating source templates...');
|
|
61
|
+
await this.handleGenerateSourceCommand(initOptions);
|
|
62
|
+
logger.endCommand('Done!');
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async handleGenerateSourceCommand(initOptions) {
|
|
66
|
+
const settings = await generateSettings(initOptions);
|
|
67
|
+
const updates = await aggregateInlineTranslations(initOptions, settings, fallbackToGtReact(this.library));
|
|
68
|
+
// Convert updates to the proper data format
|
|
69
|
+
const newData = {};
|
|
70
|
+
for (const update of updates) {
|
|
71
|
+
const { source, metadata } = update;
|
|
72
|
+
const { hash, id } = metadata;
|
|
73
|
+
if (id) {
|
|
74
|
+
newData[id] = source;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
newData[hash] = source;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Save source file if files.json is provided
|
|
81
|
+
if (settings.files && settings.files.placeholderPaths.gt) {
|
|
82
|
+
const translationFiles = resolveLocaleFiles(settings.files.placeholderPaths, settings.defaultLocale);
|
|
83
|
+
if (!translationFiles.gt) {
|
|
84
|
+
logger.error(noFilesError);
|
|
85
|
+
exitSync(1);
|
|
86
|
+
}
|
|
87
|
+
await saveJSON(translationFiles.gt, newData);
|
|
88
|
+
logger.step('Source file saved successfully!');
|
|
89
|
+
// Also save translations (after merging with existing translations)
|
|
90
|
+
for (const locale of settings.locales) {
|
|
91
|
+
const translationsFile = resolveLocaleFiles(settings.files.placeholderPaths, locale);
|
|
92
|
+
if (!translationsFile.gt) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const existingTranslations = loadJSON(translationsFile.gt);
|
|
96
|
+
const mergedTranslations = {
|
|
97
|
+
...newData,
|
|
98
|
+
...existingTranslations,
|
|
99
|
+
};
|
|
100
|
+
// Filter out keys that don't exist in newData
|
|
101
|
+
const filteredTranslations = Object.fromEntries(Object.entries(mergedTranslations).filter(([key]) => newData[key]));
|
|
102
|
+
await saveJSON(translationsFile.gt, filteredTranslations);
|
|
103
|
+
}
|
|
104
|
+
logger.step('Merged translations successfully!');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async handleValidate(initOptions, files) {
|
|
108
|
+
validateConfigExists();
|
|
109
|
+
const settings = await generateSettings(initOptions);
|
|
110
|
+
// First run the base class's handleTranslate method
|
|
111
|
+
const options = { ...initOptions, ...settings };
|
|
112
|
+
// Fallback to gt-react
|
|
113
|
+
const pkg = fallbackToGtReact(this.library);
|
|
114
|
+
if (files && files.length > 0) {
|
|
115
|
+
// Validate specific files using createInlineUpdates
|
|
116
|
+
await validateProject(options, pkg, files);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Validate whole project as before
|
|
120
|
+
await validateProject(options, pkg);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function fallbackToGtReact(library) {
|
|
125
|
+
return ['gt-next', 'gt-node'].includes(library)
|
|
126
|
+
? library
|
|
127
|
+
: 'gt-react';
|
|
128
|
+
}
|
package/dist/cli/next.d.ts
CHANGED
|
@@ -3,8 +3,6 @@ import { ReactCLI } from './react.js';
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
export declare class NextCLI extends ReactCLI {
|
|
5
5
|
constructor(command: Command, library: 'gt-next', additionalModules?: SupportedLibraries[]);
|
|
6
|
-
init(): void;
|
|
7
|
-
execute(): void;
|
|
8
6
|
protected wrapContent(options: WrapOptions, framework: SupportedFrameworks, errors: string[], warnings: string[]): Promise<{
|
|
9
7
|
filesUpdated: string[];
|
|
10
8
|
}>;
|
package/dist/cli/next.js
CHANGED
|
@@ -5,16 +5,6 @@ export class NextCLI extends ReactCLI {
|
|
|
5
5
|
constructor(command, library, additionalModules) {
|
|
6
6
|
super(command, library, additionalModules);
|
|
7
7
|
}
|
|
8
|
-
init() {
|
|
9
|
-
this.setupSetupProjectCommand();
|
|
10
|
-
this.setupStageCommand();
|
|
11
|
-
this.setupTranslateCommand();
|
|
12
|
-
this.setupGenerateSourceCommand();
|
|
13
|
-
this.setupValidateCommand();
|
|
14
|
-
}
|
|
15
|
-
execute() {
|
|
16
|
-
super.execute();
|
|
17
|
-
}
|
|
18
8
|
wrapContent(options, framework, errors, warnings) {
|
|
19
9
|
return wrapContentNext(options, pkg, errors, warnings);
|
|
20
10
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { SupportedLibraries } from '../types/index.js';
|
|
3
|
+
import { InlineCLI } from './inline.js';
|
|
4
|
+
/**
|
|
5
|
+
* CLI tool for managing translations with gt-node
|
|
6
|
+
*/
|
|
7
|
+
export declare class NodeCLI extends InlineCLI {
|
|
8
|
+
constructor(command: Command, library: 'gt-node', additionalModules?: SupportedLibraries[]);
|
|
9
|
+
}
|
package/dist/cli/node.js
ADDED
package/dist/cli/react.d.ts
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
export declare class ReactCLI extends
|
|
2
|
+
import { SupportedFrameworks, WrapOptions, SupportedLibraries } from '../types/index.js';
|
|
3
|
+
import { InlineCLI } from './inline.js';
|
|
4
|
+
export declare class ReactCLI extends InlineCLI {
|
|
5
5
|
constructor(command: Command, library: 'gt-react' | 'gt-next', additionalModules?: SupportedLibraries[]);
|
|
6
6
|
init(): void;
|
|
7
|
-
execute(): void;
|
|
8
7
|
protected wrapContent(options: WrapOptions, framework: SupportedFrameworks, errors: string[], warnings: string[]): Promise<{
|
|
9
8
|
filesUpdated: string[];
|
|
10
9
|
}>;
|
|
11
10
|
protected setupSetupProjectCommand(): void;
|
|
12
|
-
protected setupStageCommand(): void;
|
|
13
|
-
protected setupTranslateCommand(): void;
|
|
14
|
-
protected setupValidateCommand(): void;
|
|
15
|
-
protected setupGenerateSourceCommand(): void;
|
|
16
|
-
protected handleGenerateSourceCommand(initOptions: TranslateFlags): Promise<void>;
|
|
17
11
|
protected handleScanCommand(options: WrapOptions): Promise<void>;
|
|
18
|
-
protected handleValidate(initOptions: Options, files?: string[]): Promise<void>;
|
|
19
12
|
}
|
package/dist/cli/react.js
CHANGED
|
@@ -1,40 +1,25 @@
|
|
|
1
1
|
import { displayHeader, exitSync, promptConfirm } from '../console/logging.js';
|
|
2
2
|
import { logger } from '../console/logger.js';
|
|
3
|
-
import loadJSON from '../fs/loadJSON.js';
|
|
4
|
-
import findFilepath from '../fs/findFilepath.js';
|
|
5
3
|
import chalk from 'chalk';
|
|
6
4
|
import { formatFiles } from '../hooks/postProcess.js';
|
|
7
|
-
import { BaseCLI } from './base.js';
|
|
8
5
|
import { wrapContentReact } from '../react/parse/wrapContent.js';
|
|
9
6
|
import { generateSettings } from '../config/generateSettings.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { noFilesError } from '../console/index.js';
|
|
13
|
-
import { aggregateReactTranslations } from '../translation/stage.js';
|
|
14
|
-
import { validateConfigExists } from '../config/validateSettings.js';
|
|
15
|
-
import { validateProject } from '../translation/validate.js';
|
|
16
|
-
import { intro } from '@clack/prompts';
|
|
17
|
-
import { attachAdditionalReactTranslateFlags, attachTranslateFlags, } from './flags.js';
|
|
7
|
+
import { attachInlineTranslateFlags, attachTranslateFlags } from './flags.js';
|
|
8
|
+
import { InlineCLI } from './inline.js';
|
|
18
9
|
const pkg = 'gt-react';
|
|
19
|
-
export class ReactCLI extends
|
|
10
|
+
export class ReactCLI extends InlineCLI {
|
|
20
11
|
constructor(command, library, additionalModules) {
|
|
21
12
|
super(command, library, additionalModules);
|
|
22
13
|
}
|
|
23
14
|
init() {
|
|
15
|
+
super.init();
|
|
24
16
|
this.setupSetupProjectCommand();
|
|
25
|
-
this.setupStageCommand();
|
|
26
|
-
this.setupTranslateCommand();
|
|
27
|
-
this.setupGenerateSourceCommand();
|
|
28
|
-
this.setupValidateCommand();
|
|
29
|
-
}
|
|
30
|
-
execute() {
|
|
31
|
-
super.execute();
|
|
32
17
|
}
|
|
33
18
|
wrapContent(options, framework, errors, warnings) {
|
|
34
19
|
return wrapContentReact(options, pkg, framework, errors, warnings);
|
|
35
20
|
}
|
|
36
21
|
setupSetupProjectCommand() {
|
|
37
|
-
|
|
22
|
+
attachInlineTranslateFlags(attachTranslateFlags(this.program
|
|
38
23
|
.command('setup')
|
|
39
24
|
.description('Upload source files and setup the project for translation'))).action(async (options) => {
|
|
40
25
|
displayHeader('Uploading source files and setting up project...');
|
|
@@ -42,91 +27,6 @@ export class ReactCLI extends BaseCLI {
|
|
|
42
27
|
logger.endCommand('Done!');
|
|
43
28
|
});
|
|
44
29
|
}
|
|
45
|
-
setupStageCommand() {
|
|
46
|
-
attachAdditionalReactTranslateFlags(attachTranslateFlags(this.program
|
|
47
|
-
.command('stage')
|
|
48
|
-
.description('Submits the project to the General Translation API for translation. Translations created using this command will require human approval.'))).action(async (options) => {
|
|
49
|
-
displayHeader('Staging project for translation with approval required...');
|
|
50
|
-
await this.handleStage(options);
|
|
51
|
-
logger.endCommand('Done!');
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
setupTranslateCommand() {
|
|
55
|
-
attachAdditionalReactTranslateFlags(attachTranslateFlags(this.program
|
|
56
|
-
.command('translate')
|
|
57
|
-
.description('Scans the project for a dictionary and/or <T> tags, and sends the updates to the General Translation API for translation.'))).action(async (options) => {
|
|
58
|
-
displayHeader('Translating project...');
|
|
59
|
-
await this.handleTranslate(options);
|
|
60
|
-
logger.endCommand('Done!');
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
setupValidateCommand() {
|
|
64
|
-
this.program
|
|
65
|
-
.command('validate [files...]')
|
|
66
|
-
.description('Scans the project for a dictionary and/or <T> tags, and validates the project for errors.')
|
|
67
|
-
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', findFilepath(['gt.config.json']))
|
|
68
|
-
.option('--tsconfig, --jsconfig <path>', 'Path to jsconfig or tsconfig file', findFilepath(['./tsconfig.json', './jsconfig.json']))
|
|
69
|
-
.option('--dictionary <path>', 'Path to dictionary file')
|
|
70
|
-
.option('--src <paths...>', "Space-separated list of glob patterns containing the app's source code, by default 'src/**/*.{js,jsx,ts,tsx}' 'app/**/*.{js,jsx,ts,tsx}' 'pages/**/*.{js,jsx,ts,tsx}' 'components/**/*.{js,jsx,ts,tsx}'")
|
|
71
|
-
.option('--inline', 'Include inline <T> tags in addition to dictionary file', true)
|
|
72
|
-
.action(async (files, options) => {
|
|
73
|
-
// intro here since we don't want to show the ascii title
|
|
74
|
-
intro(chalk.cyan('Validating project...'));
|
|
75
|
-
await this.handleValidate(options, files);
|
|
76
|
-
logger.endCommand('Done!');
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
setupGenerateSourceCommand() {
|
|
80
|
-
attachAdditionalReactTranslateFlags(attachTranslateFlags(this.program
|
|
81
|
-
.command('generate')
|
|
82
|
-
.description('Generate a translation file for the source locale. This command should be used if you are handling your own translations.'))).action(async (initOptions) => {
|
|
83
|
-
displayHeader('Generating source templates...');
|
|
84
|
-
await this.handleGenerateSourceCommand(initOptions);
|
|
85
|
-
logger.endCommand('Done!');
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
async handleGenerateSourceCommand(initOptions) {
|
|
89
|
-
const settings = await generateSettings(initOptions);
|
|
90
|
-
const updates = await aggregateReactTranslations(initOptions, settings, this.library === 'gt-next' ? 'gt-next' : 'gt-react');
|
|
91
|
-
// Convert updates to the proper data format
|
|
92
|
-
const newData = {};
|
|
93
|
-
for (const update of updates) {
|
|
94
|
-
const { source, metadata } = update;
|
|
95
|
-
const { hash, id } = metadata;
|
|
96
|
-
if (id) {
|
|
97
|
-
newData[id] = source;
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
newData[hash] = source;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
// Save source file if files.json is provided
|
|
104
|
-
if (settings.files && settings.files.placeholderPaths.gt) {
|
|
105
|
-
const translationFiles = resolveLocaleFiles(settings.files.placeholderPaths, settings.defaultLocale);
|
|
106
|
-
if (!translationFiles.gt) {
|
|
107
|
-
logger.error(noFilesError);
|
|
108
|
-
exitSync(1);
|
|
109
|
-
}
|
|
110
|
-
await saveJSON(translationFiles.gt, newData);
|
|
111
|
-
logger.step('Source file saved successfully!');
|
|
112
|
-
// Also save translations (after merging with existing translations)
|
|
113
|
-
for (const locale of settings.locales) {
|
|
114
|
-
const translationsFile = resolveLocaleFiles(settings.files.placeholderPaths, locale);
|
|
115
|
-
if (!translationsFile.gt) {
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
const existingTranslations = loadJSON(translationsFile.gt);
|
|
119
|
-
const mergedTranslations = {
|
|
120
|
-
...newData,
|
|
121
|
-
...existingTranslations,
|
|
122
|
-
};
|
|
123
|
-
// Filter out keys that don't exist in newData
|
|
124
|
-
const filteredTranslations = Object.fromEntries(Object.entries(mergedTranslations).filter(([key]) => newData[key]));
|
|
125
|
-
await saveJSON(translationsFile.gt, filteredTranslations);
|
|
126
|
-
}
|
|
127
|
-
logger.step('Merged translations successfully!');
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
30
|
async handleScanCommand(options) {
|
|
131
31
|
// Ask user for confirmation using inquirer
|
|
132
32
|
const answer = await promptConfirm({
|
|
@@ -168,19 +68,4 @@ export class ReactCLI extends BaseCLI {
|
|
|
168
68
|
.join('\n'));
|
|
169
69
|
}
|
|
170
70
|
}
|
|
171
|
-
async handleValidate(initOptions, files) {
|
|
172
|
-
validateConfigExists();
|
|
173
|
-
const settings = await generateSettings(initOptions);
|
|
174
|
-
// First run the base class's handleTranslate method
|
|
175
|
-
const options = { ...initOptions, ...settings };
|
|
176
|
-
const pkg = this.library === 'gt-next' ? 'gt-next' : 'gt-react';
|
|
177
|
-
if (files && files.length > 0) {
|
|
178
|
-
// Validate specific files using createInlineUpdates
|
|
179
|
-
await validateProject(options, pkg, files);
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
// Validate whole project as before
|
|
183
|
-
await validateProject(options, pkg);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
71
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logErrorAndExit } from '../../console/logging.js';
|
|
2
2
|
import { invalidConfigurationError } from '../../console/index.js';
|
|
3
3
|
import { aggregateFiles } from '../../formats/files/translate.js';
|
|
4
|
-
import {
|
|
4
|
+
import { aggregateInlineTranslations } from '../../translation/stage.js';
|
|
5
5
|
import { hashStringSync } from '../../utils/hash.js';
|
|
6
6
|
import { TEMPLATE_FILE_NAME, TEMPLATE_FILE_ID } from '../../utils/constants.js';
|
|
7
7
|
export async function collectFiles(options, settings, library) {
|
|
@@ -9,8 +9,10 @@ export async function collectFiles(options, settings, library) {
|
|
|
9
9
|
const allFiles = await aggregateFiles(settings);
|
|
10
10
|
// Parse for React components
|
|
11
11
|
let reactComponents = 0;
|
|
12
|
-
if (library === 'gt-react' ||
|
|
13
|
-
|
|
12
|
+
if (library === 'gt-react' ||
|
|
13
|
+
library === 'gt-next' ||
|
|
14
|
+
library === 'gt-node') {
|
|
15
|
+
const updates = await aggregateInlineTranslations(options, settings, library);
|
|
14
16
|
if (updates.length > 0) {
|
|
15
17
|
if (!settings.publish && !settings.files?.placeholderPaths.gt) {
|
|
16
18
|
logErrorAndExit(invalidConfigurationError);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "2.6.
|
|
1
|
+
export declare const PACKAGE_VERSION = "2.6.18";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const PACKAGE_VERSION = '2.6.
|
|
2
|
+
export const PACKAGE_VERSION = '2.6.18';
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { BaseCLI } from './cli/base.js';
|
|
|
2
2
|
import { NextCLI } from './cli/next.js';
|
|
3
3
|
import { ReactCLI } from './cli/react.js';
|
|
4
4
|
import { determineLibrary } from './fs/determineFramework.js';
|
|
5
|
+
import { NodeCLI } from './cli/node.js';
|
|
5
6
|
export function main(program) {
|
|
6
7
|
program.name('gtx-cli');
|
|
7
8
|
const { library, additionalModules } = determineLibrary();
|
|
@@ -12,6 +13,9 @@ export function main(program) {
|
|
|
12
13
|
else if (library === 'gt-react') {
|
|
13
14
|
cli = new ReactCLI(program, library, additionalModules);
|
|
14
15
|
}
|
|
16
|
+
else if (library === 'gt-node') {
|
|
17
|
+
cli = new NodeCLI(program, library, additionalModules);
|
|
18
|
+
}
|
|
15
19
|
else {
|
|
16
20
|
cli = new BaseCLI(program, library, additionalModules);
|
|
17
21
|
}
|