mirror of
https://github.com/logto-io/logto.git
synced 2025-03-10 22:22:45 -05:00
feat(cli): add option to skip core check in translate cli commands (#5085)
* feat(cli): add option to skip core check in translate cli commands * chore(cli): add changeset * feat(cli): support any string value package name in translate command * chore: update changeset
This commit is contained in:
parent
6b2e1c8908
commit
e4c73e7bb7
6 changed files with 61 additions and 40 deletions
5
.changeset/few-turtles-crash.md
Normal file
5
.changeset/few-turtles-crash.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@logto/cli": minor
|
||||
---
|
||||
|
||||
Add "--skip-core-check" option in translate cli commands, in order to support any arbitrary package name other than "phrases" and "phrases-experience".
|
|
@ -16,6 +16,11 @@ const translate: CommandModule = {
|
|||
type: 'string',
|
||||
describe: 'The path to your Logto instance directory',
|
||||
})
|
||||
.option('skip-core-check', {
|
||||
alias: 'sc',
|
||||
type: 'boolean',
|
||||
describe: 'Skip checking if the core package is existed',
|
||||
})
|
||||
.command(create)
|
||||
.command(listTags)
|
||||
.command(sync)
|
||||
|
|
|
@ -10,8 +10,15 @@ import { consoleLog, inquireInstancePath, lintLocaleFiles } from '../../../utils
|
|||
import { parseLocaleFiles, syncPhraseKeysAndFileStructure } from './utils.js';
|
||||
|
||||
const syncKeys: CommandModule<
|
||||
{ path?: string },
|
||||
{ path?: string; baseline: string; target: string; skipLint?: boolean; package: string }
|
||||
{ path?: string; skipCoreCheck?: boolean },
|
||||
{
|
||||
path?: string;
|
||||
skipCoreCheck?: boolean;
|
||||
baseline: string;
|
||||
target: string;
|
||||
skipLint?: boolean;
|
||||
package: string;
|
||||
}
|
||||
> = {
|
||||
command: ['sync-keys', 'sk'],
|
||||
describe: [
|
||||
|
@ -31,7 +38,7 @@ const syncKeys: CommandModule<
|
|||
.option('package', {
|
||||
alias: 'pkg',
|
||||
type: 'string',
|
||||
describe: 'The package name of the phrases, one of `phrases` or `phrases-experience`',
|
||||
describe: 'The package name of the phrases, e.g. `phrases` or `phrases-experience`',
|
||||
default: 'phrases',
|
||||
})
|
||||
.option('target', {
|
||||
|
@ -40,13 +47,14 @@ const syncKeys: CommandModule<
|
|||
describe: 'The target language tag, or `all` to sync all languages',
|
||||
})
|
||||
.option('skip-lint', {
|
||||
alias: 's',
|
||||
alias: 'sl',
|
||||
type: 'boolean',
|
||||
describe: 'Skip running `eslint --fix` for locales after syncing',
|
||||
})
|
||||
.demandOption(['baseline', 'target']),
|
||||
handler: async ({
|
||||
path: inputPath,
|
||||
skipCoreCheck,
|
||||
baseline: baselineTag,
|
||||
target: targetTag,
|
||||
skipLint,
|
||||
|
@ -64,11 +72,7 @@ const syncKeys: CommandModule<
|
|||
consoleLog.fatal('Baseline and target cannot be the same');
|
||||
}
|
||||
|
||||
if (packageName !== 'phrases' && packageName !== 'phrases-experience') {
|
||||
consoleLog.fatal('Invalid package name, expected `phrases` or `phrases-experience`');
|
||||
}
|
||||
|
||||
const instancePath = await inquireInstancePath(inputPath);
|
||||
const instancePath = await inquireInstancePath(inputPath, skipCoreCheck);
|
||||
const phrasesPath = path.join(instancePath, 'packages', packageName);
|
||||
const localesPath = path.join(phrasesPath, 'src/locales');
|
||||
const entrypoint = path.join(localesPath, baselineTag.toLowerCase(), 'index.ts');
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { languages } from '@logto/language-kit';
|
||||
import { isBuiltInLanguageTag as isPhrasesBuiltInLanguageTag } from '@logto/phrases';
|
||||
import { isBuiltInLanguageTag as isPhrasesUiBuiltInLanguageTag } from '@logto/phrases-experience';
|
||||
import PQueue from 'p-queue';
|
||||
import type { CommandModule } from 'yargs';
|
||||
|
||||
|
@ -8,13 +7,24 @@ import { inquireInstancePath, lintLocaleFiles } from '../../utils.js';
|
|||
|
||||
import { type TranslationOptions, baseLanguage, syncTranslation } from './utils.js';
|
||||
|
||||
const sync: CommandModule<{ path?: string }, { path?: string }> = {
|
||||
const sync: CommandModule<
|
||||
{ path?: string; skipCoreCheck?: boolean },
|
||||
{ path?: string; skipCoreCheck?: boolean; package: string }
|
||||
> = {
|
||||
command: ['sync'],
|
||||
describe:
|
||||
'Translate all untranslated phrases using ChatGPT. Note the environment variable `OPENAI_API_KEY` is required to work.',
|
||||
handler: async ({ path: inputPath }) => {
|
||||
builder: (yargs) =>
|
||||
yargs.option('package', {
|
||||
alias: 'pkg',
|
||||
type: 'string',
|
||||
describe: 'The package name of the phrases, e.g. `phrases` or `phrases-experience`',
|
||||
default: 'phrases',
|
||||
}),
|
||||
handler: async ({ path: inputPath, skipCoreCheck, package: packageName }) => {
|
||||
const queue = new PQueue({ concurrency: 5 });
|
||||
const instancePath = await inquireInstancePath(inputPath);
|
||||
const instancePath = await inquireInstancePath(inputPath, skipCoreCheck);
|
||||
const packages = packageName ? [packageName] : ['phrases', 'phrases-experience'];
|
||||
|
||||
for (const languageTag of Object.keys(languages)) {
|
||||
if (languageTag === baseLanguage) {
|
||||
|
@ -27,28 +37,22 @@ const sync: CommandModule<{ path?: string }, { path?: string }> = {
|
|||
queue,
|
||||
} satisfies Partial<TranslationOptions>;
|
||||
|
||||
/* eslint-disable no-await-in-loop */
|
||||
if (isPhrasesBuiltInLanguageTag(languageTag)) {
|
||||
await syncTranslation({
|
||||
...baseOptions,
|
||||
packageName: 'phrases',
|
||||
languageTag,
|
||||
});
|
||||
for (const packageName of packages) {
|
||||
/* eslint-disable no-await-in-loop */
|
||||
if (isPhrasesBuiltInLanguageTag(languageTag)) {
|
||||
await syncTranslation({
|
||||
...baseOptions,
|
||||
packageName,
|
||||
languageTag,
|
||||
});
|
||||
}
|
||||
/* eslint-enable no-await-in-loop */
|
||||
}
|
||||
|
||||
if (isPhrasesUiBuiltInLanguageTag(languageTag)) {
|
||||
await syncTranslation({
|
||||
...baseOptions,
|
||||
packageName: 'phrases-experience',
|
||||
languageTag,
|
||||
});
|
||||
}
|
||||
/* eslint-enable no-await-in-loop */
|
||||
}
|
||||
|
||||
await queue.onIdle();
|
||||
|
||||
void lintLocaleFiles(instancePath);
|
||||
void lintLocaleFiles(instancePath, packageName);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ export const readBaseLocaleFiles = async (directory: string): Promise<string[]>
|
|||
|
||||
export type TranslationOptions = {
|
||||
instancePath: string;
|
||||
packageName: 'phrases' | 'phrases-experience';
|
||||
packageName: string;
|
||||
languageTag: LanguageTag;
|
||||
verbose?: boolean;
|
||||
queue?: PQueue;
|
||||
|
|
|
@ -7,7 +7,7 @@ import { promisify } from 'node:util';
|
|||
|
||||
import { ConsoleLog } from '@logto/shared';
|
||||
import type { Optional } from '@silverhand/essentials';
|
||||
import { assert, conditionalString } from '@silverhand/essentials';
|
||||
import { assert, conditional, conditionalString } from '@silverhand/essentials';
|
||||
import chalk from 'chalk';
|
||||
import type { Progress } from 'got';
|
||||
import { got } from 'got';
|
||||
|
@ -197,9 +197,9 @@ const validatePath = async (value: string) => {
|
|||
return true;
|
||||
};
|
||||
|
||||
export const inquireInstancePath = async (initialPath?: string) => {
|
||||
export const inquireInstancePath = async (initialPath?: string, skipCoreCheck?: boolean) => {
|
||||
const inquire = async () => {
|
||||
if (!initialPath && (await validatePath('.')) === true) {
|
||||
if (!initialPath && (skipCoreCheck ?? (await validatePath('.')) === true)) {
|
||||
return path.resolve('.');
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ export const inquireInstancePath = async (initialPath?: string) => {
|
|||
type: 'input',
|
||||
default: defaultPath,
|
||||
filter: (value: string) => value.trim(),
|
||||
validate: validatePath,
|
||||
validate: conditional(!skipCoreCheck && validatePath),
|
||||
},
|
||||
{ instancePath: initialPath }
|
||||
);
|
||||
|
@ -225,10 +225,13 @@ export const inquireInstancePath = async (initialPath?: string) => {
|
|||
};
|
||||
|
||||
const instancePath = await inquire();
|
||||
const validated = await validatePath(instancePath);
|
||||
|
||||
if (validated !== true) {
|
||||
consoleLog.fatal(validated);
|
||||
if (!skipCoreCheck) {
|
||||
const validated = await validatePath(instancePath);
|
||||
|
||||
if (validated !== true) {
|
||||
consoleLog.fatal(validated);
|
||||
}
|
||||
}
|
||||
|
||||
return instancePath;
|
||||
|
@ -274,8 +277,8 @@ const execPromise = promisify(execFile);
|
|||
export const lintLocaleFiles = async (
|
||||
/** Logto instance path */
|
||||
instancePath: string,
|
||||
/** Target package name, ignore to lint both packages */
|
||||
packageName?: 'phrases' | 'phrases-experience'
|
||||
/** Target package name, ignore to lint both `phrases` and `phrases-experience` packages */
|
||||
packageName?: string
|
||||
) => {
|
||||
const spinner = ora({
|
||||
text: 'Running `eslint --fix` for locales',
|
||||
|
|
Loading…
Add table
Reference in a new issue