@purposeinplay/payload-ai-translate 0.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/LICENSE +21 -0
- package/README.md +714 -0
- package/dist/alerts-collection.d.ts +21 -0
- package/dist/alerts-collection.js +159 -0
- package/dist/api.d.ts +4 -0
- package/dist/api.js +918 -0
- package/dist/bulk-translate-batches-collection.d.ts +29 -0
- package/dist/bulk-translate-batches-collection.js +404 -0
- package/dist/bulk-translate-units-collection.d.ts +35 -0
- package/dist/bulk-translate-units-collection.js +310 -0
- package/dist/client/estimated-cost-cell.d.ts +6 -0
- package/dist/client/estimated-cost-cell.js +12 -0
- package/dist/client/excluded-fields-field.d.ts +45 -0
- package/dist/client/excluded-fields-field.js +553 -0
- package/dist/client/field-translate-button.d.ts +6 -0
- package/dist/client/field-translate-button.js +199 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +6 -0
- package/dist/client/lib/use-global-kill-switches.d.ts +20 -0
- package/dist/client/lib/use-global-kill-switches.js +58 -0
- package/dist/client/translate-button.d.ts +2 -0
- package/dist/client/translate-button.js +228 -0
- package/dist/client/translate-modal.d.ts +16 -0
- package/dist/client/translate-modal.js +549 -0
- package/dist/client/translation-progress.d.ts +10 -0
- package/dist/client/translation-progress.js +297 -0
- package/dist/components/TranslationNavGroup.d.ts +45 -0
- package/dist/components/TranslationNavGroup.js +104 -0
- package/dist/defaults.d.ts +11 -0
- package/dist/defaults.js +16 -0
- package/dist/endpoints/client-config.d.ts +44 -0
- package/dist/endpoints/client-config.js +145 -0
- package/dist/endpoints/estimate.d.ts +5 -0
- package/dist/endpoints/estimate.js +237 -0
- package/dist/endpoints/progress.d.ts +2 -0
- package/dist/endpoints/progress.js +314 -0
- package/dist/endpoints/translate.d.ts +11 -0
- package/dist/endpoints/translate.js +376 -0
- package/dist/endpoints/translation-hub/_helpers.d.ts +140 -0
- package/dist/endpoints/translation-hub/_helpers.js +297 -0
- package/dist/endpoints/translation-hub/active.d.ts +21 -0
- package/dist/endpoints/translation-hub/active.js +220 -0
- package/dist/endpoints/translation-hub/cancel.d.ts +22 -0
- package/dist/endpoints/translation-hub/cancel.js +233 -0
- package/dist/endpoints/translation-hub/enqueue.d.ts +70 -0
- package/dist/endpoints/translation-hub/enqueue.js +529 -0
- package/dist/endpoints/translation-hub/failures.d.ts +12 -0
- package/dist/endpoints/translation-hub/failures.js +67 -0
- package/dist/endpoints/translation-hub/force-reset.d.ts +20 -0
- package/dist/endpoints/translation-hub/force-reset.js +144 -0
- package/dist/endpoints/translation-hub/index.d.ts +21 -0
- package/dist/endpoints/translation-hub/index.js +20 -0
- package/dist/endpoints/translation-hub/list.d.ts +40 -0
- package/dist/endpoints/translation-hub/list.js +182 -0
- package/dist/endpoints/translation-hub/preflight.d.ts +19 -0
- package/dist/endpoints/translation-hub/preflight.js +141 -0
- package/dist/endpoints/translation-hub/retry-failed.d.ts +38 -0
- package/dist/endpoints/translation-hub/retry-failed.js +235 -0
- package/dist/endpoints/translation-hub/revert.d.ts +88 -0
- package/dist/endpoints/translation-hub/revert.js +405 -0
- package/dist/endpoints/translation-hub/status.d.ts +45 -0
- package/dist/endpoints/translation-hub/status.js +391 -0
- package/dist/endpoints/translation-hub/usage-summary.d.ts +114 -0
- package/dist/endpoints/translation-hub/usage-summary.js +481 -0
- package/dist/exports/client.d.ts +6 -0
- package/dist/exports/client.js +6 -0
- package/dist/exports/components.d.ts +6 -0
- package/dist/exports/components.js +5 -0
- package/dist/exports/index.d.ts +8 -0
- package/dist/exports/index.js +7 -0
- package/dist/exports/providers.d.ts +9 -0
- package/dist/exports/providers.js +5 -0
- package/dist/exports/views-client.d.ts +23 -0
- package/dist/exports/views-client.js +22 -0
- package/dist/exports/views.d.ts +30 -0
- package/dist/exports/views.js +29 -0
- package/dist/hooks/after-change-global.d.ts +4 -0
- package/dist/hooks/after-change-global.js +109 -0
- package/dist/hooks/after-change.d.ts +16 -0
- package/dist/hooks/after-change.js +205 -0
- package/dist/hooks/after-delete.d.ts +30 -0
- package/dist/hooks/after-delete.js +95 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/jobs-collection.d.ts +17 -0
- package/dist/jobs-collection.js +139 -0
- package/dist/lexical/classifier.d.ts +3 -0
- package/dist/lexical/classifier.js +108 -0
- package/dist/lexical/deserializer.d.ts +4 -0
- package/dist/lexical/deserializer.js +263 -0
- package/dist/lexical/placeholder-integrity.d.ts +6 -0
- package/dist/lexical/placeholder-integrity.js +21 -0
- package/dist/lexical/placeholders.d.ts +21 -0
- package/dist/lexical/placeholders.js +117 -0
- package/dist/lexical/serializer.d.ts +21 -0
- package/dist/lexical/serializer.js +233 -0
- package/dist/lexical/types.d.ts +32 -0
- package/dist/lexical/types.js +1 -0
- package/dist/lib/auth-diagnostics.d.ts +14 -0
- package/dist/lib/auth-diagnostics.js +19 -0
- package/dist/lib/batch-counts.d.ts +58 -0
- package/dist/lib/batch-counts.js +105 -0
- package/dist/lib/bulk-translate-migrations.d.ts +92 -0
- package/dist/lib/bulk-translate-migrations.js +153 -0
- package/dist/lib/coalescing-queue.d.ts +38 -0
- package/dist/lib/coalescing-queue.js +69 -0
- package/dist/lib/content-extractor.d.ts +16 -0
- package/dist/lib/content-extractor.js +410 -0
- package/dist/lib/content-hash.d.ts +1 -0
- package/dist/lib/content-hash.js +19 -0
- package/dist/lib/content-patcher.d.ts +15 -0
- package/dist/lib/content-patcher.js +293 -0
- package/dist/lib/cost-guards.d.ts +2 -0
- package/dist/lib/cost-guards.js +18 -0
- package/dist/lib/daily-spend-cap.d.ts +58 -0
- package/dist/lib/daily-spend-cap.js +233 -0
- package/dist/lib/effective-locales.d.ts +181 -0
- package/dist/lib/effective-locales.js +302 -0
- package/dist/lib/error-messages.d.ts +245 -0
- package/dist/lib/error-messages.js +626 -0
- package/dist/lib/events.d.ts +39 -0
- package/dist/lib/events.js +146 -0
- package/dist/lib/exclude-fields.d.ts +3 -0
- package/dist/lib/exclude-fields.js +64 -0
- package/dist/lib/field-breadcrumb.d.ts +31 -0
- package/dist/lib/field-breadcrumb.js +227 -0
- package/dist/lib/field-diff.d.ts +1 -0
- package/dist/lib/field-diff.js +25 -0
- package/dist/lib/field-empty.d.ts +2 -0
- package/dist/lib/field-empty.js +68 -0
- package/dist/lib/field-resolver.d.ts +3 -0
- package/dist/lib/field-resolver.js +164 -0
- package/dist/lib/group-soft-skips.d.ts +39 -0
- package/dist/lib/group-soft-skips.js +45 -0
- package/dist/lib/locale-merge.d.ts +44 -0
- package/dist/lib/locale-merge.js +357 -0
- package/dist/lib/locale-row-check.d.ts +30 -0
- package/dist/lib/locale-row-check.js +64 -0
- package/dist/lib/logger.d.ts +74 -0
- package/dist/lib/logger.js +97 -0
- package/dist/lib/manual-edit-guard.d.ts +128 -0
- package/dist/lib/manual-edit-guard.js +393 -0
- package/dist/lib/output-validation.d.ts +48 -0
- package/dist/lib/output-validation.js +148 -0
- package/dist/lib/payload-read.d.ts +16 -0
- package/dist/lib/payload-read.js +51 -0
- package/dist/lib/per-doc-claim.d.ts +90 -0
- package/dist/lib/per-doc-claim.js +140 -0
- package/dist/lib/per-doc-lock.d.ts +94 -0
- package/dist/lib/per-doc-lock.js +119 -0
- package/dist/lib/persist-usage.d.ts +91 -0
- package/dist/lib/persist-usage.js +116 -0
- package/dist/lib/progress-store.d.ts +103 -0
- package/dist/lib/progress-store.js +314 -0
- package/dist/lib/rate-limiter.d.ts +3 -0
- package/dist/lib/rate-limiter.js +53 -0
- package/dist/lib/snapshot-select.d.ts +43 -0
- package/dist/lib/snapshot-select.js +108 -0
- package/dist/lib/translate-prompt.d.ts +31 -0
- package/dist/lib/translate-prompt.js +66 -0
- package/dist/lib/translation-token-bucket.d.ts +57 -0
- package/dist/lib/translation-token-bucket.js +365 -0
- package/dist/lib/truncate-source-value.d.ts +1 -0
- package/dist/lib/truncate-source-value.js +27 -0
- package/dist/manual-edit-collection.d.ts +22 -0
- package/dist/manual-edit-collection.js +124 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.js +934 -0
- package/dist/providers/ai-sdk-adapter.d.ts +35 -0
- package/dist/providers/ai-sdk-adapter.js +100 -0
- package/dist/providers/anthropic.d.ts +31 -0
- package/dist/providers/anthropic.js +66 -0
- package/dist/providers/custom.d.ts +36 -0
- package/dist/providers/custom.js +24 -0
- package/dist/providers/gemini.d.ts +20 -0
- package/dist/providers/gemini.js +48 -0
- package/dist/providers/mock.d.ts +2 -0
- package/dist/providers/mock.js +29 -0
- package/dist/providers/openai.d.ts +28 -0
- package/dist/providers/openai.js +69 -0
- package/dist/settings-global.d.ts +74 -0
- package/dist/settings-global.js +216 -0
- package/dist/tasks/bulk-translate-coordinator.d.ts +115 -0
- package/dist/tasks/bulk-translate-coordinator.js +708 -0
- package/dist/tasks/bulk-translate-doc-task.d.ts +142 -0
- package/dist/tasks/bulk-translate-doc-task.js +1000 -0
- package/dist/tasks/bulk-translate-janitor.d.ts +87 -0
- package/dist/tasks/bulk-translate-janitor.js +311 -0
- package/dist/tasks/translate-job-task.d.ts +51 -0
- package/dist/tasks/translate-job-task.js +154 -0
- package/dist/translate.d.ts +113 -0
- package/dist/translate.js +911 -0
- package/dist/translation-daily-spend-collection.d.ts +24 -0
- package/dist/translation-daily-spend-collection.js +133 -0
- package/dist/translation-rate-limits-collection.d.ts +30 -0
- package/dist/translation-rate-limits-collection.js +144 -0
- package/dist/types.d.ts +672 -0
- package/dist/types.js +1 -0
- package/dist/usage-collection.d.ts +14 -0
- package/dist/usage-collection.js +377 -0
- package/dist/views/BulkRunsHub/BatchRow.d.ts +32 -0
- package/dist/views/BulkRunsHub/BatchRow.js +1222 -0
- package/dist/views/BulkRunsHub/BucketRow.d.ts +62 -0
- package/dist/views/BulkRunsHub/BucketRow.js +982 -0
- package/dist/views/BulkRunsHub/BulkRunsHub.client.d.ts +18 -0
- package/dist/views/BulkRunsHub/BulkRunsHub.client.js +331 -0
- package/dist/views/BulkRunsHub/EmptyState.d.ts +6 -0
- package/dist/views/BulkRunsHub/EmptyState.js +64 -0
- package/dist/views/BulkRunsHub/FilterBar.d.ts +16 -0
- package/dist/views/BulkRunsHub/FilterBar.js +284 -0
- package/dist/views/BulkRunsHub/InFlightBanner.d.ts +14 -0
- package/dist/views/BulkRunsHub/InFlightBanner.js +59 -0
- package/dist/views/BulkRunsHub/StatusBadge.d.ts +64 -0
- package/dist/views/BulkRunsHub/StatusBadge.js +248 -0
- package/dist/views/BulkRunsHub/SummaryStrip.d.ts +22 -0
- package/dist/views/BulkRunsHub/SummaryStrip.js +249 -0
- package/dist/views/BulkRunsHub/bucket-grouping.d.ts +200 -0
- package/dist/views/BulkRunsHub/bucket-grouping.js +344 -0
- package/dist/views/BulkRunsHub/bucketFailureSummary.d.ts +9 -0
- package/dist/views/BulkRunsHub/bucketFailureSummary.js +36 -0
- package/dist/views/BulkRunsHub/dedupedStatusFetch.d.ts +5 -0
- package/dist/views/BulkRunsHub/dedupedStatusFetch.js +45 -0
- package/dist/views/BulkRunsHub/index.d.ts +17 -0
- package/dist/views/BulkRunsHub/index.js +80 -0
- package/dist/views/BulkRunsHub/urlFilters.d.ts +14 -0
- package/dist/views/BulkRunsHub/urlFilters.js +50 -0
- package/dist/views/BulkRunsHub/useBulkRunsList.d.ts +26 -0
- package/dist/views/BulkRunsHub/useBulkRunsList.js +204 -0
- package/dist/views/BulkRunsHub/useUrlFilters.d.ts +10 -0
- package/dist/views/BulkRunsHub/useUrlFilters.js +88 -0
- package/dist/views/TranslationHub/ActiveJobs.d.ts +6 -0
- package/dist/views/TranslationHub/ActiveJobs.js +320 -0
- package/dist/views/TranslationHub/AdvancedPanel.d.ts +17 -0
- package/dist/views/TranslationHub/AdvancedPanel.js +996 -0
- package/dist/views/TranslationHub/AlertBanner.d.ts +6 -0
- package/dist/views/TranslationHub/AlertBanner.js +568 -0
- package/dist/views/TranslationHub/AuditPanel.d.ts +6 -0
- package/dist/views/TranslationHub/AuditPanel.helpers.d.ts +44 -0
- package/dist/views/TranslationHub/AuditPanel.helpers.js +71 -0
- package/dist/views/TranslationHub/AuditPanel.js +1367 -0
- package/dist/views/TranslationHub/BulkTranslate.types.d.ts +242 -0
- package/dist/views/TranslationHub/BulkTranslate.types.js +36 -0
- package/dist/views/TranslationHub/BulkTranslateFailureDrawer.d.ts +19 -0
- package/dist/views/TranslationHub/BulkTranslateFailureDrawer.js +332 -0
- package/dist/views/TranslationHub/BulkTranslateMonitor.d.ts +28 -0
- package/dist/views/TranslationHub/BulkTranslateMonitor.js +305 -0
- package/dist/views/TranslationHub/BulkTranslateNarrowViewportBanner.d.ts +3 -0
- package/dist/views/TranslationHub/BulkTranslateNarrowViewportBanner.js +42 -0
- package/dist/views/TranslationHub/BulkTranslatePostEnqueueTransition.d.ts +26 -0
- package/dist/views/TranslationHub/BulkTranslatePostEnqueueTransition.js +95 -0
- package/dist/views/TranslationHub/BulkTranslatePreflightModal.d.ts +22 -0
- package/dist/views/TranslationHub/BulkTranslatePreflightModal.js +879 -0
- package/dist/views/TranslationHub/BulkTranslateTerminalCard.d.ts +29 -0
- package/dist/views/TranslationHub/BulkTranslateTerminalCard.js +445 -0
- package/dist/views/TranslationHub/BulkTranslateTrigger.d.ts +66 -0
- package/dist/views/TranslationHub/BulkTranslateTrigger.js +161 -0
- package/dist/views/TranslationHub/EditorRecentRunsPanel.d.ts +33 -0
- package/dist/views/TranslationHub/EditorRecentRunsPanel.js +290 -0
- package/dist/views/TranslationHub/Hub.client.d.ts +74 -0
- package/dist/views/TranslationHub/Hub.client.js +357 -0
- package/dist/views/TranslationHub/ModelCombobox.d.ts +14 -0
- package/dist/views/TranslationHub/ModelCombobox.js +415 -0
- package/dist/views/TranslationHub/PerCollectionConfig.d.ts +10 -0
- package/dist/views/TranslationHub/PerCollectionConfig.helpers.d.ts +16 -0
- package/dist/views/TranslationHub/PerCollectionConfig.helpers.js +19 -0
- package/dist/views/TranslationHub/PerCollectionConfig.js +759 -0
- package/dist/views/TranslationHub/SettingsRail.d.ts +11 -0
- package/dist/views/TranslationHub/SettingsRail.js +382 -0
- package/dist/views/TranslationHub/StatusStrip.d.ts +6 -0
- package/dist/views/TranslationHub/StatusStrip.js +451 -0
- package/dist/views/TranslationHub/UsageTable.d.ts +6 -0
- package/dist/views/TranslationHub/UsageTable.helpers.d.ts +69 -0
- package/dist/views/TranslationHub/UsageTable.helpers.js +49 -0
- package/dist/views/TranslationHub/UsageTable.js +1240 -0
- package/dist/views/TranslationHub/alertGrouping.d.ts +70 -0
- package/dist/views/TranslationHub/alertGrouping.js +99 -0
- package/dist/views/TranslationHub/index.d.ts +20 -0
- package/dist/views/TranslationHub/index.js +109 -0
- package/dist/views/TranslationHub/tabNavigation.d.ts +53 -0
- package/dist/views/TranslationHub/tabNavigation.js +74 -0
- package/dist/views/TranslationHub/terminalBannerVisibility.d.ts +33 -0
- package/dist/views/TranslationHub/terminalBannerVisibility.js +124 -0
- package/dist/views/TranslationHub/useBulkTranslateActive.d.ts +49 -0
- package/dist/views/TranslationHub/useBulkTranslateActive.js +251 -0
- package/dist/views/TranslationHub/useFocusTrap.d.ts +6 -0
- package/dist/views/TranslationHub/useFocusTrap.js +81 -0
- package/dist/views/TranslationHub/useTranslationHubUsageSummary.d.ts +77 -0
- package/dist/views/TranslationHub/useTranslationHubUsageSummary.js +267 -0
- package/dist/views/shared/EditorError.d.ts +97 -0
- package/dist/views/shared/EditorError.js +205 -0
- package/dist/views/shared/ModelCell.d.ts +18 -0
- package/dist/views/shared/ModelCell.js +31 -0
- package/dist/views/shared/docHref.d.ts +16 -0
- package/dist/views/shared/docHref.js +26 -0
- package/dist/views/shared/fetch-error-body.d.ts +25 -0
- package/dist/views/shared/fetch-error-body.js +42 -0
- package/dist/views/shared/filterPillStyle.d.ts +35 -0
- package/dist/views/shared/filterPillStyle.js +40 -0
- package/dist/views/shared/format.d.ts +75 -0
- package/dist/views/shared/format.js +131 -0
- package/package.json +141 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { invalidateSettingsCache } from './lib/effective-locales.js';
|
|
2
|
+
export const DEFAULT_SETTINGS_GLOBAL_SLUG = 'translation-settings';
|
|
3
|
+
export function createSettingsGlobal(providerKeys, targetLocales, options, trackedSurfaces = []) {
|
|
4
|
+
const slug = options?.globalSlug ?? DEFAULT_SETTINGS_GLOBAL_SLUG;
|
|
5
|
+
const defaultAdminAccess = ({ req })=>req?.user?.roles?.includes('admin') ?? false;
|
|
6
|
+
const providerOptions = providerKeys.map((key)=>({
|
|
7
|
+
label: key,
|
|
8
|
+
value: key
|
|
9
|
+
}));
|
|
10
|
+
const localeOptions = targetLocales.map((locale)=>({
|
|
11
|
+
label: locale,
|
|
12
|
+
value: locale
|
|
13
|
+
}));
|
|
14
|
+
const surfaceOptions = trackedSurfaces.map((slugName)=>({
|
|
15
|
+
label: slugName,
|
|
16
|
+
value: slugName
|
|
17
|
+
}));
|
|
18
|
+
const fields = [];
|
|
19
|
+
// Provider selector — only meaningful when there's something to switch
|
|
20
|
+
// between. Single-provider consumers see only the locale toggle.
|
|
21
|
+
if (providerKeys.length > 0) {
|
|
22
|
+
fields.push({
|
|
23
|
+
name: 'activeProvider',
|
|
24
|
+
type: 'select',
|
|
25
|
+
required: false,
|
|
26
|
+
options: providerOptions,
|
|
27
|
+
admin: {
|
|
28
|
+
description: 'The provider used for new translations. When unset, the plugin falls back to the default `provider` configured in code.'
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
// Per-locale auto-translate toggle. Empty = "all enabled" so that
|
|
33
|
+
// existing consumers see no behavior change after upgrading.
|
|
34
|
+
fields.push({
|
|
35
|
+
name: 'enabledTargetLocales',
|
|
36
|
+
type: 'select',
|
|
37
|
+
hasMany: true,
|
|
38
|
+
required: false,
|
|
39
|
+
options: localeOptions,
|
|
40
|
+
admin: {
|
|
41
|
+
description: '⚠️ EMPTY = ALL LOCALES ENABLED (back-compat default). Select locales here to NARROW auto-translate to that subset; unselected locales are skipped by automation. Clearing the list does NOT disable auto-translate — to fully stop automation, uncheck "Enabled" or "Auto on publish" on every per-collection row below. Manual Translate from the dialog is never gated by this field.'
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
// Three independent plugin-wide kill switches. Each one supersedes
|
|
45
|
+
// every per-collection setting below — when off, no surface receives
|
|
46
|
+
// work via that subsystem regardless of the per-surface `enabled` /
|
|
47
|
+
// `autoOnPublish` flags. Defaults are `true` so upgrades don't break
|
|
48
|
+
// existing consumers; admins flip them off when they need an
|
|
49
|
+
// emergency stop without redeploying.
|
|
50
|
+
//
|
|
51
|
+
// Storage shape: three top-level checkboxes (not nested in a group)
|
|
52
|
+
// so Payload's drizzle generator emits flat boolean columns —
|
|
53
|
+
// `global_auto_translate_enabled` etc. on the `translation_settings`
|
|
54
|
+
// table — instead of a join table or a JSON blob. Flat columns make
|
|
55
|
+
// the migration a no-op `ADD COLUMN IF NOT EXISTS ... DEFAULT true`
|
|
56
|
+
// on both consumer repos.
|
|
57
|
+
//
|
|
58
|
+
// Read path: every gate uses `getGlobalKillSwitches` in
|
|
59
|
+
// `lib/effective-locales.ts`, which shares the 30s-TTL settings
|
|
60
|
+
// cache with the per-collection helpers. The settings global's own
|
|
61
|
+
// `afterChange` already invalidates the cache, so admin edits
|
|
62
|
+
// propagate on the next read.
|
|
63
|
+
fields.push({
|
|
64
|
+
name: 'globalAutoTranslateEnabled',
|
|
65
|
+
type: 'checkbox',
|
|
66
|
+
defaultValue: true,
|
|
67
|
+
admin: {
|
|
68
|
+
description: '🛑 GLOBAL KILL SWITCH — auto-translate. When unchecked, the after-change hook does nothing on every save. Per-collection `Enabled` / `Auto on publish` still apply WITHIN this switch — flipping it back on resumes whatever per-surface config was already in place. Manual Translate and Bulk Translate are unaffected by this flag.'
|
|
69
|
+
}
|
|
70
|
+
}, {
|
|
71
|
+
name: 'globalManualTranslateEnabled',
|
|
72
|
+
type: 'checkbox',
|
|
73
|
+
defaultValue: true,
|
|
74
|
+
admin: {
|
|
75
|
+
description: '🛑 GLOBAL KILL SWITCH — manual Translate dialog + per-field button. When unchecked, the dialog and the per-field button hide in the admin UI, and the underlying endpoint returns 403. Per-collection `Enabled` still applies WITHIN this switch. Auto-translate and Bulk Translate are unaffected by this flag.'
|
|
76
|
+
}
|
|
77
|
+
}, {
|
|
78
|
+
name: 'globalBulkTranslateEnabled',
|
|
79
|
+
type: 'checkbox',
|
|
80
|
+
defaultValue: true,
|
|
81
|
+
admin: {
|
|
82
|
+
description: '🛑 GLOBAL KILL SWITCH — Bulk Translate (new runs). When unchecked, enqueueing a new bulk run is rejected and the BulkTranslate trigger in the Hub renders disabled. In-flight bulk runs that were already enqueued continue to completion — flipping this switch does NOT cancel running work. Manual Translate and auto-translate are unaffected by this flag.'
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
// Per-collection / per-global configuration. Each tracked surface
|
|
86
|
+
// gets a row; admins can disable a surface entirely, turn off
|
|
87
|
+
// auto-on-publish, or narrow the target locales for just that
|
|
88
|
+
// surface. Empty rows / missing entries fall back to the site-wide
|
|
89
|
+
// defaults — so consumers upgrading without admin action see no
|
|
90
|
+
// behavior change.
|
|
91
|
+
if (trackedSurfaces.length > 0) {
|
|
92
|
+
fields.push({
|
|
93
|
+
name: 'perCollection',
|
|
94
|
+
type: 'array',
|
|
95
|
+
required: false,
|
|
96
|
+
labels: {
|
|
97
|
+
singular: 'Collection / Global setting',
|
|
98
|
+
plural: 'Per-collection settings'
|
|
99
|
+
},
|
|
100
|
+
// Postgres identifier limit is 63 chars; the default-generated
|
|
101
|
+
// table / enum names from `translation_settings_per_collection_*`
|
|
102
|
+
// overflow. Pin compact db identifiers so generated migrations
|
|
103
|
+
// are portable across adapters.
|
|
104
|
+
dbName: 'tr_st_pc',
|
|
105
|
+
admin: {
|
|
106
|
+
description: 'Override site-wide settings for a specific collection or global. Rows that are missing or have all defaults inherit the site-wide config above.',
|
|
107
|
+
initCollapsed: true
|
|
108
|
+
},
|
|
109
|
+
fields: [
|
|
110
|
+
{
|
|
111
|
+
name: 'slug',
|
|
112
|
+
type: 'select',
|
|
113
|
+
required: true,
|
|
114
|
+
options: surfaceOptions,
|
|
115
|
+
enumName: 'enum_tr_st_pc_slug',
|
|
116
|
+
admin: {
|
|
117
|
+
description: 'The collection or global this row configures.'
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'enabled',
|
|
122
|
+
type: 'checkbox',
|
|
123
|
+
defaultValue: true,
|
|
124
|
+
admin: {
|
|
125
|
+
description: 'KILL SWITCH. Unchecked = translation is fully disabled for this surface — auto-on-publish AND manual Translate dialog AND per-field button. Use the "Auto on publish" toggle below if you want to disable ONLY automation while keeping manual translate available.'
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'autoOnPublish',
|
|
130
|
+
type: 'checkbox',
|
|
131
|
+
defaultValue: true,
|
|
132
|
+
admin: {
|
|
133
|
+
description: 'AUTOMATION ONLY. When checked, publishing a doc in this surface fires auto-translate. Uncheck to keep this collection manual-only — editors can still trigger Translate… on demand. Has no effect when "Enabled" above is unchecked (the kill switch takes precedence).'
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'targetLocalesOverride',
|
|
138
|
+
type: 'select',
|
|
139
|
+
hasMany: true,
|
|
140
|
+
required: false,
|
|
141
|
+
options: localeOptions,
|
|
142
|
+
enumName: 'enum_tr_st_pc_tlo',
|
|
143
|
+
admin: {
|
|
144
|
+
description: '⚠️ EMPTY = INHERIT site-wide locales (back-compat default). Select locales here to NARROW auto-translate for THIS surface specifically. A locale must be enabled at BOTH the site-wide level AND here to fan out. Clearing the list does NOT opt this surface out — uncheck "Enabled" above to do that.'
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
// Opt this surface's `slug` field into translation. Defaults
|
|
149
|
+
// to false because the plugin's `excludeFields` config
|
|
150
|
+
// typically lists `slug` to prevent accidental URL churn
|
|
151
|
+
// across locales. Editors who want per-locale SEO-friendly
|
|
152
|
+
// URLs check this on a per-collection basis.
|
|
153
|
+
//
|
|
154
|
+
// Pre-requisite: the slug field on the collection schema
|
|
155
|
+
// must be `localized: true` — otherwise the resolver can't
|
|
156
|
+
// see it and this toggle has no effect. The widget below
|
|
157
|
+
// surfaces the path only when localized; the description
|
|
158
|
+
// makes this explicit.
|
|
159
|
+
name: 'translateSlug',
|
|
160
|
+
type: 'checkbox',
|
|
161
|
+
defaultValue: false,
|
|
162
|
+
admin: {
|
|
163
|
+
description: 'Include the slug field in translation runs for this surface. The slug field must also be `localized: true` on the collection schema for this to take effect — otherwise the toggle is a no-op. Applies to BOTH automation and the manual Translate… dialog.'
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
// Storage shape: `text hasMany` => Postgres join table.
|
|
168
|
+
// Parent array's `dbName: 'tr_st_pc'` keeps the generated
|
|
169
|
+
// join-table name under the 63-char identifier limit.
|
|
170
|
+
// Stored as opaque strings — the plugin doesn't enforce
|
|
171
|
+
// that listed paths currently exist, so renaming a field
|
|
172
|
+
// doesn't auto-clean stale entries. Stale entries are
|
|
173
|
+
// harmless downstream: the filter is a Set membership
|
|
174
|
+
// check; paths absent from the resolver don't match
|
|
175
|
+
// anything and pass through unchanged.
|
|
176
|
+
name: 'excludedFieldPaths',
|
|
177
|
+
type: 'text',
|
|
178
|
+
hasMany: true,
|
|
179
|
+
required: false,
|
|
180
|
+
admin: {
|
|
181
|
+
description: 'Fields excluded from translation for this surface. Applies to BOTH automation and the Translate… dialog — different from the AUTOMATION-ONLY flags above. Renders a checkbox list driven by the current "Slug" value: uncheck a field to opt it out of every translation path (auto + manual). Leave all checked to translate every detected field (back-compat default).',
|
|
182
|
+
components: {
|
|
183
|
+
Field: '@purposeinplay/payload-ai-translate/client#ExcludedFieldsField'
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
slug,
|
|
192
|
+
label: 'Translation Settings',
|
|
193
|
+
admin: {
|
|
194
|
+
group: 'System',
|
|
195
|
+
description: 'Configure runtime translation behaviour: which provider runs new translations and which locales auto-translate on publish.',
|
|
196
|
+
// Hide from non-admins — same posture as `translation-usage`.
|
|
197
|
+
hidden: ({ user })=>!user?.roles?.includes('admin')
|
|
198
|
+
},
|
|
199
|
+
access: {
|
|
200
|
+
read: options?.access?.read ?? defaultAdminAccess,
|
|
201
|
+
update: options?.access?.update ?? defaultAdminAccess
|
|
202
|
+
},
|
|
203
|
+
hooks: {
|
|
204
|
+
// Invalidate the `effective-locales` cache whenever the settings
|
|
205
|
+
// global is saved so admin edits propagate to the next publish
|
|
206
|
+
// cycle without waiting for the 30s TTL.
|
|
207
|
+
afterChange: [
|
|
208
|
+
()=>{
|
|
209
|
+
invalidateSettingsCache(slug);
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
},
|
|
213
|
+
graphQL: false,
|
|
214
|
+
fields
|
|
215
|
+
};
|
|
216
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { Payload, TaskConfig } from 'payload';
|
|
2
|
+
export declare const BULK_TRANSLATE_COORDINATOR_SLUG = "bulk-translate-coordinator";
|
|
3
|
+
export declare const BULK_TRANSLATE_DOC_TASK_SLUG = "bulk-translate-doc";
|
|
4
|
+
/**
|
|
5
|
+
* Coordinator persists this shape into `bulk-translate-batches
|
|
6
|
+
* .lastEnumerationCursor` so a crashed-mid-enumeration run can resume
|
|
7
|
+
* from where it left off rather than re-scan every doc on restart.
|
|
8
|
+
*
|
|
9
|
+
* Phase ordering: collections → globals → (canary sampling, when
|
|
10
|
+
* mode='canary') → done. Each phase is independently resumable.
|
|
11
|
+
*/
|
|
12
|
+
export type EnumerationCursor = {
|
|
13
|
+
phase: 'collections' | 'globals' | 'canary' | 'done';
|
|
14
|
+
collectionIndex: number;
|
|
15
|
+
page: number;
|
|
16
|
+
globalIndex: number;
|
|
17
|
+
};
|
|
18
|
+
export type BulkBatchScope = {
|
|
19
|
+
/**
|
|
20
|
+
* Collection slugs to enumerate. Required when targeting collection
|
|
21
|
+
* docs. Empty + `globals: []` is a no-op (the coordinator immediately
|
|
22
|
+
* transitions the batch to `completed` with `totalUnits: 0`).
|
|
23
|
+
*/
|
|
24
|
+
collections?: string[];
|
|
25
|
+
/** Global slugs to enumerate. */
|
|
26
|
+
globals?: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Target locales the batch should translate to. Coordinator creates
|
|
29
|
+
* one unit per (doc, locale). Must be non-empty.
|
|
30
|
+
*/
|
|
31
|
+
locales: string[];
|
|
32
|
+
/**
|
|
33
|
+
* Collections to skip even when listed in `collections`. Honors
|
|
34
|
+
* `BulkTranslateConfig.excludeCollections` (e.g. `users` per
|
|
35
|
+
* Decision #32 / F-SEC-USERS-BIO).
|
|
36
|
+
*/
|
|
37
|
+
excludeCollections?: string[];
|
|
38
|
+
/** Optional whitelist of specific doc IDs (scopes enumeration). */
|
|
39
|
+
documentIds?: string[];
|
|
40
|
+
/** Source locale snapshotted at enqueue. Used to read source docs. */
|
|
41
|
+
sourceLocale: string;
|
|
42
|
+
/** Batch mode. `canary` mode caps the unit count via `canaryLimit`. */
|
|
43
|
+
mode: 'changed' | 'force' | 'canary';
|
|
44
|
+
/** Canary fan-out cap (only meaningful when `mode === 'canary'`). */
|
|
45
|
+
canaryLimit?: number;
|
|
46
|
+
};
|
|
47
|
+
export interface BulkCoordinatorOptions {
|
|
48
|
+
/** Slug override for the batches collection. */
|
|
49
|
+
batchesCollectionSlug?: string;
|
|
50
|
+
/** Slug override for the units collection. */
|
|
51
|
+
unitsCollectionSlug?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Per-tick wall-clock budget. When the coordinator hits this limit
|
|
54
|
+
* mid-enumeration it persists the cursor and re-enqueues itself
|
|
55
|
+
* instead of running until Payload's job-runner times out.
|
|
56
|
+
*
|
|
57
|
+
* Default 25_000ms — well under Vercel Pro's 300s function ceiling
|
|
58
|
+
* and Payload's default `runJobs` async-function timeout.
|
|
59
|
+
*/
|
|
60
|
+
tickBudgetMs?: number;
|
|
61
|
+
/**
|
|
62
|
+
* Per-collection pagination size. Default 100 — Payload's local API
|
|
63
|
+
* defaults to 10, which would over-trample the jobs queue with
|
|
64
|
+
* coordinator re-enqueues.
|
|
65
|
+
*/
|
|
66
|
+
pageSize?: number;
|
|
67
|
+
/** Slug for the worker task. Mirrors `BULK_TRANSLATE_DOC_TASK_SLUG`. */
|
|
68
|
+
workerTaskSlug?: string;
|
|
69
|
+
}
|
|
70
|
+
type CoordinatorTaskInput = {
|
|
71
|
+
batchId: string;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Coordinator task that enumerates every (doc, locale) under
|
|
75
|
+
* `batch.scope`, inserts a `bulk-translate-units` row per unit and
|
|
76
|
+
* queues a `bulk-translate-doc` task per unit. Both ops are wrapped
|
|
77
|
+
* in a single transaction per (doc, locale) tuple to close F-DA-TOCTOU
|
|
78
|
+
* scenario A — the worker can never dequeue before the unit row has
|
|
79
|
+
* committed.
|
|
80
|
+
*
|
|
81
|
+
* Long enumerations trampoline: the task self-re-enqueues with the
|
|
82
|
+
* same `batchId` and a persisted `lastEnumerationCursor` once it hits
|
|
83
|
+
* `tickBudgetMs`. Resume from the cursor is exact (collection +
|
|
84
|
+
* pagination page), not approximate.
|
|
85
|
+
*
|
|
86
|
+
* For `mode: 'canary'`, the coordinator performs full enumeration
|
|
87
|
+
* (so the candidate pool is the same as `mode: 'changed'` would
|
|
88
|
+
* scope) and selects N units via random-stratified sampling keyed
|
|
89
|
+
* on `batchId` for reproducibility.
|
|
90
|
+
*/
|
|
91
|
+
export declare function buildBulkTranslateCoordinator(options?: BulkCoordinatorOptions): TaskConfig<{
|
|
92
|
+
input: CoordinatorTaskInput;
|
|
93
|
+
output: {
|
|
94
|
+
ok: true;
|
|
95
|
+
cursor: EnumerationCursor;
|
|
96
|
+
};
|
|
97
|
+
}>;
|
|
98
|
+
export type CoordinatorTickParams = {
|
|
99
|
+
payload: Payload;
|
|
100
|
+
batchId: string;
|
|
101
|
+
batchesSlug: string;
|
|
102
|
+
unitsSlug: string;
|
|
103
|
+
tickBudgetMs: number;
|
|
104
|
+
pageSize: number;
|
|
105
|
+
workerSlug: string;
|
|
106
|
+
/** Test override — injects current time for deterministic budget checks. */
|
|
107
|
+
now?: () => number;
|
|
108
|
+
};
|
|
109
|
+
export type CoordinatorTickResult = {
|
|
110
|
+
cursor: EnumerationCursor;
|
|
111
|
+
unitsCreated: number;
|
|
112
|
+
finished: boolean;
|
|
113
|
+
};
|
|
114
|
+
export declare function runCoordinatorTick(params: CoordinatorTickParams): Promise<CoordinatorTickResult>;
|
|
115
|
+
export {};
|