@nocobase/cli 2.1.0-alpha.21 → 2.1.0-alpha.22

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.
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { spawn } from 'node:child_process';
10
10
  import { createServer } from 'node:http';
11
+ import { createCliTranslate, resolveCliLocale, resolveLocalizedText, } from "./cli-locale.js";
11
12
  import { isPromptBlockSkipped, runPromptFieldValidate, selectOptionValues, } from "./prompt-catalog.js";
12
13
  const DEFAULT_SUBMIT = '/__pwc_ui_submit';
13
14
  const DEFAULT_REFLOW = '/__pwc_ui_reflow';
@@ -19,6 +20,9 @@ export const PWC_FORM_META_STEP = '_pwcStep';
19
20
  export const PWC_FORM_META_FIELD = '_pwcField';
20
21
  const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
21
22
  const DEFAULT_HOST = '127.0.0.1';
23
+ function resolveUiText(text, locale, fallback = '') {
24
+ return resolveLocalizedText(text, { locale, fallback });
25
+ }
22
26
  function hasValueKey(iv, key) {
23
27
  return (Object.prototype.hasOwnProperty.call(iv, key) && iv[key] !== undefined && iv[key] !== null);
24
28
  }
@@ -171,6 +175,8 @@ function normalizeWebRawForBlock(def, raw, key) {
171
175
  * Runs per-field **`validate`** (including async) from the catalog (honoring {@link BuildWebPresetFromBodyOptions}).
172
176
  */
173
177
  export async function buildWebPresetFromBody(catalog, raw, userSeed = {}, buildOpts = {}) {
178
+ const locale = resolveCliLocale(buildOpts.locale);
179
+ const t = createCliTranslate(locale);
174
180
  const scope = buildOpts.scopeKeys ?? null;
175
181
  const inScope = (k) => scope === null || scope.has(k);
176
182
  const preset = {};
@@ -198,18 +204,18 @@ export async function buildWebPresetFromBody(catalog, raw, userSeed = {}, buildO
198
204
  val = defaultValueForInput(key, def, preset);
199
205
  }
200
206
  if (def.type === 'text' && def.required && val === '' && inScope(key)) {
201
- return { preset: {}, error: `Field "${key}" is required.`, fieldKey: key };
207
+ return { preset: {}, error: t('promptCatalog.web.fieldRequired', { key }), fieldKey: key };
202
208
  }
203
209
  if (def.type === 'password' && def.required && val === '' && inScope(key)) {
204
- return { preset: {}, error: `Field "${key}" is required.`, fieldKey: key };
210
+ return { preset: {}, error: t('promptCatalog.web.fieldRequired', { key }), fieldKey: key };
205
211
  }
206
212
  if (def.type === 'integer' && def.required && inScope(key)) {
207
- const t = String(raw[key] ?? '').trim();
208
- if (t === '') {
209
- return { preset: {}, error: `Field "${key}" is required.`, fieldKey: key };
213
+ const trimmed = String(raw[key] ?? '').trim();
214
+ if (trimmed === '') {
215
+ return { preset: {}, error: t('promptCatalog.web.fieldRequired', { key }), fieldKey: key };
210
216
  }
211
- if (!/^-?\d+$/.test(t)) {
212
- return { preset: {}, error: `Field "${key}" must be an integer.`, fieldKey: key };
217
+ if (!/^-?\d+$/.test(trimmed)) {
218
+ return { preset: {}, error: t('promptCatalog.web.fieldMustBeInteger', { key }), fieldKey: key };
213
219
  }
214
220
  }
215
221
  preset[key] = val;
@@ -229,7 +235,8 @@ function escapeHtml(s) {
229
235
  .replace(/"/g, '"')
230
236
  .replace(/'/g, ''');
231
237
  }
232
- function computePwcWizardSteps(options, merged) {
238
+ function computePwcWizardSteps(options, merged, locale) {
239
+ const t = createCliTranslate(locale);
233
240
  if (options.stages && options.stages.length > 0) {
234
241
  if (options.stages.length === 1) {
235
242
  const st0 = options.stages[0];
@@ -239,12 +246,12 @@ function computePwcWizardSteps(options, merged) {
239
246
  allKeys.push(key);
240
247
  }
241
248
  }
242
- const t = st0.sectionTitle?.trim();
243
- const d = st0.sectionDescription?.trim();
249
+ const title = resolveUiText(st0.sectionTitle, locale).trim();
250
+ const description = resolveUiText(st0.sectionDescription, locale).trim();
244
251
  return [
245
252
  {
246
- title: t && t.length > 0 ? t : 'Form',
247
- ...(d && d.length > 0 ? { description: d } : {}),
253
+ title: title && title.length > 0 ? title : t('promptCatalog.web.defaultFormTitle'),
254
+ ...(description && description.length > 0 ? { description } : {}),
248
255
  keys: allKeys,
249
256
  },
250
257
  ];
@@ -256,11 +263,11 @@ function computePwcWizardSteps(options, merged) {
256
263
  keys.push(key);
257
264
  }
258
265
  }
259
- const t = st.sectionTitle?.trim();
260
- const d = st.sectionDescription?.trim();
266
+ const title = resolveUiText(st.sectionTitle, locale).trim();
267
+ const description = resolveUiText(st.sectionDescription, locale).trim();
261
268
  return {
262
- title: t && t.length > 0 ? t : `Step ${i + 1}`,
263
- ...(d && d.length > 0 ? { description: d } : {}),
269
+ title: title && title.length > 0 ? title : t('promptCatalog.web.defaultStepTitle', { index: i + 1 }),
270
+ ...(description && description.length > 0 ? { description } : {}),
264
271
  keys,
265
272
  };
266
273
  });
@@ -275,18 +282,22 @@ function computePwcWizardSteps(options, merged) {
275
282
  return [];
276
283
  }
277
284
  /* Single `catalog` (no `stages`): one page, no side Steps nav — use `stages` for multi-page UI. */
278
- return [{ title: 'Form', keys: allKeys }];
285
+ return [{ title: t('promptCatalog.web.defaultFormTitle'), keys: allKeys }];
279
286
  }
280
287
  /** antd Form.Item-style explain line (per-field error / help). */
281
288
  const PWC_FORM_ITEM_EXPLAIN = '<div class="pwc-form-item-explain" data-pwc-explain="1" role="alert" hidden></div>';
282
289
  /** Suffix slot for status icon (e.g. fail) — filled by client script. */
283
290
  const PWC_FORM_ITEM_SUFFIX = '<span class="pwc-form-item-suffix" data-pwc-suffix="1" aria-hidden="true"></span>';
284
- function renderPwcRadioOptions(key, def, defaults, hidden) {
291
+ function renderPwcRadioOptions(key, def, defaults, hidden, locale) {
285
292
  return def.options
286
293
  .map((o, index) => {
287
294
  const val = typeof o === 'string' ? o : o.value;
288
- const lab = typeof o === 'string' ? o : o.label ?? o.value;
289
- const hint = typeof o === 'string' ? '' : o.hint ? `<div class="pwc-radio-option-hint">${escapeHtml(o.hint)}</div>` : '';
295
+ const lab = typeof o === 'string' ? o : resolveUiText(o.label, locale, o.value);
296
+ const hint = typeof o === 'string'
297
+ ? ''
298
+ : o.hint
299
+ ? `<div class="pwc-radio-option-hint">${escapeHtml(resolveUiText(o.hint, locale))}</div>`
300
+ : '';
290
301
  const checked = String(defaults[key] ?? '') === val ? ' checked' : '';
291
302
  const required = def.required && index === 0 ? ' required' : '';
292
303
  const disabled = hidden ? ' disabled' : '';
@@ -300,18 +311,18 @@ function renderPwcRadioOptions(key, def, defaults, hidden) {
300
311
  })
301
312
  .join('');
302
313
  }
303
- function renderPwcFieldRow(key, def, defaults, show) {
314
+ function renderPwcFieldRow(key, def, defaults, show, locale) {
304
315
  if (!isInputBlock(def)) {
305
316
  return '';
306
317
  }
307
- const labelText = 'message' in def ? def.message : key;
318
+ const labelText = 'message' in def ? resolveUiText(def.message, locale, key) : key;
308
319
  const hidden = show[key] === false;
309
320
  const display = hidden ? 'none' : 'block';
310
321
  const itemOpen = (extraClass) => `<div class="pwc-form-item${extraClass ? ` ${extraClass}` : ''}" data-pwc-wrap="${escapeHtml(key)}" data-pwc-field="${escapeHtml(key)}" style="display:${display}">`;
311
322
  if (def.type === 'text') {
312
323
  const req = def.required ? ' required' : '';
313
324
  const disabled = hidden ? ' disabled' : '';
314
- const ph = def.placeholder ? ` placeholder="${escapeHtml(def.placeholder)}"` : '';
325
+ const ph = def.placeholder ? ` placeholder="${escapeHtml(resolveUiText(def.placeholder, locale))}"` : '';
315
326
  const v = escapeHtml(String(defaults[key] ?? ''));
316
327
  return (itemOpen('') +
317
328
  `<div class="pwc-form-item-label"><span class="pwc-l">${escapeHtml(labelText)}</span></div>` +
@@ -334,7 +345,7 @@ function renderPwcFieldRow(key, def, defaults, show) {
334
345
  }
335
346
  if (def.type === 'select') {
336
347
  if (def.variant === 'radio') {
337
- const opts = renderPwcRadioOptions(key, def, defaults, hidden);
348
+ const opts = renderPwcRadioOptions(key, def, defaults, hidden, locale);
338
349
  return (itemOpen('') +
339
350
  `<div class="pwc-form-item-label"><span class="pwc-l">${escapeHtml(labelText)}</span></div>` +
340
351
  `<div class="pwc-form-item-control">` +
@@ -348,7 +359,7 @@ function renderPwcFieldRow(key, def, defaults, show) {
348
359
  const opts = def.options
349
360
  .map((o) => {
350
361
  const val = typeof o === 'string' ? o : o.value;
351
- const lab = typeof o === 'string' ? o : o.label ?? o.value;
362
+ const lab = typeof o === 'string' ? o : resolveUiText(o.label, locale, o.value);
352
363
  const sel = String(defaults[key] ?? '') === val ? ' selected' : '';
353
364
  return `<option value="${escapeHtml(String(val))}"${sel}>${escapeHtml(String(lab))}</option>`;
354
365
  })
@@ -382,7 +393,7 @@ function renderPwcFieldRow(key, def, defaults, show) {
382
393
  `</div></div>`);
383
394
  }
384
395
  if (def.type === 'integer') {
385
- const ph = def.placeholder ? ` placeholder="${escapeHtml(def.placeholder)}"` : '';
396
+ const ph = def.placeholder ? ` placeholder="${escapeHtml(resolveUiText(def.placeholder, locale))}"` : '';
386
397
  const req = def.required ? ' required' : '';
387
398
  const disabled = hidden ? ' disabled' : '';
388
399
  const v = String(defaults[key] ?? 0);
@@ -412,7 +423,7 @@ const PWC_FORM_FAIL_ICON_SVG = `<svg class="pwc-form-fail__svg" viewBox="0 0 14
412
423
  * with CSS aligned to antd tokens (icon 32px, 14px title, `colorSplit` rail, `wait` / `process` / `finish`).
413
424
  * Primary in steps uses antd default blue in light / `#1668dc` in dark; form primary buttons still use the page accent.
414
425
  */
415
- function buildPwcAntdStyleStepsHeader(stepDefs, currentIndex, total, visibleStepIndices) {
426
+ function buildPwcAntdStyleStepsHeader(stepDefs, currentIndex, total, visibleStepIndices, uiText) {
416
427
  const parts = [];
417
428
  for (let i = 0; i < total; i += 1) {
418
429
  const st = i < stepDefs.length ? stepDefs[i] : { title: `Step ${i + 1}`, keys: [] };
@@ -427,7 +438,7 @@ function buildPwcAntdStyleStepsHeader(stepDefs, currentIndex, total, visibleStep
427
438
  const num = visiblePos + 1;
428
439
  const hiddenAttr = visiblePos === -1 ? ' hidden' : '';
429
440
  const iconHtml = state === 'finish'
430
- ? `<span class="pwc-ad-icon pwc-ad-icon--finish" aria-label="done">${PWC_AD_CHECK_SVG}</span>`
441
+ ? `<span class="pwc-ad-icon pwc-ad-icon--finish" aria-label="${escapeHtml(uiText.doneAriaLabel)}">${PWC_AD_CHECK_SVG}</span>`
431
442
  : `<span class="pwc-ad-icon" aria-label="${num}"><span class="pwc-ad-icon-num">${num}</span></span>`;
432
443
  const ariaCurrent = state === 'process' ? 'step' : 'false';
433
444
  const nextVisible = visibleStepIndices.indexOf(i + 1) !== -1;
@@ -447,7 +458,7 @@ function buildPwcAntdStyleStepsHeader(stepDefs, currentIndex, total, visibleStep
447
458
  `</div>` +
448
459
  `</div></li>`);
449
460
  }
450
- return (`<nav class="pwc-ad-steps pwc-ad-steps--vertical" id="pwcAntSteps" aria-label="Form steps" style="--pwc-ad-n:${total}">` +
461
+ return (`<nav class="pwc-ad-steps pwc-ad-steps--vertical" id="pwcAntSteps" aria-label="${escapeHtml(uiText.stepsAriaLabel)}" style="--pwc-ad-n:${total}">` +
451
462
  `<ol class="pwc-ad-steps-list pwc-ad-steps-list--vertical">${parts.join('')}</ol></nav>`);
452
463
  }
453
464
  function computeInitialVisibleStepIndices(catalog, stepDefs, show) {
@@ -467,7 +478,7 @@ function computeInitialVisibleStepIndices(catalog, stepDefs, show) {
467
478
  }
468
479
  return visible.length > 0 ? visible : [0];
469
480
  }
470
- function buildPwcFormHtml(catalog, defaults, show, stepDefs, initialStepIndex, totalSteps) {
481
+ function buildPwcFormHtml(catalog, defaults, show, stepDefs, initialStepIndex, totalSteps, locale, uiText) {
471
482
  if (stepDefs.length === 0) {
472
483
  return '';
473
484
  }
@@ -476,8 +487,8 @@ function buildPwcFormHtml(catalog, defaults, show, stepDefs, initialStepIndex, t
476
487
  const out = [];
477
488
  if (!oneStep) {
478
489
  out.push('<div class="pwc-wizard pwc-wizard--with-sidebar" id="pwcWizard">');
479
- out.push('<aside class="pwc-wizard-sidenav" id="pwcWizardSidenav" aria-label="Steps">');
480
- out.push(buildPwcAntdStyleStepsHeader(stepDefs, initialStepIndex, totalSteps, visibleStepIndices));
490
+ out.push(`<aside class="pwc-wizard-sidenav" id="pwcWizardSidenav" aria-label="${escapeHtml(uiText.stepsSidebarAriaLabel)}">`);
491
+ out.push(buildPwcAntdStyleStepsHeader(stepDefs, initialStepIndex, totalSteps, visibleStepIndices, uiText));
481
492
  out.push('</aside><div class="pwc-wizard-main">');
482
493
  }
483
494
  else {
@@ -494,23 +505,23 @@ function buildPwcFormHtml(catalog, defaults, show, stepDefs, initialStepIndex, t
494
505
  for (const key of sd.keys) {
495
506
  const def = catalog[key];
496
507
  if (def) {
497
- out.push(renderPwcFieldRow(key, def, defaults, show));
508
+ out.push(renderPwcFieldRow(key, def, defaults, show, locale));
498
509
  }
499
510
  }
500
511
  out.push('</section>');
501
512
  }
502
513
  if (!oneStep) {
503
- out.push(`<div class="pwc-wizard-ctl" id="pwcWizardCtl" role="group" aria-label="Step navigation and submit">` +
504
- `<button type="button" class="pwc-btn-pager" id="pwcBack" ${initialStepIndex === 0 ? 'hidden' : ''}>Back</button>` +
514
+ out.push(`<div class="pwc-wizard-ctl" id="pwcWizardCtl" role="group" aria-label="${escapeHtml(uiText.stepNavigationAriaLabel)}">` +
515
+ `<button type="button" class="pwc-btn-pager" id="pwcBack" ${initialStepIndex === 0 ? 'hidden' : ''}>${escapeHtml(uiText.back)}</button>` +
505
516
  `<div class="pwc-wizard-ctl-spacer" aria-hidden="true"></div>` +
506
- `<button type="button" class="pwc-btn-pager pwc-btn-pager--primary" id="pwcNext" ${initialStepIndex >= totalSteps - 1 ? 'hidden' : ''}>Next</button>` +
507
- `<button type="submit" class="pwc-btn-submit pwc-wizard-ctl__submit" id="pwcFormSubmit" ${initialStepIndex < totalSteps - 1 ? 'hidden' : ''}>Submit &amp; continue in terminal</button>` +
517
+ `<button type="button" class="pwc-btn-pager pwc-btn-pager--primary" id="pwcNext" ${initialStepIndex >= totalSteps - 1 ? 'hidden' : ''}>${escapeHtml(uiText.next)}</button>` +
518
+ `<button type="submit" class="pwc-btn-submit pwc-wizard-ctl__submit" id="pwcFormSubmit" ${initialStepIndex < totalSteps - 1 ? 'hidden' : ''}>${escapeHtml(uiText.submit)}</button>` +
508
519
  `</div>`);
509
520
  }
510
521
  else {
511
- out.push(`<div class="pwc-wizard-ctl" id="pwcWizardCtl" role="group" aria-label="Submit">` +
522
+ out.push(`<div class="pwc-wizard-ctl" id="pwcWizardCtl" role="group" aria-label="${escapeHtml(uiText.submitAriaLabel)}">` +
512
523
  `<div class="pwc-wizard-ctl-spacer" aria-hidden="true"></div>` +
513
- `<button type="submit" class="pwc-btn-submit pwc-wizard-ctl__submit" id="pwcFormSubmit">Submit &amp; continue in terminal</button>` +
524
+ `<button type="submit" class="pwc-btn-submit pwc-wizard-ctl__submit" id="pwcFormSubmit">${escapeHtml(uiText.submit)}</button>` +
514
525
  `</div>`);
515
526
  }
516
527
  /* Status / error Alert: under main form column only, not full-width under the side Steps. */
@@ -565,7 +576,7 @@ export function mergeWebUICatalogsFromStages(stages) {
565
576
  const sectionBeforeKey = new Map();
566
577
  const used = new Set();
567
578
  for (const stage of stages) {
568
- const title = stage.sectionTitle?.trim();
579
+ const title = typeof stage.sectionTitle === 'string' ? stage.sectionTitle.trim() : '';
569
580
  let needTitle = Boolean(title);
570
581
  for (const [key, def] of Object.entries(stage.catalog)) {
571
582
  if (isInputBlock(def) && needTitle && title) {
@@ -652,6 +663,8 @@ export function runPromptCatalogWebUI(catalogOrOptions, options) {
652
663
  return runPromptCatalogWebUIImpl({ catalog: catalogOrOptions });
653
664
  }
654
665
  function runPromptCatalogWebUIImpl(options) {
666
+ const locale = resolveCliLocale(options.locale);
667
+ const t = createCliTranslate(locale);
655
668
  const { merged } = resolveMergedCatalog(options);
656
669
  const userSeed = mergeValueSeedsFromOptions(options);
657
670
  const formDefaults = buildWebFormValuesFromCatalog(merged, userSeed);
@@ -660,15 +673,34 @@ function runPromptCatalogWebUIImpl(options) {
660
673
  const reflowPath = options.reflowPath ?? DEFAULT_REFLOW;
661
674
  const host = options.host ?? DEFAULT_HOST;
662
675
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
663
- const pageTitle = options.pageTitle ?? 'Prompt catalog (local UI)';
664
- const h1 = options.documentHeading ?? 'Configure parameters (localhost only)';
665
- const documentHint = options.documentHint ??
666
- 'This server is only bound to the loopback interface. After submit, the CLI continues in the same terminal session.';
676
+ const pageTitle = resolveUiText(options.pageTitle, locale, t('promptCatalog.web.pageTitle'));
677
+ const h1 = resolveUiText(options.documentHeading, locale, t('promptCatalog.web.documentHeading'));
678
+ const documentHint = resolveUiText(options.documentHint, locale, t('promptCatalog.web.documentHint'));
667
679
  const catalog = merged;
668
- const pwcStepDefs = computePwcWizardSteps(options, catalog);
680
+ const pwcStepDefs = computePwcWizardSteps(options, catalog, locale);
669
681
  const pwcNSteps = Math.max(1, pwcStepDefs.length);
670
682
  const resolveValidateStepPath = options.validateStepPath ?? DEFAULT_VALIDATE_STEP;
671
683
  const resolveValidateFieldPath = options.validateFieldPath ?? DEFAULT_VALIDATE_FIELD;
684
+ const uiText = {
685
+ stepsAriaLabel: t('promptCatalog.web.stepsAriaLabel'),
686
+ stepsSidebarAriaLabel: t('promptCatalog.web.stepsSidebarAriaLabel'),
687
+ stepNavigationAriaLabel: t('promptCatalog.web.stepNavigationAriaLabel'),
688
+ submitAriaLabel: t('promptCatalog.web.submitAriaLabel'),
689
+ back: t('promptCatalog.web.back'),
690
+ next: t('promptCatalog.web.next'),
691
+ submit: t('promptCatalog.web.submit'),
692
+ checking: t('promptCatalog.web.checking'),
693
+ sending: t('promptCatalog.web.sending'),
694
+ successTitle: t('promptCatalog.web.successTitle'),
695
+ errorTitle: t('promptCatalog.web.errorTitle'),
696
+ savedAndClosing: t('promptCatalog.web.savedAndClosing'),
697
+ savedCloseBlocked: t('promptCatalog.web.savedCloseBlocked'),
698
+ invalidValue: t('promptCatalog.web.invalidValue'),
699
+ invalidRequest: t('promptCatalog.web.invalidRequest'),
700
+ invalidStep: t('promptCatalog.web.invalidStep'),
701
+ invalidField: t('promptCatalog.web.invalidField'),
702
+ doneAriaLabel: 'done',
703
+ };
672
704
  let server;
673
705
  let timeoutId;
674
706
  return new Promise((resolve, reject) => {
@@ -686,15 +718,16 @@ function runPromptCatalogWebUIImpl(options) {
686
718
  };
687
719
  const servePage = (port) => {
688
720
  const base = `http://${host}:${port}`;
689
- const formInner = buildPwcFormHtml(catalog, formDefaults, initialShow, pwcStepDefs, 0, pwcNSteps);
721
+ const formInner = buildPwcFormHtml(catalog, formDefaults, initialShow, pwcStepDefs, 0, pwcNSteps, locale, uiText);
690
722
  const wizardClientJson = JSON.stringify({ n: pwcNSteps, stepDefs: pwcStepDefs });
691
723
  const pwcValStepUrl = pwcNSteps > 1 ? JSON.stringify(base + resolveValidateStepPath) : 'null';
692
724
  const pwcValFieldUrl = JSON.stringify(base + resolveValidateFieldPath);
725
+ const uiTextJson = JSON.stringify(uiText);
693
726
  const pwcShellClass = options.stages && options.stages.length > 0
694
727
  ? 'pwc-shell pwc-shell--stages'
695
728
  : 'pwc-shell';
696
729
  const page = `<!doctype html>
697
- <html lang="en">
730
+ <html lang="${escapeHtml(locale)}">
698
731
  <head>
699
732
  <meta charset="utf-8" />
700
733
  <meta name="viewport" content="width=device-width, initial-scale=1" />
@@ -1328,6 +1361,7 @@ function runPromptCatalogWebUIImpl(options) {
1328
1361
  var pwcFieldMeta = ${JSON.stringify(PWC_FORM_META_FIELD)};
1329
1362
  var s = document.getElementById('pwcStatus');
1330
1363
  var wcfg = ${wizardClientJson};
1364
+ var uiText = ${uiTextJson};
1331
1365
  var pwcN = wcfg && typeof wcfg.n === 'number' ? wcfg.n : 1;
1332
1366
  var pwcSteps = (wcfg && wcfg.stepDefs) || [];
1333
1367
  var pwcCur = 0;
@@ -1367,7 +1401,7 @@ function runPromptCatalogWebUIImpl(options) {
1367
1401
  s.setAttribute('role', 'alert');
1368
1402
  s.innerHTML =
1369
1403
  '<span class="pwc-ad-alert__icon" aria-hidden="true">' + pwcErrIcon + '</span>' +
1370
- '<div class="pwc-ad-alert__inner"><div class="pwc-ad-alert__title">Error</div>' +
1404
+ '<div class="pwc-ad-alert__inner"><div class="pwc-ad-alert__title">' + pwcEsc(uiText.errorTitle) + '</div>' +
1371
1405
  '<div class="pwc-ad-alert__desc">' + pwcEsc(t) + '</div></div>';
1372
1406
  }
1373
1407
  function pwcSetStatusSuccess(message) {
@@ -1377,7 +1411,7 @@ function runPromptCatalogWebUIImpl(options) {
1377
1411
  s.setAttribute('role', 'status');
1378
1412
  s.innerHTML =
1379
1413
  '<span class="pwc-ad-alert__icon" aria-hidden="true">' + pwcOkIcon + '</span>' +
1380
- '<div class="pwc-ad-alert__inner"><div class="pwc-ad-alert__title">Success</div>' +
1414
+ '<div class="pwc-ad-alert__inner"><div class="pwc-ad-alert__title">' + pwcEsc(uiText.successTitle) + '</div>' +
1381
1415
  '<div class="pwc-ad-alert__desc">' + pwcEsc(t) + '</div></div>';
1382
1416
  }
1383
1417
  function pwcScheduleWindowClose() {
@@ -1387,9 +1421,9 @@ function runPromptCatalogWebUIImpl(options) {
1387
1421
  window.close();
1388
1422
  pwcCloseProbeTimer = setTimeout(function () {
1389
1423
  if (!s || document.visibilityState !== 'visible') { return; }
1390
- pwcSetStatusSuccess('Saved. Automatic close was blocked by the browser. You can close this tab now.');
1424
+ pwcSetStatusSuccess(uiText.savedCloseBlocked);
1391
1425
  }, 600);
1392
- }, 2000);
1426
+ }, 5000);
1393
1427
  }
1394
1428
  function pwcSetFieldError(key, message) {
1395
1429
  if (!form || !key) { return; }
@@ -1701,8 +1735,8 @@ function runPromptCatalogWebUIImpl(options) {
1701
1735
  var inp = getControl(form, k);
1702
1736
  if (inp == null) { continue; }
1703
1737
  if (typeof inp.checkValidity === 'function' && !inp.checkValidity()) {
1704
- var vm = (typeof inp.validationMessage === 'string' && inp.validationMessage) ? inp.validationMessage : 'Invalid value';
1705
- pwcSetFieldError(k, vm);
1738
+ var vm = (typeof inp.validationMessage === 'string' && inp.validationMessage) ? inp.validationMessage : uiText.invalidValue;
1739
+ pwcSetFieldError(k, vm);
1706
1740
  if (typeof inp.focus === 'function') { inp.focus(); }
1707
1741
  return false;
1708
1742
  }
@@ -1760,7 +1794,7 @@ function runPromptCatalogWebUIImpl(options) {
1760
1794
  if (pwcValStep == null) {
1761
1795
  return reflow().then(function () { pwcSetStep(pwcVisibleNext(pwcCur)); });
1762
1796
  }
1763
- pwcSetStatusHint('Checking…');
1797
+ pwcSetStatusHint(uiText.checking);
1764
1798
  return fetch(pwcValStep, {
1765
1799
  method: 'POST',
1766
1800
  headers: { 'Content-Type': 'application/json' },
@@ -1828,7 +1862,7 @@ function runPromptCatalogWebUIImpl(options) {
1828
1862
  form.addEventListener('submit', function (e) {
1829
1863
  e.preventDefault();
1830
1864
  if (pwcN > 1 && pwcVisibleStepPosition(pwcCur) < pwcVisibleSteps.length - 1) { return; }
1831
- pwcSetStatusHint('Sending…');
1865
+ pwcSetStatusHint(uiText.sending);
1832
1866
  pwcClearAllFieldErrors();
1833
1867
  fetch(sub, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(collect()) })
1834
1868
  .then(function (r) {
@@ -1843,7 +1877,7 @@ function runPromptCatalogWebUIImpl(options) {
1843
1877
  return r.json();
1844
1878
  })
1845
1879
  .then(function () {
1846
- pwcSetStatusSuccess('Saved. This tab will close automatically in 2 seconds.');
1880
+ pwcSetStatusSuccess(uiText.savedAndClosing);
1847
1881
  pwcScheduleWindowClose();
1848
1882
  })
1849
1883
  .catch(function (err) {
@@ -1913,10 +1947,10 @@ function runPromptCatalogWebUIImpl(options) {
1913
1947
  : NaN;
1914
1948
  if (!Number.isInteger(step) || step < 0 || step >= pwcStepDefs.length) {
1915
1949
  res.writeHead(400, { 'Content-Type': 'application/json' });
1916
- res.end(JSON.stringify({ ok: false, error: 'Invalid or missing wizard step.' }));
1950
+ res.end(JSON.stringify({ ok: false, error: t('promptCatalog.web.invalidStep') }));
1917
1951
  return;
1918
1952
  }
1919
- const { error, fieldKey } = await buildWebPresetFromBody(catalog, readFormFromClient(readFormFromClientStrippingPwcMeta(raw)), userSeed, { scopeKeys: new Set(pwcStepDefs[step].keys) });
1953
+ const { error, fieldKey } = await buildWebPresetFromBody(catalog, readFormFromClient(readFormFromClientStrippingPwcMeta(raw)), userSeed, { scopeKeys: new Set(pwcStepDefs[step].keys), locale });
1920
1954
  if (error) {
1921
1955
  res.writeHead(400, { 'Content-Type': 'application/json' });
1922
1956
  res.end(JSON.stringify(fieldKey ? { ok: false, error, fieldKey } : { ok: false, error }));
@@ -1927,7 +1961,7 @@ function runPromptCatalogWebUIImpl(options) {
1927
1961
  }
1928
1962
  catch {
1929
1963
  res.writeHead(400, { 'Content-Type': 'application/json' });
1930
- res.end(JSON.stringify({ ok: false, error: 'Invalid request' }));
1964
+ res.end(JSON.stringify({ ok: false, error: t('promptCatalog.web.invalidRequest') }));
1931
1965
  }
1932
1966
  })();
1933
1967
  });
@@ -1946,10 +1980,10 @@ function runPromptCatalogWebUIImpl(options) {
1946
1980
  : '';
1947
1981
  if (!fieldKey || !Object.prototype.hasOwnProperty.call(catalog, fieldKey)) {
1948
1982
  res.writeHead(400, { 'Content-Type': 'application/json' });
1949
- res.end(JSON.stringify({ ok: false, error: 'Invalid or missing field key.' }));
1983
+ res.end(JSON.stringify({ ok: false, error: t('promptCatalog.web.invalidField') }));
1950
1984
  return;
1951
1985
  }
1952
- const { error } = await buildWebPresetFromBody(catalog, readFormFromClient(readFormFromClientStrippingPwcMeta(raw)), userSeed, { scopeKeys: new Set([fieldKey]) });
1986
+ const { error } = await buildWebPresetFromBody(catalog, readFormFromClient(readFormFromClientStrippingPwcMeta(raw)), userSeed, { scopeKeys: new Set([fieldKey]), locale });
1953
1987
  if (error) {
1954
1988
  res.writeHead(400, { 'Content-Type': 'application/json' });
1955
1989
  res.end(JSON.stringify({ ok: false, error, fieldKey }));
@@ -1960,7 +1994,7 @@ function runPromptCatalogWebUIImpl(options) {
1960
1994
  }
1961
1995
  catch {
1962
1996
  res.writeHead(400, { 'Content-Type': 'application/json' });
1963
- res.end(JSON.stringify({ ok: false, error: 'Invalid request' }));
1997
+ res.end(JSON.stringify({ ok: false, error: t('promptCatalog.web.invalidRequest') }));
1964
1998
  }
1965
1999
  })();
1966
2000
  });
@@ -1973,7 +2007,7 @@ function runPromptCatalogWebUIImpl(options) {
1973
2007
  void (async () => {
1974
2008
  try {
1975
2009
  const raw = JSON.parse(Buffer.concat(chunks).toString('utf8'));
1976
- const { preset, error, fieldKey } = await buildWebPresetFromBody(catalog, readFormFromClient(raw), userSeed);
2010
+ const { preset, error, fieldKey } = await buildWebPresetFromBody(catalog, readFormFromClient(raw), userSeed, { locale });
1977
2011
  if (error) {
1978
2012
  res.writeHead(400, { 'Content-Type': 'application/json' });
1979
2013
  res.end(JSON.stringify(fieldKey ? { ok: false, error, fieldKey } : { ok: false, error }));
@@ -1994,7 +2028,7 @@ function runPromptCatalogWebUIImpl(options) {
1994
2028
  }
1995
2029
  catch (e) {
1996
2030
  res.writeHead(400, { 'Content-Type': 'text/plain' });
1997
- res.end('Invalid request');
2031
+ res.end(t('promptCatalog.web.invalidRequest'));
1998
2032
  }
1999
2033
  })();
2000
2034
  });
@@ -1,3 +1,11 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
1
9
  import { createHash } from 'node:crypto';
2
10
  import { loadBuildConfig } from './build-config.js';
3
11
  import { toKebabCase, toLogicalActionName, toLogicalResourceName, toResourceSegments } from './naming.js';
@@ -171,7 +179,10 @@ function formatFlagExample(parameter) {
171
179
  if (parameter.type === 'boolean') {
172
180
  return `--${parameter.flagName}`;
173
181
  }
174
- if (parameter.type === 'object') {
182
+ if (parameter.type === 'object' || parameter.jsonEncoded) {
183
+ if (parameter.type === 'array' || parameter.isArray) {
184
+ return `--${parameter.flagName} '[]'`;
185
+ }
175
186
  return `--${parameter.flagName} '{\"key\":\"value\"}'`;
176
187
  }
177
188
  if (parameter.isArray) {