gtx-cli 1.2.7 → 1.2.8-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/base.d.ts +4 -1
- package/dist/cli/base.js +38 -12
- package/dist/cli/react.js +9 -7
- package/dist/config/generateSettings.js +1 -0
- package/dist/console/colors.d.ts +5 -0
- package/dist/console/colors.js +26 -0
- package/dist/console/index.d.ts +8 -6
- package/dist/console/index.js +13 -9
- package/dist/formats/files/translate.js +3 -0
- package/dist/fs/config/setupConfig.d.ts +2 -1
- package/dist/fs/config/setupConfig.js +1 -0
- package/dist/react/jsx/parse/parseStringFunction.js +2 -2
- package/dist/react/jsx/utils/parseJsx.js +2 -2
- package/dist/react/jsx/utils/parseStringFunction.d.ts +2 -2
- package/dist/react/jsx/utils/parseStringFunction.js +7 -4
- package/dist/react/jsx/wrapJsx.js +1 -1
- package/dist/setup/wizard.js +5 -3
- package/dist/translation/stage.js +7 -4
- package/dist/types/index.d.ts +1 -0
- package/dist/utils/credentials.d.ts +4 -4
- package/dist/utils/credentials.js +30 -6
- package/package.json +2 -2
package/dist/cli/base.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ export type TranslateOptions = {
|
|
|
7
7
|
projectId?: string;
|
|
8
8
|
dryRun: boolean;
|
|
9
9
|
};
|
|
10
|
+
export type LoginOptions = {
|
|
11
|
+
keyType?: 'development' | 'production';
|
|
12
|
+
};
|
|
10
13
|
export declare class BaseCLI {
|
|
11
14
|
protected library: SupportedLibraries;
|
|
12
15
|
protected additionalModules: SupportedLibraries[];
|
|
@@ -21,5 +24,5 @@ export declare class BaseCLI {
|
|
|
21
24
|
protected handleGenericTranslate(settings: Settings & TranslateOptions): Promise<void>;
|
|
22
25
|
protected handleSetupReactCommand(options: SetupOptions): Promise<void>;
|
|
23
26
|
protected handleInitCommand(ranReactSetup: boolean): Promise<void>;
|
|
24
|
-
protected handleLoginCommand(): Promise<void>;
|
|
27
|
+
protected handleLoginCommand(options: LoginOptions): Promise<void>;
|
|
25
28
|
}
|
package/dist/cli/base.js
CHANGED
|
@@ -98,10 +98,32 @@ class BaseCLI {
|
|
|
98
98
|
.command('auth')
|
|
99
99
|
.description('Generate a General Translation API key and project ID')
|
|
100
100
|
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
101
|
-
.
|
|
101
|
+
.option('-t, --key-type <type>', 'Type of key to generate, production | development')
|
|
102
|
+
.action(async (options) => {
|
|
102
103
|
(0, console_1.displayHeader)('Authenticating with General Translation...');
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
if (!options.keyType) {
|
|
105
|
+
const packageJson = await (0, packageJson_1.searchForPackageJson)();
|
|
106
|
+
const isUsingGTNext = packageJson
|
|
107
|
+
? (0, packageJson_1.isPackageInstalled)('gt-next', packageJson)
|
|
108
|
+
: false;
|
|
109
|
+
const isUsingGTReact = packageJson
|
|
110
|
+
? (0, packageJson_1.isPackageInstalled)('gt-react', packageJson)
|
|
111
|
+
: false;
|
|
112
|
+
if (isUsingGTNext || isUsingGTReact) {
|
|
113
|
+
options.keyType = 'development';
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
options.keyType = 'production';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
if (options.keyType !== 'development' &&
|
|
121
|
+
options.keyType !== 'production') {
|
|
122
|
+
(0, console_1.logErrorAndExit)('Invalid key type, must be development or production');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
await this.handleLoginCommand(options);
|
|
126
|
+
(0, console_1.endCommand)(`Done! A ${options.keyType} key has been generated and saved to your .env.local file.`);
|
|
105
127
|
});
|
|
106
128
|
}
|
|
107
129
|
setupInitCommand() {
|
|
@@ -109,7 +131,7 @@ class BaseCLI {
|
|
|
109
131
|
.command('init')
|
|
110
132
|
.description('Run the setup wizard to configure your project for General Translation')
|
|
111
133
|
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components", (0, findFilepath_1.findFilepaths)(['./src', './app', './pages', './components']))
|
|
112
|
-
.option('--config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
134
|
+
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
113
135
|
.action(async (options) => {
|
|
114
136
|
(0, console_1.displayHeader)('Running setup wizard...');
|
|
115
137
|
const packageJson = await (0, packageJson_1.searchForPackageJson)();
|
|
@@ -154,7 +176,7 @@ See the docs for more information: https://generaltranslation.com/docs/react/tut
|
|
|
154
176
|
.command('setup')
|
|
155
177
|
.description('Run the setup to configure your Next.js or React project for General Translation')
|
|
156
178
|
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components", (0, findFilepath_1.findFilepaths)(['./src', './app', './pages', './components']))
|
|
157
|
-
.option('--config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
179
|
+
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
158
180
|
.action(async (options) => {
|
|
159
181
|
(0, console_1.displayHeader)('Running React setup wizard...');
|
|
160
182
|
await this.handleSetupReactCommand(options);
|
|
@@ -207,12 +229,12 @@ See the docs for more information: https://generaltranslation.com/docs/react/tut
|
|
|
207
229
|
? await (0, console_1.promptConfirm)({
|
|
208
230
|
message: `Auto-detected that you're using gt-next or gt-react. Would you like to use the General Translation CDN to store your translations?\nSee ${isUsingGTNext
|
|
209
231
|
? 'https://generaltranslation.com/docs/next/reference/local-tx'
|
|
210
|
-
: 'https://generaltranslation.com/docs/react/reference/local-tx'} for more information.\nIf you answer no, we'll
|
|
232
|
+
: 'https://generaltranslation.com/docs/react/reference/local-tx'} for more information.\nIf you answer no, we'll configure the CLI tool to download completed translations.`,
|
|
211
233
|
defaultValue: true,
|
|
212
234
|
})
|
|
213
235
|
: false;
|
|
214
236
|
if (isUsingGT && !usingCDN) {
|
|
215
|
-
(0, console_1.logMessage)(`To
|
|
237
|
+
(0, console_1.logMessage)(`To prevent translations from being published, please disable the project setting on the dashboard: ${chalk_1.default.cyan('https://dash.generaltranslation.com/settings/project')}`);
|
|
216
238
|
}
|
|
217
239
|
// Ask where the translations are stored
|
|
218
240
|
const translationsDir = isUsingGT && !usingCDN
|
|
@@ -276,18 +298,22 @@ See the docs for more information: https://generaltranslation.com/docs/react/tut
|
|
|
276
298
|
// Set credentials
|
|
277
299
|
if (!(0, credentials_2.areCredentialsSet)()) {
|
|
278
300
|
const loginQuestion = await (0, console_1.promptConfirm)({
|
|
279
|
-
message:
|
|
301
|
+
message: `Would you like the wizard to automatically generate a ${isUsingGT ? 'development' : 'production'} API key and project ID for you?`,
|
|
280
302
|
defaultValue: true,
|
|
281
303
|
});
|
|
282
304
|
if (loginQuestion) {
|
|
283
|
-
await
|
|
305
|
+
const settings = await (0, generateSettings_1.generateSettings)({});
|
|
306
|
+
const keyType = isUsingGT ? 'development' : 'production';
|
|
307
|
+
const credentials = await (0, credentials_1.retrieveCredentials)(settings, keyType);
|
|
308
|
+
await (0, credentials_1.setCredentials)(credentials, keyType, settings.framework);
|
|
284
309
|
}
|
|
285
310
|
}
|
|
286
311
|
}
|
|
287
|
-
async handleLoginCommand() {
|
|
312
|
+
async handleLoginCommand(options) {
|
|
288
313
|
const settings = await (0, generateSettings_1.generateSettings)({});
|
|
289
|
-
const
|
|
290
|
-
await (0, credentials_1.
|
|
314
|
+
const keyType = options.keyType || 'production';
|
|
315
|
+
const credentials = await (0, credentials_1.retrieveCredentials)(settings, keyType);
|
|
316
|
+
await (0, credentials_1.setCredentials)(credentials, keyType, settings.framework);
|
|
291
317
|
}
|
|
292
318
|
}
|
|
293
319
|
exports.BaseCLI = BaseCLI;
|
package/dist/cli/react.js
CHANGED
|
@@ -77,7 +77,7 @@ class ReactCLI extends base_1.BaseCLI {
|
|
|
77
77
|
commander_1.program
|
|
78
78
|
.command('stage')
|
|
79
79
|
.description('Submits the project to the General Translation API for translation. Translations created using this command will require human approval.')
|
|
80
|
-
.option('--config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
80
|
+
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
81
81
|
.option('--api-key <key>', 'API key for General Translation cloud service')
|
|
82
82
|
.option('--project-id <id>', 'Project ID for the translation service', (0, utils_1.resolveProjectId)())
|
|
83
83
|
.option('--version-id <id>', 'Version ID for the translation service')
|
|
@@ -100,7 +100,7 @@ class ReactCLI extends base_1.BaseCLI {
|
|
|
100
100
|
commander_1.program
|
|
101
101
|
.command('translate')
|
|
102
102
|
.description('Scans the project for a dictionary and/or <T> tags, and sends the updates to the General Translation API for translation.')
|
|
103
|
-
.option('--config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
103
|
+
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
104
104
|
.option('--api-key <key>', 'API key for General Translation cloud service')
|
|
105
105
|
.option('--project-id <id>', 'Project ID for the translation service', (0, utils_1.resolveProjectId)())
|
|
106
106
|
.option('--version-id <id>', 'Version ID for the translation service')
|
|
@@ -141,7 +141,7 @@ class ReactCLI extends base_1.BaseCLI {
|
|
|
141
141
|
.command('scan')
|
|
142
142
|
.description('Scans the project and wraps all JSX elements in the src directory with a <T> tag, with unique ids')
|
|
143
143
|
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components", (0, findFilepath_1.findFilepaths)(['./src', './app', './pages', './components']))
|
|
144
|
-
.option('--config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
144
|
+
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', (0, findFilepath_1.default)(['gt.config.json']))
|
|
145
145
|
.option('--disable-ids', 'Disable id generation for the <T> tags', false)
|
|
146
146
|
.option('--disable-formatting', 'Disable formatting of edited files', false)
|
|
147
147
|
.action(async (options) => {
|
|
@@ -168,14 +168,16 @@ class ReactCLI extends base_1.BaseCLI {
|
|
|
168
168
|
const { updates, errors } = await (0, parse_1.createUpdates)(options, options.dictionary, this.library === 'gt-next' ? 'gt-next' : 'gt-react');
|
|
169
169
|
if (errors.length > 0) {
|
|
170
170
|
if (options.ignoreErrors) {
|
|
171
|
-
(0, console_1.logWarning)(chalk_1.default.
|
|
171
|
+
(0, console_1.logWarning)(chalk_1.default.yellow(`CLI tool encountered errors while scanning for translatable content. These components will not be translated.\n` +
|
|
172
172
|
errors
|
|
173
|
-
.map((error) => chalk_1.default.yellow('• Warning: ') + error)
|
|
173
|
+
.map((error) => chalk_1.default.yellow('• Warning: ') + chalk_1.default.white(error))
|
|
174
174
|
.join('\n')));
|
|
175
175
|
}
|
|
176
176
|
else {
|
|
177
|
-
(0, console_1.logErrorAndExit)(chalk_1.default.red(`CLI tool encountered errors while scanning for
|
|
178
|
-
errors
|
|
177
|
+
(0, console_1.logErrorAndExit)(chalk_1.default.red(`CLI tool encountered errors while scanning for translatable content. ${chalk_1.default.gray('To ignore these errors, re-run with --ignore-errors')}\n` +
|
|
178
|
+
errors
|
|
179
|
+
.map((error) => chalk_1.default.red('• Error: ') + chalk_1.default.white(error))
|
|
180
|
+
.join('\n')));
|
|
179
181
|
}
|
|
180
182
|
}
|
|
181
183
|
// Convert updates to the proper data format
|
|
@@ -86,6 +86,7 @@ async function generateSettings(options) {
|
|
|
86
86
|
projectId: mergedOptions.projectId,
|
|
87
87
|
defaultLocale: mergedOptions.defaultLocale,
|
|
88
88
|
locales: mergedOptions.locales?.length > 0 ? mergedOptions.locales : undefined,
|
|
89
|
+
framework: mergedOptions.framework,
|
|
89
90
|
});
|
|
90
91
|
}
|
|
91
92
|
(0, validateSettings_1.validateSettings)(mergedOptions);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function colorizeFilepath(filepath: string): string;
|
|
2
|
+
export declare function colorizeComponent(component: string): string;
|
|
3
|
+
export declare function colorizeIdString(id: string): string;
|
|
4
|
+
export declare function colorizeContent(content: string): string;
|
|
5
|
+
export declare function colorizeLine(line: string): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.colorizeFilepath = colorizeFilepath;
|
|
7
|
+
exports.colorizeComponent = colorizeComponent;
|
|
8
|
+
exports.colorizeIdString = colorizeIdString;
|
|
9
|
+
exports.colorizeContent = colorizeContent;
|
|
10
|
+
exports.colorizeLine = colorizeLine;
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
function colorizeFilepath(filepath) {
|
|
13
|
+
return chalk_1.default.cyan(filepath);
|
|
14
|
+
}
|
|
15
|
+
function colorizeComponent(component) {
|
|
16
|
+
return chalk_1.default.yellow(component);
|
|
17
|
+
}
|
|
18
|
+
function colorizeIdString(id) {
|
|
19
|
+
return chalk_1.default.yellow(id);
|
|
20
|
+
}
|
|
21
|
+
function colorizeContent(content) {
|
|
22
|
+
return chalk_1.default.yellow(content);
|
|
23
|
+
}
|
|
24
|
+
function colorizeLine(line) {
|
|
25
|
+
return chalk_1.default.gray(line);
|
|
26
|
+
}
|
package/dist/console/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export * from './logging';
|
|
2
2
|
export declare const warnApiKeyInConfigSync: (optionsFilepath: string) => string;
|
|
3
|
-
export declare const warnVariablePropSync: (file: string, attrName: string, value: string) => string;
|
|
4
|
-
export declare const
|
|
5
|
-
export declare const
|
|
6
|
-
export declare const
|
|
7
|
-
export declare const
|
|
8
|
-
export declare const warnTernarySync: (file: string) => string;
|
|
3
|
+
export declare const warnVariablePropSync: (file: string, attrName: string, value: string, location?: string) => string;
|
|
4
|
+
export declare const warnHasUnwrappedExpressionSync: (file: string, unwrappedExpressions: string[], id?: string, location?: string) => string;
|
|
5
|
+
export declare const warnNonStaticExpressionSync: (file: string, attrName: string, value: string, location?: string) => string;
|
|
6
|
+
export declare const warnTemplateLiteralSync: (file: string, value: string, location?: string) => string;
|
|
7
|
+
export declare const warnNonStringSync: (file: string, value: string, location?: string) => string;
|
|
8
|
+
export declare const warnTernarySync: (file: string, location?: string) => string;
|
|
9
|
+
export declare const withLocation: (file: string, message: string, location?: string) => string;
|
|
9
10
|
export declare const noLocalesError = "No locales found! Please provide a list of locales to translate to, or specify them in your gt.config.json file.";
|
|
10
11
|
export declare const noDefaultLocaleError = "No default locale found! Please provide a default locale, or specify it in your gt.config.json file.";
|
|
11
12
|
export declare const noFilesError = "Incorrect or missing files configuration! Please make sure your files are configured correctly in your gt.config.json file.";
|
|
@@ -13,5 +14,6 @@ export declare const noSourceFileError = "No source file found! Please double ch
|
|
|
13
14
|
export declare const noDataFormatError = "No data format found! Please make sure your translationsDir parameter ends with a supported file extension.";
|
|
14
15
|
export declare const noSupportedDataFormatError = "Unsupported data format! Please make sure your translationsDir parameter ends with a supported file extension.";
|
|
15
16
|
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.";
|
|
17
|
+
export declare const devApiKeyError = "You are using a development API key. Please use a production API key to send files to General Translation.\nYou can generate a production API key with the command: npx gtx-cli auth -t production";
|
|
16
18
|
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.";
|
|
17
19
|
export declare const noVersionIdError = "No version ID found! Please provide a version ID using the --version-id flag or specify it in your gt.config.json file as the _versionId property.";
|
package/dist/console/index.js
CHANGED
|
@@ -14,24 +14,27 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.noVersionIdError = exports.noProjectIdError = exports.noApiKeyError = exports.noSupportedDataFormatError = exports.noDataFormatError = exports.noSourceFileError = exports.noFilesError = exports.noDefaultLocaleError = exports.noLocalesError = exports.warnTernarySync = exports.
|
|
17
|
+
exports.noVersionIdError = exports.noProjectIdError = exports.devApiKeyError = exports.noApiKeyError = exports.noSupportedDataFormatError = exports.noDataFormatError = exports.noSourceFileError = exports.noFilesError = exports.noDefaultLocaleError = exports.noLocalesError = exports.withLocation = exports.warnTernarySync = exports.warnNonStringSync = exports.warnTemplateLiteralSync = exports.warnNonStaticExpressionSync = exports.warnHasUnwrappedExpressionSync = exports.warnVariablePropSync = exports.warnApiKeyInConfigSync = void 0;
|
|
18
18
|
// Export all logging functions
|
|
19
19
|
__exportStar(require("./logging"), exports);
|
|
20
|
+
const colors_1 = require("./colors");
|
|
20
21
|
// Synchronous wrappers for backward compatibility
|
|
21
|
-
const warnApiKeyInConfigSync = (optionsFilepath) =>
|
|
22
|
+
const warnApiKeyInConfigSync = (optionsFilepath) => `${(0, colors_1.colorizeFilepath)(optionsFilepath)}: Your API key is exposed! Please remove it from the file and include it as an environment variable.`;
|
|
22
23
|
exports.warnApiKeyInConfigSync = warnApiKeyInConfigSync;
|
|
23
|
-
const warnVariablePropSync = (file, attrName, value) =>
|
|
24
|
+
const warnVariablePropSync = (file, attrName, value, location) => (0, exports.withLocation)(file, `${(0, colors_1.colorizeComponent)('<T>')} component has dynamic attribute ${(0, colors_1.colorizeIdString)(attrName)} with value: ${(0, colors_1.colorizeContent)(value)}. Change ${(0, colors_1.colorizeIdString)(attrName)} to ensure this content is translated.`, location);
|
|
24
25
|
exports.warnVariablePropSync = warnVariablePropSync;
|
|
25
|
-
const
|
|
26
|
-
exports.warnNoIdSync = warnNoIdSync;
|
|
27
|
-
const warnHasUnwrappedExpressionSync = (file, id, unwrappedExpressions) => `<T> with id "${id}" in ${file} has children: ${unwrappedExpressions.join(', ')} that could change at runtime. Use a variable component like <Var> to translate this properly.`;
|
|
26
|
+
const warnHasUnwrappedExpressionSync = (file, unwrappedExpressions, id, location) => (0, exports.withLocation)(file, `${(0, colors_1.colorizeComponent)('<T>')} component${id ? ` with id ${(0, colors_1.colorizeIdString)(id)}` : ''} has children that could change at runtime. Use a variable component like ${(0, colors_1.colorizeComponent)('<Var>')} to ensure this content is translated.\n${(0, colors_1.colorizeContent)(unwrappedExpressions.join('\n'))}`, location);
|
|
28
27
|
exports.warnHasUnwrappedExpressionSync = warnHasUnwrappedExpressionSync;
|
|
29
|
-
const warnNonStaticExpressionSync = (file, attrName, value) => `Found non-static expression
|
|
28
|
+
const warnNonStaticExpressionSync = (file, attrName, value, location) => (0, exports.withLocation)(file, `Found non-static expression for attribute ${(0, colors_1.colorizeIdString)(attrName)}: ${(0, colors_1.colorizeContent)(value)}. Change "${(0, colors_1.colorizeIdString)(attrName)}" to ensure this content is translated.`, location);
|
|
30
29
|
exports.warnNonStaticExpressionSync = warnNonStaticExpressionSync;
|
|
31
|
-
const warnTemplateLiteralSync = (file, value) => `Found template literal with quasis (${value})
|
|
30
|
+
const warnTemplateLiteralSync = (file, value, location) => (0, exports.withLocation)(file, `Found template literal with quasis (${(0, colors_1.colorizeContent)(value)}). Change the template literal to a string to ensure this content is translated.`, location);
|
|
32
31
|
exports.warnTemplateLiteralSync = warnTemplateLiteralSync;
|
|
33
|
-
const
|
|
32
|
+
const warnNonStringSync = (file, value, location) => (0, exports.withLocation)(file, `Found non-string literal (${(0, colors_1.colorizeContent)(value)}). Change the value to a string literal to ensure this content is translated.`, location);
|
|
33
|
+
exports.warnNonStringSync = warnNonStringSync;
|
|
34
|
+
const warnTernarySync = (file, location) => (0, exports.withLocation)(file, 'Found ternary expression. A Branch component may be more appropriate here.', location);
|
|
34
35
|
exports.warnTernarySync = warnTernarySync;
|
|
36
|
+
const withLocation = (file, message, location) => `${(0, colors_1.colorizeFilepath)(file)}${location ? ` (${(0, colors_1.colorizeLine)(location)})` : ''}: ${message}`;
|
|
37
|
+
exports.withLocation = withLocation;
|
|
35
38
|
// Re-export error messages
|
|
36
39
|
exports.noLocalesError = `No locales found! Please provide a list of locales to translate to, or specify them in your gt.config.json file.`;
|
|
37
40
|
exports.noDefaultLocaleError = `No default locale found! Please provide a default locale, or specify it in your gt.config.json file.`;
|
|
@@ -40,5 +43,6 @@ exports.noSourceFileError = `No source file found! Please double check your tran
|
|
|
40
43
|
exports.noDataFormatError = `No data format found! Please make sure your translationsDir parameter ends with a supported file extension.`;
|
|
41
44
|
exports.noSupportedDataFormatError = `Unsupported data format! Please make sure your translationsDir parameter ends with a supported file extension.`;
|
|
42
45
|
exports.noApiKeyError = `No API key found! Please provide an API key using the --api-key flag or set the GT_API_KEY environment variable.`;
|
|
46
|
+
exports.devApiKeyError = `You are using a development API key. Please use a production API key to send files to General Translation.\nYou can generate a production API key with the command: npx gtx-cli auth -t production`;
|
|
43
47
|
exports.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.`;
|
|
44
48
|
exports.noVersionIdError = `No version ID found! Please provide a version ID using the --version-id flag or specify it in your gt.config.json file as the _versionId property.`;
|
|
@@ -84,6 +84,9 @@ async function translateFiles(filePaths, placeholderPaths, transformPaths, dataF
|
|
|
84
84
|
if (!options.apiKey) {
|
|
85
85
|
(0, console_1.logErrorAndExit)(console_1.noApiKeyError);
|
|
86
86
|
}
|
|
87
|
+
if (options.apiKey.startsWith('gtx-dev-')) {
|
|
88
|
+
(0, console_1.logErrorAndExit)(console_1.devApiKeyError);
|
|
89
|
+
}
|
|
87
90
|
if (!options.projectId) {
|
|
88
91
|
(0, console_1.logErrorAndExit)(console_1.noProjectIdError);
|
|
89
92
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FilesOptions } from '../../types';
|
|
1
|
+
import { FilesOptions, SupportedFrameworks } from '../../types';
|
|
2
2
|
/**
|
|
3
3
|
* Checks if the config file exists.
|
|
4
4
|
* If yes, make sure make sure projectId is correct
|
|
@@ -11,4 +11,5 @@ export default function createOrUpdateConfig(configFilepath: string, options: {
|
|
|
11
11
|
defaultLocale?: string;
|
|
12
12
|
locales?: string[];
|
|
13
13
|
files?: FilesOptions;
|
|
14
|
+
framework?: SupportedFrameworks;
|
|
14
15
|
}): Promise<string>;
|
|
@@ -19,6 +19,7 @@ async function createOrUpdateConfig(configFilepath, options) {
|
|
|
19
19
|
...(options.projectId && { projectId: options.projectId }),
|
|
20
20
|
...(options.defaultLocale && { defaultLocale: options.defaultLocale }),
|
|
21
21
|
...(options.files && { files: options.files }),
|
|
22
|
+
...(options.framework && { framework: options.framework }),
|
|
22
23
|
};
|
|
23
24
|
try {
|
|
24
25
|
// if file exists
|
|
@@ -91,7 +91,7 @@ function parseStrings(importName, path, updates, errors, file) {
|
|
|
91
91
|
t.isExpression(prop.value)) {
|
|
92
92
|
const result = (0, evaluateJsx_1.isStaticExpression)(prop.value);
|
|
93
93
|
if (!result.isStatic) {
|
|
94
|
-
errors.push((0, console_1.warnNonStaticExpressionSync)(file, attribute, (0, generator_1.default)(prop.value).code));
|
|
94
|
+
errors.push((0, console_1.warnNonStaticExpressionSync)(file, attribute, (0, generator_1.default)(prop.value).code, `${prop.loc?.start?.line}:${prop.loc?.start?.column}`));
|
|
95
95
|
}
|
|
96
96
|
if (result.isStatic && result.value) {
|
|
97
97
|
metadata[attribute] = result.value;
|
|
@@ -108,7 +108,7 @@ function parseStrings(importName, path, updates, errors, file) {
|
|
|
108
108
|
}
|
|
109
109
|
else if (t.isTemplateLiteral(arg)) {
|
|
110
110
|
// warn if template literal
|
|
111
|
-
errors.push((0, console_1.warnTemplateLiteralSync)(file, (0, generator_1.default)(arg).code));
|
|
111
|
+
errors.push((0, console_1.warnTemplateLiteralSync)(file, (0, generator_1.default)(arg).code, `${arg.loc?.start?.line}:${arg.loc?.start?.column}`));
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
});
|
|
@@ -205,7 +205,7 @@ function parseJSXElement(importAliases, node, updates, errors, file) {
|
|
|
205
205
|
if (attrName === 'id' || attrName === 'context') {
|
|
206
206
|
const staticAnalysis = (0, evaluateJsx_1.isStaticExpression)(expr);
|
|
207
207
|
if (!staticAnalysis.isStatic) {
|
|
208
|
-
errors.push((0, console_1.warnVariablePropSync)(file, attrName, code));
|
|
208
|
+
errors.push((0, console_1.warnVariablePropSync)(file, attrName, code, `${expr.loc?.start?.line}:${expr.loc?.start?.column}`));
|
|
209
209
|
}
|
|
210
210
|
// Use the static value if available
|
|
211
211
|
if (staticAnalysis.isStatic && staticAnalysis.value !== undefined) {
|
|
@@ -231,7 +231,7 @@ function parseJSXElement(importAliases, node, updates, errors, file) {
|
|
|
231
231
|
const id = componentObj.props.id;
|
|
232
232
|
// If we found an unwrapped expression, skip
|
|
233
233
|
if (unwrappedExpressions.length > 0) {
|
|
234
|
-
errors.push((0, console_1.warnHasUnwrappedExpressionSync)(file, id,
|
|
234
|
+
errors.push((0, console_1.warnHasUnwrappedExpressionSync)(file, unwrappedExpressions, id, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
|
|
235
235
|
}
|
|
236
236
|
if (errors.length > 0)
|
|
237
237
|
return;
|
|
@@ -3,8 +3,8 @@ import { Updates } from '../../../types';
|
|
|
3
3
|
export declare const attributes: string[];
|
|
4
4
|
/**
|
|
5
5
|
* For the following example code:
|
|
6
|
-
* const
|
|
7
|
-
*
|
|
6
|
+
* const t = useGT();
|
|
7
|
+
* t('string to translate', { id: 'exampleId', context: 'exampleContext' });
|
|
8
8
|
*
|
|
9
9
|
* This function will find all call expressions of useGT(), then find all call expressions
|
|
10
10
|
* of the subsequent tx() calls, and append the content and metadata to the updates array.
|
|
@@ -46,8 +46,8 @@ const generator_1 = __importDefault(require("@babel/generator"));
|
|
|
46
46
|
exports.attributes = ['id', 'context'];
|
|
47
47
|
/**
|
|
48
48
|
* For the following example code:
|
|
49
|
-
* const
|
|
50
|
-
*
|
|
49
|
+
* const t = useGT();
|
|
50
|
+
* t('string to translate', { id: 'exampleId', context: 'exampleContext' });
|
|
51
51
|
*
|
|
52
52
|
* This function will find all call expressions of useGT(), then find all call expressions
|
|
53
53
|
* of the subsequent tx() calls, and append the content and metadata to the updates array.
|
|
@@ -91,7 +91,7 @@ function parseStrings(importName, path, updates, errors, file) {
|
|
|
91
91
|
t.isExpression(prop.value)) {
|
|
92
92
|
const result = (0, evaluateJsx_1.isStaticExpression)(prop.value);
|
|
93
93
|
if (!result.isStatic) {
|
|
94
|
-
errors.push((0, console_1.warnNonStaticExpressionSync)(file, attribute, (0, generator_1.default)(prop.value).code));
|
|
94
|
+
errors.push((0, console_1.warnNonStaticExpressionSync)(file, attribute, (0, generator_1.default)(prop.value).code, `${prop.loc?.start?.line}:${prop.loc?.start?.column}`));
|
|
95
95
|
}
|
|
96
96
|
if (result.isStatic && result.value) {
|
|
97
97
|
metadata[attribute] = result.value;
|
|
@@ -108,7 +108,10 @@ function parseStrings(importName, path, updates, errors, file) {
|
|
|
108
108
|
}
|
|
109
109
|
else if (t.isTemplateLiteral(arg)) {
|
|
110
110
|
// warn if template literal
|
|
111
|
-
errors.push((0, console_1.warnTemplateLiteralSync)(file, (0, generator_1.default)(arg).code));
|
|
111
|
+
errors.push((0, console_1.warnTemplateLiteralSync)(file, (0, generator_1.default)(arg).code, `${arg.loc?.start?.line}:${arg.loc?.start?.column}`));
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
errors.push((0, console_1.warnNonStringSync)(file, (0, generator_1.default)(arg).code, `${arg.loc?.start?.line}:${arg.loc?.start?.column}`));
|
|
112
115
|
}
|
|
113
116
|
}
|
|
114
117
|
});
|
|
@@ -86,7 +86,7 @@ function wrapJsxExpression(node, options, isMeaningful, mark) {
|
|
|
86
86
|
}
|
|
87
87
|
// Warn about ternary (should use branch instead)
|
|
88
88
|
if (result.wrappedInT && !mark) {
|
|
89
|
-
options.warnings.push((0, console_1.warnTernarySync)(options.file));
|
|
89
|
+
options.warnings.push((0, console_1.warnTernarySync)(options.file, `${consequent.loc?.start?.line}:${consequent.loc?.start?.column}`));
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
else if (t.isConditionalExpression(consequent) ||
|
package/dist/setup/wizard.js
CHANGED
|
@@ -10,7 +10,6 @@ const console_2 = require("../console");
|
|
|
10
10
|
const chalk_1 = __importDefault(require("chalk"));
|
|
11
11
|
const console_3 = require("../console");
|
|
12
12
|
const findFilepath_1 = __importDefault(require("../fs/findFilepath"));
|
|
13
|
-
const generateSettings_1 = require("../config/generateSettings");
|
|
14
13
|
const postProcess_2 = require("../hooks/postProcess");
|
|
15
14
|
const handleInitGT_1 = __importDefault(require("../next/parse/handleInitGT"));
|
|
16
15
|
const packageJson_1 = require("../utils/packageJson");
|
|
@@ -18,6 +17,7 @@ const wrapContent_1 = __importDefault(require("../react/parse/wrapContent"));
|
|
|
18
17
|
const wrapContent_2 = __importDefault(require("../next/parse/wrapContent"));
|
|
19
18
|
const packageManager_1 = require("../utils/packageManager");
|
|
20
19
|
const installPackage_1 = require("../utils/installPackage");
|
|
20
|
+
const setupConfig_1 = __importDefault(require("../fs/config/setupConfig"));
|
|
21
21
|
async function handleSetupReactCommand(options) {
|
|
22
22
|
// Ask user for confirmation using inquirer
|
|
23
23
|
const answer = await (0, console_3.promptConfirm)({
|
|
@@ -50,6 +50,10 @@ Make sure you have committed or stashed any changes. Do you want to continue?`),
|
|
|
50
50
|
Please let us know what you would like to see supported at https://github.com/generaltranslation/gt/issues`);
|
|
51
51
|
process.exit(0);
|
|
52
52
|
}
|
|
53
|
+
// ----- Create a starter gt.config.json file -----
|
|
54
|
+
await (0, setupConfig_1.default)(options.config || 'gt.config.json', {
|
|
55
|
+
framework: frameworkType,
|
|
56
|
+
});
|
|
53
57
|
const packageJson = await (0, packageJson_1.getPackageJson)();
|
|
54
58
|
// Check if gt-next or gt-react is installed
|
|
55
59
|
if (frameworkType === 'next-app' &&
|
|
@@ -68,8 +72,6 @@ Please let us know what you would like to see supported at https://github.com/ge
|
|
|
68
72
|
await (0, installPackage_1.installPackage)('gt-react', packageManager);
|
|
69
73
|
spinner.stop(chalk_1.default.green('Automatically installed gt-react.'));
|
|
70
74
|
}
|
|
71
|
-
// ----- Create a starter gt.config.json file -----
|
|
72
|
-
await (0, generateSettings_1.generateSettings)(options);
|
|
73
75
|
let errors = [];
|
|
74
76
|
let warnings = [];
|
|
75
77
|
let filesUpdated = [];
|
|
@@ -34,15 +34,15 @@ async function stageProject(settings, pkg) {
|
|
|
34
34
|
const { updates, errors } = await (0, parse_1.createUpdates)(settings, settings.dictionary, pkg);
|
|
35
35
|
if (errors.length > 0) {
|
|
36
36
|
if (settings.ignoreErrors) {
|
|
37
|
-
(0, logging_1.logWarning)(chalk_1.default.
|
|
37
|
+
(0, logging_1.logWarning)(chalk_1.default.yellow(`Warning: CLI tool encountered syntax errors while scanning for translatable content. These components will not be translated.\n` +
|
|
38
38
|
errors
|
|
39
|
-
.map((error) => chalk_1.default.yellow('•
|
|
39
|
+
.map((error) => chalk_1.default.yellow('• ') + chalk_1.default.white(error) + '\n')
|
|
40
40
|
.join('')));
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
43
|
-
(0, errors_1.logErrorAndExit)(chalk_1.default.red(`CLI tool encountered errors while scanning for
|
|
43
|
+
(0, errors_1.logErrorAndExit)(chalk_1.default.red(`Error: CLI tool encountered syntax errors while scanning for translatable content. ${chalk_1.default.gray('To ignore these errors, re-run with --ignore-errors')}\n` +
|
|
44
44
|
errors
|
|
45
|
-
.map((error) => chalk_1.default.red('•
|
|
45
|
+
.map((error) => chalk_1.default.red('• ') + chalk_1.default.white(error) + '\n')
|
|
46
46
|
.join('')));
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -64,6 +64,9 @@ async function stageProject(settings, pkg) {
|
|
|
64
64
|
if (!settings.apiKey) {
|
|
65
65
|
(0, errors_1.logErrorAndExit)(errors_2.noApiKeyError);
|
|
66
66
|
}
|
|
67
|
+
if (settings.apiKey.startsWith('gtx-dev-')) {
|
|
68
|
+
(0, errors_1.logErrorAndExit)(errors_1.devApiKeyError);
|
|
69
|
+
}
|
|
67
70
|
if (!settings.projectId) {
|
|
68
71
|
(0, errors_1.logErrorAndExit)(errors_2.noProjectIdError);
|
|
69
72
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { Settings } from '../types';
|
|
1
|
+
import { Settings, SupportedFrameworks } from '../types';
|
|
2
2
|
type Credentials = {
|
|
3
3
|
apiKey: string;
|
|
4
4
|
projectId: string;
|
|
5
5
|
};
|
|
6
|
-
export declare function retrieveCredentials(settings: Settings): Promise<Credentials>;
|
|
7
|
-
export declare function generateCredentialsSession(url: string): Promise<{
|
|
6
|
+
export declare function retrieveCredentials(settings: Settings, keyType: 'development' | 'production'): Promise<Credentials>;
|
|
7
|
+
export declare function generateCredentialsSession(url: string, keyType: 'development' | 'production'): Promise<{
|
|
8
8
|
sessionId: string;
|
|
9
9
|
}>;
|
|
10
10
|
export declare function areCredentialsSet(): string | undefined;
|
|
11
|
-
export declare function setCredentials(credentials: Credentials): Promise<void>;
|
|
11
|
+
export declare function setCredentials(credentials: Credentials, type: 'development' | 'production', framework?: SupportedFrameworks): Promise<void>;
|
|
12
12
|
export {};
|
|
@@ -12,9 +12,9 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
12
12
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
13
|
const chalk_1 = __importDefault(require("chalk"));
|
|
14
14
|
// Fetches project ID and API key by opening the dashboard in the browser
|
|
15
|
-
async function retrieveCredentials(settings) {
|
|
15
|
+
async function retrieveCredentials(settings, keyType) {
|
|
16
16
|
// Generate a session ID
|
|
17
|
-
const { sessionId } = await generateCredentialsSession(settings.baseUrl);
|
|
17
|
+
const { sessionId } = await generateCredentialsSession(settings.baseUrl, keyType);
|
|
18
18
|
const urlToOpen = `${settings.dashboardUrl}/cli/wizard/${sessionId}`;
|
|
19
19
|
await import('open').then((open) => open.default(urlToOpen, {
|
|
20
20
|
wait: false,
|
|
@@ -53,12 +53,15 @@ async function retrieveCredentials(settings) {
|
|
|
53
53
|
spinner.stop('Received credentials');
|
|
54
54
|
return credentials;
|
|
55
55
|
}
|
|
56
|
-
async function generateCredentialsSession(url) {
|
|
56
|
+
async function generateCredentialsSession(url, keyType) {
|
|
57
57
|
const res = await fetch(`${url}/cli/wizard/session`, {
|
|
58
58
|
method: 'POST',
|
|
59
59
|
headers: {
|
|
60
60
|
'Content-Type': 'application/json',
|
|
61
61
|
},
|
|
62
|
+
body: JSON.stringify({
|
|
63
|
+
keyType,
|
|
64
|
+
}),
|
|
62
65
|
});
|
|
63
66
|
if (!res.ok) {
|
|
64
67
|
(0, console_1.logErrorAndExit)('Failed to generate credentials session');
|
|
@@ -70,7 +73,7 @@ function areCredentialsSet() {
|
|
|
70
73
|
return process.env.GT_PROJECT_ID && process.env.GT_API_KEY;
|
|
71
74
|
}
|
|
72
75
|
// Sets the credentials in .env.local file
|
|
73
|
-
async function setCredentials(credentials) {
|
|
76
|
+
async function setCredentials(credentials, type, framework) {
|
|
74
77
|
const envFile = node_path_1.default.join(process.cwd(), '.env.local');
|
|
75
78
|
let envContent = '';
|
|
76
79
|
// Check if .env.local exists, create it if it doesn't
|
|
@@ -95,8 +98,29 @@ async function setCredentials(credentials) {
|
|
|
95
98
|
envContent = await node_fs_1.default.promises.readFile(envFile, 'utf8');
|
|
96
99
|
}
|
|
97
100
|
// Always append the credentials to the file
|
|
98
|
-
|
|
99
|
-
|
|
101
|
+
let prefix = '';
|
|
102
|
+
if (framework === 'next-pages') {
|
|
103
|
+
prefix = 'NEXT_PUBLIC_';
|
|
104
|
+
}
|
|
105
|
+
else if (framework === 'vite') {
|
|
106
|
+
prefix = 'VITE_';
|
|
107
|
+
}
|
|
108
|
+
else if (framework === 'gatsby') {
|
|
109
|
+
prefix = 'GATSBY_';
|
|
110
|
+
}
|
|
111
|
+
else if (framework === 'react') {
|
|
112
|
+
prefix = 'REACT_APP_';
|
|
113
|
+
}
|
|
114
|
+
else if (framework === 'redwood') {
|
|
115
|
+
prefix = 'REDWOOD_ENV_';
|
|
116
|
+
}
|
|
117
|
+
envContent += `\n${prefix}GT_PROJECT_ID=${credentials.projectId}\n`;
|
|
118
|
+
if (type === 'development') {
|
|
119
|
+
envContent += `${prefix || ''}GT_DEV_API_KEY=${credentials.apiKey}\n`;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
envContent += `GT_API_KEY=${credentials.apiKey}\n`;
|
|
123
|
+
}
|
|
100
124
|
// Ensure we don't have excessive newlines
|
|
101
125
|
envContent = envContent.replace(/\n{3,}/g, '\n\n').trim() + '\n';
|
|
102
126
|
// Write the updated content back to the file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gtx-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.8-alpha.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": "dist/main.js",
|
|
6
6
|
"scripts": {
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"chalk": "^4.1.2",
|
|
70
70
|
"commander": "^12.1.0",
|
|
71
71
|
"dotenv": "^16.4.5",
|
|
72
|
-
"esbuild": "^0.
|
|
72
|
+
"esbuild": "^0.25.4",
|
|
73
73
|
"fast-glob": "^3.3.3",
|
|
74
74
|
"form-data": "^4.0.2",
|
|
75
75
|
"generaltranslation": "^6.2.4",
|