Skip to content

Commit 12a60d7

Browse files
committed
✨ feat(core): add i18n for parameter errors
1 parent 84ecb22 commit 12a60d7

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

packages/core/src/cli.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ export class Clerc<C extends CommandRecord = {}> {
356356
argv: resolveArgv(),
357357
...optionsOrArgv,
358358
};
359-
this.#argv = argv;
359+
this.#argv = [...argv];
360360
this.#validateMeta();
361361
if (run) {
362362
this.runMatchedCommand();
@@ -379,6 +379,7 @@ export class Clerc<C extends CommandRecord = {}> {
379379

380380
#getContext(getCommand: () => ReturnType<typeof resolveCommand>) {
381381
const argv = this.#argv!;
382+
const { t } = this.i18n;
382383
const [command, called] = getCommand();
383384
const isCommandResolved = !!command;
384385
// [...argv] is a workaround since TypeFlag modifies argv
@@ -398,19 +399,22 @@ export class Clerc<C extends CommandRecord = {}> {
398399

399400
mapParametersToArguments(
400401
mapping,
401-
parseParameters(commandParameters),
402+
parseParameters(commandParameters, t),
402403
parameters,
404+
t,
403405
);
404406
mapParametersToArguments(
405407
mapping,
406-
parseParameters(eofParameters),
408+
parseParameters(eofParameters, t),
407409
eofArguments,
410+
t,
408411
);
409412
} else {
410413
mapParametersToArguments(
411414
mapping,
412-
parseParameters(commandParameters),
415+
parseParameters(commandParameters, t),
413416
parameters,
417+
t,
414418
);
415419
}
416420
const mergedFlags = { ...flags, ...unknownFlags };

packages/core/src/locales.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ export const locales: Locales = {
1212
"core.badNameFormat": "Bad name format: %s.",
1313
"core.localeMustBeCalledFirst": "locale() or fallbackLocale() must be called at first.",
1414
"core.cliParseMustBeCalled": "cli.parse() must be called.",
15+
"core.spreadParameterMustBeLast": "Invalid Parameter: Spread parameter %s must be last.",
16+
"core.requiredParameterCannotComeAfterOptionalParameter": "Invalid Parameter: Required parameter %s cannot come after optional parameter %s.",
17+
"core.parameterMustBeWrappedInBrackets": "Invalid Parameter: Parameter %s must be wrapped in <> (required parameter) or [] (optional parameter).",
18+
"core.parameterIsUsedMoreThanOnce": "Invalid Parameter: Parameter %s is used more than once.",
19+
"core.missingRequiredParameter": "Missing required parameter %s.",
1520
},
1621
"zh-CN": {
1722
"core.commandExists": "命令 \"%s\" 已存在。",
@@ -24,5 +29,10 @@ export const locales: Locales = {
2429
"core.badNameFormat": "错误的命令名字格式: %s。",
2530
"core.localeMustBeCalledFirst": "locale() 或 fallbackLocale() 必须在最开始调用。",
2631
"core.cliParseMustBeCalled": "cli.parse() 必须被调用。",
32+
"core.spreadParameterMustBeLast": "不合法的参数: 展开参数 %s 必须在最后。",
33+
"core.requiredParameterCannotComeAfterOptionalParameter": "不合法的参数: 必填参数 %s 不能在可选参数 %s 之后。",
34+
"core.parameterMustBeWrappedInBrackets": "不合法的参数: 参数 %s 必须被 <> (必填参数) 或 [] (可选参数) 包裹。",
35+
"core.parameterIsUsedMoreThanOnce": "不合法的参数: 参数 %s 被使用了多次。",
36+
"core.missingRequiredParameter": "缺少必填参数 %s。",
2737
},
2838
};

packages/core/src/parameters.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Thanks for his awesome work!
33
import { camelCase } from "@clerc/utils";
44

5+
import type { TranslateFn } from "./types";
6+
57
const { stringify } = JSON;
68

79
interface ParsedParameter {
@@ -10,15 +12,15 @@ interface ParsedParameter {
1012
spread: boolean
1113
}
1214

13-
export function parseParameters(parameters: string[]) {
15+
export function parseParameters(parameters: string[], t: TranslateFn) {
1416
const parsedParameters: ParsedParameter[] = [];
1517

1618
let hasOptional: string | undefined;
1719
let hasSpread: string | undefined;
1820

1921
for (const parameter of parameters) {
2022
if (hasSpread) {
21-
throw new Error(`Invalid parameter: Spread parameter ${stringify(hasSpread)} must be last`);
23+
throw new Error (t("core.spreadParameterMustBeLast", stringify(hasSpread)));
2224
}
2325

2426
const firstCharacter = parameter[0];
@@ -29,7 +31,7 @@ export function parseParameters(parameters: string[]) {
2931
required = true;
3032

3133
if (hasOptional) {
32-
throw new Error(`Invalid parameter: Required parameter ${stringify(parameter)} cannot come after optional parameter ${stringify(hasOptional)}`);
34+
throw new Error(t("core.requiredParameterMustBeBeforeOptional", stringify(parameter), stringify(hasOptional)));
3335
}
3436
}
3537

@@ -39,7 +41,7 @@ export function parseParameters(parameters: string[]) {
3941
}
4042

4143
if (required === undefined) {
42-
throw new Error(`Invalid parameter: ${stringify(parameter)}. Must be wrapped in <> (required parameter) or [] (optional parameter)`);
44+
throw new Error(t("core.parameterMustBeWrappedInBrackets", stringify(parameter)));
4345
}
4446

4547
let name = parameter.slice(1, -1);
@@ -65,12 +67,13 @@ export function mapParametersToArguments(
6567
mapping: Record<string, string | string[]>,
6668
parameters: ParsedParameter[],
6769
cliArguments: string[],
70+
t: TranslateFn,
6871
) {
6972
for (let i = 0; i < parameters.length; i += 1) {
7073
const { name, required, spread } = parameters[i];
7174
const camelCaseName = camelCase(name);
7275
if (camelCaseName in mapping) {
73-
throw new Error(`Invalid parameter: ${stringify(name)} is used more than once.`);
76+
throw new Error(t("core.parameterIsUsedMoreThanOnce", stringify(name)));
7477
}
7578

7679
const value = spread ? cliArguments.slice(i) : cliArguments[i];
@@ -83,7 +86,7 @@ export function mapParametersToArguments(
8386
required
8487
&& (!value || (spread && value.length === 0))
8588
) {
86-
throw new Error(`Missing required parameter ${stringify(name)}`);
89+
throw new Error(t("core.missingRequiredParameter", stringify(name)));
8790
}
8891

8992
mapping[camelCaseName] = value;

0 commit comments

Comments
 (0)