gt 2.16.0 → 2.16.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/CHANGELOG.md +19 -0
- package/dist/cli/base.js +39 -9
- package/dist/cli/base.js.map +1 -1
- package/dist/cli/flags.js +1 -1
- package/dist/cli/flags.js.map +1 -1
- package/dist/fs/config/setupConfig.js +12 -0
- package/dist/fs/config/setupConfig.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/generated/version.js.map +1 -1
- package/dist/setup/setupViteSPA.d.ts +9 -0
- package/dist/setup/setupViteSPA.js +111 -0
- package/dist/setup/setupViteSPA.js.map +1 -0
- package/dist/setup/userInput.d.ts +4 -1
- package/dist/setup/userInput.js +5 -3
- package/dist/setup/userInput.js.map +1 -1
- package/dist/setup/wizard.js +1 -9
- package/dist/setup/wizard.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# gtx-cli
|
|
2
2
|
|
|
3
|
+
## 2.16.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#2029](https://github.com/generaltranslation/gt/pull/2029) [`c1fd8a0`](https://github.com/generaltranslation/gt/commit/c1fd8a05c5325775e3ec8104e2d48d35da864de6) Thanks [@eoinest](https://github.com/eoinest)! - Configure Vite React apps with `initializeGTSPA` and bundled translation loading without adding the compiler.
|
|
8
|
+
|
|
9
|
+
## 2.16.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#2019](https://github.com/generaltranslation/gt/pull/2019) [`60d154c`](https://github.com/generaltranslation/gt/commit/60d154c851d6ae0510447b7d66ec5e12104f0d1b) Thanks [@eoinest](https://github.com/eoinest)! - Save local edits before translation by default, with a `--no-save-local` flag to opt out.
|
|
14
|
+
|
|
15
|
+
- [#2028](https://github.com/generaltranslation/gt/pull/2028) [`8066d0a`](https://github.com/generaltranslation/gt/commit/8066d0ad64d4f9c3475a935e6bbb27d9f7389b20) Thanks [@eoinest](https://github.com/eoinest)! - Stop the setup wizard at monorepo workspace roots and direct users to run it from the app they want to localize.
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [[`9b3eb92`](https://github.com/generaltranslation/gt/commit/9b3eb92fb1a916b5f47d15f51a9f39f6c62840a9)]:
|
|
18
|
+
- generaltranslation@9.1.1
|
|
19
|
+
- @generaltranslation/python-extractor@0.2.34
|
|
20
|
+
- @generaltranslation/supported-locales@2.1.14
|
|
21
|
+
|
|
3
22
|
## 2.16.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
package/dist/cli/base.js
CHANGED
|
@@ -6,6 +6,7 @@ import { displayHeader, exitSync, logErrorAndExit, promptConfirm, promptGlobPatt
|
|
|
6
6
|
import findFilepath from "../fs/findFilepath.js";
|
|
7
7
|
import { lottieTranslateError } from "../console/index.js";
|
|
8
8
|
import { INLINE_LIBRARIES } from "../types/libraries.js";
|
|
9
|
+
import { loadConfig } from "../fs/config/loadConfig.js";
|
|
9
10
|
import { FILE_EXT_TO_EXT_LABEL } from "../formats/files/supportedFiles.js";
|
|
10
11
|
import { generateSettings } from "../config/generateSettings.js";
|
|
11
12
|
import { createOrUpdateConfig } from "../fs/config/setupConfig.js";
|
|
@@ -35,9 +36,11 @@ import { splitMintlifyLanguageRefs } from "../utils/splitMintlifyLanguageRefs.js
|
|
|
35
36
|
import { runMergeDriver } from "../git/mergeDrivers.js";
|
|
36
37
|
import { setupGitMergeDrivers } from "../git/setupMergeDrivers.js";
|
|
37
38
|
import { warnReactPackageCompatibility } from "../utils/reactPackageCompatibility.js";
|
|
39
|
+
import { setupViteSPA } from "../setup/setupViteSPA.js";
|
|
38
40
|
import chalk from "chalk";
|
|
39
41
|
import path from "node:path";
|
|
40
42
|
import fs from "node:fs";
|
|
43
|
+
import { createDiagnosticMessage } from "generaltranslation/internal";
|
|
41
44
|
//#region src/cli/base.ts
|
|
42
45
|
const ID_COMPATIBILITY_WARNING_COMMANDS = new Set([
|
|
43
46
|
"download",
|
|
@@ -48,6 +51,24 @@ const ID_COMPATIBILITY_WARNING_COMMANDS = new Set([
|
|
|
48
51
|
"translate",
|
|
49
52
|
"validate"
|
|
50
53
|
]);
|
|
54
|
+
const workspaceRootSetupError = createDiagnosticMessage({
|
|
55
|
+
source: "gt",
|
|
56
|
+
severity: "Error",
|
|
57
|
+
whatHappened: "The setup wizard cannot run from a monorepo workspace root",
|
|
58
|
+
why: "GT must be configured in the specific app you want to localize",
|
|
59
|
+
fix: "Change to that app's directory and rerun `npx gt@latest`"
|
|
60
|
+
});
|
|
61
|
+
const electronSetupError = createDiagnosticMessage({
|
|
62
|
+
source: "gt",
|
|
63
|
+
severity: "Error",
|
|
64
|
+
whatHappened: "The automatic setup wizard is not ready for Electron applications",
|
|
65
|
+
docsUrl: "https://generaltranslation.com/docs/react"
|
|
66
|
+
});
|
|
67
|
+
async function exitIfUnsupportedSetupTarget() {
|
|
68
|
+
const packageJson = await searchForPackageJson();
|
|
69
|
+
if (packageJson && isPackageInstalled("electron", packageJson, false, true)) logErrorAndExit(electronSetupError);
|
|
70
|
+
if (fs.existsSync(path.join(process.cwd(), "pnpm-workspace.yaml")) || packageJson?.workspaces) logErrorAndExit(workspaceRootSetupError);
|
|
71
|
+
}
|
|
51
72
|
var BaseCLI = class {
|
|
52
73
|
library;
|
|
53
74
|
additionalModules;
|
|
@@ -262,6 +283,7 @@ var BaseCLI = class {
|
|
|
262
283
|
}
|
|
263
284
|
setupInitCommand() {
|
|
264
285
|
this.program.command("init").description("Run the setup wizard to configure your project for General Translation").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}'").option("-c, --config <path>", "Filepath to config file, by default gt.config.json", findFilepath(["gt.config.json"])).action(async (options) => {
|
|
286
|
+
await exitIfUnsupportedSetupTarget();
|
|
265
287
|
const settings = await generateSettings(options);
|
|
266
288
|
displayHeader("Running setup wizard...");
|
|
267
289
|
const framework = await detectFramework();
|
|
@@ -281,7 +303,7 @@ var BaseCLI = class {
|
|
|
281
303
|
const frameworkDisplayName = framework.type === "react" ? getFrameworkDisplayName(framework) : null;
|
|
282
304
|
const library = framework.type === "react" ? getReactFrameworkLibrary(framework) : null;
|
|
283
305
|
const defaultTranslationsDir = framework.name === "vite" ? DEFAULT_VITE_TRANSLATIONS_DIR : DEFAULT_TRANSLATIONS_DIR;
|
|
284
|
-
const defaultsDescription = framework.type === "react" ? `${library} & GTProvider, ${frameworkDisplayName}, Files saved locally in ${defaultTranslationsDir}` : `Files saved locally in ${defaultTranslationsDir}`;
|
|
306
|
+
const defaultsDescription = framework.name === "vite" ? `${library} & initializeGTSPA, ${frameworkDisplayName}, Files saved locally in ${defaultTranslationsDir}` : framework.type === "react" ? `${library} & GTProvider, ${frameworkDisplayName}, Files saved locally in ${defaultTranslationsDir}` : `Files saved locally in ${defaultTranslationsDir}`;
|
|
285
307
|
const useDefaults = await promptConfirm({
|
|
286
308
|
message: `Would you like to use the recommended General Translation defaults? ${chalk.dim(`(${defaultsDescription})`)}`,
|
|
287
309
|
defaultValue: true
|
|
@@ -289,7 +311,7 @@ var BaseCLI = class {
|
|
|
289
311
|
let ranReactSetup = false;
|
|
290
312
|
if (framework.type === "react") {
|
|
291
313
|
if (useDefaults ? true : await promptConfirm({
|
|
292
|
-
message: `Would you like to install ${library} and add the GTProvider? See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`,
|
|
314
|
+
message: framework.name === "vite" ? `Would you like to install ${library} and configure initializeGTSPA? See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart` : `Would you like to install ${library} and add the GTProvider? See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`,
|
|
293
315
|
defaultValue: true
|
|
294
316
|
})) {
|
|
295
317
|
logger.info(`${chalk.yellow("[EXPERIMENTAL]")} Configuring project...`);
|
|
@@ -307,6 +329,7 @@ var BaseCLI = class {
|
|
|
307
329
|
}
|
|
308
330
|
setupConfigureCommand() {
|
|
309
331
|
this.program.command("configure").description("Configure your project for General Translation. This will create a gt.config.json file in your codebase.").action(async () => {
|
|
332
|
+
await exitIfUnsupportedSetupTarget();
|
|
310
333
|
displayHeader("Configuring project...");
|
|
311
334
|
logger.info("Welcome! This tool will help you configure your gt.config.json file. See the docs: https://generaltranslation.com/docs/cli/reference/config for more information.");
|
|
312
335
|
const framework = await detectFramework();
|
|
@@ -319,7 +342,8 @@ var BaseCLI = class {
|
|
|
319
342
|
await upload(settings);
|
|
320
343
|
}
|
|
321
344
|
async handleInitCommand(ranReactSetup, useDefaults = false, isVite = false) {
|
|
322
|
-
const
|
|
345
|
+
const configFilepath = !isVite && fs.existsSync("src/gt.config.json") ? "src/gt.config.json" : "gt.config.json";
|
|
346
|
+
const { defaultLocale, locales } = await getDesiredLocales(loadConfig(configFilepath));
|
|
323
347
|
const packageJson = await searchForPackageJson();
|
|
324
348
|
const gtInstalled = !!packageJson && INLINE_LIBRARIES.some((lib) => isPackageInstalled(lib, packageJson));
|
|
325
349
|
const isUsingGT = ranReactSetup || gtInstalled;
|
|
@@ -343,7 +367,7 @@ var BaseCLI = class {
|
|
|
343
367
|
message: "What is the path to the directory where you would like to store your translation files?",
|
|
344
368
|
defaultValue: defaultTranslationsDir
|
|
345
369
|
}) : null)?.trim() || defaultTranslationsDir;
|
|
346
|
-
if (isUsingGT && !usingCDN) {
|
|
370
|
+
if (isUsingGT && !usingCDN && !isVite) {
|
|
347
371
|
await createLoadTranslationsFile(process.cwd(), finalTranslationsDir, locales);
|
|
348
372
|
logger.message(`Created ${chalk.cyan("loadTranslations.js")} file for local translations.
|
|
349
373
|
Make sure to add this function to your app configuration.
|
|
@@ -390,23 +414,29 @@ See https://generaltranslation.com/en/docs/next/guides/local-tx`);
|
|
|
390
414
|
})) };
|
|
391
415
|
}
|
|
392
416
|
if (isUsingGT && !usingCDN) files.gt = { output: path.join(finalTranslationsDir, `[locale].json`) };
|
|
393
|
-
let configFilepath = "gt.config.json";
|
|
394
|
-
if (fs.existsSync("src/gt.config.json")) configFilepath = "src/gt.config.json";
|
|
395
417
|
await createOrUpdateConfig(configFilepath, {
|
|
396
418
|
defaultLocale,
|
|
397
419
|
locales,
|
|
398
420
|
files: Object.keys(files).length > 0 ? files : void 0,
|
|
421
|
+
framework: isVite ? "vite" : void 0,
|
|
399
422
|
publish: isUsingGT && usingCDN
|
|
400
423
|
});
|
|
401
424
|
logger.success(`Edit ${chalk.cyan(configFilepath)} to customize your translation setup. Docs: https://generaltranslation.com/docs/cli/reference/config`);
|
|
402
|
-
if (
|
|
425
|
+
if (ranReactSetup && isVite) await setupViteSPA({
|
|
426
|
+
appDirectory: process.cwd(),
|
|
427
|
+
configFilepath,
|
|
428
|
+
defaultLocale,
|
|
429
|
+
locales,
|
|
430
|
+
translationsDir: usingCDN ? void 0 : finalTranslationsDir
|
|
431
|
+
});
|
|
432
|
+
if (!(packageJson ? isPackageInstalled("gt", packageJson, true, true) : true) && !(isUsingGT && isVite)) {
|
|
403
433
|
const packageManager = await getPackageManager();
|
|
404
434
|
const spinner = logger.createSpinner();
|
|
405
435
|
spinner.start(`Installing gt as a dev dependency with ${packageManager.name}...`);
|
|
406
436
|
await installPackage("gt", packageManager, true);
|
|
407
437
|
spinner.stop(chalk.green("Installed gt."));
|
|
408
438
|
}
|
|
409
|
-
if (!areCredentialsSet()) {
|
|
439
|
+
if ((!isVite || !isUsingGT || usingCDN) && !areCredentialsSet()) {
|
|
410
440
|
if (useDefaults ? true : await promptConfirm({
|
|
411
441
|
message: "Would you like the wizard to automatically generate API keys and a project ID for you?",
|
|
412
442
|
defaultValue: true
|
|
@@ -429,7 +459,7 @@ See https://generaltranslation.com/en/docs/next/guides/local-tx`);
|
|
|
429
459
|
}
|
|
430
460
|
],
|
|
431
461
|
defaultValue: "all"
|
|
432
|
-
})), settings.framework);
|
|
462
|
+
})), isVite ? "vite" : settings.framework);
|
|
433
463
|
}
|
|
434
464
|
}
|
|
435
465
|
}
|
package/dist/cli/base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","names":[],"sources":["../../src/cli/base.ts"],"sourcesContent":["import { Command } from 'commander';\nimport {\n DEFAULT_TRANSLATIONS_DIR,\n DEFAULT_VITE_TRANSLATIONS_DIR,\n} from '../utils/constants.js';\nimport { createOrUpdateConfig } from '../fs/config/setupConfig.js';\nimport findFilepath from '../fs/findFilepath.js';\nimport {\n displayHeader,\n promptText,\n logErrorAndExit,\n exitSync,\n promptConfirm,\n promptMultiSelect,\n promptSelect,\n promptGlobPatterns,\n} from '../console/logging.js';\nimport { logger } from '../console/logger.js';\nimport { lottieTranslateError } from '../console/index.js';\nimport { parseGlobPatterns } from '../console/promptParsing.js';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport {\n FilesOptions,\n Settings,\n SupportedLibraries,\n SetupOptions,\n TranslateFlags,\n SharedFlags,\n} from '../types/index.js';\nimport { generateSettings } from '../config/generateSettings.js';\nimport chalk from 'chalk';\nimport { FILE_EXT_TO_EXT_LABEL } from '../formats/files/supportedFiles.js';\nimport { handleSetupReactCommand } from '../setup/wizard.js';\nimport {\n isPackageInstalled,\n searchForPackageJson,\n} from '../utils/packageJson.js';\nimport { getDesiredLocales } from '../setup/userInput.js';\nimport { installPackage } from '../utils/installPackage.js';\nimport { getPackageManager } from '../utils/packageManager.js';\nimport { retrieveCredentials, setCredentials } from '../utils/credentials.js';\nimport { areCredentialsSet } from '../utils/credentials.js';\nimport { upload } from './commands/upload.js';\nimport { attachSharedFlags, attachTranslateFlags } from './flags.js';\nimport { handleStage } from './commands/stage.js';\nimport { handleSetupProject } from './commands/setupProject.js';\nimport { handleDownload } from './commands/download.js';\nimport {\n handleTranslate,\n postProcessTranslations,\n} from './commands/translate.js';\nimport {\n getNeedsPostprocessing,\n clearDownloaded,\n} from '../state/recentDownloads.js';\nimport { clearWarnings } from '../state/translateWarnings.js';\nimport { displayTranslateSummary } from '../console/displayTranslateSummary.js';\nimport updateConfig from '../fs/config/updateConfig.js';\nimport { createLoadTranslationsFile } from '../fs/createLoadTranslationsFile.js';\nimport { saveLocalEdits } from '../api/saveLocalEdits.js';\nimport processSharedStaticAssets, {\n mirrorAssetsToLocales,\n} from '../utils/sharedStaticAssets.js';\nimport { setupLocadex } from '../locadex/setupFlow.js';\nimport { detectFramework } from '../setup/detectFramework.js';\nimport {\n getFrameworkDisplayName,\n getReactFrameworkLibrary,\n} from '../setup/frameworkUtils.js';\nimport { INLINE_LIBRARIES } from '../types/libraries.js';\nimport { handleEnqueue } from './commands/enqueue.js';\nimport { splitMintlifyLanguageRefs } from '../utils/splitMintlifyLanguageRefs.js';\nimport { runMergeDriver, type MergeDriverName } from '../git/mergeDrivers.js';\nimport { setupGitMergeDrivers } from '../git/setupMergeDrivers.js';\nimport { warnReactPackageCompatibility } from '../utils/reactPackageCompatibility.js';\n\nconst ID_COMPATIBILITY_WARNING_COMMANDS = new Set([\n 'download',\n 'enqueue',\n 'generate',\n 'setup',\n 'stage',\n 'translate',\n 'validate',\n]);\n\nexport type UploadOptions = {\n config?: string;\n apiKey?: string;\n projectId?: string;\n defaultLocale?: string;\n};\n\nexport type LoginOptions = {\n config?: string;\n keyType?: 'development' | 'production' | 'all';\n};\n\nexport type GitSetupOptions = {\n config?: string;\n dryRun?: boolean;\n omitConfigIds?: boolean;\n driverCommand?: string;\n};\n\nexport class BaseCLI {\n protected library: SupportedLibraries;\n protected additionalModules: SupportedLibraries[];\n protected program: Command;\n // Constructor is shared amongst all CLI class types\n public constructor(\n program: Command,\n library: SupportedLibraries,\n additionalModules?: SupportedLibraries[]\n ) {\n this.program = program;\n this.library = library;\n this.additionalModules = additionalModules || [];\n\n this.program.option(\n '--skip-version-check',\n 'Skip the monorepo GT package version consistency check'\n );\n this.program.option(\n '--suppress-id-compatibility-warning',\n 'Suppress the React package ID compatibility warning'\n );\n this.program.option(\n '-q, --quiet',\n 'Suppress informational output; only warnings and errors are shown'\n );\n // Apply --quiet before any other hook or command action runs so the\n // singleton logger is muted for the rest of the invocation. The flag is a\n // global root option, so commander resolves it in any position and for\n // nested commands (e.g. `gt git setup --quiet`).\n this.program.hook('preAction', () => {\n logger.setQuiet(Boolean(this.program.opts().quiet));\n });\n this.program.hook('preAction', async (thisCommand, actionCommand) => {\n // Nested commands (e.g. `gt git setup`) can share leaf names with\n // translation commands; only direct children of the root qualify\n if (actionCommand.parent !== thisCommand) return;\n if (!ID_COMPATIBILITY_WARNING_COMMANDS.has(actionCommand.name())) return;\n await warnReactPackageCompatibility(\n Boolean(this.program.opts().suppressIdCompatibilityWarning)\n );\n });\n\n this.setupInitCommand();\n this.setupConfigureCommand();\n this.setupUploadCommand();\n this.setupLoginCommand();\n this.setupSendDiffsCommand();\n this.setupGitCommand();\n }\n // Init is never called in a child class\n public init() {\n this.setupSetupProjectCommand();\n this.setupStageCommand();\n this.setupTranslateCommand();\n this.setupDownloadCommand();\n this.setupEnqueueCommand();\n }\n // Execute is called by the main program\n public execute() {\n // If no command is specified, run 'init'\n if (process.argv.length <= 2) {\n process.argv.push('init');\n }\n }\n\n protected setupSetupProjectCommand(): void {\n attachTranslateFlags(\n this.program\n .command('setup')\n .description(\n 'Upload source files and setup the project for translation'\n )\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Uploading source files and setting up project...');\n await this.handleSetupProject(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupStageCommand(): void {\n attachTranslateFlags(\n this.program\n .command('stage')\n .description(\n 'Submits the project to the General Translation API for translation. Translations created using this command will require human approval.'\n )\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader(\n 'Staging project for translation with approval required...'\n );\n await this.handleStage(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n /**\n * Enqueues translations for a given set of files\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected setupEnqueueCommand(): void {\n attachTranslateFlags(\n this.program\n .command('enqueue')\n .description('Enqueues translations for a given set of files')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Enqueuing translations...');\n await this.handleEnqueue(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n /**\n * Downloads translations that were originally staged\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected setupDownloadCommand(): void {\n attachTranslateFlags(\n this.program\n .command('download')\n .description('Download translations that were originally staged')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Downloading translations...');\n await this.handleDownload(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupTranslateCommand(): void {\n attachTranslateFlags(\n this.program\n .command('translate')\n .description('Translate your project using General Translation')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Starting translation...');\n await this.handleTranslate(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupSendDiffsCommand(): void {\n attachSharedFlags(\n this.program\n .command('save-local')\n .description(\n 'Save local edits for all configured files by sending diffs (no translation enqueued)'\n )\n )\n .option('--publish', 'Publish translations to the CDN', false)\n .action(async (initOptions: SharedFlags) => {\n displayHeader('Saving local edits...');\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n await saveLocalEdits(settings);\n logger.endCommand('Saved local edits');\n });\n }\n\n protected setupGitCommand(): void {\n const gitCommand = this.program\n .command('git')\n .description('Configure Git integrations for General Translation');\n\n gitCommand\n .command('setup')\n .description('Set up GT merge drivers for generated translation files')\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .option('--dry-run', 'Print changes without writing files', false)\n .option(\n '--omit-config-ids',\n 'Persist omitConfigIds and remove generated config IDs'\n )\n .option(\n '--driver-command <command>',\n 'Command Git should use to invoke gt, e.g. \"pnpm exec gt\"'\n )\n .action(async (options: GitSetupOptions) => {\n displayHeader('Setting up GT Git merge drivers...');\n const settings = await generateSettings(options, undefined, {\n requireConfig: true,\n });\n const omitConfigIds = await this.resolveGitSetupOmitConfigIds(\n options,\n settings\n );\n const result = await setupGitMergeDrivers(settings, {\n dryRun: options.dryRun,\n omitConfigIds,\n driverCommand: options.driverCommand,\n });\n\n for (const line of result.addedAttributes) {\n logger.step(\n `${options.dryRun ? 'Would add' : 'Added'} ${chalk.cyan(\n line\n )} to ${chalk.cyan(result.gitattributesPath)}`\n );\n }\n if (result.addedAttributes.length === 0) {\n logger.info(`${chalk.cyan('.gitattributes')} is already configured.`);\n }\n\n for (const args of result.gitConfigCommands) {\n logger.step(\n `${options.dryRun ? 'Would run' : 'Configured'} ${chalk.cyan(\n `git config --local ${args.join(' ')}`\n )}`\n );\n }\n\n if (result.updatedConfig) {\n logger.step(\n `${options.dryRun ? 'Would persist' : 'Persisted'} ${chalk.cyan(\n 'omitConfigIds: true'\n )} in ${chalk.cyan(settings.config)}`\n );\n } else if (options.dryRun && !settings.omitConfigIds) {\n logger.info(\n `Run without ${chalk.cyan('--dry-run')} to be prompted to persist ${chalk.cyan(\n 'omitConfigIds: true'\n )}, or pass ${chalk.cyan('--omit-config-ids')}.`\n );\n }\n\n for (const warning of result.warnings) {\n logger.warn(chalk.yellow(warning));\n }\n\n logger.endCommand(\n options.dryRun\n ? 'Dry run complete.'\n : 'GT Git merge drivers configured.'\n );\n });\n\n gitCommand\n .command('merge-driver', { hidden: true })\n .argument('<driver>', 'Merge driver name')\n .argument('<base>', 'Common ancestor file')\n .argument('<ours>', 'Current branch file')\n .argument('<theirs>', 'Incoming branch file')\n .argument('[path]', 'Merged path')\n .action((driver: string, base: string, ours: string, theirs: string) => {\n if (driver !== 'gt-lock' && driver !== 'gtjson') {\n logger.error(`Unknown GT merge driver: ${driver}`);\n exitSync(1);\n }\n const result = runMergeDriver(\n driver as MergeDriverName,\n base,\n ours,\n theirs\n );\n if (!result.ok) {\n logger.error(result.reason);\n exitSync(1);\n }\n });\n }\n\n protected async resolveGitSetupOmitConfigIds(\n options: GitSetupOptions,\n settings: Settings\n ): Promise<boolean> {\n if (options.omitConfigIds) return true;\n // Already opted in: persist again so stale config IDs still get removed\n if (settings.omitConfigIds) return true;\n if (options.dryRun || !process.stdin.isTTY || !process.stdout.isTTY) {\n return false;\n }\n return promptConfirm({\n message:\n 'Also set omitConfigIds: true to reduce gt.config.json merge conflicts?',\n defaultValue: true,\n });\n }\n\n protected async handleSetupProject(\n initOptions: TranslateFlags\n ): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n await handleSetupProject(initOptions, settings, this.library);\n }\n\n protected async handleStage(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n if (!settings.stageTranslations) {\n // Update settings.stageTranslations to true\n settings.stageTranslations = true;\n await updateConfig(settings.config, {\n stageTranslations: true,\n });\n }\n await handleStage(initOptions, settings, this.library, true);\n }\n\n /**\n * Enqueues translations for a given set of files\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected async handleEnqueue(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n await handleEnqueue(initOptions, settings, this.library);\n }\n\n /**\n * Downloads translations that were originally staged\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected async handleDownload(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n await handleDownload(initOptions, settings, this.library);\n }\n\n protected async handleTranslate(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n if (!settings.stageTranslations) {\n // Lottie translations finish asynchronously server-side (layout\n // refinement runs after the translation job completes), so the immediate\n // translate flow would try to download them before they're ready. Only\n // the stage + download flow supports them.\n if (settings.files?.resolvedPaths.lottie?.length) {\n return logErrorAndExit(lottieTranslateError);\n }\n const results = await handleStage(\n initOptions,\n settings,\n this.library,\n false\n );\n if (results) {\n await handleTranslate(\n initOptions,\n settings,\n results.fileVersionData,\n results.jobData,\n results.branchData,\n results.publishMap\n );\n }\n } else {\n await handleDownload(initOptions, settings, this.library);\n }\n // Only postprocess files downloaded in this run\n const include = getNeedsPostprocessing();\n if (include.size > 0) {\n await postProcessTranslations(settings, include);\n }\n // Split Mintlify language entries into $ref files to keep docs.json small\n await splitMintlifyLanguageRefs(settings);\n // Mirror assets after translations are downloaded and locale dirs are populated\n await mirrorAssetsToLocales(settings);\n clearDownloaded();\n displayTranslateSummary();\n clearWarnings();\n }\n\n protected setupUploadCommand(): void {\n attachTranslateFlags(\n this.program\n .command('upload')\n .description(\n 'Upload source files and translations to the General Translation platform'\n )\n ).action(async (initOptions: UploadOptions) => {\n displayHeader('Starting upload...');\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n const options = { ...initOptions, ...settings };\n\n await this.handleUploadCommand(options);\n logger.endCommand('Done!');\n });\n }\n\n protected setupLoginCommand(): void {\n this.program\n .command('auth')\n .description('Generate General Translation API keys and project ID')\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .option(\n '-t, --key-type <type>',\n 'Type of key to generate, production | development | all'\n )\n .action(async (options: LoginOptions) => {\n displayHeader('Authenticating with General Translation...');\n if (!options.keyType) {\n options.keyType = await promptSelect<\n 'development' | 'production' | 'all'\n >({\n message: 'What type of API key would you like to generate?',\n options: [\n { value: 'development', label: 'Development' },\n { value: 'production', label: 'Production' },\n { value: 'all', label: 'Both' },\n ],\n defaultValue: 'all',\n });\n } else {\n if (\n options.keyType !== 'development' &&\n options.keyType !== 'production' &&\n options.keyType !== 'all'\n ) {\n logErrorAndExit(\n 'Invalid key type, must be development, production, or all'\n );\n }\n }\n await this.handleLoginCommand(options);\n logger.endCommand(\n `Done! ${options.keyType} keys have been generated and saved to your .env.local file.`\n );\n });\n }\n\n protected setupInitCommand(): void {\n this.program\n .command('init')\n .description(\n 'Run the setup wizard to configure your project for General Translation'\n )\n .option(\n '--src <paths...>',\n \"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}'\"\n )\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .action(async (options: SetupOptions) => {\n const settings = await generateSettings(options);\n displayHeader('Running setup wizard...');\n\n const framework = await detectFramework();\n\n const useAgent = await (async () => {\n let useAgentMessage;\n if (framework.name === 'mintlify') {\n useAgentMessage = `Mintlify project detected. Would you like to connect to GitHub so that the Locadex AI Agent can translate your project automatically?`;\n }\n if (framework.name === 'next-app') {\n useAgentMessage = `Next.js App Router detected. Would you like to connect to GitHub so that the Locadex AI Agent can set up your project automatically?`;\n }\n if (useAgentMessage) {\n return await promptConfirm({\n message: useAgentMessage,\n defaultValue: false,\n });\n }\n return false;\n })();\n\n if (useAgent) {\n await setupLocadex(settings);\n logger.endCommand(\n 'Once installed, Locadex will open a PR to your repository. See the docs for more information: https://generaltranslation.com/docs/locadex'\n );\n } else {\n // Get framework display info for the defaults message\n const frameworkDisplayName =\n framework.type === 'react'\n ? getFrameworkDisplayName(framework)\n : null;\n const library =\n framework.type === 'react'\n ? getReactFrameworkLibrary(framework)\n : null;\n\n // Build defaults description based on detected framework\n const defaultTranslationsDir =\n framework.name === 'vite'\n ? DEFAULT_VITE_TRANSLATIONS_DIR\n : DEFAULT_TRANSLATIONS_DIR;\n\n const defaultsDescription =\n framework.type === 'react'\n ? `${library} & GTProvider, ${frameworkDisplayName}, Files saved locally in ${defaultTranslationsDir}`\n : `Files saved locally in ${defaultTranslationsDir}`;\n\n // Ask if user wants to use defaults\n const useDefaults = await promptConfirm({\n message: `Would you like to use the recommended General Translation defaults? ${chalk.dim(`(${defaultsDescription})`)}`,\n defaultValue: true,\n });\n\n let ranReactSetup = false;\n\n // so that people can run init in non-js projects\n if (framework.type === 'react') {\n const wrap = useDefaults\n ? true\n : await promptConfirm({\n message: `Would you like to install ${library} and add the GTProvider? See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`,\n defaultValue: true,\n });\n\n if (wrap) {\n logger.info(\n `${chalk.yellow('[EXPERIMENTAL]')} Configuring project...`\n );\n await handleSetupReactCommand(options, framework, useDefaults);\n logger.endCommand(\n `Done! Since this wizard is experimental, please review the changes and make modifications as needed.\n\\nNext step: start internationalizing! See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`\n );\n ranReactSetup = true;\n }\n }\n\n if (ranReactSetup) {\n logger.startCommand('Setting up project config...');\n }\n // Configure gt.config.json\n await this.handleInitCommand(\n ranReactSetup,\n useDefaults,\n framework.name === 'vite'\n );\n\n logger.endCommand(\n 'Done! Check out our docs for more information on how to use General Translation: https://generaltranslation.com/docs'\n );\n }\n });\n }\n\n protected setupConfigureCommand(): void {\n this.program\n .command('configure')\n .description(\n 'Configure your project for General Translation. This will create a gt.config.json file in your codebase.'\n )\n .action(async () => {\n displayHeader('Configuring project...');\n\n logger.info(\n 'Welcome! This tool will help you configure your gt.config.json file. See the docs: https://generaltranslation.com/docs/cli/reference/config for more information.'\n );\n\n // Configure gt.config.json\n const framework = await detectFramework();\n await this.handleInitCommand(false, false, framework.name === 'vite');\n\n logger.endCommand(\n 'Done! Make sure you have an API key and project ID to use General Translation. Get them on the dashboard: https://generaltranslation.com/dashboard'\n );\n });\n }\n\n protected async handleUploadCommand(\n settings: Settings & UploadOptions\n ): Promise<void> {\n if (!settings.files) {\n return;\n }\n\n // Process all file types at once with a single call\n await upload(settings);\n }\n\n // Wizard for configuring gt.config.json\n protected async handleInitCommand(\n ranReactSetup: boolean,\n useDefaults: boolean = false,\n isVite: boolean = false\n ): Promise<void> {\n const { defaultLocale, locales } = await getDesiredLocales(); // Locales should still be asked for even if using defaults\n\n const packageJson = await searchForPackageJson();\n\n // Ask if using another i18n library\n const gtInstalled =\n !!packageJson &&\n INLINE_LIBRARIES.some((lib) => isPackageInstalled(lib, packageJson));\n const isUsingGT = ranReactSetup || gtInstalled;\n\n // Ask where the translations are stored\n const usingCDN = await (async () => {\n if (!isUsingGT) return false;\n if (useDefaults) return false; // Default to local\n const selectedValue = await promptSelect({\n message: `Would you like to save translation files locally or use the General Translation CDN to store them?`,\n options: [\n { value: 'local', label: 'Save locally' },\n { value: 'cdn', label: 'Use CDN' },\n ],\n defaultValue: 'local',\n });\n return selectedValue === 'cdn';\n })();\n\n const defaultTranslationsDir = isVite\n ? DEFAULT_VITE_TRANSLATIONS_DIR\n : DEFAULT_TRANSLATIONS_DIR;\n\n // Ask where the translations are stored\n const translationsDir =\n isUsingGT && !usingCDN\n ? useDefaults\n ? defaultTranslationsDir\n : await promptText({\n message:\n 'What is the path to the directory where you would like to store your translation files?',\n defaultValue: defaultTranslationsDir,\n })\n : null;\n\n // Determine final translations directory with fallback\n const finalTranslationsDir =\n translationsDir?.trim() || defaultTranslationsDir;\n\n if (isUsingGT && !usingCDN) {\n // Create loadTranslations.js file for local translations\n await createLoadTranslationsFile(\n process.cwd(),\n finalTranslationsDir,\n locales\n );\n logger.message(\n `Created ${chalk.cyan('loadTranslations.js')} file for local translations.\nMake sure to add this function to your app configuration.\nSee https://generaltranslation.com/en/docs/next/guides/local-tx`\n );\n }\n\n const message = !isUsingGT\n ? 'What is the format of your language resource files? Select as many as applicable.\\nAdditionally, you can translate any other files you have in your project.'\n : `Do you have any additional files in this project to translate? For example, Markdown files for docs. ${chalk.dim(\n '(To continue without selecting press Enter)'\n )}`;\n const fileExtensions =\n useDefaults && isUsingGT\n ? [] // Skip for GT projects when using defaults\n : await promptMultiSelect({\n message,\n options: [\n { value: 'json', label: FILE_EXT_TO_EXT_LABEL.json },\n { value: 'md', label: FILE_EXT_TO_EXT_LABEL.md },\n { value: 'mdx', label: FILE_EXT_TO_EXT_LABEL.mdx },\n { value: 'ts', label: FILE_EXT_TO_EXT_LABEL.ts },\n { value: 'js', label: FILE_EXT_TO_EXT_LABEL.js },\n { value: 'yaml', label: FILE_EXT_TO_EXT_LABEL.yaml },\n // TWILIO_CONTENT_JSON not supported in CLI init as its too niche\n ],\n required: !isUsingGT,\n });\n\n const files: FilesOptions = {};\n for (const fileExtension of fileExtensions) {\n const label = FILE_EXT_TO_EXT_LABEL[fileExtension];\n const paths = await promptGlobPatterns({\n label,\n message: `${chalk.cyan(FILE_EXT_TO_EXT_LABEL[fileExtension])}: Enter a space-separated list of glob patterns matching the location of the ${FILE_EXT_TO_EXT_LABEL[fileExtension]} files you would like to translate.\\nMake sure to include [locale] in the patterns.\\nSee https://generaltranslation.com/docs/cli/reference/config#include for more information.`,\n defaultValue: `./**/[locale]/*.${fileExtension}`,\n });\n\n files[fileExtension] = {\n include: parseGlobPatterns(paths),\n };\n }\n\n // Add GT translations if using GT and storing locally\n if (isUsingGT && !usingCDN) {\n files.gt = {\n output: path.join(finalTranslationsDir, `[locale].json`),\n };\n }\n\n let configFilepath = 'gt.config.json';\n if (fs.existsSync('src/gt.config.json')) {\n configFilepath = 'src/gt.config.json';\n }\n\n // Create gt.config.json\n await createOrUpdateConfig(configFilepath, {\n defaultLocale,\n locales,\n files: Object.keys(files).length > 0 ? files : undefined,\n publish: isUsingGT && usingCDN,\n });\n\n logger.success(\n `Edit ${chalk.cyan(\n configFilepath\n )} to customize your translation setup. Docs: https://generaltranslation.com/docs/cli/reference/config`\n );\n\n // Install gt if not installed\n const isCLIInstalled = packageJson\n ? isPackageInstalled('gt', packageJson, true, true)\n : true; // if no package.json, we can't install it\n\n if (!isCLIInstalled) {\n const packageManager = await getPackageManager();\n const spinner = logger.createSpinner();\n spinner.start(\n `Installing gt as a dev dependency with ${packageManager.name}...`\n );\n await installPackage('gt', packageManager, true);\n spinner.stop(chalk.green('Installed gt.'));\n }\n\n // Set credentials\n if (!areCredentialsSet()) {\n const loginQuestion = useDefaults\n ? true\n : await promptConfirm({\n message:\n 'Would you like the wizard to automatically generate API keys and a project ID for you?',\n defaultValue: true,\n });\n if (loginQuestion) {\n const settings = await generateSettings({});\n const keyType = useDefaults\n ? 'all'\n : await promptSelect<'development' | 'production' | 'all'>({\n message: 'What type of API key would you like to generate?',\n options: [\n { value: 'development', label: 'Development' },\n { value: 'production', label: 'Production' },\n { value: 'all', label: 'Both' },\n ],\n defaultValue: 'all',\n });\n const credentials = await retrieveCredentials(settings, keyType);\n await setCredentials(credentials, settings.framework);\n }\n }\n }\n protected async handleLoginCommand(options: LoginOptions): Promise<void> {\n const settings = await generateSettings({ config: options.config });\n const keyType = options.keyType || 'all';\n const credentials = await retrieveCredentials(settings, keyType);\n await setCredentials(credentials, settings.framework);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6EA,MAAM,oCAAoC,IAAI,IAAI;CAChD;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAqBF,IAAa,UAAb,MAAqB;CACnB;CACA;CACA;CAEA,YACE,SACA,SACA,mBACA;AACA,OAAK,UAAU;AACf,OAAK,UAAU;AACf,OAAK,oBAAoB,qBAAqB,EAAE;AAEhD,OAAK,QAAQ,OACX,wBACA,yDACD;AACD,OAAK,QAAQ,OACX,uCACA,sDACD;AACD,OAAK,QAAQ,OACX,eACA,oEACD;AAKD,OAAK,QAAQ,KAAK,mBAAmB;AACnC,UAAO,SAAS,QAAQ,KAAK,QAAQ,MAAM,CAAC,MAAM,CAAC;IACnD;AACF,OAAK,QAAQ,KAAK,aAAa,OAAO,aAAa,kBAAkB;AAGnE,OAAI,cAAc,WAAW,YAAa;AAC1C,OAAI,CAAC,kCAAkC,IAAI,cAAc,MAAM,CAAC,CAAE;AAClE,SAAM,8BACJ,QAAQ,KAAK,QAAQ,MAAM,CAAC,+BAA+B,CAC5D;IACD;AAEF,OAAK,kBAAkB;AACvB,OAAK,uBAAuB;AAC5B,OAAK,oBAAoB;AACzB,OAAK,mBAAmB;AACxB,OAAK,uBAAuB;AAC5B,OAAK,iBAAiB;;CAGxB,OAAc;AACZ,OAAK,0BAA0B;AAC/B,OAAK,mBAAmB;AACxB,OAAK,uBAAuB;AAC5B,OAAK,sBAAsB;AAC3B,OAAK,qBAAqB;;CAG5B,UAAiB;AAEf,MAAI,QAAQ,KAAK,UAAU,EACzB,SAAQ,KAAK,KAAK,OAAO;;CAI7B,2BAA2C;AACzC,uBACE,KAAK,QACF,QAAQ,QAAQ,CAChB,YACC,4DACD,CACJ,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,mDAAmD;AACjE,SAAM,KAAK,mBAAmB,YAAY;AAC1C,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,oBAAoC;AAClC,uBACE,KAAK,QACF,QAAQ,QAAQ,CAChB,YACC,2IACD,CACJ,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBACE,4DACD;AACD,SAAM,KAAK,YAAY,YAAY;AACnC,UAAO,WAAW,QAAQ;IAC1B;;;;;;;CAQJ,sBAAsC;AACpC,uBACE,KAAK,QACF,QAAQ,UAAU,CAClB,YAAY,iDAAiD,CACjE,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,4BAA4B;AAC1C,SAAM,KAAK,cAAc,YAAY;AACrC,UAAO,WAAW,QAAQ;IAC1B;;;;;;;CAQJ,uBAAuC;AACrC,uBACE,KAAK,QACF,QAAQ,WAAW,CACnB,YAAY,oDAAoD,CACpE,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,8BAA8B;AAC5C,SAAM,KAAK,eAAe,YAAY;AACtC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,wBAAwC;AACtC,uBACE,KAAK,QACF,QAAQ,YAAY,CACpB,YAAY,mDAAmD,CACnE,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,0BAA0B;AACxC,SAAM,KAAK,gBAAgB,YAAY;AACvC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,wBAAwC;AACtC,oBACE,KAAK,QACF,QAAQ,aAAa,CACrB,YACC,uFACD,CACJ,CACE,OAAO,aAAa,mCAAmC,MAAM,CAC7D,OAAO,OAAO,gBAA6B;AAC1C,iBAAc,wBAAwB;AAItC,SAAM,eAAe,MAHE,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC,CAC4B;AAC9B,UAAO,WAAW,oBAAoB;IACtC;;CAGN,kBAAkC;EAChC,MAAM,aAAa,KAAK,QACrB,QAAQ,MAAM,CACd,YAAY,qDAAqD;AAEpE,aACG,QAAQ,QAAQ,CAChB,YAAY,0DAA0D,CACtE,OACC,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACA,OAAO,aAAa,uCAAuC,MAAM,CACjE,OACC,qBACA,wDACD,CACA,OACC,8BACA,6DACD,CACA,OAAO,OAAO,YAA6B;AAC1C,iBAAc,qCAAqC;GACnD,MAAM,WAAW,MAAM,iBAAiB,SAAS,KAAA,GAAW,EAC1D,eAAe,MAChB,CAAC;GACF,MAAM,gBAAgB,MAAM,KAAK,6BAC/B,SACA,SACD;GACD,MAAM,SAAS,MAAM,qBAAqB,UAAU;IAClD,QAAQ,QAAQ;IAChB;IACA,eAAe,QAAQ;IACxB,CAAC;AAEF,QAAK,MAAM,QAAQ,OAAO,gBACxB,QAAO,KACL,GAAG,QAAQ,SAAS,cAAc,QAAQ,GAAG,MAAM,KACjD,KACD,CAAC,MAAM,MAAM,KAAK,OAAO,kBAAkB,GAC7C;AAEH,OAAI,OAAO,gBAAgB,WAAW,EACpC,QAAO,KAAK,GAAG,MAAM,KAAK,iBAAiB,CAAC,yBAAyB;AAGvE,QAAK,MAAM,QAAQ,OAAO,kBACxB,QAAO,KACL,GAAG,QAAQ,SAAS,cAAc,aAAa,GAAG,MAAM,KACtD,sBAAsB,KAAK,KAAK,IAAI,GACrC,GACF;AAGH,OAAI,OAAO,cACT,QAAO,KACL,GAAG,QAAQ,SAAS,kBAAkB,YAAY,GAAG,MAAM,KACzD,sBACD,CAAC,MAAM,MAAM,KAAK,SAAS,OAAO,GACpC;YACQ,QAAQ,UAAU,CAAC,SAAS,cACrC,QAAO,KACL,eAAe,MAAM,KAAK,YAAY,CAAC,6BAA6B,MAAM,KACxE,sBACD,CAAC,YAAY,MAAM,KAAK,oBAAoB,CAAC,GAC/C;AAGH,QAAK,MAAM,WAAW,OAAO,SAC3B,QAAO,KAAK,MAAM,OAAO,QAAQ,CAAC;AAGpC,UAAO,WACL,QAAQ,SACJ,sBACA,mCACL;IACD;AAEJ,aACG,QAAQ,gBAAgB,EAAE,QAAQ,MAAM,CAAC,CACzC,SAAS,YAAY,oBAAoB,CACzC,SAAS,UAAU,uBAAuB,CAC1C,SAAS,UAAU,sBAAsB,CACzC,SAAS,YAAY,uBAAuB,CAC5C,SAAS,UAAU,cAAc,CACjC,QAAQ,QAAgB,MAAc,MAAc,WAAmB;AACtE,OAAI,WAAW,aAAa,WAAW,UAAU;AAC/C,WAAO,MAAM,4BAA4B,SAAS;AAClD,aAAS,EAAE;;GAEb,MAAM,SAAS,eACb,QACA,MACA,MACA,OACD;AACD,OAAI,CAAC,OAAO,IAAI;AACd,WAAO,MAAM,OAAO,OAAO;AAC3B,aAAS,EAAE;;IAEb;;CAGN,MAAgB,6BACd,SACA,UACkB;AAClB,MAAI,QAAQ,cAAe,QAAO;AAElC,MAAI,SAAS,cAAe,QAAO;AACnC,MAAI,QAAQ,UAAU,CAAC,QAAQ,MAAM,SAAS,CAAC,QAAQ,OAAO,MAC5D,QAAO;AAET,SAAO,cAAc;GACnB,SACE;GACF,cAAc;GACf,CAAC;;CAGJ,MAAgB,mBACd,aACe;EACf,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;AAGF,QAAM,0BAA0B,SAAS;AAEzC,QAAM,mBAAmB,aAAa,UAAU,KAAK,QAAQ;;CAG/D,MAAgB,YAAY,aAA4C;EACtE,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;AAGF,QAAM,0BAA0B,SAAS;AAEzC,MAAI,CAAC,SAAS,mBAAmB;AAE/B,YAAS,oBAAoB;AAC7B,SAAM,aAAa,SAAS,QAAQ,EAClC,mBAAmB,MACpB,CAAC;;AAEJ,QAAM,YAAY,aAAa,UAAU,KAAK,SAAS,KAAK;;;;;;;CAQ9D,MAAgB,cAAc,aAA4C;AAIxE,QAAM,cAAc,aAAa,MAHV,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC,EACyC,KAAK,QAAQ;;;;;;;CAQ1D,MAAgB,eAAe,aAA4C;AAIzE,QAAM,eAAe,aAAa,MAHX,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC,EAC0C,KAAK,QAAQ;;CAG3D,MAAgB,gBAAgB,aAA4C;EAC1E,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;AAGF,QAAM,0BAA0B,SAAS;AAEzC,MAAI,CAAC,SAAS,mBAAmB;AAK/B,OAAI,SAAS,OAAO,cAAc,QAAQ,OACxC,QAAO,gBAAgB,qBAAqB;GAE9C,MAAM,UAAU,MAAM,YACpB,aACA,UACA,KAAK,SACL,MACD;AACD,OAAI,QACF,OAAM,gBACJ,aACA,UACA,QAAQ,iBACR,QAAQ,SACR,QAAQ,YACR,QAAQ,WACT;QAGH,OAAM,eAAe,aAAa,UAAU,KAAK,QAAQ;EAG3D,MAAM,UAAU,wBAAwB;AACxC,MAAI,QAAQ,OAAO,EACjB,OAAM,wBAAwB,UAAU,QAAQ;AAGlD,QAAM,0BAA0B,SAAS;AAEzC,QAAM,sBAAsB,SAAS;AACrC,mBAAiB;AACjB,2BAAyB;AACzB,iBAAe;;CAGjB,qBAAqC;AACnC,uBACE,KAAK,QACF,QAAQ,SAAS,CACjB,YACC,2EACD,CACJ,CAAC,OAAO,OAAO,gBAA+B;AAC7C,iBAAc,qBAAqB;GACnC,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;GAEF,MAAM,UAAU;IAAE,GAAG;IAAa,GAAG;IAAU;AAE/C,SAAM,KAAK,oBAAoB,QAAQ;AACvC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,oBAAoC;AAClC,OAAK,QACF,QAAQ,OAAO,CACf,YAAY,uDAAuD,CACnE,OACC,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACA,OACC,yBACA,0DACD,CACA,OAAO,OAAO,YAA0B;AACvC,iBAAc,6CAA6C;AAC3D,OAAI,CAAC,QAAQ,QACX,SAAQ,UAAU,MAAM,aAEtB;IACA,SAAS;IACT,SAAS;KACP;MAAE,OAAO;MAAe,OAAO;MAAe;KAC9C;MAAE,OAAO;MAAc,OAAO;MAAc;KAC5C;MAAE,OAAO;MAAO,OAAO;MAAQ;KAChC;IACD,cAAc;IACf,CAAC;YAGA,QAAQ,YAAY,iBACpB,QAAQ,YAAY,gBACpB,QAAQ,YAAY,MAEpB,iBACE,4DACD;AAGL,SAAM,KAAK,mBAAmB,QAAQ;AACtC,UAAO,WACL,SAAS,QAAQ,QAAQ,8DAC1B;IACD;;CAGN,mBAAmC;AACjC,OAAK,QACF,QAAQ,OAAO,CACf,YACC,yEACD,CACA,OACC,oBACA,0MACD,CACA,OACC,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACA,OAAO,OAAO,YAA0B;GACvC,MAAM,WAAW,MAAM,iBAAiB,QAAQ;AAChD,iBAAc,0BAA0B;GAExC,MAAM,YAAY,MAAM,iBAAiB;AAmBzC,OAAI,OAjBoB,YAAY;IAClC,IAAI;AACJ,QAAI,UAAU,SAAS,WACrB,mBAAkB;AAEpB,QAAI,UAAU,SAAS,WACrB,mBAAkB;AAEpB,QAAI,gBACF,QAAO,MAAM,cAAc;KACzB,SAAS;KACT,cAAc;KACf,CAAC;AAEJ,WAAO;OACL,EAEU;AACZ,UAAM,aAAa,SAAS;AAC5B,WAAO,WACL,4IACD;UACI;IAEL,MAAM,uBACJ,UAAU,SAAS,UACf,wBAAwB,UAAU,GAClC;IACN,MAAM,UACJ,UAAU,SAAS,UACf,yBAAyB,UAAU,GACnC;IAGN,MAAM,yBACJ,UAAU,SAAS,SACf,gCACA;IAEN,MAAM,sBACJ,UAAU,SAAS,UACf,GAAG,QAAQ,iBAAiB,qBAAqB,2BAA2B,2BAC5E,0BAA0B;IAGhC,MAAM,cAAc,MAAM,cAAc;KACtC,SAAS,uEAAuE,MAAM,IAAI,IAAI,oBAAoB,GAAG;KACrH,cAAc;KACf,CAAC;IAEF,IAAI,gBAAgB;AAGpB,QAAI,UAAU,SAAS;SACR,cACT,OACA,MAAM,cAAc;MAClB,SAAS,6BAA6B,QAAQ;MAC9C,cAAc;MACf,CAAC,EAEI;AACR,aAAO,KACL,GAAG,MAAM,OAAO,iBAAiB,CAAC,yBACnC;AACD,YAAM,wBAAwB,SAAS,WAAW,YAAY;AAC9D,aAAO,WACL;0IAED;AACD,sBAAgB;;;AAIpB,QAAI,cACF,QAAO,aAAa,+BAA+B;AAGrD,UAAM,KAAK,kBACT,eACA,aACA,UAAU,SAAS,OACpB;AAED,WAAO,WACL,uHACD;;IAEH;;CAGN,wBAAwC;AACtC,OAAK,QACF,QAAQ,YAAY,CACpB,YACC,2GACD,CACA,OAAO,YAAY;AAClB,iBAAc,yBAAyB;AAEvC,UAAO,KACL,oKACD;GAGD,MAAM,YAAY,MAAM,iBAAiB;AACzC,SAAM,KAAK,kBAAkB,OAAO,OAAO,UAAU,SAAS,OAAO;AAErE,UAAO,WACL,qJACD;IACD;;CAGN,MAAgB,oBACd,UACe;AACf,MAAI,CAAC,SAAS,MACZ;AAIF,QAAM,OAAO,SAAS;;CAIxB,MAAgB,kBACd,eACA,cAAuB,OACvB,SAAkB,OACH;EACf,MAAM,EAAE,eAAe,YAAY,MAAM,mBAAmB;EAE5D,MAAM,cAAc,MAAM,sBAAsB;EAGhD,MAAM,cACJ,CAAC,CAAC,eACF,iBAAiB,MAAM,QAAQ,mBAAmB,KAAK,YAAY,CAAC;EACtE,MAAM,YAAY,iBAAiB;EAGnC,MAAM,WAAW,OAAO,YAAY;AAClC,OAAI,CAAC,UAAW,QAAO;AACvB,OAAI,YAAa,QAAO;AASxB,UAAO,MARqB,aAAa;IACvC,SAAS;IACT,SAAS,CACP;KAAE,OAAO;KAAS,OAAO;KAAgB,EACzC;KAAE,OAAO;KAAO,OAAO;KAAW,CACnC;IACD,cAAc;IACf,CAAC,KACuB;MACvB;EAEJ,MAAM,yBAAyB,SAC3B,gCACA;EAeJ,MAAM,wBAXJ,aAAa,CAAC,WACV,cACE,yBACA,MAAM,WAAW;GACf,SACE;GACF,cAAc;GACf,CAAC,GACJ,OAIa,MAAM,IAAI;AAE7B,MAAI,aAAa,CAAC,UAAU;AAE1B,SAAM,2BACJ,QAAQ,KAAK,EACb,sBACA,QACD;AACD,UAAO,QACL,WAAW,MAAM,KAAK,sBAAsB,CAAC;;iEAG9C;;EAGH,MAAM,UAAU,CAAC,YACb,iKACA,wGAAwG,MAAM,IAC5G,8CACD;EACL,MAAM,iBACJ,eAAe,YACX,EAAE,GACF,MAAM,kBAAkB;GACtB;GACA,SAAS;IACP;KAAE,OAAO;KAAQ,OAAO,sBAAsB;KAAM;IACpD;KAAE,OAAO;KAAM,OAAO,sBAAsB;KAAI;IAChD;KAAE,OAAO;KAAO,OAAO,sBAAsB;KAAK;IAClD;KAAE,OAAO;KAAM,OAAO,sBAAsB;KAAI;IAChD;KAAE,OAAO;KAAM,OAAO,sBAAsB;KAAI;IAChD;KAAE,OAAO;KAAQ,OAAO,sBAAsB;KAAM;IAErD;GACD,UAAU,CAAC;GACZ,CAAC;EAER,MAAM,QAAsB,EAAE;AAC9B,OAAK,MAAM,iBAAiB,gBAAgB;GAC1C,MAAM,QAAQ,sBAAsB;AAOpC,SAAM,iBAAiB,EACrB,SAAS,kBAAkB,MAPT,mBAAmB;IACrC;IACA,SAAS,GAAG,MAAM,KAAK,sBAAsB,eAAe,CAAC,+EAA+E,sBAAsB,eAAe;IACjL,cAAc,mBAAmB;IAClC,CAAC,CAGiC,EAClC;;AAIH,MAAI,aAAa,CAAC,SAChB,OAAM,KAAK,EACT,QAAQ,KAAK,KAAK,sBAAsB,gBAAgB,EACzD;EAGH,IAAI,iBAAiB;AACrB,MAAI,GAAG,WAAW,qBAAqB,CACrC,kBAAiB;AAInB,QAAM,qBAAqB,gBAAgB;GACzC;GACA;GACA,OAAO,OAAO,KAAK,MAAM,CAAC,SAAS,IAAI,QAAQ,KAAA;GAC/C,SAAS,aAAa;GACvB,CAAC;AAEF,SAAO,QACL,QAAQ,MAAM,KACZ,eACD,CAAC,sGACH;AAOD,MAAI,EAJmB,cACnB,mBAAmB,MAAM,aAAa,MAAM,KAAK,GACjD,OAEiB;GACnB,MAAM,iBAAiB,MAAM,mBAAmB;GAChD,MAAM,UAAU,OAAO,eAAe;AACtC,WAAQ,MACN,0CAA0C,eAAe,KAAK,KAC/D;AACD,SAAM,eAAe,MAAM,gBAAgB,KAAK;AAChD,WAAQ,KAAK,MAAM,MAAM,gBAAgB,CAAC;;AAI5C,MAAI,CAAC,mBAAmB;OACA,cAClB,OACA,MAAM,cAAc;IAClB,SACE;IACF,cAAc;IACf,CAAC,EACa;IACjB,MAAM,WAAW,MAAM,iBAAiB,EAAE,CAAC;AAa3C,UAAM,eAAe,MADK,oBAAoB,UAX9B,cACZ,QACA,MAAM,aAAmD;KACvD,SAAS;KACT,SAAS;MACP;OAAE,OAAO;OAAe,OAAO;OAAe;MAC9C;OAAE,OAAO;OAAc,OAAO;OAAc;MAC5C;OAAE,OAAO;OAAO,OAAO;OAAQ;MAChC;KACD,cAAc;KACf,CAAC,CAC0D,EAC9B,SAAS,UAAU;;;;CAI3D,MAAgB,mBAAmB,SAAsC;EACvE,MAAM,WAAW,MAAM,iBAAiB,EAAE,QAAQ,QAAQ,QAAQ,CAAC;AAGnE,QAAM,eAAe,MADK,oBAAoB,UAD9B,QAAQ,WAAW,MAC6B,EAC9B,SAAS,UAAU"}
|
|
1
|
+
{"version":3,"file":"base.js","names":[],"sources":["../../src/cli/base.ts"],"sourcesContent":["import { Command } from 'commander';\nimport {\n DEFAULT_TRANSLATIONS_DIR,\n DEFAULT_VITE_TRANSLATIONS_DIR,\n} from '../utils/constants.js';\nimport { createOrUpdateConfig } from '../fs/config/setupConfig.js';\nimport findFilepath from '../fs/findFilepath.js';\nimport {\n displayHeader,\n promptText,\n logErrorAndExit,\n exitSync,\n promptConfirm,\n promptMultiSelect,\n promptSelect,\n promptGlobPatterns,\n} from '../console/logging.js';\nimport { logger } from '../console/logger.js';\nimport { lottieTranslateError } from '../console/index.js';\nimport { parseGlobPatterns } from '../console/promptParsing.js';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport {\n FilesOptions,\n Settings,\n SupportedLibraries,\n SetupOptions,\n TranslateFlags,\n SharedFlags,\n} from '../types/index.js';\nimport { generateSettings } from '../config/generateSettings.js';\nimport chalk from 'chalk';\nimport { FILE_EXT_TO_EXT_LABEL } from '../formats/files/supportedFiles.js';\nimport { handleSetupReactCommand } from '../setup/wizard.js';\nimport {\n isPackageInstalled,\n searchForPackageJson,\n} from '../utils/packageJson.js';\nimport { getDesiredLocales } from '../setup/userInput.js';\nimport { installPackage } from '../utils/installPackage.js';\nimport { getPackageManager } from '../utils/packageManager.js';\nimport { retrieveCredentials, setCredentials } from '../utils/credentials.js';\nimport { areCredentialsSet } from '../utils/credentials.js';\nimport { upload } from './commands/upload.js';\nimport { attachSharedFlags, attachTranslateFlags } from './flags.js';\nimport { handleStage } from './commands/stage.js';\nimport { handleSetupProject } from './commands/setupProject.js';\nimport { handleDownload } from './commands/download.js';\nimport {\n handleTranslate,\n postProcessTranslations,\n} from './commands/translate.js';\nimport {\n getNeedsPostprocessing,\n clearDownloaded,\n} from '../state/recentDownloads.js';\nimport { clearWarnings } from '../state/translateWarnings.js';\nimport { displayTranslateSummary } from '../console/displayTranslateSummary.js';\nimport updateConfig from '../fs/config/updateConfig.js';\nimport { loadConfig } from '../fs/config/loadConfig.js';\nimport { createLoadTranslationsFile } from '../fs/createLoadTranslationsFile.js';\nimport { saveLocalEdits } from '../api/saveLocalEdits.js';\nimport processSharedStaticAssets, {\n mirrorAssetsToLocales,\n} from '../utils/sharedStaticAssets.js';\nimport { setupLocadex } from '../locadex/setupFlow.js';\nimport { detectFramework } from '../setup/detectFramework.js';\nimport {\n getFrameworkDisplayName,\n getReactFrameworkLibrary,\n} from '../setup/frameworkUtils.js';\nimport { INLINE_LIBRARIES } from '../types/libraries.js';\nimport { handleEnqueue } from './commands/enqueue.js';\nimport { splitMintlifyLanguageRefs } from '../utils/splitMintlifyLanguageRefs.js';\nimport { runMergeDriver, type MergeDriverName } from '../git/mergeDrivers.js';\nimport { setupGitMergeDrivers } from '../git/setupMergeDrivers.js';\nimport { warnReactPackageCompatibility } from '../utils/reactPackageCompatibility.js';\nimport { createDiagnosticMessage } from 'generaltranslation/internal';\nimport { setupViteSPA } from '../setup/setupViteSPA.js';\n\nconst ID_COMPATIBILITY_WARNING_COMMANDS = new Set([\n 'download',\n 'enqueue',\n 'generate',\n 'setup',\n 'stage',\n 'translate',\n 'validate',\n]);\nconst workspaceRootSetupError = createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The setup wizard cannot run from a monorepo workspace root',\n why: 'GT must be configured in the specific app you want to localize',\n fix: \"Change to that app's directory and rerun `npx gt@latest`\",\n});\nconst electronSetupError = createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened:\n 'The automatic setup wizard is not ready for Electron applications',\n docsUrl: 'https://generaltranslation.com/docs/react',\n});\n\nasync function exitIfUnsupportedSetupTarget(): Promise<void> {\n const packageJson = await searchForPackageJson();\n if (packageJson && isPackageInstalled('electron', packageJson, false, true)) {\n logErrorAndExit(electronSetupError);\n }\n if (\n fs.existsSync(path.join(process.cwd(), 'pnpm-workspace.yaml')) ||\n packageJson?.workspaces\n ) {\n logErrorAndExit(workspaceRootSetupError);\n }\n}\n\nexport type UploadOptions = {\n config?: string;\n apiKey?: string;\n projectId?: string;\n defaultLocale?: string;\n};\n\nexport type LoginOptions = {\n config?: string;\n keyType?: 'development' | 'production' | 'all';\n};\n\nexport type GitSetupOptions = {\n config?: string;\n dryRun?: boolean;\n omitConfigIds?: boolean;\n driverCommand?: string;\n};\n\nexport class BaseCLI {\n protected library: SupportedLibraries;\n protected additionalModules: SupportedLibraries[];\n protected program: Command;\n // Constructor is shared amongst all CLI class types\n public constructor(\n program: Command,\n library: SupportedLibraries,\n additionalModules?: SupportedLibraries[]\n ) {\n this.program = program;\n this.library = library;\n this.additionalModules = additionalModules || [];\n\n this.program.option(\n '--skip-version-check',\n 'Skip the monorepo GT package version consistency check'\n );\n this.program.option(\n '--suppress-id-compatibility-warning',\n 'Suppress the React package ID compatibility warning'\n );\n this.program.option(\n '-q, --quiet',\n 'Suppress informational output; only warnings and errors are shown'\n );\n // Apply --quiet before any other hook or command action runs so the\n // singleton logger is muted for the rest of the invocation. The flag is a\n // global root option, so commander resolves it in any position and for\n // nested commands (e.g. `gt git setup --quiet`).\n this.program.hook('preAction', () => {\n logger.setQuiet(Boolean(this.program.opts().quiet));\n });\n this.program.hook('preAction', async (thisCommand, actionCommand) => {\n // Nested commands (e.g. `gt git setup`) can share leaf names with\n // translation commands; only direct children of the root qualify\n if (actionCommand.parent !== thisCommand) return;\n if (!ID_COMPATIBILITY_WARNING_COMMANDS.has(actionCommand.name())) return;\n await warnReactPackageCompatibility(\n Boolean(this.program.opts().suppressIdCompatibilityWarning)\n );\n });\n\n this.setupInitCommand();\n this.setupConfigureCommand();\n this.setupUploadCommand();\n this.setupLoginCommand();\n this.setupSendDiffsCommand();\n this.setupGitCommand();\n }\n // Init is never called in a child class\n public init() {\n this.setupSetupProjectCommand();\n this.setupStageCommand();\n this.setupTranslateCommand();\n this.setupDownloadCommand();\n this.setupEnqueueCommand();\n }\n // Execute is called by the main program\n public execute() {\n // If no command is specified, run 'init'\n if (process.argv.length <= 2) {\n process.argv.push('init');\n }\n }\n\n protected setupSetupProjectCommand(): void {\n attachTranslateFlags(\n this.program\n .command('setup')\n .description(\n 'Upload source files and setup the project for translation'\n )\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Uploading source files and setting up project...');\n await this.handleSetupProject(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupStageCommand(): void {\n attachTranslateFlags(\n this.program\n .command('stage')\n .description(\n 'Submits the project to the General Translation API for translation. Translations created using this command will require human approval.'\n )\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader(\n 'Staging project for translation with approval required...'\n );\n await this.handleStage(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n /**\n * Enqueues translations for a given set of files\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected setupEnqueueCommand(): void {\n attachTranslateFlags(\n this.program\n .command('enqueue')\n .description('Enqueues translations for a given set of files')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Enqueuing translations...');\n await this.handleEnqueue(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n /**\n * Downloads translations that were originally staged\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected setupDownloadCommand(): void {\n attachTranslateFlags(\n this.program\n .command('download')\n .description('Download translations that were originally staged')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Downloading translations...');\n await this.handleDownload(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupTranslateCommand(): void {\n attachTranslateFlags(\n this.program\n .command('translate')\n .description('Translate your project using General Translation')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Starting translation...');\n await this.handleTranslate(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupSendDiffsCommand(): void {\n attachSharedFlags(\n this.program\n .command('save-local')\n .description(\n 'Save local edits for all configured files by sending diffs (no translation enqueued)'\n )\n )\n .option('--publish', 'Publish translations to the CDN', false)\n .action(async (initOptions: SharedFlags) => {\n displayHeader('Saving local edits...');\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n await saveLocalEdits(settings);\n logger.endCommand('Saved local edits');\n });\n }\n\n protected setupGitCommand(): void {\n const gitCommand = this.program\n .command('git')\n .description('Configure Git integrations for General Translation');\n\n gitCommand\n .command('setup')\n .description('Set up GT merge drivers for generated translation files')\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .option('--dry-run', 'Print changes without writing files', false)\n .option(\n '--omit-config-ids',\n 'Persist omitConfigIds and remove generated config IDs'\n )\n .option(\n '--driver-command <command>',\n 'Command Git should use to invoke gt, e.g. \"pnpm exec gt\"'\n )\n .action(async (options: GitSetupOptions) => {\n displayHeader('Setting up GT Git merge drivers...');\n const settings = await generateSettings(options, undefined, {\n requireConfig: true,\n });\n const omitConfigIds = await this.resolveGitSetupOmitConfigIds(\n options,\n settings\n );\n const result = await setupGitMergeDrivers(settings, {\n dryRun: options.dryRun,\n omitConfigIds,\n driverCommand: options.driverCommand,\n });\n\n for (const line of result.addedAttributes) {\n logger.step(\n `${options.dryRun ? 'Would add' : 'Added'} ${chalk.cyan(\n line\n )} to ${chalk.cyan(result.gitattributesPath)}`\n );\n }\n if (result.addedAttributes.length === 0) {\n logger.info(`${chalk.cyan('.gitattributes')} is already configured.`);\n }\n\n for (const args of result.gitConfigCommands) {\n logger.step(\n `${options.dryRun ? 'Would run' : 'Configured'} ${chalk.cyan(\n `git config --local ${args.join(' ')}`\n )}`\n );\n }\n\n if (result.updatedConfig) {\n logger.step(\n `${options.dryRun ? 'Would persist' : 'Persisted'} ${chalk.cyan(\n 'omitConfigIds: true'\n )} in ${chalk.cyan(settings.config)}`\n );\n } else if (options.dryRun && !settings.omitConfigIds) {\n logger.info(\n `Run without ${chalk.cyan('--dry-run')} to be prompted to persist ${chalk.cyan(\n 'omitConfigIds: true'\n )}, or pass ${chalk.cyan('--omit-config-ids')}.`\n );\n }\n\n for (const warning of result.warnings) {\n logger.warn(chalk.yellow(warning));\n }\n\n logger.endCommand(\n options.dryRun\n ? 'Dry run complete.'\n : 'GT Git merge drivers configured.'\n );\n });\n\n gitCommand\n .command('merge-driver', { hidden: true })\n .argument('<driver>', 'Merge driver name')\n .argument('<base>', 'Common ancestor file')\n .argument('<ours>', 'Current branch file')\n .argument('<theirs>', 'Incoming branch file')\n .argument('[path]', 'Merged path')\n .action((driver: string, base: string, ours: string, theirs: string) => {\n if (driver !== 'gt-lock' && driver !== 'gtjson') {\n logger.error(`Unknown GT merge driver: ${driver}`);\n exitSync(1);\n }\n const result = runMergeDriver(\n driver as MergeDriverName,\n base,\n ours,\n theirs\n );\n if (!result.ok) {\n logger.error(result.reason);\n exitSync(1);\n }\n });\n }\n\n protected async resolveGitSetupOmitConfigIds(\n options: GitSetupOptions,\n settings: Settings\n ): Promise<boolean> {\n if (options.omitConfigIds) return true;\n // Already opted in: persist again so stale config IDs still get removed\n if (settings.omitConfigIds) return true;\n if (options.dryRun || !process.stdin.isTTY || !process.stdout.isTTY) {\n return false;\n }\n return promptConfirm({\n message:\n 'Also set omitConfigIds: true to reduce gt.config.json merge conflicts?',\n defaultValue: true,\n });\n }\n\n protected async handleSetupProject(\n initOptions: TranslateFlags\n ): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n await handleSetupProject(initOptions, settings, this.library);\n }\n\n protected async handleStage(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n if (!settings.stageTranslations) {\n // Update settings.stageTranslations to true\n settings.stageTranslations = true;\n await updateConfig(settings.config, {\n stageTranslations: true,\n });\n }\n await handleStage(initOptions, settings, this.library, true);\n }\n\n /**\n * Enqueues translations for a given set of files\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected async handleEnqueue(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n await handleEnqueue(initOptions, settings, this.library);\n }\n\n /**\n * Downloads translations that were originally staged\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected async handleDownload(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n await handleDownload(initOptions, settings, this.library);\n }\n\n protected async handleTranslate(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n if (!settings.stageTranslations) {\n // Lottie translations finish asynchronously server-side (layout\n // refinement runs after the translation job completes), so the immediate\n // translate flow would try to download them before they're ready. Only\n // the stage + download flow supports them.\n if (settings.files?.resolvedPaths.lottie?.length) {\n return logErrorAndExit(lottieTranslateError);\n }\n const results = await handleStage(\n initOptions,\n settings,\n this.library,\n false\n );\n if (results) {\n await handleTranslate(\n initOptions,\n settings,\n results.fileVersionData,\n results.jobData,\n results.branchData,\n results.publishMap\n );\n }\n } else {\n await handleDownload(initOptions, settings, this.library);\n }\n // Only postprocess files downloaded in this run\n const include = getNeedsPostprocessing();\n if (include.size > 0) {\n await postProcessTranslations(settings, include);\n }\n // Split Mintlify language entries into $ref files to keep docs.json small\n await splitMintlifyLanguageRefs(settings);\n // Mirror assets after translations are downloaded and locale dirs are populated\n await mirrorAssetsToLocales(settings);\n clearDownloaded();\n displayTranslateSummary();\n clearWarnings();\n }\n\n protected setupUploadCommand(): void {\n attachTranslateFlags(\n this.program\n .command('upload')\n .description(\n 'Upload source files and translations to the General Translation platform'\n )\n ).action(async (initOptions: UploadOptions) => {\n displayHeader('Starting upload...');\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n const options = { ...initOptions, ...settings };\n\n await this.handleUploadCommand(options);\n logger.endCommand('Done!');\n });\n }\n\n protected setupLoginCommand(): void {\n this.program\n .command('auth')\n .description('Generate General Translation API keys and project ID')\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .option(\n '-t, --key-type <type>',\n 'Type of key to generate, production | development | all'\n )\n .action(async (options: LoginOptions) => {\n displayHeader('Authenticating with General Translation...');\n if (!options.keyType) {\n options.keyType = await promptSelect<\n 'development' | 'production' | 'all'\n >({\n message: 'What type of API key would you like to generate?',\n options: [\n { value: 'development', label: 'Development' },\n { value: 'production', label: 'Production' },\n { value: 'all', label: 'Both' },\n ],\n defaultValue: 'all',\n });\n } else {\n if (\n options.keyType !== 'development' &&\n options.keyType !== 'production' &&\n options.keyType !== 'all'\n ) {\n logErrorAndExit(\n 'Invalid key type, must be development, production, or all'\n );\n }\n }\n await this.handleLoginCommand(options);\n logger.endCommand(\n `Done! ${options.keyType} keys have been generated and saved to your .env.local file.`\n );\n });\n }\n\n protected setupInitCommand(): void {\n this.program\n .command('init')\n .description(\n 'Run the setup wizard to configure your project for General Translation'\n )\n .option(\n '--src <paths...>',\n \"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}'\"\n )\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .action(async (options: SetupOptions) => {\n await exitIfUnsupportedSetupTarget();\n const settings = await generateSettings(options);\n displayHeader('Running setup wizard...');\n\n const framework = await detectFramework();\n\n const useAgent = await (async () => {\n let useAgentMessage;\n if (framework.name === 'mintlify') {\n useAgentMessage = `Mintlify project detected. Would you like to connect to GitHub so that the Locadex AI Agent can translate your project automatically?`;\n }\n if (framework.name === 'next-app') {\n useAgentMessage = `Next.js App Router detected. Would you like to connect to GitHub so that the Locadex AI Agent can set up your project automatically?`;\n }\n if (useAgentMessage) {\n return await promptConfirm({\n message: useAgentMessage,\n defaultValue: false,\n });\n }\n return false;\n })();\n\n if (useAgent) {\n await setupLocadex(settings);\n logger.endCommand(\n 'Once installed, Locadex will open a PR to your repository. See the docs for more information: https://generaltranslation.com/docs/locadex'\n );\n } else {\n // Get framework display info for the defaults message\n const frameworkDisplayName =\n framework.type === 'react'\n ? getFrameworkDisplayName(framework)\n : null;\n const library =\n framework.type === 'react'\n ? getReactFrameworkLibrary(framework)\n : null;\n\n // Build defaults description based on detected framework\n const defaultTranslationsDir =\n framework.name === 'vite'\n ? DEFAULT_VITE_TRANSLATIONS_DIR\n : DEFAULT_TRANSLATIONS_DIR;\n\n const defaultsDescription =\n framework.name === 'vite'\n ? `${library} & initializeGTSPA, ${frameworkDisplayName}, Files saved locally in ${defaultTranslationsDir}`\n : framework.type === 'react'\n ? `${library} & GTProvider, ${frameworkDisplayName}, Files saved locally in ${defaultTranslationsDir}`\n : `Files saved locally in ${defaultTranslationsDir}`;\n\n // Ask if user wants to use defaults\n const useDefaults = await promptConfirm({\n message: `Would you like to use the recommended General Translation defaults? ${chalk.dim(`(${defaultsDescription})`)}`,\n defaultValue: true,\n });\n\n let ranReactSetup = false;\n\n // so that people can run init in non-js projects\n if (framework.type === 'react') {\n const wrap = useDefaults\n ? true\n : await promptConfirm({\n message:\n framework.name === 'vite'\n ? `Would you like to install ${library} and configure initializeGTSPA? See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`\n : `Would you like to install ${library} and add the GTProvider? See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`,\n defaultValue: true,\n });\n\n if (wrap) {\n logger.info(\n `${chalk.yellow('[EXPERIMENTAL]')} Configuring project...`\n );\n await handleSetupReactCommand(options, framework, useDefaults);\n logger.endCommand(\n `Done! Since this wizard is experimental, please review the changes and make modifications as needed.\n\\nNext step: start internationalizing! See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`\n );\n ranReactSetup = true;\n }\n }\n\n if (ranReactSetup) {\n logger.startCommand('Setting up project config...');\n }\n // Configure gt.config.json\n await this.handleInitCommand(\n ranReactSetup,\n useDefaults,\n framework.name === 'vite'\n );\n\n logger.endCommand(\n 'Done! Check out our docs for more information on how to use General Translation: https://generaltranslation.com/docs'\n );\n }\n });\n }\n\n protected setupConfigureCommand(): void {\n this.program\n .command('configure')\n .description(\n 'Configure your project for General Translation. This will create a gt.config.json file in your codebase.'\n )\n .action(async () => {\n await exitIfUnsupportedSetupTarget();\n displayHeader('Configuring project...');\n\n logger.info(\n 'Welcome! This tool will help you configure your gt.config.json file. See the docs: https://generaltranslation.com/docs/cli/reference/config for more information.'\n );\n\n // Configure gt.config.json\n const framework = await detectFramework();\n await this.handleInitCommand(false, false, framework.name === 'vite');\n\n logger.endCommand(\n 'Done! Make sure you have an API key and project ID to use General Translation. Get them on the dashboard: https://generaltranslation.com/dashboard'\n );\n });\n }\n\n protected async handleUploadCommand(\n settings: Settings & UploadOptions\n ): Promise<void> {\n if (!settings.files) {\n return;\n }\n\n // Process all file types at once with a single call\n await upload(settings);\n }\n\n // Wizard for configuring gt.config.json\n protected async handleInitCommand(\n ranReactSetup: boolean,\n useDefaults: boolean = false,\n isVite: boolean = false\n ): Promise<void> {\n const configFilepath =\n !isVite && fs.existsSync('src/gt.config.json')\n ? 'src/gt.config.json'\n : 'gt.config.json';\n const existingConfig = loadConfig(configFilepath);\n const { defaultLocale, locales } = await getDesiredLocales(existingConfig);\n\n const packageJson = await searchForPackageJson();\n\n // Ask if using another i18n library\n const gtInstalled =\n !!packageJson &&\n INLINE_LIBRARIES.some((lib) => isPackageInstalled(lib, packageJson));\n const isUsingGT = ranReactSetup || gtInstalled;\n\n // Ask where the translations are stored\n const usingCDN = await (async () => {\n if (!isUsingGT) return false;\n if (useDefaults) return false; // Default to local\n const selectedValue = await promptSelect({\n message: `Would you like to save translation files locally or use the General Translation CDN to store them?`,\n options: [\n { value: 'local', label: 'Save locally' },\n { value: 'cdn', label: 'Use CDN' },\n ],\n defaultValue: 'local',\n });\n return selectedValue === 'cdn';\n })();\n\n const defaultTranslationsDir = isVite\n ? DEFAULT_VITE_TRANSLATIONS_DIR\n : DEFAULT_TRANSLATIONS_DIR;\n\n // Ask where the translations are stored\n const translationsDir =\n isUsingGT && !usingCDN\n ? useDefaults\n ? defaultTranslationsDir\n : await promptText({\n message:\n 'What is the path to the directory where you would like to store your translation files?',\n defaultValue: defaultTranslationsDir,\n })\n : null;\n\n // Determine final translations directory with fallback\n const finalTranslationsDir =\n translationsDir?.trim() || defaultTranslationsDir;\n\n if (isUsingGT && !usingCDN && !isVite) {\n // Create loadTranslations.js file for local translations\n await createLoadTranslationsFile(\n process.cwd(),\n finalTranslationsDir,\n locales\n );\n logger.message(\n `Created ${chalk.cyan('loadTranslations.js')} file for local translations.\nMake sure to add this function to your app configuration.\nSee https://generaltranslation.com/en/docs/next/guides/local-tx`\n );\n }\n\n const message = !isUsingGT\n ? 'What is the format of your language resource files? Select as many as applicable.\\nAdditionally, you can translate any other files you have in your project.'\n : `Do you have any additional files in this project to translate? For example, Markdown files for docs. ${chalk.dim(\n '(To continue without selecting press Enter)'\n )}`;\n const fileExtensions =\n useDefaults && isUsingGT\n ? [] // Skip for GT projects when using defaults\n : await promptMultiSelect({\n message,\n options: [\n { value: 'json', label: FILE_EXT_TO_EXT_LABEL.json },\n { value: 'md', label: FILE_EXT_TO_EXT_LABEL.md },\n { value: 'mdx', label: FILE_EXT_TO_EXT_LABEL.mdx },\n { value: 'ts', label: FILE_EXT_TO_EXT_LABEL.ts },\n { value: 'js', label: FILE_EXT_TO_EXT_LABEL.js },\n { value: 'yaml', label: FILE_EXT_TO_EXT_LABEL.yaml },\n // TWILIO_CONTENT_JSON not supported in CLI init as its too niche\n ],\n required: !isUsingGT,\n });\n\n const files: FilesOptions = {};\n for (const fileExtension of fileExtensions) {\n const label = FILE_EXT_TO_EXT_LABEL[fileExtension];\n const paths = await promptGlobPatterns({\n label,\n message: `${chalk.cyan(FILE_EXT_TO_EXT_LABEL[fileExtension])}: Enter a space-separated list of glob patterns matching the location of the ${FILE_EXT_TO_EXT_LABEL[fileExtension]} files you would like to translate.\\nMake sure to include [locale] in the patterns.\\nSee https://generaltranslation.com/docs/cli/reference/config#include for more information.`,\n defaultValue: `./**/[locale]/*.${fileExtension}`,\n });\n\n files[fileExtension] = {\n include: parseGlobPatterns(paths),\n };\n }\n\n // Add GT translations if using GT and storing locally\n if (isUsingGT && !usingCDN) {\n files.gt = {\n output: path.join(finalTranslationsDir, `[locale].json`),\n };\n }\n\n // Create gt.config.json\n await createOrUpdateConfig(configFilepath, {\n defaultLocale,\n locales,\n files: Object.keys(files).length > 0 ? files : undefined,\n framework: isVite ? 'vite' : undefined,\n publish: isUsingGT && usingCDN,\n });\n\n logger.success(\n `Edit ${chalk.cyan(\n configFilepath\n )} to customize your translation setup. Docs: https://generaltranslation.com/docs/cli/reference/config`\n );\n\n if (ranReactSetup && isVite) {\n await setupViteSPA({\n appDirectory: process.cwd(),\n configFilepath,\n defaultLocale,\n locales,\n translationsDir: usingCDN ? undefined : finalTranslationsDir,\n });\n }\n\n // Install gt if not installed\n const isCLIInstalled = packageJson\n ? isPackageInstalled('gt', packageJson, true, true)\n : true; // if no package.json, we can't install it\n\n if (!isCLIInstalled && !(isUsingGT && isVite)) {\n const packageManager = await getPackageManager();\n const spinner = logger.createSpinner();\n spinner.start(\n `Installing gt as a dev dependency with ${packageManager.name}...`\n );\n await installPackage('gt', packageManager, true);\n spinner.stop(chalk.green('Installed gt.'));\n }\n\n // Set credentials\n if ((!isVite || !isUsingGT || usingCDN) && !areCredentialsSet()) {\n const loginQuestion = useDefaults\n ? true\n : await promptConfirm({\n message:\n 'Would you like the wizard to automatically generate API keys and a project ID for you?',\n defaultValue: true,\n });\n if (loginQuestion) {\n const settings = await generateSettings({});\n const keyType = useDefaults\n ? 'all'\n : await promptSelect<'development' | 'production' | 'all'>({\n message: 'What type of API key would you like to generate?',\n options: [\n { value: 'development', label: 'Development' },\n { value: 'production', label: 'Production' },\n { value: 'all', label: 'Both' },\n ],\n defaultValue: 'all',\n });\n const credentials = await retrieveCredentials(settings, keyType);\n await setCredentials(credentials, isVite ? 'vite' : settings.framework);\n }\n }\n }\n protected async handleLoginCommand(options: LoginOptions): Promise<void> {\n const settings = await generateSettings({ config: options.config });\n const keyType = options.keyType || 'all';\n const credentials = await retrieveCredentials(settings, keyType);\n await setCredentials(credentials, settings.framework);\n }\n}\n"],"mappings":"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"}
|
package/dist/cli/flags.js
CHANGED
|
@@ -12,7 +12,7 @@ function attachTranslateFlags(command) {
|
|
|
12
12
|
if (isNaN(parsedValue)) throw new Error("Invalid timeout: not a number.");
|
|
13
13
|
if (parsedValue < 0) throw new Error("Invalid timeout: must be a positive number.");
|
|
14
14
|
return parsedValue;
|
|
15
|
-
}, DEFAULT_TIMEOUT).option("--save-local", "Detect and save local edits before enqueuing translations",
|
|
15
|
+
}, DEFAULT_TIMEOUT).option("--save-local", "Detect and save local edits before enqueuing translations", true).option("--no-save-local", "Skip detecting and saving local edits before enqueuing translations").option("--publish", "Publish translations to the CDN", false).option("--experimental-localize-static-urls", "Triggering this will run a script after the cli tool that localizes all urls in content files. Currently only supported for md and mdx files.", false).option("--experimental-hide-default-locale", "When localizing static locales, hide the default locale from the path", false).option("--experimental-flatten-json-files", "Triggering this will flatten the json files into a single file. This is useful for projects that have a lot of json files.", false).option("--experimental-localize-static-imports", "Triggering this will run a script after the cli tool that localizes all static imports in content files. Currently only supported for md and mdx files.", false).option("--experimental-localize-relative-assets", "Triggering this will rewrite relative image asset URLs in translated md/mdx files to valid paths.", false).option("--force", "Force a retranslation, invalidating all existing cached translations if they exist.", false).option("--force-download", "Force download and overwrite local files, bypassing gt-lock.json checks.", false).option("--omit-config-ids", "Do not write _versionId or _branchId to gt.config.json").option("--experimental-clear-locale-dirs", "Clear locale directories before downloading new translations", false).option("--branch <branch>", "Specify a custom branch to use for translations").option("--disable-branch-detection", "Disable additional branch detection and optimizations and use the manually specified branch", false).option("--enable-branching", "Enable branching for the project").option("--remote-name <name>", "Specify a custom remote name to use for branch detection", DEFAULT_GIT_REMOTE_NAME).option("--tag [value]", "Tag this translation run (auto-resolves from git if no value provided)").option("-m, --message <message>", "Message to attach to the translation tag");
|
|
16
16
|
return command;
|
|
17
17
|
}
|
|
18
18
|
/**
|
package/dist/cli/flags.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flags.js","names":[],"sources":["../../src/cli/flags.ts"],"sourcesContent":["import { Command } from 'commander';\nimport findFilepath from '../fs/findFilepath.js';\nimport { DEFAULT_GIT_REMOTE_NAME } from '../utils/constants.js';\n\nconst DEFAULT_TIMEOUT = 900;\n\nexport function attachSharedFlags(command: Command) {\n command\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .option('--api-key <key>', 'API key for General Translation cloud service')\n .option('--project-id <id>', 'General Translation project ID');\n return command;\n}\n\nexport function attachTranslateFlags(command: Command) {\n attachSharedFlags(command)\n .option('--version-id <id>', 'General Translation version ID')\n .option(\n '--default-language, --default-locale <locale>',\n 'Default locale (e.g., en)'\n )\n .option(\n '--new, --locales <locales...>',\n 'Space-separated list of locales (e.g., en fr es)'\n )\n .option(\n '--dry-run',\n 'Dry run, do not send updates to the General Translation API',\n false\n )\n .option(\n '--timeout <seconds>',\n 'Translation wait timeout in seconds',\n (value) => {\n const parsedValue = parseInt(value, 10);\n if (isNaN(parsedValue)) {\n throw new Error('Invalid timeout: not a number.');\n }\n if (parsedValue < 0) {\n throw new Error('Invalid timeout: must be a positive number.');\n }\n return parsedValue;\n },\n DEFAULT_TIMEOUT\n )\n .option(\n '--save-local',\n 'Detect and save local edits before enqueuing translations',\n
|
|
1
|
+
{"version":3,"file":"flags.js","names":[],"sources":["../../src/cli/flags.ts"],"sourcesContent":["import { Command } from 'commander';\nimport findFilepath from '../fs/findFilepath.js';\nimport { DEFAULT_GIT_REMOTE_NAME } from '../utils/constants.js';\n\nconst DEFAULT_TIMEOUT = 900;\n\nexport function attachSharedFlags(command: Command) {\n command\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .option('--api-key <key>', 'API key for General Translation cloud service')\n .option('--project-id <id>', 'General Translation project ID');\n return command;\n}\n\nexport function attachTranslateFlags(command: Command) {\n attachSharedFlags(command)\n .option('--version-id <id>', 'General Translation version ID')\n .option(\n '--default-language, --default-locale <locale>',\n 'Default locale (e.g., en)'\n )\n .option(\n '--new, --locales <locales...>',\n 'Space-separated list of locales (e.g., en fr es)'\n )\n .option(\n '--dry-run',\n 'Dry run, do not send updates to the General Translation API',\n false\n )\n .option(\n '--timeout <seconds>',\n 'Translation wait timeout in seconds',\n (value) => {\n const parsedValue = parseInt(value, 10);\n if (isNaN(parsedValue)) {\n throw new Error('Invalid timeout: not a number.');\n }\n if (parsedValue < 0) {\n throw new Error('Invalid timeout: must be a positive number.');\n }\n return parsedValue;\n },\n DEFAULT_TIMEOUT\n )\n .option(\n '--save-local',\n 'Detect and save local edits before enqueuing translations',\n true\n )\n .option(\n '--no-save-local',\n 'Skip detecting and saving local edits before enqueuing translations'\n )\n .option('--publish', 'Publish translations to the CDN', false)\n .option(\n '--experimental-localize-static-urls',\n 'Triggering this will run a script after the cli tool that localizes all urls in content files. Currently only supported for md and mdx files.',\n false\n )\n .option(\n '--experimental-hide-default-locale',\n 'When localizing static locales, hide the default locale from the path',\n false\n )\n .option(\n '--experimental-flatten-json-files',\n 'Triggering this will flatten the json files into a single file. This is useful for projects that have a lot of json files.',\n false\n )\n .option(\n '--experimental-localize-static-imports',\n 'Triggering this will run a script after the cli tool that localizes all static imports in content files. Currently only supported for md and mdx files.',\n false\n )\n .option(\n '--experimental-localize-relative-assets',\n 'Triggering this will rewrite relative image asset URLs in translated md/mdx files to valid paths.',\n false\n )\n .option(\n '--force',\n 'Force a retranslation, invalidating all existing cached translations if they exist.',\n false\n )\n .option(\n '--force-download',\n 'Force download and overwrite local files, bypassing gt-lock.json checks.',\n false\n )\n .option(\n '--omit-config-ids',\n 'Do not write _versionId or _branchId to gt.config.json'\n )\n .option(\n '--experimental-clear-locale-dirs',\n 'Clear locale directories before downloading new translations',\n false\n )\n .option(\n '--branch <branch>',\n 'Specify a custom branch to use for translations'\n )\n .option(\n '--disable-branch-detection',\n 'Disable additional branch detection and optimizations and use the manually specified branch',\n false\n )\n .option('--enable-branching', 'Enable branching for the project')\n .option(\n '--remote-name <name>',\n 'Specify a custom remote name to use for branch detection',\n DEFAULT_GIT_REMOTE_NAME\n )\n .option(\n '--tag [value]',\n 'Tag this translation run (auto-resolves from git if no value provided)'\n )\n .option(\n '-m, --message <message>',\n 'Message to attach to the translation tag'\n );\n return command;\n}\n\n/**\n * Attaches flags necessary for parsing inline content\n * @param command - The command to attach the flags to\n * @returns The command with the inline content parsing flags attached\n */\nfunction attachInlineContentParsingFlags(command: Command) {\n return command\n .option(\n '--tsconfig, --jsconfig <path>',\n 'Path to custom jsconfig or tsconfig file',\n findFilepath(['./tsconfig.json', './jsconfig.json'])\n )\n .option('--dictionary <path>', 'Path to dictionary file')\n .option(\n '--src <paths...>',\n \"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}'\"\n )\n .option(\n '--inline',\n 'Include inline content in translations (e.g., inline jsx translations, inline string translations, etc.)',\n true\n );\n}\n\n/**\n * Attaches flags necessary for validating a project\n * @param command\n * @returns The command with the validate flags attached\n */\nexport function attachValidateFlags(command: Command) {\n return attachInlineContentParsingFlags(\n command.option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n );\n}\n\n/**\n * Attaches flags necessary for translating a project\n * @param command\n * @returns The command with the translate flags attached\n */\nexport function attachInlineTranslateFlags(command: Command) {\n return attachInlineContentParsingFlags(\n command.option(\n '--ignore-errors',\n 'Ignore errors encountered while scanning for inline content',\n false\n )\n );\n}\n"],"mappings":";;;AAIA,MAAM,kBAAkB;AAExB,SAAgB,kBAAkB,SAAkB;AAClD,SACG,OACC,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACA,OAAO,mBAAmB,gDAAgD,CAC1E,OAAO,qBAAqB,iCAAiC;AAChE,QAAO;;AAGT,SAAgB,qBAAqB,SAAkB;AACrD,mBAAkB,QAAQ,CACvB,OAAO,qBAAqB,iCAAiC,CAC7D,OACC,iDACA,4BACD,CACA,OACC,iCACA,mDACD,CACA,OACC,aACA,+DACA,MACD,CACA,OACC,uBACA,wCACC,UAAU;EACT,MAAM,cAAc,SAAS,OAAO,GAAG;AACvC,MAAI,MAAM,YAAY,CACpB,OAAM,IAAI,MAAM,iCAAiC;AAEnD,MAAI,cAAc,EAChB,OAAM,IAAI,MAAM,8CAA8C;AAEhE,SAAO;IAET,gBACD,CACA,OACC,gBACA,6DACA,KACD,CACA,OACC,mBACA,sEACD,CACA,OAAO,aAAa,mCAAmC,MAAM,CAC7D,OACC,uCACA,iJACA,MACD,CACA,OACC,sCACA,yEACA,MACD,CACA,OACC,qCACA,8HACA,MACD,CACA,OACC,0CACA,2JACA,MACD,CACA,OACC,2CACA,qGACA,MACD,CACA,OACC,WACA,uFACA,MACD,CACA,OACC,oBACA,4EACA,MACD,CACA,OACC,qBACA,yDACD,CACA,OACC,oCACA,gEACA,MACD,CACA,OACC,qBACA,kDACD,CACA,OACC,8BACA,+FACA,MACD,CACA,OAAO,sBAAsB,mCAAmC,CAChE,OACC,wBACA,4DACA,wBACD,CACA,OACC,iBACA,yEACD,CACA,OACC,2BACA,2CACD;AACH,QAAO;;;;;;;AAQT,SAAS,gCAAgC,SAAkB;AACzD,QAAO,QACJ,OACC,iCACA,4CACA,aAAa,CAAC,mBAAmB,kBAAkB,CAAC,CACrD,CACA,OAAO,uBAAuB,0BAA0B,CACxD,OACC,oBACA,0MACD,CACA,OACC,YACA,4GACA,KACD;;;;;;;AAQL,SAAgB,oBAAoB,SAAkB;AACpD,QAAO,gCACL,QAAQ,OACN,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACF;;;;;;;AAQH,SAAgB,2BAA2B,SAAkB;AAC3D,QAAO,gCACL,QAAQ,OACN,mBACA,+DACA,MACD,CACF"}
|
|
@@ -30,6 +30,18 @@ async function createOrUpdateConfig(configFilepath, options) {
|
|
|
30
30
|
...oldContent,
|
|
31
31
|
...newContent
|
|
32
32
|
};
|
|
33
|
+
if (options.files) {
|
|
34
|
+
const oldFiles = oldContent.files && typeof oldContent.files === "object" ? oldContent.files : {};
|
|
35
|
+
const oldGt = oldFiles.gt && typeof oldFiles.gt === "object" ? oldFiles.gt : {};
|
|
36
|
+
mergedContent.files = {
|
|
37
|
+
...oldFiles,
|
|
38
|
+
...options.files,
|
|
39
|
+
...options.files.gt && { gt: {
|
|
40
|
+
...oldGt,
|
|
41
|
+
...options.files.gt
|
|
42
|
+
} }
|
|
43
|
+
};
|
|
44
|
+
}
|
|
33
45
|
if (options.locales) mergedContent.locales = mergedContent.locales ? [...new Set([...mergedContent.locales, ...options.locales])] : options.locales;
|
|
34
46
|
const mergedJsonContent = JSON.stringify(mergedContent, null, 2);
|
|
35
47
|
await fs.promises.writeFile(configFilepath, mergedJsonContent, "utf-8");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupConfig.js","names":[],"sources":["../../../src/fs/config/setupConfig.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { displayCreatedConfigFile } from '../../console/logging.js';\nimport { FilesOptions, SupportedFrameworks } from '../../types/index.js';\nimport { logger } from '../../console/logger.js';\nimport { GT_CONFIG_SCHEMA_URL } from '../../utils/constants.js';\n\n/**\n * Checks if the config file exists.\n * If yes, make sure make sure projectId is correct\n * If not, creates a new JSON file at the given filepath and writes the provided config object to it.\n * @param {string} configFilepath - The path to the config file.\n * @param {Record<string, any>} configObject - The config object to write if the file does not exist.\n */\nexport async function createOrUpdateConfig(\n configFilepath: string,\n options: {\n projectId?: string;\n defaultLocale?: string;\n locales?: string[];\n files?: FilesOptions;\n framework?: SupportedFrameworks;\n baseUrl?: string;\n publish?: boolean;\n }\n): Promise<string> {\n // Filter out empty string values from the config object\n const newContent = {\n ...(options.projectId && { projectId: options.projectId }),\n ...(options.defaultLocale && { defaultLocale: options.defaultLocale }),\n ...(options.files && { files: options.files }),\n ...(options.framework && { framework: options.framework }),\n ...(options.baseUrl && { baseUrl: options.baseUrl }),\n ...(options.publish && { publish: options.publish }),\n };\n try {\n // if file exists\n let oldContent: Record<string, unknown> = {};\n if (fs.existsSync(configFilepath)) {\n const parsed = JSON.parse(\n await fs.promises.readFile(configFilepath, 'utf-8')\n );\n oldContent =\n typeof parsed === 'object' && parsed !== null\n ? (parsed as Record<string, unknown>)\n : {};\n }\n\n // merge old and new content\n const mergedContent = {\n $schema: GT_CONFIG_SCHEMA_URL,\n ...oldContent,\n ...newContent,\n } as Record<string, unknown> & { locales?: string[] };\n\n // Add locales to mergedContent if they exist\n if (options.locales) {\n mergedContent.locales = mergedContent.locales\n ? [...new Set([...mergedContent.locales, ...options.locales])]\n : options.locales;\n }\n\n // write to file\n const mergedJsonContent = JSON.stringify(mergedContent, null, 2);\n await fs.promises.writeFile(configFilepath, mergedJsonContent, 'utf-8');\n\n // show update in console\n displayCreatedConfigFile(configFilepath);\n } catch (error) {\n logger.error(\n `An error occurred while updating ${configFilepath}: ${error}`\n );\n }\n return configFilepath;\n}\n"],"mappings":";;;;;;;;;;;;AAaA,eAAsB,qBACpB,gBACA,SASiB;CAEjB,MAAM,aAAa;EACjB,GAAI,QAAQ,aAAa,EAAE,WAAW,QAAQ,WAAW;EACzD,GAAI,QAAQ,iBAAiB,EAAE,eAAe,QAAQ,eAAe;EACrE,GAAI,QAAQ,SAAS,EAAE,OAAO,QAAQ,OAAO;EAC7C,GAAI,QAAQ,aAAa,EAAE,WAAW,QAAQ,WAAW;EACzD,GAAI,QAAQ,WAAW,EAAE,SAAS,QAAQ,SAAS;EACnD,GAAI,QAAQ,WAAW,EAAE,SAAS,QAAQ,SAAS;EACpD;AACD,KAAI;EAEF,IAAI,aAAsC,EAAE;AAC5C,MAAI,GAAG,WAAW,eAAe,EAAE;GACjC,MAAM,SAAS,KAAK,MAClB,MAAM,GAAG,SAAS,SAAS,gBAAgB,QAAQ,CACpD;AACD,gBACE,OAAO,WAAW,YAAY,WAAW,OACpC,SACD,EAAE;;EAIV,MAAM,gBAAgB;GACpB,SAAS;GACT,GAAG;GACH,GAAG;GACJ;
|
|
1
|
+
{"version":3,"file":"setupConfig.js","names":[],"sources":["../../../src/fs/config/setupConfig.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { displayCreatedConfigFile } from '../../console/logging.js';\nimport { FilesOptions, SupportedFrameworks } from '../../types/index.js';\nimport { logger } from '../../console/logger.js';\nimport { GT_CONFIG_SCHEMA_URL } from '../../utils/constants.js';\n\n/**\n * Checks if the config file exists.\n * If yes, make sure make sure projectId is correct\n * If not, creates a new JSON file at the given filepath and writes the provided config object to it.\n * @param {string} configFilepath - The path to the config file.\n * @param {Record<string, any>} configObject - The config object to write if the file does not exist.\n */\nexport async function createOrUpdateConfig(\n configFilepath: string,\n options: {\n projectId?: string;\n defaultLocale?: string;\n locales?: string[];\n files?: FilesOptions;\n framework?: SupportedFrameworks;\n baseUrl?: string;\n publish?: boolean;\n }\n): Promise<string> {\n // Filter out empty string values from the config object\n const newContent = {\n ...(options.projectId && { projectId: options.projectId }),\n ...(options.defaultLocale && { defaultLocale: options.defaultLocale }),\n ...(options.files && { files: options.files }),\n ...(options.framework && { framework: options.framework }),\n ...(options.baseUrl && { baseUrl: options.baseUrl }),\n ...(options.publish && { publish: options.publish }),\n };\n try {\n // if file exists\n let oldContent: Record<string, unknown> = {};\n if (fs.existsSync(configFilepath)) {\n const parsed = JSON.parse(\n await fs.promises.readFile(configFilepath, 'utf-8')\n );\n oldContent =\n typeof parsed === 'object' && parsed !== null\n ? (parsed as Record<string, unknown>)\n : {};\n }\n\n // merge old and new content\n const mergedContent = {\n $schema: GT_CONFIG_SCHEMA_URL,\n ...oldContent,\n ...newContent,\n } as Record<string, unknown> & { locales?: string[] };\n\n // Preserve unrelated file configuration and nested GT options when setup\n // only needs to add or update a translation output path.\n if (options.files) {\n const oldFiles =\n oldContent.files && typeof oldContent.files === 'object'\n ? (oldContent.files as Record<string, unknown>)\n : {};\n const oldGt =\n oldFiles.gt && typeof oldFiles.gt === 'object'\n ? (oldFiles.gt as Record<string, unknown>)\n : {};\n mergedContent.files = {\n ...oldFiles,\n ...options.files,\n ...(options.files.gt && {\n gt: { ...oldGt, ...options.files.gt },\n }),\n };\n }\n\n // Add locales to mergedContent if they exist\n if (options.locales) {\n mergedContent.locales = mergedContent.locales\n ? [...new Set([...mergedContent.locales, ...options.locales])]\n : options.locales;\n }\n\n // write to file\n const mergedJsonContent = JSON.stringify(mergedContent, null, 2);\n await fs.promises.writeFile(configFilepath, mergedJsonContent, 'utf-8');\n\n // show update in console\n displayCreatedConfigFile(configFilepath);\n } catch (error) {\n logger.error(\n `An error occurred while updating ${configFilepath}: ${error}`\n );\n }\n return configFilepath;\n}\n"],"mappings":";;;;;;;;;;;;AAaA,eAAsB,qBACpB,gBACA,SASiB;CAEjB,MAAM,aAAa;EACjB,GAAI,QAAQ,aAAa,EAAE,WAAW,QAAQ,WAAW;EACzD,GAAI,QAAQ,iBAAiB,EAAE,eAAe,QAAQ,eAAe;EACrE,GAAI,QAAQ,SAAS,EAAE,OAAO,QAAQ,OAAO;EAC7C,GAAI,QAAQ,aAAa,EAAE,WAAW,QAAQ,WAAW;EACzD,GAAI,QAAQ,WAAW,EAAE,SAAS,QAAQ,SAAS;EACnD,GAAI,QAAQ,WAAW,EAAE,SAAS,QAAQ,SAAS;EACpD;AACD,KAAI;EAEF,IAAI,aAAsC,EAAE;AAC5C,MAAI,GAAG,WAAW,eAAe,EAAE;GACjC,MAAM,SAAS,KAAK,MAClB,MAAM,GAAG,SAAS,SAAS,gBAAgB,QAAQ,CACpD;AACD,gBACE,OAAO,WAAW,YAAY,WAAW,OACpC,SACD,EAAE;;EAIV,MAAM,gBAAgB;GACpB,SAAS;GACT,GAAG;GACH,GAAG;GACJ;AAID,MAAI,QAAQ,OAAO;GACjB,MAAM,WACJ,WAAW,SAAS,OAAO,WAAW,UAAU,WAC3C,WAAW,QACZ,EAAE;GACR,MAAM,QACJ,SAAS,MAAM,OAAO,SAAS,OAAO,WACjC,SAAS,KACV,EAAE;AACR,iBAAc,QAAQ;IACpB,GAAG;IACH,GAAG,QAAQ;IACX,GAAI,QAAQ,MAAM,MAAM,EACtB,IAAI;KAAE,GAAG;KAAO,GAAG,QAAQ,MAAM;KAAI,EACtC;IACF;;AAIH,MAAI,QAAQ,QACV,eAAc,UAAU,cAAc,UAClC,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,cAAc,SAAS,GAAG,QAAQ,QAAQ,CAAC,CAAC,GAC5D,QAAQ;EAId,MAAM,oBAAoB,KAAK,UAAU,eAAe,MAAM,EAAE;AAChE,QAAM,GAAG,SAAS,UAAU,gBAAgB,mBAAmB,QAAQ;AAGvE,2BAAyB,eAAe;UACjC,OAAO;AACd,SAAO,MACL,oCAAoC,eAAe,IAAI,QACxD;;AAEH,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "2.16.
|
|
1
|
+
export declare const PACKAGE_VERSION = "2.16.2";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","names":[],"sources":["../../src/generated/version.ts"],"sourcesContent":["// This file is auto-generated. Do not edit manually.\nexport const PACKAGE_VERSION = '2.16.
|
|
1
|
+
{"version":3,"file":"version.js","names":[],"sources":["../../src/generated/version.ts"],"sourcesContent":["// This file is auto-generated. Do not edit manually.\nexport const PACKAGE_VERSION = '2.16.2';\n"],"mappings":";AACA,MAAa,kBAAkB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type SetupViteSPAOptions = {
|
|
2
|
+
appDirectory: string;
|
|
3
|
+
configFilepath: string;
|
|
4
|
+
defaultLocale: string;
|
|
5
|
+
locales: string[];
|
|
6
|
+
translationsDir?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function setupViteSPA({ appDirectory, configFilepath, defaultLocale, locales, translationsDir, }: SetupViteSPAOptions): Promise<void>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { logger } from "../console/logger.js";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { createDiagnosticMessage } from "generaltranslation/internal";
|
|
5
|
+
//#region src/setup/setupViteSPA.ts
|
|
6
|
+
const defaultBootstrapFilename = "gt-entry.ts";
|
|
7
|
+
const alternateBootstrapFilename = "gt-bootstrap.ts";
|
|
8
|
+
function getBootstrapConflictError(filename) {
|
|
9
|
+
return createDiagnosticMessage({
|
|
10
|
+
source: "gt",
|
|
11
|
+
severity: "Error",
|
|
12
|
+
whatHappened: "The Vite bootstrap file already exists",
|
|
13
|
+
why: `GT will not overwrite an existing src/${filename} file`,
|
|
14
|
+
fix: "Move or rename that file and rerun `npx gt@latest`"
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function getLoaderContent(translationsImport) {
|
|
18
|
+
return `export default async function loadTranslations(locale: string) {
|
|
19
|
+
const translations = await import(\`${translationsImport}/\${locale}.json\`);
|
|
20
|
+
return translations.default;
|
|
21
|
+
}
|
|
22
|
+
`;
|
|
23
|
+
}
|
|
24
|
+
function isGeneratedLoader(content) {
|
|
25
|
+
return /^export default async function loadTranslations\(locale: string\) \{\r?\n const translations = await import\(`[^`]+\/\$\{locale\}\.json`\);\r?\n return translations\.default;\r?\n\}\r?\n?$/.test(content);
|
|
26
|
+
}
|
|
27
|
+
function toRelativeImport(fromDirectory, toPath) {
|
|
28
|
+
const relativePath = path.relative(fromDirectory, toPath).split(path.sep).join(path.posix.sep);
|
|
29
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
30
|
+
}
|
|
31
|
+
function getEntryImport(appDirectory, sourceDirectory, source) {
|
|
32
|
+
const sourcePath = source.replace(/[?#].*$/, "");
|
|
33
|
+
return toRelativeImport(sourceDirectory, sourcePath.startsWith("/") ? path.resolve(appDirectory, `.${sourcePath}`) : path.resolve(appDirectory, sourcePath)).replace(/\.(?:[cm]?[jt]sx?)$/i, "");
|
|
34
|
+
}
|
|
35
|
+
function getBootstrapEntry(bootstrap) {
|
|
36
|
+
return bootstrap.match(/await\s+import\(\s*(['"])([^'"]+)\1\s*\)/)?.[2];
|
|
37
|
+
}
|
|
38
|
+
function getModuleEntry(indexHtml) {
|
|
39
|
+
const moduleScripts = indexHtml.match(/<script\b[^>]*\btype=(['"])module\1[^>]*>\s*<\/script>/gi);
|
|
40
|
+
for (const script of moduleScripts ?? []) {
|
|
41
|
+
const source = script.match(/\bsrc=(['"])([^'"]+)\1/i)?.[2];
|
|
42
|
+
if (source) return {
|
|
43
|
+
script,
|
|
44
|
+
source
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
throw new Error(createDiagnosticMessage({
|
|
48
|
+
source: "gt",
|
|
49
|
+
severity: "Error",
|
|
50
|
+
whatHappened: "No Vite module entry was found in index.html",
|
|
51
|
+
fix: "Add a module script for the app entry and rerun `npx gt@latest`"
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
async function setupViteSPA({ appDirectory, configFilepath, defaultLocale, locales, translationsDir }) {
|
|
55
|
+
const indexHtmlPath = path.join(appDirectory, "index.html");
|
|
56
|
+
const sourceDirectory = path.join(appDirectory, "src");
|
|
57
|
+
const indexHtml = await fs.promises.readFile(indexHtmlPath, "utf8");
|
|
58
|
+
const { script, source } = getModuleEntry(indexHtml);
|
|
59
|
+
const declaredEntryImport = getEntryImport(appDirectory, sourceDirectory, source);
|
|
60
|
+
const configuredBootstrap = source.match(/^\/?src\/(gt-entry\.ts|gt-bootstrap\.ts)(?:[?#].*)?$/)?.[1];
|
|
61
|
+
const isAlreadyConfigured = configuredBootstrap !== void 0;
|
|
62
|
+
const bootstrapFilename = configuredBootstrap ?? (declaredEntryImport === "./gt-entry" ? alternateBootstrapFilename : defaultBootstrapFilename);
|
|
63
|
+
const bootstrapPath = path.join(sourceDirectory, bootstrapFilename);
|
|
64
|
+
let existingBootstrap;
|
|
65
|
+
if (fs.existsSync(bootstrapPath)) {
|
|
66
|
+
existingBootstrap = await fs.promises.readFile(bootstrapPath, "utf8");
|
|
67
|
+
if (!existingBootstrap.includes("initializeGTSPA")) throw new Error(getBootstrapConflictError(bootstrapFilename));
|
|
68
|
+
}
|
|
69
|
+
const entryImport = isAlreadyConfigured ? existingBootstrap && getBootstrapEntry(existingBootstrap) : declaredEntryImport;
|
|
70
|
+
if (!entryImport) throw new Error(createDiagnosticMessage({
|
|
71
|
+
source: "gt",
|
|
72
|
+
severity: "Error",
|
|
73
|
+
whatHappened: "The existing Vite bootstrap has no app entry import",
|
|
74
|
+
fix: "Restore the app entry import and rerun `npx gt@latest`"
|
|
75
|
+
}));
|
|
76
|
+
await fs.promises.mkdir(sourceDirectory, { recursive: true });
|
|
77
|
+
let loadTranslationsImport = "";
|
|
78
|
+
let loadTranslationsOption = "gtConfig";
|
|
79
|
+
if (translationsDir) {
|
|
80
|
+
const translationsPath = path.resolve(appDirectory, translationsDir);
|
|
81
|
+
const loaderPath = path.join(sourceDirectory, "loadTranslations.ts");
|
|
82
|
+
const translationsImport = toRelativeImport(sourceDirectory, translationsPath);
|
|
83
|
+
const existingLoader = fs.existsSync(loaderPath) ? await fs.promises.readFile(loaderPath, "utf8") : void 0;
|
|
84
|
+
if (!existingLoader || isGeneratedLoader(existingLoader)) await fs.promises.writeFile(loaderPath, getLoaderContent(translationsImport));
|
|
85
|
+
await fs.promises.mkdir(translationsPath, { recursive: true });
|
|
86
|
+
for (const locale of new Set(locales)) {
|
|
87
|
+
if (locale === defaultLocale) continue;
|
|
88
|
+
const stubPath = path.join(translationsPath, `${locale}.json`);
|
|
89
|
+
if (!fs.existsSync(stubPath)) await fs.promises.writeFile(stubPath, "{}\n");
|
|
90
|
+
}
|
|
91
|
+
loadTranslationsImport = "import loadTranslations from './loadTranslations';\n";
|
|
92
|
+
loadTranslationsOption = "{ ...gtConfig, loadTranslations }";
|
|
93
|
+
}
|
|
94
|
+
const configImport = toRelativeImport(sourceDirectory, path.resolve(appDirectory, configFilepath));
|
|
95
|
+
await fs.promises.writeFile(bootstrapPath, `import { initializeGTSPA } from 'gt-react';
|
|
96
|
+
import gtConfig from '${configImport}';
|
|
97
|
+
${loadTranslationsImport}
|
|
98
|
+
await initializeGTSPA(${loadTranslationsOption});
|
|
99
|
+
|
|
100
|
+
await import('${entryImport}');
|
|
101
|
+
`);
|
|
102
|
+
if (!isAlreadyConfigured) {
|
|
103
|
+
const updatedScript = script.replace(source, `/src/${bootstrapFilename}`);
|
|
104
|
+
await fs.promises.writeFile(indexHtmlPath, indexHtml.replace(script, updatedScript));
|
|
105
|
+
}
|
|
106
|
+
logger.success("Configured initializeGTSPA for this Vite application.");
|
|
107
|
+
}
|
|
108
|
+
//#endregion
|
|
109
|
+
export { setupViteSPA };
|
|
110
|
+
|
|
111
|
+
//# sourceMappingURL=setupViteSPA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setupViteSPA.js","names":[],"sources":["../../src/setup/setupViteSPA.ts"],"sourcesContent":["import { createDiagnosticMessage } from 'generaltranslation/internal';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { logger } from '../console/logger.js';\n\ntype SetupViteSPAOptions = {\n appDirectory: string;\n configFilepath: string;\n defaultLocale: string;\n locales: string[];\n translationsDir?: string;\n};\n\nconst defaultBootstrapFilename = 'gt-entry.ts';\nconst alternateBootstrapFilename = 'gt-bootstrap.ts';\n\nfunction getBootstrapConflictError(filename: string): string {\n return createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The Vite bootstrap file already exists',\n why: `GT will not overwrite an existing src/${filename} file`,\n fix: 'Move or rename that file and rerun `npx gt@latest`',\n });\n}\n\nfunction getLoaderContent(translationsImport: string): string {\n return `export default async function loadTranslations(locale: string) {\n const translations = await import(\\`${translationsImport}/\\${locale}.json\\`);\n return translations.default;\n}\n`;\n}\n\nfunction isGeneratedLoader(content: string): boolean {\n return /^export default async function loadTranslations\\(locale: string\\) \\{\\r?\\n const translations = await import\\(`[^`]+\\/\\$\\{locale\\}\\.json`\\);\\r?\\n return translations\\.default;\\r?\\n\\}\\r?\\n?$/.test(\n content\n );\n}\n\nfunction toRelativeImport(fromDirectory: string, toPath: string): string {\n const relativePath = path\n .relative(fromDirectory, toPath)\n .split(path.sep)\n .join(path.posix.sep);\n return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;\n}\n\nfunction getEntryImport(\n appDirectory: string,\n sourceDirectory: string,\n source: string\n): string {\n const sourcePath = source.replace(/[?#].*$/, '');\n const entryPath = sourcePath.startsWith('/')\n ? path.resolve(appDirectory, `.${sourcePath}`)\n : path.resolve(appDirectory, sourcePath);\n return toRelativeImport(sourceDirectory, entryPath).replace(\n /\\.(?:[cm]?[jt]sx?)$/i,\n ''\n );\n}\n\nfunction getBootstrapEntry(bootstrap: string): string | undefined {\n return bootstrap.match(/await\\s+import\\(\\s*(['\"])([^'\"]+)\\1\\s*\\)/)?.[2];\n}\n\nfunction getModuleEntry(indexHtml: string): {\n script: string;\n source: string;\n} {\n const moduleScripts = indexHtml.match(\n /<script\\b[^>]*\\btype=(['\"])module\\1[^>]*>\\s*<\\/script>/gi\n );\n for (const script of moduleScripts ?? []) {\n const source = script.match(/\\bsrc=(['\"])([^'\"]+)\\1/i)?.[2];\n if (source) return { script, source };\n }\n\n throw new Error(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'No Vite module entry was found in index.html',\n fix: 'Add a module script for the app entry and rerun `npx gt@latest`',\n })\n );\n}\n\nexport async function setupViteSPA({\n appDirectory,\n configFilepath,\n defaultLocale,\n locales,\n translationsDir,\n}: SetupViteSPAOptions): Promise<void> {\n const indexHtmlPath = path.join(appDirectory, 'index.html');\n const sourceDirectory = path.join(appDirectory, 'src');\n const indexHtml = await fs.promises.readFile(indexHtmlPath, 'utf8');\n const { script, source } = getModuleEntry(indexHtml);\n const declaredEntryImport = getEntryImport(\n appDirectory,\n sourceDirectory,\n source\n );\n const configuredBootstrap = source.match(\n /^\\/?src\\/(gt-entry\\.ts|gt-bootstrap\\.ts)(?:[?#].*)?$/\n )?.[1];\n const isAlreadyConfigured = configuredBootstrap !== undefined;\n const bootstrapFilename =\n configuredBootstrap ??\n (declaredEntryImport === './gt-entry'\n ? alternateBootstrapFilename\n : defaultBootstrapFilename);\n const bootstrapPath = path.join(sourceDirectory, bootstrapFilename);\n let existingBootstrap: string | undefined;\n\n if (fs.existsSync(bootstrapPath)) {\n existingBootstrap = await fs.promises.readFile(bootstrapPath, 'utf8');\n if (!existingBootstrap.includes('initializeGTSPA')) {\n throw new Error(getBootstrapConflictError(bootstrapFilename));\n }\n }\n\n const entryImport = isAlreadyConfigured\n ? existingBootstrap && getBootstrapEntry(existingBootstrap)\n : declaredEntryImport;\n if (!entryImport) {\n throw new Error(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The existing Vite bootstrap has no app entry import',\n fix: 'Restore the app entry import and rerun `npx gt@latest`',\n })\n );\n }\n\n await fs.promises.mkdir(sourceDirectory, { recursive: true });\n\n let loadTranslationsImport = '';\n let loadTranslationsOption = 'gtConfig';\n if (translationsDir) {\n const translationsPath = path.resolve(appDirectory, translationsDir);\n const loaderPath = path.join(sourceDirectory, 'loadTranslations.ts');\n const translationsImport = toRelativeImport(\n sourceDirectory,\n translationsPath\n );\n const existingLoader = fs.existsSync(loaderPath)\n ? await fs.promises.readFile(loaderPath, 'utf8')\n : undefined;\n if (!existingLoader || isGeneratedLoader(existingLoader)) {\n await fs.promises.writeFile(\n loaderPath,\n getLoaderContent(translationsImport)\n );\n }\n\n await fs.promises.mkdir(translationsPath, { recursive: true });\n for (const locale of new Set(locales)) {\n if (locale === defaultLocale) continue;\n const stubPath = path.join(translationsPath, `${locale}.json`);\n if (!fs.existsSync(stubPath)) {\n await fs.promises.writeFile(stubPath, '{}\\n');\n }\n }\n\n loadTranslationsImport =\n \"import loadTranslations from './loadTranslations';\\n\";\n loadTranslationsOption = '{ ...gtConfig, loadTranslations }';\n }\n\n const configImport = toRelativeImport(\n sourceDirectory,\n path.resolve(appDirectory, configFilepath)\n );\n await fs.promises.writeFile(\n bootstrapPath,\n `import { initializeGTSPA } from 'gt-react';\nimport gtConfig from '${configImport}';\n${loadTranslationsImport}\nawait initializeGTSPA(${loadTranslationsOption});\n\nawait import('${entryImport}');\n`\n );\n\n if (!isAlreadyConfigured) {\n const updatedScript = script.replace(source, `/src/${bootstrapFilename}`);\n await fs.promises.writeFile(\n indexHtmlPath,\n indexHtml.replace(script, updatedScript)\n );\n }\n\n logger.success('Configured initializeGTSPA for this Vite application.');\n}\n"],"mappings":"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"}
|
package/dist/setup/userInput.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { promptLocale, promptLocaleList } from "../console/logging.js";
|
|
2
2
|
import { libraryDefaultLocale } from "generaltranslation/internal";
|
|
3
3
|
//#region src/setup/userInput.ts
|
|
4
|
-
async function getDesiredLocales() {
|
|
4
|
+
async function getDesiredLocales(existingConfig) {
|
|
5
|
+
const configuredDefaultLocale = typeof existingConfig?.defaultLocale === "string" && existingConfig.defaultLocale ? existingConfig.defaultLocale : void 0;
|
|
6
|
+
const configuredLocales = Array.isArray(existingConfig?.locales) && existingConfig.locales.every((locale) => typeof locale === "string") ? existingConfig.locales : void 0;
|
|
5
7
|
return {
|
|
6
|
-
defaultLocale: await promptLocale({
|
|
8
|
+
defaultLocale: configuredDefaultLocale ?? await promptLocale({
|
|
7
9
|
message: "What is the default locale for your project?",
|
|
8
10
|
defaultValue: libraryDefaultLocale
|
|
9
11
|
}),
|
|
10
|
-
locales: await promptLocaleList({ message: "Which languages would you like to translate your project into?" })
|
|
12
|
+
locales: configuredLocales ?? await promptLocaleList({ message: "Which languages would you like to translate your project into?" })
|
|
11
13
|
};
|
|
12
14
|
}
|
|
13
15
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"userInput.js","names":[],"sources":["../../src/setup/userInput.ts"],"sourcesContent":["import { libraryDefaultLocale } from 'generaltranslation/internal';\nimport { promptLocale, promptLocaleList } from '../console/logging.js';\n\nexport async function getDesiredLocales(): Promise<{\n defaultLocale: string;\n locales: string[];\n}> {\n // Ask for the default locale\n const defaultLocale
|
|
1
|
+
{"version":3,"file":"userInput.js","names":[],"sources":["../../src/setup/userInput.ts"],"sourcesContent":["import { libraryDefaultLocale } from 'generaltranslation/internal';\nimport { promptLocale, promptLocaleList } from '../console/logging.js';\n\nexport async function getDesiredLocales(existingConfig?: {\n defaultLocale?: unknown;\n locales?: unknown;\n}): Promise<{\n defaultLocale: string;\n locales: string[];\n}> {\n const configuredDefaultLocale =\n typeof existingConfig?.defaultLocale === 'string' &&\n existingConfig.defaultLocale\n ? existingConfig.defaultLocale\n : undefined;\n const configuredLocales =\n Array.isArray(existingConfig?.locales) &&\n existingConfig.locales.every((locale) => typeof locale === 'string')\n ? (existingConfig.locales as string[])\n : undefined;\n\n // Ask for the default locale\n const defaultLocale =\n configuredDefaultLocale ??\n (await promptLocale({\n message: 'What is the default locale for your project?',\n defaultValue: libraryDefaultLocale,\n }));\n\n // Ask for the locales\n const locales =\n configuredLocales ??\n (await promptLocaleList({\n message: 'Which languages would you like to translate your project into?',\n }));\n return { defaultLocale, locales };\n}\n"],"mappings":";;;AAGA,eAAsB,kBAAkB,gBAMrC;CACD,MAAM,0BACJ,OAAO,gBAAgB,kBAAkB,YACzC,eAAe,gBACX,eAAe,gBACf,KAAA;CACN,MAAM,oBACJ,MAAM,QAAQ,gBAAgB,QAAQ,IACtC,eAAe,QAAQ,OAAO,WAAW,OAAO,WAAW,SAAS,GAC/D,eAAe,UAChB,KAAA;AAgBN,QAAO;EAAE,eAZP,2BACC,MAAM,aAAa;GAClB,SAAS;GACT,cAAc;GACf,CAAC;EAQoB,SAJtB,qBACC,MAAM,iBAAiB,EACtB,SAAS,kEACV,CAAC;EAC6B"}
|
package/dist/setup/wizard.js
CHANGED
|
@@ -10,7 +10,6 @@ import { handleInitGT } from "../next/parse/handleInitGT.js";
|
|
|
10
10
|
import { wrapContentNext } from "../next/parse/wrapContent.js";
|
|
11
11
|
import { getPackageManager } from "../utils/packageManager.js";
|
|
12
12
|
import { installPackage } from "../utils/installPackage.js";
|
|
13
|
-
import { addVitePlugin } from "../react/parse/addVitePlugin/index.js";
|
|
14
13
|
import { getFrameworkDisplayName } from "./frameworkUtils.js";
|
|
15
14
|
import chalk from "chalk";
|
|
16
15
|
//#region src/setup/wizard.ts
|
|
@@ -67,7 +66,7 @@ Make sure you have committed or stashed any changes. Do you want to continue?`),
|
|
|
67
66
|
Please let us know what you would like to see added at https://github.com/generaltranslation/gt/issues`);
|
|
68
67
|
exitSync(0);
|
|
69
68
|
}
|
|
70
|
-
await createOrUpdateConfig(options.config || "gt.config.json", { framework: frameworkType });
|
|
69
|
+
if (frameworkType !== "vite") await createOrUpdateConfig(options.config || "gt.config.json", { framework: frameworkType });
|
|
71
70
|
const packageJson = await getPackageJson();
|
|
72
71
|
if (!packageJson) {
|
|
73
72
|
logger.error(chalk.red("No package.json found in the current directory. Run this command from the root of your project."));
|
|
@@ -123,13 +122,6 @@ Please let us know what you would like to see added at https://github.com/genera
|
|
|
123
122
|
await handleInitGT(nextConfigPath, errors, warnings, filesUpdated, packageJson, tsconfigJson);
|
|
124
123
|
logger.step(chalk.green(`Added withGTConfig() to your ${nextConfigPath} file.`));
|
|
125
124
|
}
|
|
126
|
-
if (frameworkType === "vite") await addVitePlugin({
|
|
127
|
-
errors,
|
|
128
|
-
warnings,
|
|
129
|
-
filesUpdated,
|
|
130
|
-
packageJson,
|
|
131
|
-
tsconfigJson
|
|
132
|
-
});
|
|
133
125
|
if (errors.length > 0) logger.error(chalk.red("Failed to write files:\n") + errors.join("\n"));
|
|
134
126
|
if (warnings.length > 0) logger.warn(chalk.yellow("Warnings encountered:") + "\n" + warnings.map((warning) => `${chalk.yellow("-")} ${warning}`).join("\n"));
|
|
135
127
|
const formatter = await detectFormatter();
|
package/dist/setup/wizard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wizard.js","names":[],"sources":["../../src/setup/wizard.ts"],"sourcesContent":["import { detectFormatter } from '../hooks/postProcess.js';\nimport { promptSelect } from '../console/logging.js';\nimport { logger } from '../console/logger.js';\nimport chalk from 'chalk';\nimport { promptConfirm } from '../console/logging.js';\nimport { SetupOptions, SupportedReactFrameworks } from '../types/index.js';\nimport findFilepath from '../fs/findFilepath.js';\nimport { formatFiles } from '../hooks/postProcess.js';\nimport { handleInitGT } from '../next/parse/handleInitGT.js';\nimport { getPackageJson, isPackageInstalled } from '../utils/packageJson.js';\nimport { wrapContentNext } from '../next/parse/wrapContent.js';\nimport { getPackageManager } from '../utils/packageManager.js';\nimport { installPackage } from '../utils/installPackage.js';\nimport { createOrUpdateConfig } from '../fs/config/setupConfig.js';\nimport { loadConfig } from '../fs/config/loadConfig.js';\nimport { addVitePlugin } from '../react/parse/addVitePlugin/index.js';\nimport { exitSync } from '../console/logging.js';\nimport { ReactFrameworkObject } from '../types/index.js';\nimport { getFrameworkDisplayName } from './frameworkUtils.js';\nimport { Libraries } from '../types/libraries.js';\n\nexport async function handleSetupReactCommand(\n options: SetupOptions,\n frameworkObject: ReactFrameworkObject,\n useDefaults: boolean = false\n): Promise<void> {\n const frameworkDisplayName = getFrameworkDisplayName(frameworkObject);\n\n // Ask user for confirmation using inquirer\n if (!useDefaults) {\n const answer = await promptConfirm({\n message: chalk.yellow(\n `This wizard will configure your ${frameworkDisplayName} project for internationalization with GT. If your project is already using a different i18n library, this wizard may cause issues.\n\nMake sure you have committed or stashed any changes. Do you want to continue?`\n ),\n defaultValue: true,\n cancelMessage:\n 'Operation cancelled. You can re-run this wizard with: npx gt setup',\n });\n if (!answer) {\n logger.info(\n 'Operation cancelled. You can re-run this wizard with: npx gt setup'\n );\n exitSync(0);\n }\n }\n\n const frameworkType =\n useDefaults && frameworkObject?.name\n ? frameworkObject.name\n : await promptSelect<SupportedReactFrameworks | 'other'>({\n message: 'Which framework are you using?',\n options: [\n { value: 'next-app', label: chalk.blue('Next.js App Router') },\n { value: 'next-pages', label: chalk.green('Next.js Pages Router') },\n { value: 'vite', label: chalk.cyan('Vite + React') },\n { value: 'gatsby', label: chalk.magenta('Gatsby') },\n { value: 'react', label: chalk.yellow('React') },\n { value: 'redwood', label: chalk.red('RedwoodJS') },\n { value: 'other', label: chalk.dim('Other') },\n ],\n defaultValue: frameworkObject?.name || 'other',\n });\n if (frameworkType === 'other') {\n logger.error(\n `Sorry, the wizard doesn't currently support other React frameworks.\nPlease let us know what you would like to see added at https://github.com/generaltranslation/gt/issues`\n );\n exitSync(0);\n }\n\n // ----- Create a starter gt.config.json file -----\n await createOrUpdateConfig(options.config || 'gt.config.json', {\n framework: frameworkType as SupportedReactFrameworks,\n });\n\n const packageJson = await getPackageJson();\n if (!packageJson) {\n logger.error(\n chalk.red(\n 'No package.json found in the current directory. Run this command from the root of your project.'\n )\n );\n exitSync(1);\n }\n // Check if gt-next or gt-react is installed\n if (\n frameworkType === 'next-app' &&\n !isPackageInstalled(Libraries.GT_NEXT, packageJson)\n ) {\n const packageManager = await getPackageManager();\n const spinner = logger.createSpinner('timer');\n spinner.start(\n `Installing ${Libraries.GT_NEXT} with ${packageManager.name}...`\n );\n await installPackage(Libraries.GT_NEXT, packageManager);\n spinner.stop(chalk.green(`Automatically installed ${Libraries.GT_NEXT}.`));\n } else if (\n ['next-pages', 'react', 'redwood', 'vite', 'gatsby'].includes(\n frameworkType\n ) &&\n !isPackageInstalled(Libraries.GT_REACT, packageJson)\n ) {\n const packageManager = await getPackageManager();\n const spinner = logger.createSpinner('timer');\n spinner.start(\n `Installing ${Libraries.GT_REACT} with ${packageManager.name}...`\n );\n await installPackage(Libraries.GT_REACT, packageManager);\n spinner.stop(chalk.green(`Automatically installed ${Libraries.GT_REACT}.`));\n }\n\n const errors: string[] = [];\n const warnings: string[] = [];\n let filesUpdated: string[] = [];\n\n // Read tsconfig.json if it exists\n const tsconfigPath = findFilepath(['tsconfig.json']);\n const tsconfigJson = tsconfigPath ? loadConfig(tsconfigPath) : undefined;\n\n if (frameworkType === 'next-app') {\n // Check if they have a next.config.js file\n const nextConfigPath = findFilepath([\n './next.config.js',\n './next.config.ts',\n './next.config.mjs',\n './next.config.mts',\n ]);\n if (!nextConfigPath) {\n logger.error('No next.config.[js|ts|mjs|mts] file found.');\n exitSync(1);\n }\n\n const mergeOptions = {\n ...options,\n disableIds: true,\n disableFormatting: true,\n skipTs: true,\n addGTProvider: true,\n };\n const spinner = logger.createSpinner();\n spinner.start('Wrapping JSX content with <T> tags...');\n // Wrap all JSX elements in the src directory with a <T> tag, with unique ids\n const { filesUpdated: filesUpdatedNext } = await wrapContentNext(\n mergeOptions,\n Libraries.GT_NEXT,\n errors,\n warnings\n );\n filesUpdated = [...filesUpdated, ...filesUpdatedNext];\n\n spinner.stop(\n chalk.green(\n `Success! Updated ${chalk.bold.cyan(filesUpdated.length)} files:\\n`\n ) + filesUpdated.map((file) => `${chalk.green('-')} ${file}`).join('\\n')\n );\n\n // Add the withGTConfig() function to the next.config.js file\n await handleInitGT(\n nextConfigPath,\n errors,\n warnings,\n filesUpdated,\n packageJson,\n tsconfigJson\n );\n logger.step(\n chalk.green(`Added withGTConfig() to your ${nextConfigPath} file.`)\n );\n }\n\n // Add gt compiler plugin\n if (frameworkType === 'vite') {\n await addVitePlugin({\n errors,\n warnings,\n filesUpdated,\n packageJson,\n tsconfigJson,\n });\n }\n\n if (errors.length > 0) {\n logger.error(chalk.red('Failed to write files:\\n') + errors.join('\\n'));\n }\n\n if (warnings.length > 0) {\n logger.warn(\n chalk.yellow('Warnings encountered:') +\n '\\n' +\n warnings.map((warning) => `${chalk.yellow('-')} ${warning}`).join('\\n')\n );\n }\n\n const formatter = await detectFormatter();\n\n if (!formatter || filesUpdated.length === 0) {\n return;\n }\n\n const applyFormatting = useDefaults\n ? true\n : await promptConfirm({\n message: `Would you like the wizard to auto-format the modified files? ${chalk.dim(\n `(${formatter})`\n )}`,\n defaultValue: true,\n });\n // Format updated files if formatters are available\n if (applyFormatting) await formatFiles(filesUpdated, formatter);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAqBA,eAAsB,wBACpB,SACA,iBACA,cAAuB,OACR;CACf,MAAM,uBAAuB,wBAAwB,gBAAgB;AAGrE,KAAI,CAAC;MAWC,CAAC,MAVgB,cAAc;GACjC,SAAS,MAAM,OACb,mCAAmC,qBAAqB;;+EAGzD;GACD,cAAc;GACd,eACE;GACH,CAAC,EACW;AACX,UAAO,KACL,qEACD;AACD,YAAS,EAAE;;;CAIf,MAAM,gBACJ,eAAe,iBAAiB,OAC5B,gBAAgB,OAChB,MAAM,aAAiD;EACrD,SAAS;EACT,SAAS;GACP;IAAE,OAAO;IAAY,OAAO,MAAM,KAAK,qBAAqB;IAAE;GAC9D;IAAE,OAAO;IAAc,OAAO,MAAM,MAAM,uBAAuB;IAAE;GACnE;IAAE,OAAO;IAAQ,OAAO,MAAM,KAAK,eAAe;IAAE;GACpD;IAAE,OAAO;IAAU,OAAO,MAAM,QAAQ,SAAS;IAAE;GACnD;IAAE,OAAO;IAAS,OAAO,MAAM,OAAO,QAAQ;IAAE;GAChD;IAAE,OAAO;IAAW,OAAO,MAAM,IAAI,YAAY;IAAE;GACnD;IAAE,OAAO;IAAS,OAAO,MAAM,IAAI,QAAQ;IAAE;GAC9C;EACD,cAAc,iBAAiB,QAAQ;EACxC,CAAC;AACR,KAAI,kBAAkB,SAAS;AAC7B,SAAO,MACL;wGAED;AACD,WAAS,EAAE;;AAIb,OAAM,qBAAqB,QAAQ,UAAU,kBAAkB,EAC7D,WAAW,eACZ,CAAC;CAEF,MAAM,cAAc,MAAM,gBAAgB;AAC1C,KAAI,CAAC,aAAa;AAChB,SAAO,MACL,MAAM,IACJ,kGACD,CACF;AACD,WAAS,EAAE;;AAGb,KACE,kBAAkB,cAClB,CAAC,mBAAA,WAAsC,YAAY,EACnD;EACA,MAAM,iBAAiB,MAAM,mBAAmB;EAChD,MAAM,UAAU,OAAO,cAAc,QAAQ;AAC7C,UAAQ,MACN,2BAAwC,eAAe,KAAK,KAC7D;AACD,QAAM,eAAA,WAAkC,eAAe;AACvD,UAAQ,KAAK,MAAM,MAAM,mCAAgD,CAAC;YAE1E;EAAC;EAAc;EAAS;EAAW;EAAQ;EAAS,CAAC,SACnD,cACD,IACD,CAAC,mBAAA,YAAuC,YAAY,EACpD;EACA,MAAM,iBAAiB,MAAM,mBAAmB;EAChD,MAAM,UAAU,OAAO,cAAc,QAAQ;AAC7C,UAAQ,MACN,4BAAyC,eAAe,KAAK,KAC9D;AACD,QAAM,eAAA,YAAmC,eAAe;AACxD,UAAQ,KAAK,MAAM,MAAM,oCAAiD,CAAC;;CAG7E,MAAM,SAAmB,EAAE;CAC3B,MAAM,WAAqB,EAAE;CAC7B,IAAI,eAAyB,EAAE;CAG/B,MAAM,eAAe,aAAa,CAAC,gBAAgB,CAAC;CACpD,MAAM,eAAe,eAAe,WAAW,aAAa,GAAG,KAAA;AAE/D,KAAI,kBAAkB,YAAY;EAEhC,MAAM,iBAAiB,aAAa;GAClC;GACA;GACA;GACA;GACD,CAAC;AACF,MAAI,CAAC,gBAAgB;AACnB,UAAO,MAAM,6CAA6C;AAC1D,YAAS,EAAE;;EAGb,MAAM,eAAe;GACnB,GAAG;GACH,YAAY;GACZ,mBAAmB;GACnB,QAAQ;GACR,eAAe;GAChB;EACD,MAAM,UAAU,OAAO,eAAe;AACtC,UAAQ,MAAM,wCAAwC;EAEtD,MAAM,EAAE,cAAc,qBAAqB,MAAM,gBAC/C,cAAA,WAEA,QACA,SACD;AACD,iBAAe,CAAC,GAAG,cAAc,GAAG,iBAAiB;AAErD,UAAQ,KACN,MAAM,MACJ,oBAAoB,MAAM,KAAK,KAAK,aAAa,OAAO,CAAC,WAC1D,GAAG,aAAa,KAAK,SAAS,GAAG,MAAM,MAAM,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,KAAK,CACzE;AAGD,QAAM,aACJ,gBACA,QACA,UACA,cACA,aACA,aACD;AACD,SAAO,KACL,MAAM,MAAM,gCAAgC,eAAe,QAAQ,CACpE;;AAIH,KAAI,kBAAkB,OACpB,OAAM,cAAc;EAClB;EACA;EACA;EACA;EACA;EACD,CAAC;AAGJ,KAAI,OAAO,SAAS,EAClB,QAAO,MAAM,MAAM,IAAI,2BAA2B,GAAG,OAAO,KAAK,KAAK,CAAC;AAGzE,KAAI,SAAS,SAAS,EACpB,QAAO,KACL,MAAM,OAAO,wBAAwB,GACnC,OACA,SAAS,KAAK,YAAY,GAAG,MAAM,OAAO,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,KAAK,CAC1E;CAGH,MAAM,YAAY,MAAM,iBAAiB;AAEzC,KAAI,CAAC,aAAa,aAAa,WAAW,EACxC;AAYF,KATwB,cACpB,OACA,MAAM,cAAc;EAClB,SAAS,gEAAgE,MAAM,IAC7E,IAAI,UAAU,GACf;EACD,cAAc;EACf,CAAC,CAEe,OAAM,YAAY,cAAc,UAAU"}
|
|
1
|
+
{"version":3,"file":"wizard.js","names":[],"sources":["../../src/setup/wizard.ts"],"sourcesContent":["import { detectFormatter } from '../hooks/postProcess.js';\nimport { promptSelect } from '../console/logging.js';\nimport { logger } from '../console/logger.js';\nimport chalk from 'chalk';\nimport { promptConfirm } from '../console/logging.js';\nimport { SetupOptions, SupportedReactFrameworks } from '../types/index.js';\nimport findFilepath from '../fs/findFilepath.js';\nimport { formatFiles } from '../hooks/postProcess.js';\nimport { handleInitGT } from '../next/parse/handleInitGT.js';\nimport { getPackageJson, isPackageInstalled } from '../utils/packageJson.js';\nimport { wrapContentNext } from '../next/parse/wrapContent.js';\nimport { getPackageManager } from '../utils/packageManager.js';\nimport { installPackage } from '../utils/installPackage.js';\nimport { createOrUpdateConfig } from '../fs/config/setupConfig.js';\nimport { loadConfig } from '../fs/config/loadConfig.js';\nimport { exitSync } from '../console/logging.js';\nimport { ReactFrameworkObject } from '../types/index.js';\nimport { getFrameworkDisplayName } from './frameworkUtils.js';\nimport { Libraries } from '../types/libraries.js';\n\nexport async function handleSetupReactCommand(\n options: SetupOptions,\n frameworkObject: ReactFrameworkObject,\n useDefaults: boolean = false\n): Promise<void> {\n const frameworkDisplayName = getFrameworkDisplayName(frameworkObject);\n\n // Ask user for confirmation using inquirer\n if (!useDefaults) {\n const answer = await promptConfirm({\n message: chalk.yellow(\n `This wizard will configure your ${frameworkDisplayName} project for internationalization with GT. If your project is already using a different i18n library, this wizard may cause issues.\n\nMake sure you have committed or stashed any changes. Do you want to continue?`\n ),\n defaultValue: true,\n cancelMessage:\n 'Operation cancelled. You can re-run this wizard with: npx gt setup',\n });\n if (!answer) {\n logger.info(\n 'Operation cancelled. You can re-run this wizard with: npx gt setup'\n );\n exitSync(0);\n }\n }\n\n const frameworkType =\n useDefaults && frameworkObject?.name\n ? frameworkObject.name\n : await promptSelect<SupportedReactFrameworks | 'other'>({\n message: 'Which framework are you using?',\n options: [\n { value: 'next-app', label: chalk.blue('Next.js App Router') },\n { value: 'next-pages', label: chalk.green('Next.js Pages Router') },\n { value: 'vite', label: chalk.cyan('Vite + React') },\n { value: 'gatsby', label: chalk.magenta('Gatsby') },\n { value: 'react', label: chalk.yellow('React') },\n { value: 'redwood', label: chalk.red('RedwoodJS') },\n { value: 'other', label: chalk.dim('Other') },\n ],\n defaultValue: frameworkObject?.name || 'other',\n });\n if (frameworkType === 'other') {\n logger.error(\n `Sorry, the wizard doesn't currently support other React frameworks.\nPlease let us know what you would like to see added at https://github.com/generaltranslation/gt/issues`\n );\n exitSync(0);\n }\n\n // Vite setup writes its complete config after locales are collected.\n if (frameworkType !== 'vite') {\n await createOrUpdateConfig(options.config || 'gt.config.json', {\n framework: frameworkType as SupportedReactFrameworks,\n });\n }\n\n const packageJson = await getPackageJson();\n if (!packageJson) {\n logger.error(\n chalk.red(\n 'No package.json found in the current directory. Run this command from the root of your project.'\n )\n );\n exitSync(1);\n }\n // Check if gt-next or gt-react is installed\n if (\n frameworkType === 'next-app' &&\n !isPackageInstalled(Libraries.GT_NEXT, packageJson)\n ) {\n const packageManager = await getPackageManager();\n const spinner = logger.createSpinner('timer');\n spinner.start(\n `Installing ${Libraries.GT_NEXT} with ${packageManager.name}...`\n );\n await installPackage(Libraries.GT_NEXT, packageManager);\n spinner.stop(chalk.green(`Automatically installed ${Libraries.GT_NEXT}.`));\n } else if (\n ['next-pages', 'react', 'redwood', 'vite', 'gatsby'].includes(\n frameworkType\n ) &&\n !isPackageInstalled(Libraries.GT_REACT, packageJson)\n ) {\n const packageManager = await getPackageManager();\n const spinner = logger.createSpinner('timer');\n spinner.start(\n `Installing ${Libraries.GT_REACT} with ${packageManager.name}...`\n );\n await installPackage(Libraries.GT_REACT, packageManager);\n spinner.stop(chalk.green(`Automatically installed ${Libraries.GT_REACT}.`));\n }\n\n const errors: string[] = [];\n const warnings: string[] = [];\n let filesUpdated: string[] = [];\n\n // Read tsconfig.json if it exists\n const tsconfigPath = findFilepath(['tsconfig.json']);\n const tsconfigJson = tsconfigPath ? loadConfig(tsconfigPath) : undefined;\n\n if (frameworkType === 'next-app') {\n // Check if they have a next.config.js file\n const nextConfigPath = findFilepath([\n './next.config.js',\n './next.config.ts',\n './next.config.mjs',\n './next.config.mts',\n ]);\n if (!nextConfigPath) {\n logger.error('No next.config.[js|ts|mjs|mts] file found.');\n exitSync(1);\n }\n\n const mergeOptions = {\n ...options,\n disableIds: true,\n disableFormatting: true,\n skipTs: true,\n addGTProvider: true,\n };\n const spinner = logger.createSpinner();\n spinner.start('Wrapping JSX content with <T> tags...');\n // Wrap all JSX elements in the src directory with a <T> tag, with unique ids\n const { filesUpdated: filesUpdatedNext } = await wrapContentNext(\n mergeOptions,\n Libraries.GT_NEXT,\n errors,\n warnings\n );\n filesUpdated = [...filesUpdated, ...filesUpdatedNext];\n\n spinner.stop(\n chalk.green(\n `Success! Updated ${chalk.bold.cyan(filesUpdated.length)} files:\\n`\n ) + filesUpdated.map((file) => `${chalk.green('-')} ${file}`).join('\\n')\n );\n\n // Add the withGTConfig() function to the next.config.js file\n await handleInitGT(\n nextConfigPath,\n errors,\n warnings,\n filesUpdated,\n packageJson,\n tsconfigJson\n );\n logger.step(\n chalk.green(`Added withGTConfig() to your ${nextConfigPath} file.`)\n );\n }\n\n if (errors.length > 0) {\n logger.error(chalk.red('Failed to write files:\\n') + errors.join('\\n'));\n }\n\n if (warnings.length > 0) {\n logger.warn(\n chalk.yellow('Warnings encountered:') +\n '\\n' +\n warnings.map((warning) => `${chalk.yellow('-')} ${warning}`).join('\\n')\n );\n }\n\n const formatter = await detectFormatter();\n\n if (!formatter || filesUpdated.length === 0) {\n return;\n }\n\n const applyFormatting = useDefaults\n ? true\n : await promptConfirm({\n message: `Would you like the wizard to auto-format the modified files? ${chalk.dim(\n `(${formatter})`\n )}`,\n defaultValue: true,\n });\n // Format updated files if formatters are available\n if (applyFormatting) await formatFiles(filesUpdated, formatter);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gt",
|
|
3
|
-
"version": "2.16.
|
|
3
|
+
"version": "2.16.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": "bin/main.js",
|
|
6
6
|
"files": [
|
|
@@ -116,11 +116,11 @@
|
|
|
116
116
|
"unist-util-visit": "^5.0.0",
|
|
117
117
|
"yaml": "^2.8.0",
|
|
118
118
|
"@generaltranslation/icu": "0.1.1",
|
|
119
|
-
"@generaltranslation/python-extractor": "0.2.33",
|
|
120
119
|
"@generaltranslation/format": "0.1.4",
|
|
121
|
-
"@generaltranslation/
|
|
122
|
-
"generaltranslation": "9.1.
|
|
123
|
-
"gt-remark": "1.0.11"
|
|
120
|
+
"@generaltranslation/python-extractor": "0.2.34",
|
|
121
|
+
"generaltranslation": "9.1.1",
|
|
122
|
+
"gt-remark": "1.0.11",
|
|
123
|
+
"@generaltranslation/supported-locales": "2.1.14"
|
|
124
124
|
},
|
|
125
125
|
"devDependencies": {
|
|
126
126
|
"@types/babel__generator": "^7.27.0",
|