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