@form-engine-ts/react 5.0.1 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +67 -15
- package/dist/index.d.cts +56 -4
- package/dist/index.d.ts +56 -4
- package/dist/index.js +67 -15
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -3325,7 +3325,7 @@ function asAsyncAdapter(adapter) {
|
|
|
3325
3325
|
)
|
|
3326
3326
|
};
|
|
3327
3327
|
}
|
|
3328
|
-
var validateLocalePipeline = (locale, schema, policy, customValidator) => {
|
|
3328
|
+
var validateLocalePipeline = (locale, schema, policy, customValidator, availableLocales) => {
|
|
3329
3329
|
const canonicalLocale = (0, import_core5.normalizeLocale)(locale);
|
|
3330
3330
|
if (canonicalLocale === null) {
|
|
3331
3331
|
return {
|
|
@@ -3338,6 +3338,18 @@ var validateLocalePipeline = (locale, schema, policy, customValidator) => {
|
|
|
3338
3338
|
}
|
|
3339
3339
|
const currentLocales = (schema.supportedLocales ?? []).map((candidate) => (0, import_core5.normalizeLocale)(candidate) ?? candidate);
|
|
3340
3340
|
const defaultLocale = schema.defaultLocale === void 0 ? "" : (0, import_core5.normalizeLocale)(schema.defaultLocale) ?? schema.defaultLocale;
|
|
3341
|
+
if (availableLocales !== void 0 && !availableLocales.some((candidate) => {
|
|
3342
|
+
const value = typeof candidate === "string" ? candidate : candidate.locale;
|
|
3343
|
+
return (0, import_core5.normalizeLocale)(value) === canonicalLocale;
|
|
3344
|
+
})) {
|
|
3345
|
+
return {
|
|
3346
|
+
valid: false,
|
|
3347
|
+
error: {
|
|
3348
|
+
type: "locale_not_allowed",
|
|
3349
|
+
message: `Locale "${canonicalLocale}" is not available in the locale catalog.`
|
|
3350
|
+
}
|
|
3351
|
+
};
|
|
3352
|
+
}
|
|
3341
3353
|
if (canonicalLocale === defaultLocale || currentLocales.includes(canonicalLocale)) {
|
|
3342
3354
|
return {
|
|
3343
3355
|
valid: false,
|
|
@@ -3478,11 +3490,15 @@ function useTranslationWorkspace({
|
|
|
3478
3490
|
translationAdapter,
|
|
3479
3491
|
readOnly = false,
|
|
3480
3492
|
policy,
|
|
3493
|
+
availableLocales,
|
|
3494
|
+
onLocaleAdded,
|
|
3495
|
+
onLocaleRemoved,
|
|
3496
|
+
onLocaleChange,
|
|
3481
3497
|
beforeRemoveLocale,
|
|
3482
3498
|
validateLocale
|
|
3483
3499
|
}) {
|
|
3484
3500
|
const [draftSchema, setDraftSchema] = (0, import_react5.useState)(schema);
|
|
3485
|
-
const [selectedLocale, setSelectedLocale] = (0, import_react5.useState)(targetLocale ?? "");
|
|
3501
|
+
const [selectedLocale, setSelectedLocale] = (0, import_react5.useState)((0, import_core5.normalizeLocale)(targetLocale ?? "") ?? targetLocale ?? "");
|
|
3486
3502
|
const [isTranslating, setIsTranslating] = (0, import_react5.useState)(false);
|
|
3487
3503
|
const [error, setError] = (0, import_react5.useState)();
|
|
3488
3504
|
const currentSchema = onChange === void 0 ? draftSchema : schema;
|
|
@@ -3493,6 +3509,15 @@ function useTranslationWorkspace({
|
|
|
3493
3509
|
);
|
|
3494
3510
|
}, [currentSchema, sourceLocale]);
|
|
3495
3511
|
const activeLocale = selectedLocale.length > 0 ? selectedLocale : targetLocales[0] ?? "";
|
|
3512
|
+
const localeOptions = (0, import_react5.useMemo)(() => {
|
|
3513
|
+
if (availableLocales === void 0) {
|
|
3514
|
+
return targetLocales.map((locale) => ({ locale, label: locale }));
|
|
3515
|
+
}
|
|
3516
|
+
return availableLocales.map((candidate) => {
|
|
3517
|
+
if (typeof candidate !== "string") return candidate;
|
|
3518
|
+
return { locale: (0, import_core5.normalizeLocale)(candidate) ?? candidate, label: candidate };
|
|
3519
|
+
});
|
|
3520
|
+
}, [availableLocales, targetLocales]);
|
|
3496
3521
|
const slots = (0, import_react5.useMemo)(
|
|
3497
3522
|
() => activeLocale.length === 0 ? [] : (0, import_core5.collectTranslationSlots)(currentSchema, activeLocale),
|
|
3498
3523
|
[activeLocale, currentSchema]
|
|
@@ -3540,14 +3565,14 @@ function useTranslationWorkspace({
|
|
|
3540
3565
|
const normalized = (0, import_core5.normalizeLocale)(locale);
|
|
3541
3566
|
if (normalized === null) {
|
|
3542
3567
|
const workspaceError = workspaceLocaleValidationError(
|
|
3543
|
-
validateLocalePipeline(locale, currentSchema, policy, validateLocale),
|
|
3568
|
+
validateLocalePipeline(locale, currentSchema, policy, validateLocale, availableLocales),
|
|
3544
3569
|
(0, import_core5.collectSchemaLocales)(currentSchema).allUniqueLocales.size,
|
|
3545
3570
|
locale
|
|
3546
3571
|
);
|
|
3547
3572
|
setError(workspaceError);
|
|
3548
3573
|
return { success: false, error: workspaceError };
|
|
3549
3574
|
}
|
|
3550
|
-
const validation = validateLocalePipeline(normalized, currentSchema, policy, validateLocale);
|
|
3575
|
+
const validation = validateLocalePipeline(normalized, currentSchema, policy, validateLocale, availableLocales);
|
|
3551
3576
|
if (!validation.valid) {
|
|
3552
3577
|
const workspaceError = workspaceLocaleValidationError(
|
|
3553
3578
|
validation,
|
|
@@ -3563,33 +3588,38 @@ function useTranslationWorkspace({
|
|
|
3563
3588
|
supportedLocales: [.../* @__PURE__ */ new Set([...currentSchema.supportedLocales ?? [], normalized])]
|
|
3564
3589
|
});
|
|
3565
3590
|
setSelectedLocale(normalized);
|
|
3591
|
+
onLocaleAdded?.(normalized);
|
|
3566
3592
|
return { success: true };
|
|
3567
3593
|
},
|
|
3568
|
-
[commit, currentSchema, policy, readOnly, validateLocale]
|
|
3594
|
+
[availableLocales, commit, currentSchema, onLocaleAdded, policy, readOnly, validateLocale]
|
|
3569
3595
|
);
|
|
3570
3596
|
const isAddLocaleAllowed = (0, import_react5.useCallback)(
|
|
3571
3597
|
(locale) => {
|
|
3572
3598
|
if (readOnly) return false;
|
|
3573
3599
|
const normalized = (0, import_core5.normalizeLocale)(locale);
|
|
3574
3600
|
if (normalized === null) return false;
|
|
3575
|
-
return validateLocalePipeline(normalized, currentSchema, policy, validateLocale).valid;
|
|
3601
|
+
return validateLocalePipeline(normalized, currentSchema, policy, validateLocale, availableLocales).valid;
|
|
3576
3602
|
},
|
|
3577
|
-
[currentSchema, policy, readOnly, validateLocale]
|
|
3603
|
+
[availableLocales, currentSchema, policy, readOnly, validateLocale]
|
|
3578
3604
|
);
|
|
3579
3605
|
const removeLocale = (0, import_react5.useCallback)(
|
|
3580
3606
|
(locale) => {
|
|
3581
|
-
|
|
3607
|
+
const normalized = (0, import_core5.normalizeLocale)(locale) ?? locale;
|
|
3608
|
+
const normalizedSourceLocale = (0, import_core5.normalizeLocale)(sourceLocale) ?? sourceLocale;
|
|
3609
|
+
const normalizedDefaultLocale = currentSchema.defaultLocale === void 0 ? void 0 : (0, import_core5.normalizeLocale)(currentSchema.defaultLocale) ?? currentSchema.defaultLocale;
|
|
3610
|
+
if (readOnly || normalized === normalizedSourceLocale || normalized === normalizedDefaultLocale) return false;
|
|
3582
3611
|
const remove = () => {
|
|
3583
|
-
commit((0, import_core5.removeLocaleFromSchema)(currentSchema,
|
|
3584
|
-
if (activeLocale ===
|
|
3612
|
+
commit((0, import_core5.removeLocaleFromSchema)(currentSchema, normalized));
|
|
3613
|
+
if (activeLocale === normalized) setSelectedLocale("");
|
|
3614
|
+
onLocaleRemoved?.(normalized);
|
|
3585
3615
|
};
|
|
3586
|
-
const slotCount = (0, import_core5.collectTranslationSlots)(currentSchema,
|
|
3616
|
+
const slotCount = (0, import_core5.collectTranslationSlots)(currentSchema, normalized).length;
|
|
3587
3617
|
if (beforeRemoveLocale === void 0) {
|
|
3588
3618
|
remove();
|
|
3589
3619
|
return true;
|
|
3590
3620
|
}
|
|
3591
3621
|
try {
|
|
3592
|
-
const decision = beforeRemoveLocale(
|
|
3622
|
+
const decision = beforeRemoveLocale(normalized, { slotCount });
|
|
3593
3623
|
if (typeof decision === "boolean") {
|
|
3594
3624
|
if (!decision) return false;
|
|
3595
3625
|
remove();
|
|
@@ -3610,7 +3640,7 @@ function useTranslationWorkspace({
|
|
|
3610
3640
|
return Promise.reject(cause);
|
|
3611
3641
|
}
|
|
3612
3642
|
},
|
|
3613
|
-
[activeLocale, beforeRemoveLocale, commit, currentSchema, readOnly, sourceLocale]
|
|
3643
|
+
[activeLocale, beforeRemoveLocale, commit, currentSchema, onLocaleRemoved, readOnly, sourceLocale]
|
|
3614
3644
|
);
|
|
3615
3645
|
const translateAll = (0, import_react5.useCallback)(
|
|
3616
3646
|
async (options = {}) => {
|
|
@@ -3629,6 +3659,23 @@ function useTranslationWorkspace({
|
|
|
3629
3659
|
setError(workspaceError);
|
|
3630
3660
|
return { success: false, error: workspaceError };
|
|
3631
3661
|
}
|
|
3662
|
+
const selectedLocaleOption = localeOptions.find(
|
|
3663
|
+
(option) => ((0, import_core5.normalizeLocale)(option.locale) ?? option.locale) === activeLocale
|
|
3664
|
+
);
|
|
3665
|
+
if (selectedLocaleOption?.translatable === false) {
|
|
3666
|
+
setError(void 0);
|
|
3667
|
+
return {
|
|
3668
|
+
success: true,
|
|
3669
|
+
report: {
|
|
3670
|
+
updatedSlots: [],
|
|
3671
|
+
skippedSlots: slots,
|
|
3672
|
+
staleSlots: [],
|
|
3673
|
+
skippedReasons: Object.fromEntries(
|
|
3674
|
+
slots.map((slot) => [slot.path ?? `${slot.kind}.${slot.nodeId}.${slot.property}`, "unsupported"])
|
|
3675
|
+
)
|
|
3676
|
+
}
|
|
3677
|
+
};
|
|
3678
|
+
}
|
|
3632
3679
|
setIsTranslating(true);
|
|
3633
3680
|
setError(void 0);
|
|
3634
3681
|
try {
|
|
@@ -3656,7 +3703,7 @@ function useTranslationWorkspace({
|
|
|
3656
3703
|
setIsTranslating(false);
|
|
3657
3704
|
}
|
|
3658
3705
|
},
|
|
3659
|
-
[activeLocale, commit, currentSchema, readOnly, translationAdapter]
|
|
3706
|
+
[activeLocale, commit, currentSchema, localeOptions, readOnly, slots, translationAdapter]
|
|
3660
3707
|
);
|
|
3661
3708
|
const translateSlot = (0, import_react5.useCallback)(
|
|
3662
3709
|
async (slot) => {
|
|
@@ -3694,7 +3741,12 @@ function useTranslationWorkspace({
|
|
|
3694
3741
|
sourceLocale,
|
|
3695
3742
|
targetLocale: activeLocale,
|
|
3696
3743
|
targetLocales,
|
|
3697
|
-
|
|
3744
|
+
localeOptions,
|
|
3745
|
+
setTargetLocale: (locale) => {
|
|
3746
|
+
const normalized = (0, import_core5.normalizeLocale)(locale) ?? locale;
|
|
3747
|
+
setSelectedLocale(normalized);
|
|
3748
|
+
onLocaleChange?.(normalized);
|
|
3749
|
+
},
|
|
3698
3750
|
slots,
|
|
3699
3751
|
summary,
|
|
3700
3752
|
addLocale,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as _form_engine_ts_core from '@form-engine-ts/core';
|
|
2
|
+
import { QuestionType, FormField, ChoiceOption, FormPage, FormSchema, DisplayCondition, JsonValue, SchemaIssue, FormPolicy, Question, FieldOption, TranslationReport, ValidationIssue, ValidationError, FormValues, LocaleOption, TranslationAdapter, AsyncTranslationAdapter, PopulateTranslationOptions, FormValue, AnswerValidationResult, TranslationSlot, FormEngineTranslator, FormEngineMessages, FieldType } from '@form-engine-ts/core';
|
|
2
3
|
export { QuestionType } from '@form-engine-ts/core';
|
|
3
4
|
import * as react from 'react';
|
|
4
5
|
import { ReactNode, ComponentType, KeyboardEvent, MouseEvent, CSSProperties } from 'react';
|
|
@@ -379,6 +380,52 @@ interface BuilderLocalizationSlotProps extends BuilderSlotBaseProps {
|
|
|
379
380
|
readonly policy?: FormPolicy;
|
|
380
381
|
readonly translationAdapterAvailable?: boolean;
|
|
381
382
|
}
|
|
383
|
+
interface TranslationWorkspaceHeaderProps {
|
|
384
|
+
readonly schema: FormSchema;
|
|
385
|
+
readonly sourceLocale: string;
|
|
386
|
+
readonly targetLocale: string;
|
|
387
|
+
readonly summary: {
|
|
388
|
+
readonly totalSlots: number;
|
|
389
|
+
readonly translatedCount: number;
|
|
390
|
+
readonly missingCount: number;
|
|
391
|
+
readonly staleCount: number;
|
|
392
|
+
readonly manualCount: number;
|
|
393
|
+
readonly completionPercentage: number;
|
|
394
|
+
};
|
|
395
|
+
readonly onTranslateAll: () => void;
|
|
396
|
+
readonly isTranslating: boolean;
|
|
397
|
+
readonly readOnly: boolean;
|
|
398
|
+
}
|
|
399
|
+
interface TranslationSlotRowProps {
|
|
400
|
+
readonly slot: _form_engine_ts_core.TranslationSlot;
|
|
401
|
+
readonly readOnly: boolean;
|
|
402
|
+
readonly onChange: (text: string) => void;
|
|
403
|
+
readonly onTranslate: () => void;
|
|
404
|
+
}
|
|
405
|
+
interface LocaleSelectorProps {
|
|
406
|
+
readonly targetLocale: string;
|
|
407
|
+
readonly targetLocales: readonly string[];
|
|
408
|
+
readonly localeOptions: readonly LocaleOption[];
|
|
409
|
+
readonly newLocale: string;
|
|
410
|
+
readonly readOnly: boolean;
|
|
411
|
+
readonly onTargetLocaleChange: (locale: string) => void;
|
|
412
|
+
readonly onNewLocaleChange: (locale: string) => void;
|
|
413
|
+
readonly onAddLocale: () => void;
|
|
414
|
+
}
|
|
415
|
+
interface TranslationWorkspaceActionsProps {
|
|
416
|
+
readonly onTranslateAll: () => void;
|
|
417
|
+
readonly isTranslating: boolean;
|
|
418
|
+
readonly readOnly: boolean;
|
|
419
|
+
}
|
|
420
|
+
interface TranslationWorkspaceSlots {
|
|
421
|
+
readonly renderHeader?: (props: TranslationWorkspaceHeaderProps) => ReactNode;
|
|
422
|
+
readonly renderSlotRow?: (props: TranslationSlotRowProps) => ReactNode;
|
|
423
|
+
readonly renderLocaleSelector?: (props: LocaleSelectorProps) => ReactNode;
|
|
424
|
+
readonly renderStatusBadge?: (props: {
|
|
425
|
+
readonly status: _form_engine_ts_core.TranslationStatus;
|
|
426
|
+
}) => ReactNode;
|
|
427
|
+
readonly renderActions?: (props: TranslationWorkspaceActionsProps) => ReactNode;
|
|
428
|
+
}
|
|
382
429
|
interface LocalizationSummaryContext {
|
|
383
430
|
readonly defaultLocale: string;
|
|
384
431
|
readonly supportedLocales: readonly string[];
|
|
@@ -708,6 +755,10 @@ interface UseTranslationWorkspaceOptions {
|
|
|
708
755
|
readonly translationAdapter?: TranslationAdapter | AsyncTranslationAdapter;
|
|
709
756
|
readonly readOnly?: boolean;
|
|
710
757
|
readonly policy?: FormPolicy;
|
|
758
|
+
readonly availableLocales?: readonly (string | LocaleOption)[];
|
|
759
|
+
readonly onLocaleAdded?: (locale: string) => void;
|
|
760
|
+
readonly onLocaleRemoved?: (locale: string) => void;
|
|
761
|
+
readonly onLocaleChange?: (targetLocale: string) => void;
|
|
711
762
|
readonly beforeRemoveLocale?: (locale: string, context: {
|
|
712
763
|
readonly slotCount: number;
|
|
713
764
|
}) => Promise<boolean> | boolean;
|
|
@@ -766,6 +817,7 @@ interface UseTranslationWorkspaceResult {
|
|
|
766
817
|
readonly sourceLocale: string;
|
|
767
818
|
readonly targetLocale: string;
|
|
768
819
|
readonly targetLocales: readonly string[];
|
|
820
|
+
readonly localeOptions: readonly LocaleOption[];
|
|
769
821
|
readonly setTargetLocale: (locale: string) => void;
|
|
770
822
|
readonly slots: readonly TranslationSlot[];
|
|
771
823
|
readonly summary: TranslationSummary;
|
|
@@ -788,8 +840,8 @@ interface UseTranslationWorkspaceResult {
|
|
|
788
840
|
readonly isTranslating: boolean;
|
|
789
841
|
readonly error?: TranslationWorkspaceError;
|
|
790
842
|
}
|
|
791
|
-
declare const validateLocalePipeline: (locale: string, schema: FormSchema, policy?: FormPolicy, customValidator?: ((locale: string, currentLocales: readonly string[]) => LocaleValidationResult) | CustomLocaleValidator) => LocaleValidationResult;
|
|
792
|
-
declare function useTranslationWorkspace({ schema, onChange, sourceLocale, targetLocale, translationAdapter, readOnly, policy, beforeRemoveLocale, validateLocale }: UseTranslationWorkspaceOptions): UseTranslationWorkspaceResult;
|
|
843
|
+
declare const validateLocalePipeline: (locale: string, schema: FormSchema, policy?: FormPolicy, customValidator?: ((locale: string, currentLocales: readonly string[]) => LocaleValidationResult) | CustomLocaleValidator, availableLocales?: readonly (string | LocaleOption)[]) => LocaleValidationResult;
|
|
844
|
+
declare function useTranslationWorkspace({ schema, onChange, sourceLocale, targetLocale, translationAdapter, readOnly, policy, availableLocales, onLocaleAdded, onLocaleRemoved, onLocaleChange, beforeRemoveLocale, validateLocale }: UseTranslationWorkspaceOptions): UseTranslationWorkspaceResult;
|
|
793
845
|
|
|
794
846
|
declare const BUILDER_TRANSLATION_KEYS: {
|
|
795
847
|
readonly ADD_FIELD: "builder.actions.addField";
|
|
@@ -879,4 +931,4 @@ interface StandaloneFormRendererProps extends FormRendererPresentationProps {
|
|
|
879
931
|
type FormRendererProps = FormRendererPresentationProps | StandaloneFormRendererProps;
|
|
880
932
|
declare function FormRenderer(props: FormRendererProps): react.JSX.Element;
|
|
881
933
|
|
|
882
|
-
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ChoiceFieldLayoutMode, type ChoiceFieldTypeLayoutMap, type ChoiceGroupSlotProps, type ComponentBaseProps, type CustomLocaleValidator, type FieldComponentProps, type FieldComponents, type FieldEditorControlsConfig, type FieldEditorHeaderSlotProps, type FieldEditorMode, type FieldError, type FieldPropertyControlMode, type FieldState, type FieldTypeSelectOptionsConfig, type FieldTypeSelectOptionsContext, type FieldTypeSelectOptionsSorter, type FieldTypeSelectOptionsTransformer, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormBuilderSubmissionSettingsOptions, type FormCompletionSlotProps, type FormContextValue, FormEngineI18nContext, type FormEngineI18nContextValue, FormEngineI18nProvider, type FormEngineI18nProviderProps, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererAppearance, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlotProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocaleValidationContext, type LocaleValidationResult, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationOptions, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type TranslationSummary, type TranslationWorkspaceError, type UseFormBuilderOptions, type UseFormBuilderResult, type UseSubmissionReceiptsResult, type UseTranslationWorkspaceOptions, type UseTranslationWorkspaceResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, isTranslationUnresolved, resolveChoiceFieldLayout, resolveFieldEditorControls, resolveFieldTypeSelectOptions, resolveInitialFieldType, resolveTranslation, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useFormEngineI18n, useSubmissionReceipts, useTranslationWorkspace, validateLocalePipeline };
|
|
934
|
+
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ChoiceFieldLayoutMode, type ChoiceFieldTypeLayoutMap, type ChoiceGroupSlotProps, type ComponentBaseProps, type CustomLocaleValidator, type FieldComponentProps, type FieldComponents, type FieldEditorControlsConfig, type FieldEditorHeaderSlotProps, type FieldEditorMode, type FieldError, type FieldPropertyControlMode, type FieldState, type FieldTypeSelectOptionsConfig, type FieldTypeSelectOptionsContext, type FieldTypeSelectOptionsSorter, type FieldTypeSelectOptionsTransformer, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormBuilderSubmissionSettingsOptions, type FormCompletionSlotProps, type FormContextValue, FormEngineI18nContext, type FormEngineI18nContextValue, FormEngineI18nProvider, type FormEngineI18nProviderProps, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererAppearance, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlotProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocaleSelectorProps, type LocaleValidationContext, type LocaleValidationResult, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationOptions, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type TranslationSlotRowProps, type TranslationSummary, type TranslationWorkspaceActionsProps, type TranslationWorkspaceError, type TranslationWorkspaceHeaderProps, type TranslationWorkspaceSlots, type UseFormBuilderOptions, type UseFormBuilderResult, type UseSubmissionReceiptsResult, type UseTranslationWorkspaceOptions, type UseTranslationWorkspaceResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, isTranslationUnresolved, resolveChoiceFieldLayout, resolveFieldEditorControls, resolveFieldTypeSelectOptions, resolveInitialFieldType, resolveTranslation, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useFormEngineI18n, useSubmissionReceipts, useTranslationWorkspace, validateLocalePipeline };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as _form_engine_ts_core from '@form-engine-ts/core';
|
|
2
|
+
import { QuestionType, FormField, ChoiceOption, FormPage, FormSchema, DisplayCondition, JsonValue, SchemaIssue, FormPolicy, Question, FieldOption, TranslationReport, ValidationIssue, ValidationError, FormValues, LocaleOption, TranslationAdapter, AsyncTranslationAdapter, PopulateTranslationOptions, FormValue, AnswerValidationResult, TranslationSlot, FormEngineTranslator, FormEngineMessages, FieldType } from '@form-engine-ts/core';
|
|
2
3
|
export { QuestionType } from '@form-engine-ts/core';
|
|
3
4
|
import * as react from 'react';
|
|
4
5
|
import { ReactNode, ComponentType, KeyboardEvent, MouseEvent, CSSProperties } from 'react';
|
|
@@ -379,6 +380,52 @@ interface BuilderLocalizationSlotProps extends BuilderSlotBaseProps {
|
|
|
379
380
|
readonly policy?: FormPolicy;
|
|
380
381
|
readonly translationAdapterAvailable?: boolean;
|
|
381
382
|
}
|
|
383
|
+
interface TranslationWorkspaceHeaderProps {
|
|
384
|
+
readonly schema: FormSchema;
|
|
385
|
+
readonly sourceLocale: string;
|
|
386
|
+
readonly targetLocale: string;
|
|
387
|
+
readonly summary: {
|
|
388
|
+
readonly totalSlots: number;
|
|
389
|
+
readonly translatedCount: number;
|
|
390
|
+
readonly missingCount: number;
|
|
391
|
+
readonly staleCount: number;
|
|
392
|
+
readonly manualCount: number;
|
|
393
|
+
readonly completionPercentage: number;
|
|
394
|
+
};
|
|
395
|
+
readonly onTranslateAll: () => void;
|
|
396
|
+
readonly isTranslating: boolean;
|
|
397
|
+
readonly readOnly: boolean;
|
|
398
|
+
}
|
|
399
|
+
interface TranslationSlotRowProps {
|
|
400
|
+
readonly slot: _form_engine_ts_core.TranslationSlot;
|
|
401
|
+
readonly readOnly: boolean;
|
|
402
|
+
readonly onChange: (text: string) => void;
|
|
403
|
+
readonly onTranslate: () => void;
|
|
404
|
+
}
|
|
405
|
+
interface LocaleSelectorProps {
|
|
406
|
+
readonly targetLocale: string;
|
|
407
|
+
readonly targetLocales: readonly string[];
|
|
408
|
+
readonly localeOptions: readonly LocaleOption[];
|
|
409
|
+
readonly newLocale: string;
|
|
410
|
+
readonly readOnly: boolean;
|
|
411
|
+
readonly onTargetLocaleChange: (locale: string) => void;
|
|
412
|
+
readonly onNewLocaleChange: (locale: string) => void;
|
|
413
|
+
readonly onAddLocale: () => void;
|
|
414
|
+
}
|
|
415
|
+
interface TranslationWorkspaceActionsProps {
|
|
416
|
+
readonly onTranslateAll: () => void;
|
|
417
|
+
readonly isTranslating: boolean;
|
|
418
|
+
readonly readOnly: boolean;
|
|
419
|
+
}
|
|
420
|
+
interface TranslationWorkspaceSlots {
|
|
421
|
+
readonly renderHeader?: (props: TranslationWorkspaceHeaderProps) => ReactNode;
|
|
422
|
+
readonly renderSlotRow?: (props: TranslationSlotRowProps) => ReactNode;
|
|
423
|
+
readonly renderLocaleSelector?: (props: LocaleSelectorProps) => ReactNode;
|
|
424
|
+
readonly renderStatusBadge?: (props: {
|
|
425
|
+
readonly status: _form_engine_ts_core.TranslationStatus;
|
|
426
|
+
}) => ReactNode;
|
|
427
|
+
readonly renderActions?: (props: TranslationWorkspaceActionsProps) => ReactNode;
|
|
428
|
+
}
|
|
382
429
|
interface LocalizationSummaryContext {
|
|
383
430
|
readonly defaultLocale: string;
|
|
384
431
|
readonly supportedLocales: readonly string[];
|
|
@@ -708,6 +755,10 @@ interface UseTranslationWorkspaceOptions {
|
|
|
708
755
|
readonly translationAdapter?: TranslationAdapter | AsyncTranslationAdapter;
|
|
709
756
|
readonly readOnly?: boolean;
|
|
710
757
|
readonly policy?: FormPolicy;
|
|
758
|
+
readonly availableLocales?: readonly (string | LocaleOption)[];
|
|
759
|
+
readonly onLocaleAdded?: (locale: string) => void;
|
|
760
|
+
readonly onLocaleRemoved?: (locale: string) => void;
|
|
761
|
+
readonly onLocaleChange?: (targetLocale: string) => void;
|
|
711
762
|
readonly beforeRemoveLocale?: (locale: string, context: {
|
|
712
763
|
readonly slotCount: number;
|
|
713
764
|
}) => Promise<boolean> | boolean;
|
|
@@ -766,6 +817,7 @@ interface UseTranslationWorkspaceResult {
|
|
|
766
817
|
readonly sourceLocale: string;
|
|
767
818
|
readonly targetLocale: string;
|
|
768
819
|
readonly targetLocales: readonly string[];
|
|
820
|
+
readonly localeOptions: readonly LocaleOption[];
|
|
769
821
|
readonly setTargetLocale: (locale: string) => void;
|
|
770
822
|
readonly slots: readonly TranslationSlot[];
|
|
771
823
|
readonly summary: TranslationSummary;
|
|
@@ -788,8 +840,8 @@ interface UseTranslationWorkspaceResult {
|
|
|
788
840
|
readonly isTranslating: boolean;
|
|
789
841
|
readonly error?: TranslationWorkspaceError;
|
|
790
842
|
}
|
|
791
|
-
declare const validateLocalePipeline: (locale: string, schema: FormSchema, policy?: FormPolicy, customValidator?: ((locale: string, currentLocales: readonly string[]) => LocaleValidationResult) | CustomLocaleValidator) => LocaleValidationResult;
|
|
792
|
-
declare function useTranslationWorkspace({ schema, onChange, sourceLocale, targetLocale, translationAdapter, readOnly, policy, beforeRemoveLocale, validateLocale }: UseTranslationWorkspaceOptions): UseTranslationWorkspaceResult;
|
|
843
|
+
declare const validateLocalePipeline: (locale: string, schema: FormSchema, policy?: FormPolicy, customValidator?: ((locale: string, currentLocales: readonly string[]) => LocaleValidationResult) | CustomLocaleValidator, availableLocales?: readonly (string | LocaleOption)[]) => LocaleValidationResult;
|
|
844
|
+
declare function useTranslationWorkspace({ schema, onChange, sourceLocale, targetLocale, translationAdapter, readOnly, policy, availableLocales, onLocaleAdded, onLocaleRemoved, onLocaleChange, beforeRemoveLocale, validateLocale }: UseTranslationWorkspaceOptions): UseTranslationWorkspaceResult;
|
|
793
845
|
|
|
794
846
|
declare const BUILDER_TRANSLATION_KEYS: {
|
|
795
847
|
readonly ADD_FIELD: "builder.actions.addField";
|
|
@@ -879,4 +931,4 @@ interface StandaloneFormRendererProps extends FormRendererPresentationProps {
|
|
|
879
931
|
type FormRendererProps = FormRendererPresentationProps | StandaloneFormRendererProps;
|
|
880
932
|
declare function FormRenderer(props: FormRendererProps): react.JSX.Element;
|
|
881
933
|
|
|
882
|
-
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ChoiceFieldLayoutMode, type ChoiceFieldTypeLayoutMap, type ChoiceGroupSlotProps, type ComponentBaseProps, type CustomLocaleValidator, type FieldComponentProps, type FieldComponents, type FieldEditorControlsConfig, type FieldEditorHeaderSlotProps, type FieldEditorMode, type FieldError, type FieldPropertyControlMode, type FieldState, type FieldTypeSelectOptionsConfig, type FieldTypeSelectOptionsContext, type FieldTypeSelectOptionsSorter, type FieldTypeSelectOptionsTransformer, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormBuilderSubmissionSettingsOptions, type FormCompletionSlotProps, type FormContextValue, FormEngineI18nContext, type FormEngineI18nContextValue, FormEngineI18nProvider, type FormEngineI18nProviderProps, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererAppearance, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlotProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocaleValidationContext, type LocaleValidationResult, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationOptions, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type TranslationSummary, type TranslationWorkspaceError, type UseFormBuilderOptions, type UseFormBuilderResult, type UseSubmissionReceiptsResult, type UseTranslationWorkspaceOptions, type UseTranslationWorkspaceResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, isTranslationUnresolved, resolveChoiceFieldLayout, resolveFieldEditorControls, resolveFieldTypeSelectOptions, resolveInitialFieldType, resolveTranslation, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useFormEngineI18n, useSubmissionReceipts, useTranslationWorkspace, validateLocalePipeline };
|
|
934
|
+
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ChoiceFieldLayoutMode, type ChoiceFieldTypeLayoutMap, type ChoiceGroupSlotProps, type ComponentBaseProps, type CustomLocaleValidator, type FieldComponentProps, type FieldComponents, type FieldEditorControlsConfig, type FieldEditorHeaderSlotProps, type FieldEditorMode, type FieldError, type FieldPropertyControlMode, type FieldState, type FieldTypeSelectOptionsConfig, type FieldTypeSelectOptionsContext, type FieldTypeSelectOptionsSorter, type FieldTypeSelectOptionsTransformer, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormBuilderSubmissionSettingsOptions, type FormCompletionSlotProps, type FormContextValue, FormEngineI18nContext, type FormEngineI18nContextValue, FormEngineI18nProvider, type FormEngineI18nProviderProps, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererAppearance, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlotProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocaleSelectorProps, type LocaleValidationContext, type LocaleValidationResult, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationOptions, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type TranslationSlotRowProps, type TranslationSummary, type TranslationWorkspaceActionsProps, type TranslationWorkspaceError, type TranslationWorkspaceHeaderProps, type TranslationWorkspaceSlots, type UseFormBuilderOptions, type UseFormBuilderResult, type UseSubmissionReceiptsResult, type UseTranslationWorkspaceOptions, type UseTranslationWorkspaceResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, isTranslationUnresolved, resolveChoiceFieldLayout, resolveFieldEditorControls, resolveFieldTypeSelectOptions, resolveInitialFieldType, resolveTranslation, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useFormEngineI18n, useSubmissionReceipts, useTranslationWorkspace, validateLocalePipeline };
|
package/dist/index.js
CHANGED
|
@@ -3298,7 +3298,7 @@ function asAsyncAdapter(adapter) {
|
|
|
3298
3298
|
)
|
|
3299
3299
|
};
|
|
3300
3300
|
}
|
|
3301
|
-
var validateLocalePipeline = (locale, schema, policy, customValidator) => {
|
|
3301
|
+
var validateLocalePipeline = (locale, schema, policy, customValidator, availableLocales) => {
|
|
3302
3302
|
const canonicalLocale = normalizeLocale(locale);
|
|
3303
3303
|
if (canonicalLocale === null) {
|
|
3304
3304
|
return {
|
|
@@ -3311,6 +3311,18 @@ var validateLocalePipeline = (locale, schema, policy, customValidator) => {
|
|
|
3311
3311
|
}
|
|
3312
3312
|
const currentLocales = (schema.supportedLocales ?? []).map((candidate) => normalizeLocale(candidate) ?? candidate);
|
|
3313
3313
|
const defaultLocale = schema.defaultLocale === void 0 ? "" : normalizeLocale(schema.defaultLocale) ?? schema.defaultLocale;
|
|
3314
|
+
if (availableLocales !== void 0 && !availableLocales.some((candidate) => {
|
|
3315
|
+
const value = typeof candidate === "string" ? candidate : candidate.locale;
|
|
3316
|
+
return normalizeLocale(value) === canonicalLocale;
|
|
3317
|
+
})) {
|
|
3318
|
+
return {
|
|
3319
|
+
valid: false,
|
|
3320
|
+
error: {
|
|
3321
|
+
type: "locale_not_allowed",
|
|
3322
|
+
message: `Locale "${canonicalLocale}" is not available in the locale catalog.`
|
|
3323
|
+
}
|
|
3324
|
+
};
|
|
3325
|
+
}
|
|
3314
3326
|
if (canonicalLocale === defaultLocale || currentLocales.includes(canonicalLocale)) {
|
|
3315
3327
|
return {
|
|
3316
3328
|
valid: false,
|
|
@@ -3451,11 +3463,15 @@ function useTranslationWorkspace({
|
|
|
3451
3463
|
translationAdapter,
|
|
3452
3464
|
readOnly = false,
|
|
3453
3465
|
policy,
|
|
3466
|
+
availableLocales,
|
|
3467
|
+
onLocaleAdded,
|
|
3468
|
+
onLocaleRemoved,
|
|
3469
|
+
onLocaleChange,
|
|
3454
3470
|
beforeRemoveLocale,
|
|
3455
3471
|
validateLocale
|
|
3456
3472
|
}) {
|
|
3457
3473
|
const [draftSchema, setDraftSchema] = useState4(schema);
|
|
3458
|
-
const [selectedLocale, setSelectedLocale] = useState4(targetLocale ?? "");
|
|
3474
|
+
const [selectedLocale, setSelectedLocale] = useState4(normalizeLocale(targetLocale ?? "") ?? targetLocale ?? "");
|
|
3459
3475
|
const [isTranslating, setIsTranslating] = useState4(false);
|
|
3460
3476
|
const [error, setError] = useState4();
|
|
3461
3477
|
const currentSchema = onChange === void 0 ? draftSchema : schema;
|
|
@@ -3466,6 +3482,15 @@ function useTranslationWorkspace({
|
|
|
3466
3482
|
);
|
|
3467
3483
|
}, [currentSchema, sourceLocale]);
|
|
3468
3484
|
const activeLocale = selectedLocale.length > 0 ? selectedLocale : targetLocales[0] ?? "";
|
|
3485
|
+
const localeOptions = useMemo4(() => {
|
|
3486
|
+
if (availableLocales === void 0) {
|
|
3487
|
+
return targetLocales.map((locale) => ({ locale, label: locale }));
|
|
3488
|
+
}
|
|
3489
|
+
return availableLocales.map((candidate) => {
|
|
3490
|
+
if (typeof candidate !== "string") return candidate;
|
|
3491
|
+
return { locale: normalizeLocale(candidate) ?? candidate, label: candidate };
|
|
3492
|
+
});
|
|
3493
|
+
}, [availableLocales, targetLocales]);
|
|
3469
3494
|
const slots = useMemo4(
|
|
3470
3495
|
() => activeLocale.length === 0 ? [] : collectTranslationSlots(currentSchema, activeLocale),
|
|
3471
3496
|
[activeLocale, currentSchema]
|
|
@@ -3513,14 +3538,14 @@ function useTranslationWorkspace({
|
|
|
3513
3538
|
const normalized = normalizeLocale(locale);
|
|
3514
3539
|
if (normalized === null) {
|
|
3515
3540
|
const workspaceError = workspaceLocaleValidationError(
|
|
3516
|
-
validateLocalePipeline(locale, currentSchema, policy, validateLocale),
|
|
3541
|
+
validateLocalePipeline(locale, currentSchema, policy, validateLocale, availableLocales),
|
|
3517
3542
|
collectSchemaLocales2(currentSchema).allUniqueLocales.size,
|
|
3518
3543
|
locale
|
|
3519
3544
|
);
|
|
3520
3545
|
setError(workspaceError);
|
|
3521
3546
|
return { success: false, error: workspaceError };
|
|
3522
3547
|
}
|
|
3523
|
-
const validation = validateLocalePipeline(normalized, currentSchema, policy, validateLocale);
|
|
3548
|
+
const validation = validateLocalePipeline(normalized, currentSchema, policy, validateLocale, availableLocales);
|
|
3524
3549
|
if (!validation.valid) {
|
|
3525
3550
|
const workspaceError = workspaceLocaleValidationError(
|
|
3526
3551
|
validation,
|
|
@@ -3536,33 +3561,38 @@ function useTranslationWorkspace({
|
|
|
3536
3561
|
supportedLocales: [.../* @__PURE__ */ new Set([...currentSchema.supportedLocales ?? [], normalized])]
|
|
3537
3562
|
});
|
|
3538
3563
|
setSelectedLocale(normalized);
|
|
3564
|
+
onLocaleAdded?.(normalized);
|
|
3539
3565
|
return { success: true };
|
|
3540
3566
|
},
|
|
3541
|
-
[commit, currentSchema, policy, readOnly, validateLocale]
|
|
3567
|
+
[availableLocales, commit, currentSchema, onLocaleAdded, policy, readOnly, validateLocale]
|
|
3542
3568
|
);
|
|
3543
3569
|
const isAddLocaleAllowed = useCallback3(
|
|
3544
3570
|
(locale) => {
|
|
3545
3571
|
if (readOnly) return false;
|
|
3546
3572
|
const normalized = normalizeLocale(locale);
|
|
3547
3573
|
if (normalized === null) return false;
|
|
3548
|
-
return validateLocalePipeline(normalized, currentSchema, policy, validateLocale).valid;
|
|
3574
|
+
return validateLocalePipeline(normalized, currentSchema, policy, validateLocale, availableLocales).valid;
|
|
3549
3575
|
},
|
|
3550
|
-
[currentSchema, policy, readOnly, validateLocale]
|
|
3576
|
+
[availableLocales, currentSchema, policy, readOnly, validateLocale]
|
|
3551
3577
|
);
|
|
3552
3578
|
const removeLocale = useCallback3(
|
|
3553
3579
|
(locale) => {
|
|
3554
|
-
|
|
3580
|
+
const normalized = normalizeLocale(locale) ?? locale;
|
|
3581
|
+
const normalizedSourceLocale = normalizeLocale(sourceLocale) ?? sourceLocale;
|
|
3582
|
+
const normalizedDefaultLocale = currentSchema.defaultLocale === void 0 ? void 0 : normalizeLocale(currentSchema.defaultLocale) ?? currentSchema.defaultLocale;
|
|
3583
|
+
if (readOnly || normalized === normalizedSourceLocale || normalized === normalizedDefaultLocale) return false;
|
|
3555
3584
|
const remove = () => {
|
|
3556
|
-
commit(removeLocaleFromSchema(currentSchema,
|
|
3557
|
-
if (activeLocale ===
|
|
3585
|
+
commit(removeLocaleFromSchema(currentSchema, normalized));
|
|
3586
|
+
if (activeLocale === normalized) setSelectedLocale("");
|
|
3587
|
+
onLocaleRemoved?.(normalized);
|
|
3558
3588
|
};
|
|
3559
|
-
const slotCount = collectTranslationSlots(currentSchema,
|
|
3589
|
+
const slotCount = collectTranslationSlots(currentSchema, normalized).length;
|
|
3560
3590
|
if (beforeRemoveLocale === void 0) {
|
|
3561
3591
|
remove();
|
|
3562
3592
|
return true;
|
|
3563
3593
|
}
|
|
3564
3594
|
try {
|
|
3565
|
-
const decision = beforeRemoveLocale(
|
|
3595
|
+
const decision = beforeRemoveLocale(normalized, { slotCount });
|
|
3566
3596
|
if (typeof decision === "boolean") {
|
|
3567
3597
|
if (!decision) return false;
|
|
3568
3598
|
remove();
|
|
@@ -3583,7 +3613,7 @@ function useTranslationWorkspace({
|
|
|
3583
3613
|
return Promise.reject(cause);
|
|
3584
3614
|
}
|
|
3585
3615
|
},
|
|
3586
|
-
[activeLocale, beforeRemoveLocale, commit, currentSchema, readOnly, sourceLocale]
|
|
3616
|
+
[activeLocale, beforeRemoveLocale, commit, currentSchema, onLocaleRemoved, readOnly, sourceLocale]
|
|
3587
3617
|
);
|
|
3588
3618
|
const translateAll = useCallback3(
|
|
3589
3619
|
async (options = {}) => {
|
|
@@ -3602,6 +3632,23 @@ function useTranslationWorkspace({
|
|
|
3602
3632
|
setError(workspaceError);
|
|
3603
3633
|
return { success: false, error: workspaceError };
|
|
3604
3634
|
}
|
|
3635
|
+
const selectedLocaleOption = localeOptions.find(
|
|
3636
|
+
(option) => (normalizeLocale(option.locale) ?? option.locale) === activeLocale
|
|
3637
|
+
);
|
|
3638
|
+
if (selectedLocaleOption?.translatable === false) {
|
|
3639
|
+
setError(void 0);
|
|
3640
|
+
return {
|
|
3641
|
+
success: true,
|
|
3642
|
+
report: {
|
|
3643
|
+
updatedSlots: [],
|
|
3644
|
+
skippedSlots: slots,
|
|
3645
|
+
staleSlots: [],
|
|
3646
|
+
skippedReasons: Object.fromEntries(
|
|
3647
|
+
slots.map((slot) => [slot.path ?? `${slot.kind}.${slot.nodeId}.${slot.property}`, "unsupported"])
|
|
3648
|
+
)
|
|
3649
|
+
}
|
|
3650
|
+
};
|
|
3651
|
+
}
|
|
3605
3652
|
setIsTranslating(true);
|
|
3606
3653
|
setError(void 0);
|
|
3607
3654
|
try {
|
|
@@ -3629,7 +3676,7 @@ function useTranslationWorkspace({
|
|
|
3629
3676
|
setIsTranslating(false);
|
|
3630
3677
|
}
|
|
3631
3678
|
},
|
|
3632
|
-
[activeLocale, commit, currentSchema, readOnly, translationAdapter]
|
|
3679
|
+
[activeLocale, commit, currentSchema, localeOptions, readOnly, slots, translationAdapter]
|
|
3633
3680
|
);
|
|
3634
3681
|
const translateSlot = useCallback3(
|
|
3635
3682
|
async (slot) => {
|
|
@@ -3667,7 +3714,12 @@ function useTranslationWorkspace({
|
|
|
3667
3714
|
sourceLocale,
|
|
3668
3715
|
targetLocale: activeLocale,
|
|
3669
3716
|
targetLocales,
|
|
3670
|
-
|
|
3717
|
+
localeOptions,
|
|
3718
|
+
setTargetLocale: (locale) => {
|
|
3719
|
+
const normalized = normalizeLocale(locale) ?? locale;
|
|
3720
|
+
setSelectedLocale(normalized);
|
|
3721
|
+
onLocaleChange?.(normalized);
|
|
3722
|
+
},
|
|
3671
3723
|
slots,
|
|
3672
3724
|
summary,
|
|
3673
3725
|
addLocale,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@form-engine-ts/react",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"typescript"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@form-engine-ts/core": "5.0
|
|
46
|
-
"@form-engine-ts/privacy": "5.0
|
|
45
|
+
"@form-engine-ts/core": "5.1.0",
|
|
46
|
+
"@form-engine-ts/privacy": "5.1.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"react": ">=18.2 <20",
|