Files
MyGoNavi/frontend/src/components/data-sync/text.ts
Syngnat 56b46d95a8 fix(sync): constrain TDengine and IoTDB targets to append writes (#891)
## Summary

- expose append-only capability for TDengine and IoTDB targets
- constrain the delivery UI to INSERT/append and remove delete
propagation
- block mutation and delete configurations during backend preflight
- add Go and frontend regression coverage

## Verification

- Go sync capability and preflight regression tests passed
- frontend delivery and Wails DTO regression tests passed
- frontend production build passed
- Wails desktop build passed

Closes #883
2026-08-09 15:56:59 +08:00

873 lines
55 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const zhCN = {
'workbench.title': '数据迁移与同步',
'workbench.subtitle': '定义、验证并追踪跨数据源任务',
'workbench.close': '关闭工作台',
'workbench.new_task': '新建任务',
'workbench.save': '保存草稿',
'workbench.saving': '正在保存',
'workbench.saved': '已保存',
'workbench.unsaved': '有未保存修改',
'workbench.run_preflight': '运行预检',
'workbench.preflighting': '正在预检',
'workbench.start': '运行任务',
'workbench.enable': '启用任务',
'workbench.blocked_action': '先解决预检阻断项',
'nav.tasks': '任务',
'nav.runs': '运行记录',
'nav.schedules': '调度',
'nav.cdc': 'CDC',
'task_list.title': '任务',
'task_list.search': '搜索任务',
'task_list.empty': '没有匹配的任务',
'task_list.revision': '版本 {revision}',
'task_list.lifecycle.draft': '草稿',
'task_list.lifecycle.ready': '就绪',
'task_list.lifecycle.enabled': '已启用',
'task_list.lifecycle.paused': '已暂停',
'task_list.lifecycle.archived': '已归档',
'lifecycle.publish_ready': '发布为就绪',
'lifecycle.enable_schedule': '启用调度',
'lifecycle.pause': '暂停任务',
'lifecycle.resume_schedule': '重新启用',
'lifecycle.archive': '归档',
'task_kind.title': '选择任务类型',
'task_kind.subtitle': '类型决定可用的增量和触发策略,创建后仍可复制为其他任务。',
'task_kind.migration': '一次性迁移',
'task_kind.migration_desc': '迁移结构和数据,可创建目标对象。',
'task_kind.reconcile': '批次/差异同步',
'task_kind.reconcile_desc': '按主键执行快照比较或水位线增量。',
'task_kind.querySink': 'SQL 结果写入',
'task_kind.querySink_desc': '执行查询并把稳定结果写入目标表。',
'task_kind.compare': '只读比较',
'task_kind.compare_desc': '比较结构或数据,不修改目标端。',
'task_kind.cdc': '持续增量 CDC',
'task_kind.cdc_desc': '消费变更日志并持久化 checkpoint。',
'stage.endpoints': '选择源和目标',
'stage.mappings': '选择同步数据',
'stage.delivery': '目标写入',
'stage.trigger': '运行方式',
'stage.preflight': '检查并运行',
'route.source': '源端',
'route.target': '目标端',
'route.pending_source': '选择源连接',
'route.pending_target': '选择目标连接',
'route.capability.full': '完整支持',
'route.capability.partial': '兼容模式',
'route.capability.unsupported': '不支持',
'route.capability.unknown': '等待能力确认',
'route.database_fallback': '未选择库',
'editor.task_name': '任务名称',
'editor.task_name_placeholder': '例如:订单数据同步到分析库',
'editor.source_endpoint': '源端点',
'editor.target_endpoint': '目标端点',
'editor.connection': '已保存连接',
'editor.connection_id': '连接 ID',
'editor.connection_name': '连接名称',
'editor.database_type': '数据源类型',
'editor.database': 'Database / Catalog',
'editor.schema': 'Schema',
'editor.source_query': '源 SQL 查询',
'editor.source_query_placeholder': 'SELECT ...',
'editor.endpoint_help': '从已保存连接中选择端点;任务只保存连接引用,不保存账号、密码或连接串。',
'metadata.select_connection': '选择连接',
'metadata.select_database': '选择 Database / Catalog',
'metadata.not_selected': '未选择',
'metadata.schema_optional': '可选;留空使用默认命名空间',
'metadata.loading_connections': '正在加载连接',
'metadata.loading_databases': '正在加载数据库',
'metadata.loading_objects': '正在加载对象',
'metadata.loading_fields': '正在加载字段',
'metadata.loading_cdc_adapters': '正在加载 CDC 适配器',
'metadata.load_failed': '元数据加载失败',
'metadata.retry': '重试',
'metadata.no_eligible_connections': '没有符合当前读写方向的连接。',
'metadata.no_databases': '该连接未返回数据库列表,草稿仍可保存。',
'metadata.endpoint_required': '先选择端点',
'metadata.object_required': '先选择对象',
'metadata.objects_count': '{count} 个对象',
'metadata.fields_count': '{count} 个字段',
'mapping.title': '选择要同步的数据',
'mapping.help': '可选择一张、多张或筛选后的全部表。系统会自动匹配同名目标、识别主键并生成映射,你只需处理例外。',
'mapping.query_help': 'SQL 查询结果只写入一个目标对象;请选择已有目标表并配置写入键。',
'mapping.add': '添加映射',
'mapping.select_objects': '选择源对象',
'mapping.add_target': '添加目标对象',
'mapping.picker_title': '批量选择源对象',
'mapping.search_objects': '搜索表、视图或集合',
'mapping.include_views': '包含视图',
'mapping.selected_count': '已选 {selected} / 共 {total}',
'mapping.select_filtered': '全选当前筛选结果({count}',
'mapping.selection_fixed_scope': '保存时固化本次清单,后续新增表不会自动加入',
'mapping.object_kind.table': '表',
'mapping.object_kind.view': '视图',
'mapping.object_kind.collection': '集合',
'mapping.already_added': '已添加',
'mapping.rows_count': '{count} 行',
'mapping.no_objects': '没有匹配的对象',
'mapping.add_selected': '添加 {count} 个对象',
'mapping.detecting_keys': '正在识别主键…',
'mapping.open_object_list': '展开对象列表',
'mapping.will_create_named': '目标不存在,将创建“{name}”',
'mapping.no_matching_objects': '没有匹配的已有对象',
'mapping.remove': '删除',
'mapping.enabled': '启用',
'mapping.source': '源对象',
'mapping.target': '目标对象',
'mapping.target_mode': '目标不存在时',
'mapping.key_columns': '用于识别同一行',
'mapping.fields': '字段',
'mapping.status': '状态',
'mapping.create_or_reuse': '自动创建;已存在则校验后使用',
'mapping.existing_only': '仅写入已有目标',
'mapping.edit_exceptions': '编辑例外',
'mapping.collapse_exceptions': '收起',
'mapping.fields_count': '{count} 个字段',
'mapping.fields_pending': '自动同名写入',
'mapping.fields_automatic': '自动同名写入',
'mapping.fields_automatic_help': '无需逐列配置;仅在字段改名或转换时编辑。',
'mapping.fields_required': '需要确认同步字段',
'mapping.fields_cdc_help': '持续同步必须明确目标字段,避免源端删字段后目标残留旧值。',
'mapping.ready': '已配置',
'mapping.needs_attention': '需处理',
'mapping.key_placeholder': 'id, tenant_id',
'mapping.key_detected': '已从源端元数据自动识别,可按需修改',
'mapping.key_when_needed': '差异同步和 CDC 必须有稳定主键;一次性迁移可留空',
'mapping.source_placeholder': '搜索或选择源对象',
'mapping.target_placeholder': '搜索已有目标或输入新名称',
'mapping.query_result_source': '查询结果(唯一映射)',
'mapping.target_state.exists': '目标已存在',
'mapping.target_state.create': '将创建',
'mapping.target_state.missing': '未匹配目标',
'mapping.empty_title': '尚未选择同步对象',
'mapping.empty_desc': '先选择源对象。单表和多表使用同一个入口,也可以搜索后全选当前结果。',
'field_mapping.title': '字段映射',
'field_mapping.close': '收起',
'field_mapping.auto_match': '同名自动匹配',
'field_mapping.add': '添加字段',
'field_mapping.empty_title': '尚未配置字段映射',
'field_mapping.empty_desc': '加载两端字段后自动匹配,或手动添加并配置转换表达式。',
'field_mapping.source': '源字段',
'field_mapping.target': '目标字段',
'field_mapping.transform': '转换表达式',
'field_mapping.transform_placeholder': '留空表示直接写入',
'field_mapping.transform_identity': '直接写入',
'field_mapping.transform_argument': '参数 JSON可选',
'field_mapping.type': '类型',
'field_mapping.select_field': '选择字段',
'field_mapping.remove': '删除',
'delivery.title': '设置目标写入',
'delivery.help': '选择目标端如何写入及处理失败行。多数任务保留默认值即可;高风险和专业参数只在适用时显示。',
'delivery.write_mode': '写入模式',
'delivery.write.none': '只读',
'delivery.write.append': '追加',
'delivery.write.append_desc': '每次运行都新增记录;重复运行可能产生重复数据,系统会自动关闭重试。',
'delivery.write.upsert': '新增或更新',
'delivery.write.upsert_unavailable': '新增或更新(当前目标不支持)',
'delivery.write.upsert_desc': '按主键或唯一键识别同一行:不存在则新增,已存在则更新。',
'delivery.write.overwrite': '覆盖',
'delivery.write.overwrite_unavailable': '覆盖(当前任务系统暂不支持)',
'delivery.write.overwrite_desc': '当前没有原子替换保障,预检会阻止覆盖任务运行;请改用新增或更新。',
'delivery.read_only_title': '这是只读比较任务',
'delivery.read_only_note': '任务不会写入或删除目标端数据,因此无需配置写入、失败行处理和高级设置。',
'delivery.error_policy': '失败行处理',
'delivery.error.stop': '遇错停止',
'delivery.error.stop_desc': '任一行写入失败时立即停止,适合优先保证数据完整性的任务。',
'delivery.error.skip': '跳过错误行',
'delivery.error.skip_desc': '记录失败原因并继续处理后续行,不保存完整失败行。',
'delivery.error.quarantine': '隔离并允许重试',
'delivery.error.quarantine_desc': '完整失败行会保存在本机任务数据库中,可能包含敏感数据,可在错误行列表中重试。',
'delivery.batch_size': '批大小',
'delivery.commit_every': '提交间隔(行)',
'delivery.commit_every_note': '当前引擎按批大小提交,此值与批大小保持一致。',
'delivery.retry_limit': '重试次数',
'delivery.retry_backoff': '重试退避(毫秒)',
'delivery.row_isolation_note': '当前配置必须遇错停止。逐行跳过只适用于写入已有关系表,且不能同时自动建表、修改结构、同步删除或覆盖写入。',
'delivery.append_retry_note': '追加写入可能已部分落库,为避免重复写入,自动重试固定为 0。',
'delivery.append_only_target_note': '当前时序目标仅支持追加写入INSERT更新和删除不会同步。',
'delivery.propagate_deletes': '传播源端删除',
'delivery.delete_policy_title': '目标端删除策略',
'delivery.delete_risk_badge': '高风险',
'delivery.delete.snapshot_label': '删除源端已不存在的目标行',
'delivery.delete.snapshot_desc': '全量差异同步会按每张表的主键比对,并删除目标端中源端已不存在的行。',
'delivery.delete.cdc_label': '同步源端删除事件',
'delivery.delete.cdc_desc': 'CDC 收到删除事件后,会按键删除目标端对应行。',
'delivery.delete_risk_note': '目标端删除不可撤销。开启前请确认目标不是共享表,并在运行前核对预检范围。',
'delivery.advanced': '高级设置',
'delivery.advanced_help': '性能、重试与结构迁移',
'delivery.performance_title': '性能与重试',
'delivery.performance_help': '默认值适合多数任务;仅在明确了解目标端负载和幂等性时调整。',
'delivery.structure_title': '目标结构',
'delivery.structure_help': '仅对一次性迁移中的同名自动映射生效;显式字段、主键或改名映射不会显示这些选项。',
'delivery.auto_add_columns': '自动新增缺失字段',
'delivery.auto_add_columns_desc': '仅新增目标端缺少的字段,不修改或删除已有字段;执行 DDL 时可能短暂锁定目标表。',
'delivery.create_indexes': '复制可兼容的二级索引',
'delivery.create_indexes_desc': '仅在自动创建目标对象时复制源端可兼容的非主键索引;索引在数据写入后创建,会增加总耗时。',
'trigger.title': '设置运行方式',
'trigger.help': '选择手动、定时或持续运行,并按需要配置快照、水位线或 CDC 增量方式。',
'trigger.mode': '触发方式',
'trigger.manual': '手动',
'trigger.once': '指定时间',
'trigger.interval': '固定间隔',
'trigger.interval_seconds': '间隔(秒)',
'trigger.cron': 'Cron 调度',
'trigger.continuous': '持续运行',
'trigger.run_at': '执行时间',
'trigger.timezone': '时区',
'trigger.cron_expression': 'Cron 表达式',
'trigger.overlap': '任务重叠时',
'trigger.overlap.skip': '跳过本次',
'trigger.overlap.queue': '排队等待',
'incremental.mode': '增量策略',
'incremental.snapshot': '全量快照',
'incremental.watermark': '水位线',
'incremental.cdc': 'CDC 日志',
'incremental.watermark_column': '水位列',
'incremental.tie_breaker': '并列排序列',
'incremental.overlap_window': '重叠窗口(毫秒)',
'incremental.watermark_delivery_note': '水位线任务暂不支持追加语义InitialValue、重叠窗口和独立提交间隔尚未接入引擎因此不提供可编辑入口。',
'incremental.watermark_mixed_note': '此任务包含按对象配置的不同水位字段。当前显示第一项;编辑任一水位字段会统一全部对象。',
'incremental.initial_snapshot': '首次启动先执行全量快照',
'incremental.cdc_adapter': 'CDC 适配器',
'incremental.select_cdc_adapter': '选择适配器',
'incremental.start_position': '开始位置',
'incremental.position.latest': '最新位置',
'incremental.position.earliest': '最早位置',
'incremental.position.checkpoint': '上次 checkpoint',
'incremental.cdc_safety_title': 'CDC 起点安全边界',
'incremental.cdc_safety_note': '当前只支持从创建 latest barrier 之后,或从本任务已有 checkpoint 继续,以 at-least-once 方式消费变更。',
'incremental.cdc_snapshot_gap_warning': '如先单独执行快照再从 latest 启动,两者之间存在变更窗口,可能漏掉窗口内变更;当前不保证无缝衔接。',
'incremental.cdc_checkpoint_unavailable': '当前任务没有可用 checkpoint因此不能选择 checkpoint 起点。',
'preflight.title': '预检',
'preflight.stale': '配置已变化,需要重新预检',
'preflight.not_run': '尚未预检',
'preflight.running': '正在检查端点、映射和执行策略',
'preflight.blocked': '{count} 个阻断项',
'preflight.warning': '{count} 个警告',
'preflight.passed': '预检通过',
'preflight.empty': '配置完整后运行预检;问题会定位到对应阶段。',
'preflight.open_issue': '定位',
'preflight.current_revision': '基于任务版本 {revision}',
'preflight.approval_required': '生产写入需要审批',
'preflight.approval_not_required': '无需生产写入审批',
'preflight.approval_fail_closed': '尚未完成倒计时确认并取得一次性授权,保存到生产或运行操作保持禁用。',
'preflight.approval_granted': '一次性生产授权已取得',
'preflight.approval_begin_countdown': '开始服务端 10 秒确认',
'preflight.approval_beginning': '正在创建服务端确认',
'preflight.approval_countdown': '请等待 {seconds} 秒',
'preflight.approval_confirm': '确认生产写入并获取授权',
'preflight.approving': '正在获取授权',
'preflight.approval_expires': '授权仅保存在内存中,将于 {expiresAt} 失效,保存或运行后立即作废。',
'preflight.severity.blocker': '阻断',
'preflight.severity.warning': '警告',
'preflight.severity.info': '提示',
'preflight.index_remediation.title': '未迁移索引({count}',
'preflight.index_remediation.columns': '列:{columns}',
'preflight.index_remediation.copy': '复制补救 DDL',
'preflight.index_remediation.copy_failed': '复制失败,请从下方清单手动复制 DDL。',
'runs.title': '运行记录',
'runs.subtitle': '运行实例由 gateway 提供;后续接入持久化历史与 checkpoint。',
'runs.empty_title': '还没有运行记录',
'runs.empty_desc': '保存并运行任务后,这里会显示吞吐、错误行和 checkpoint。',
'runs.id': '运行 ID',
'runs.task': '任务',
'runs.status': '状态',
'runs.started_at': '开始时间',
'runs.rows_written': '写入行数',
'runs.rows_failed': '错误行',
'runs.checkpoint': 'Checkpoint',
'runs.view_errors': '查看错误行',
'runs.actions': '操作',
'runs.cancel': '取消',
'runs.resume': '继续',
'runs.retry': '重试运行',
'errors.title': '错误行',
'errors.empty_title': '没有隔离的错误行',
'errors.empty_desc': '选择失败运行后,可在这里查看、重试或导出错误行。',
'errors.source': '源对象',
'errors.reason': '原因',
'errors.payload': '数据预览',
'errors.retryable': '可重试',
'errors.retry': '重试行',
'errors.retry_unavailable': '后端尚未提供错误行重试接口,此操作保持禁用。',
'errors.discard': '丢弃',
'errors.discarded': '已丢弃',
'checkpoint.title': 'Checkpoint',
'checkpoint.empty': '所选运行没有持久化 checkpoint。',
'checkpoint.kind': '类型',
'checkpoint.phase': '阶段',
'checkpoint.updated_at': '更新时间',
'checkpoint.cursor': '游标',
'checkpoint.reset': '重置 checkpoint',
'checkpoint.reset_warning': '重置后不能从该位置继续CDC 任务将只能从新的 latest barrier 开始。',
'common.yes': '是',
'common.no': '否',
'common.refresh': '刷新',
'common.dismiss': '关闭',
'common.cancel': '取消',
'schedules.title': '调度',
'schedules.subtitle': '集中查看任务时区、Cron 和下一次执行。',
'schedules.empty_title': '还没有启用调度',
'schedules.empty_desc': '在任务的“触发与增量”阶段选择指定时间或 Cron。',
'cdc.title': 'CDC 源状态',
'cdc.subtitle': '状态来自适配器探测和任务 checkpoint后端未报告延迟时不会推测。',
'cdc.empty_title': '还没有可监控的 CDC 源',
'cdc.empty_desc': '创建 CDC 任务并完成权限探测后,这里会显示健康状态。',
'cdc.lag_unknown': '延迟未上报',
'cdc.status.ready': '适配器已就绪',
'cdc.status.probing': '正在探测',
'cdc.status.lagging': '延迟较高',
'cdc.status.offline': '源端离线',
'cdc.status.unsupported': '不支持',
'cdc.status.unknown': '状态未知',
'status.queued': '排队中',
'status.running': '运行中',
'status.cancelling': '正在取消',
'status.preflighting': '预检中',
'status.snapshotting': '快照中',
'status.catching_up': '追赶中',
'status.streaming': '持续同步',
'status.paused': '已暂停',
'status.succeeded': '成功',
'status.partial': '部分完成',
'status.failed': '失败',
'status.canceled': '已取消',
'status.cancelled': '已取消',
'status.interrupted': '已中断',
'validation.definition_invalid': '任务定义无效,请检查必填项、对象映射和执行策略。',
'validation.definition_hash_failed': '无法生成任务定义指纹,请检查任务配置。',
'validation.task_name_required': '填写任务名称。',
'validation.source_connection_required': '选择源连接。',
'validation.target_connection_required': '选择目标连接。',
'validation.source_connection_failed': '无法解析源连接,请确认已保存连接仍存在且配置完整。',
'validation.target_connection_failed': '无法解析目标连接,请确认已保存连接仍存在且配置完整。',
'validation.source_connect_failed': '无法初始化源数据库连接。',
'validation.source_ping_failed': '源数据库连通性检查失败。',
'validation.target_connect_failed': '无法初始化目标数据库连接。',
'validation.target_ping_failed': '目标数据库连通性检查失败。',
'validation.same_endpoint': '源端和目标端指向同一个位置,请确认不会覆盖源数据。',
'validation.same_object': '源对象和目标对象指向同一个物理对象,不能执行同步。',
'validation.route_unsupported': '当前源端与目标端组合不支持执行此同步任务。',
'validation.source_query_required': '填写源 SQL 查询。',
'validation.source_query_not_read_only': '源 SQL 必须是单条只读查询。',
'validation.mapping_required': '至少启用一条对象映射。',
'validation.source_object_required': '填写源对象名称。',
'validation.target_object_required': '填写目标对象名称。',
'validation.duplicate_source_object': '同一个源对象只能添加一次。',
'validation.duplicate_target_object': '多个映射指向同一个目标对象。',
'validation.mapping_compile_failed': '对象或字段映射无法编译,请检查映射与转换配置。',
'validation.source_columns_failed': '读取源对象字段失败,请检查对象名和元数据权限。',
'validation.target_columns_failed': '读取目标对象字段失败,请检查对象名和元数据权限。',
'validation.source_column_missing': '配置的源字段不存在。',
'validation.target_column_missing': '配置的目标字段不存在。',
'validation.key_column_missing': '配置的源端主键或唯一键字段不存在。',
'validation.watermark_column_missing': '配置的水位列在源对象中不存在。',
'validation.target_table_check_failed': '检查目标表是否存在时失败。',
'validation.target_table_missing': '目标表不存在,且当前任务不能自动创建该表。',
'validation.target_table_will_be_created': '目标表不存在,运行时将由迁移规划器自动创建。',
'validation.key_columns_required': '差异同步或 CDC 必须配置主键或唯一键。',
'validation.batch_size_invalid': '批大小必须是 1 到 10000 的整数。',
'validation.commit_every_invalid': '提交间隔必须不小于批大小。',
'validation.target_protection_blocked': '目标连接的安全保护策略禁止此次写入。',
'validation.row_error_isolation_unsupported': '当前任务不满足逐行跳过/隔离的安全条件。',
'validation.append_retry_unsupported': '追加写入不允许自动重试,以免重复写入。',
'validation.append_retry_unsafe': '追加写入不能自动重试,否则可能重复写入已提交的数据。',
'validation.append_resume_unsafe': '追加写入任务必须禁用断点恢复,否则可能重放已提交批次。',
'validation.full_overwrite_non_atomic': '持久任务暂不支持非原子全量覆盖,以免失败后留下空表或半表。',
'validation.write_mode_required': '可执行同步任务必须选择明确的写入模式。',
'validation.watermark_append_unsupported': '水位线任务暂不支持追加写入语义。',
'validation.watermark_tie_breaker_required': '水位线任务必须配置稳定的并列排序列或主键。',
'validation.watermark_initial_value_unsupported': '当前尚未实现水位初始值,请移除该配置。',
'validation.watermark_runtime_unsupported': '当前源端、目标端或执行策略不满足水位线同步条件。',
'validation.watermark_overwrite_unsupported': '水位线任务不支持全量覆盖。',
'validation.watermark_delete_unsupported': '水位线任务无法推断源端删除;请改用 CDC 或快照差异同步。',
'validation.query_sink_single_mapping_required': 'SQL 结果写入必须且只能配置一条目标映射。',
'validation.query_key_required': 'SQL 结果更新写入必须配置且只能配置一个稳定键。',
'validation.query_target_pk_mismatch': 'SQL 结果的稳定键必须映射到目标表唯一的主键。',
'validation.query_schema_runtime_validation': 'SQL 结果字段名将在实际执行只读查询时再与映射校验。',
'validation.watermark_column_required': '水位线模式必须配置水位列。',
'validation.cron_expression_required': '填写 Cron 表达式。',
'validation.timezone_required': '填写调度时区。',
'validation.interval_invalid': '固定间隔必须不少于 60 秒。',
'validation.cdc_incremental_required': 'CDC 任务必须使用 CDC 增量策略。',
'validation.cdc_trigger_required': 'CDC 任务必须持续运行。',
'validation.cdc_adapter_required': '选择 CDC 适配器。',
'validation.cdc_initial_snapshot_unsupported': '当前 CDC 不支持安全的初始快照衔接。',
'validation.cdc_initial_snapshot_handoff_unsupported': '当前 CDC 无法保证初始快照与变更流无缝衔接,请关闭初始快照。',
'validation.cdc_earliest_unsupported': '当前 CDC 适配器不支持从最早位置启动。',
'validation.cdc_probe_failed': 'CDC 能力与权限探测失败。',
'validation.cdc_adapter_not_ready': '所选 CDC 适配器当前未就绪。',
'validation.cdc_existing_target_required': 'CDC 任务当前只能写入已存在的目标表。',
'validation.cdc_upsert_required': 'CDC 任务必须使用“新增或更新”写入模式,以保证可安全重放。',
'validation.cdc_target_non_atomic': 'CDC 行隔离和 checkpoint 顺序要求目标端支持原子关系型写入。',
'validation.cdc_authoritative_columns_required': 'CDC 任务必须显式配置源字段到目标字段的映射。',
'validation.cdc_checkpoint_unavailable': '无法读取 CDC checkpoint。',
'validation.cdc_checkpoint_required': '选择 checkpoint 起点前必须存在兼容的持久化 checkpoint。',
'validation.cdc_checkpoint_incompatible': '已存在的 CDC checkpoint 与当前任务定义不兼容,请在暂停任务后显式重置。',
'validation.compare_route_unsupported': '当前源端与目标端组合不支持执行数据比对。',
'validation.index_inspection_failed': '无法读取源端索引元数据,不能确认所有索引都已迁移。',
'validation.unmigrated_index': '有索引无法自动迁移,请在执行前审核候选补救 DDL。',
'validation.capability_unverified': '当前使用静态 gateway运行前仍需后端确认数据源组合能力。',
'validation.unknown': '预检发现未识别的配置问题。',
} as const;
export type DataSyncWorkbenchTextKey = keyof typeof zhCN;
/**
* Literal keys owned by the Data Sync workbench's feature-local catalog.
* Exported so the repository-wide i18n scanner can validate these calls
* against the same catalog contract instead of treating them as global keys.
*/
export const DATA_SYNC_WORKBENCH_TEXT_KEYS: readonly DataSyncWorkbenchTextKey[] =
Object.freeze(Object.keys(zhCN) as DataSyncWorkbenchTextKey[]);
const enUS: Record<DataSyncWorkbenchTextKey, string> = {
'workbench.title': 'Data migration and sync',
'workbench.subtitle': 'Define, validate, and track cross-source jobs',
'workbench.close': 'Close workbench',
'workbench.new_task': 'New task',
'workbench.save': 'Save draft',
'workbench.saving': 'Saving',
'workbench.saved': 'Saved',
'workbench.unsaved': 'Unsaved changes',
'workbench.run_preflight': 'Run preflight',
'workbench.preflighting': 'Running preflight',
'workbench.start': 'Run task',
'workbench.enable': 'Enable task',
'workbench.blocked_action': 'Resolve preflight blockers first',
'nav.tasks': 'Tasks',
'nav.runs': 'Runs',
'nav.schedules': 'Schedules',
'nav.cdc': 'CDC',
'task_list.title': 'Tasks',
'task_list.search': 'Search tasks',
'task_list.empty': 'No matching tasks',
'task_list.revision': 'Revision {revision}',
'task_list.lifecycle.draft': 'Draft',
'task_list.lifecycle.ready': 'Ready',
'task_list.lifecycle.enabled': 'Enabled',
'task_list.lifecycle.paused': 'Paused',
'task_list.lifecycle.archived': 'Archived',
'lifecycle.publish_ready': 'Publish as ready',
'lifecycle.enable_schedule': 'Enable schedule',
'lifecycle.pause': 'Pause task',
'lifecycle.resume_schedule': 'Re-enable',
'lifecycle.archive': 'Archive',
'task_kind.title': 'Choose a task type',
'task_kind.subtitle': 'The type determines incremental and trigger options. You can copy it into another task later.',
'task_kind.migration': 'One-time migration',
'task_kind.migration_desc': 'Move schema and data, with target object creation.',
'task_kind.reconcile': 'Batch / difference sync',
'task_kind.reconcile_desc': 'Compare snapshots or use a watermark by key.',
'task_kind.querySink': 'SQL result sink',
'task_kind.querySink_desc': 'Run a query and write its stable result to a target table.',
'task_kind.compare': 'Read-only compare',
'task_kind.compare_desc': 'Compare schema or data without changing the target.',
'task_kind.cdc': 'Continuous CDC',
'task_kind.cdc_desc': 'Consume change logs and persist checkpoints.',
'stage.endpoints': 'Choose source and target',
'stage.mappings': 'Choose data',
'stage.delivery': 'Target writes',
'stage.trigger': 'Run settings',
'stage.preflight': 'Check and run',
'route.source': 'Source',
'route.target': 'Target',
'route.pending_source': 'Choose source connection',
'route.pending_target': 'Choose target connection',
'route.capability.full': 'Full support',
'route.capability.partial': 'Compatibility mode',
'route.capability.unsupported': 'Unsupported',
'route.capability.unknown': 'Awaiting capability check',
'route.database_fallback': 'No database selected',
'editor.task_name': 'Task name',
'editor.task_name_placeholder': 'For example: Sync orders to analytics',
'editor.source_endpoint': 'Source endpoint',
'editor.target_endpoint': 'Target endpoint',
'editor.connection': 'Saved connection',
'editor.connection_id': 'Connection ID',
'editor.connection_name': 'Connection name',
'editor.database_type': 'Source type',
'editor.database': 'Database / Catalog',
'editor.schema': 'Schema',
'editor.source_query': 'Source SQL query',
'editor.source_query_placeholder': 'SELECT ...',
'editor.endpoint_help': 'Choose from saved connections. Tasks store only connection references, never usernames, passwords, or connection strings.',
'metadata.select_connection': 'Choose a connection',
'metadata.select_database': 'Choose a database / catalog',
'metadata.not_selected': 'Not selected',
'metadata.schema_optional': 'Optional; blank uses the default namespace',
'metadata.loading_connections': 'Loading connections',
'metadata.loading_databases': 'Loading databases',
'metadata.loading_objects': 'Loading objects',
'metadata.loading_fields': 'Loading fields',
'metadata.loading_cdc_adapters': 'Loading CDC adapters',
'metadata.load_failed': 'Metadata failed to load',
'metadata.retry': 'Retry',
'metadata.no_eligible_connections': 'No connection supports this read/write direction.',
'metadata.no_databases': 'This connection returned no databases. The draft can still be saved.',
'metadata.endpoint_required': 'Choose an endpoint first',
'metadata.object_required': 'Choose an object first',
'metadata.objects_count': '{count} objects',
'metadata.fields_count': '{count} fields',
'mapping.title': 'Choose data to sync',
'mapping.help': 'Choose one, many, or all filtered tables. The workbench matches same-name targets, detects keys, and generates mappings so you only handle exceptions.',
'mapping.query_help': 'A SQL query writes to one target object. Choose an existing target table and configure the write key.',
'mapping.add': 'Add mapping',
'mapping.select_objects': 'Choose source objects',
'mapping.add_target': 'Add target object',
'mapping.picker_title': 'Choose source objects in bulk',
'mapping.search_objects': 'Search tables, views, or collections',
'mapping.include_views': 'Include views',
'mapping.selected_count': '{selected} selected / {total} total',
'mapping.select_filtered': 'Select all filtered results ({count})',
'mapping.selection_fixed_scope': 'This list is fixed when saved; future tables are not added automatically',
'mapping.object_kind.table': 'Table',
'mapping.object_kind.view': 'View',
'mapping.object_kind.collection': 'Collection',
'mapping.already_added': 'Already added',
'mapping.rows_count': '{count} rows',
'mapping.no_objects': 'No matching objects',
'mapping.add_selected': 'Add {count} objects',
'mapping.detecting_keys': 'Detecting keys…',
'mapping.open_object_list': 'Open object list',
'mapping.will_create_named': 'Target does not exist; “{name}” will be created',
'mapping.no_matching_objects': 'No matching existing objects',
'mapping.remove': 'Remove',
'mapping.enabled': 'Enabled',
'mapping.source': 'Source object',
'mapping.target': 'Target object',
'mapping.target_mode': 'If the target is missing',
'mapping.key_columns': 'Identify the same row by',
'mapping.fields': 'Fields',
'mapping.status': 'Status',
'mapping.create_or_reuse': 'Create automatically; validate and reuse if present',
'mapping.existing_only': 'Write only to an existing target',
'mapping.edit_exceptions': 'Edit exception',
'mapping.collapse_exceptions': 'Collapse',
'mapping.fields_count': '{count} fields',
'mapping.fields_pending': 'Automatic same-name fields',
'mapping.fields_automatic': 'Automatic same-name fields',
'mapping.fields_automatic_help': 'No per-column setup is needed unless a field is renamed or transformed.',
'mapping.fields_required': 'Confirm synchronized fields',
'mapping.fields_cdc_help': 'Continuous sync needs explicit target fields so removed source fields do not leave stale target values.',
'mapping.ready': 'Configured',
'mapping.needs_attention': 'Needs attention',
'mapping.key_placeholder': 'id, tenant_id',
'mapping.key_detected': 'Detected from source metadata; edit if needed',
'mapping.key_when_needed': 'Difference sync and CDC need a stable key; one-time migration may leave this blank',
'mapping.source_placeholder': 'Search or choose a source object',
'mapping.target_placeholder': 'Search an existing target or enter a new name',
'mapping.query_result_source': 'Query result (single mapping)',
'mapping.target_state.exists': 'Target exists',
'mapping.target_state.create': 'Will create',
'mapping.target_state.missing': 'Target not matched',
'mapping.empty_title': 'No sync objects selected',
'mapping.empty_desc': 'Choose source objects first. The same picker handles one table, many tables, or all current search results.',
'field_mapping.title': 'Field mappings',
'field_mapping.close': 'Collapse',
'field_mapping.auto_match': 'Match same names',
'field_mapping.add': 'Add field',
'field_mapping.empty_title': 'No field mappings yet',
'field_mapping.empty_desc': 'Load both sides and match by name, or add a row and enter a transform.',
'field_mapping.source': 'Source field',
'field_mapping.target': 'Target field',
'field_mapping.transform': 'Transform',
'field_mapping.transform_placeholder': 'Blank writes the value directly',
'field_mapping.transform_identity': 'Identity',
'field_mapping.transform_argument': 'Argument JSON (optional)',
'field_mapping.type': 'Type',
'field_mapping.select_field': 'Choose a field',
'field_mapping.remove': 'Remove',
'delivery.title': 'Configure target writes',
'delivery.help': 'Choose how the target is written and how failed rows are handled. Defaults fit most tasks; risky and specialist options appear only when applicable.',
'delivery.write_mode': 'Write mode',
'delivery.write.none': 'Read only',
'delivery.write.append': 'Append',
'delivery.write.append_desc': 'Each run inserts new rows. Re-running may create duplicates, so automatic retries are disabled.',
'delivery.write.upsert': 'Insert or update',
'delivery.write.upsert_unavailable': 'Insert or update (not supported by this target)',
'delivery.write.upsert_desc': 'Use a primary or unique key to identify a row: insert when missing and update when present.',
'delivery.write.overwrite': 'Overwrite',
'delivery.write.overwrite_unavailable': 'Overwrite (not yet supported for jobs)',
'delivery.write.overwrite_desc': 'Atomic replacement is not available, so preflight blocks overwrite jobs. Use insert or update instead.',
'delivery.read_only_title': 'This is a read-only comparison',
'delivery.read_only_note': 'The task never writes to or deletes from the target, so delivery, failed-row handling, and advanced settings do not apply.',
'delivery.error_policy': 'Failed-row handling',
'delivery.error.stop': 'Stop on error',
'delivery.error.stop_desc': 'Stop as soon as any row fails to write. Use this when data completeness is the priority.',
'delivery.error.skip': 'Skip bad rows',
'delivery.error.skip_desc': 'Record the failure and continue with later rows without storing the complete failed row.',
'delivery.error.quarantine': 'Quarantine and retry later',
'delivery.error.quarantine_desc': 'Store the complete failed row in the local task database. It may contain sensitive data and can be retried from the error-row list.',
'delivery.batch_size': 'Batch size',
'delivery.commit_every': 'Commit interval (rows)',
'delivery.commit_every_note': 'The current engine commits by batch size, so this value follows batch size.',
'delivery.retry_limit': 'Retry limit',
'delivery.retry_backoff': 'Retry backoff (ms)',
'delivery.row_isolation_note': 'This configuration must stop on error. Row-level skip is available only for existing relational targets without auto-create, schema changes, delete propagation, or overwrite.',
'delivery.append_retry_note': 'Append writes may be partially committed. Automatic retries stay at zero to prevent duplicates.',
'delivery.append_only_target_note': 'This time-series target supports append/INSERT-only delivery; updates and deletes are not synchronized.',
'delivery.propagate_deletes': 'Propagate source deletes',
'delivery.delete_policy_title': 'Target deletion policy',
'delivery.delete_risk_badge': 'High risk',
'delivery.delete.snapshot_label': 'Delete target rows missing from the source',
'delivery.delete.snapshot_desc': 'A full reconcile compares each table by key and deletes target rows that no longer exist in the source.',
'delivery.delete.cdc_label': 'Apply source delete events',
'delivery.delete.cdc_desc': 'When CDC receives a delete event, it deletes the matching target row by key.',
'delivery.delete_risk_note': 'Target deletes cannot be undone. Confirm the target is not shared and review the preflight scope before running.',
'delivery.advanced': 'Advanced settings',
'delivery.advanced_help': 'Performance, retries, and schema migration',
'delivery.performance_title': 'Performance and retries',
'delivery.performance_help': 'The defaults fit most tasks. Adjust only when you understand target load and retry idempotency.',
'delivery.structure_title': 'Target schema',
'delivery.structure_help': 'Available only for automatic same-name mappings in one-time migrations. Explicit fields, keys, or renamed mappings hide these options.',
'delivery.auto_add_columns': 'Add missing target columns',
'delivery.auto_add_columns_desc': 'Only adds columns missing from the target; existing columns are not changed or removed. DDL may briefly lock the target table.',
'delivery.create_indexes': 'Copy compatible secondary indexes',
'delivery.create_indexes_desc': 'Copies compatible non-primary indexes only when the target is auto-created. Indexes are created after data is loaded and increase total run time.',
'trigger.title': 'Configure run settings',
'trigger.help': 'Choose manual, scheduled, or continuous execution, then configure snapshot, watermark, or CDC incrementality when needed.',
'trigger.mode': 'Trigger',
'trigger.manual': 'Manual',
'trigger.once': 'At a specified time',
'trigger.interval': 'Fixed interval',
'trigger.interval_seconds': 'Interval (seconds)',
'trigger.cron': 'Cron schedule',
'trigger.continuous': 'Continuous',
'trigger.run_at': 'Run at',
'trigger.timezone': 'Timezone',
'trigger.cron_expression': 'Cron expression',
'trigger.overlap': 'When runs overlap',
'trigger.overlap.skip': 'Skip this run',
'trigger.overlap.queue': 'Queue this run',
'incremental.mode': 'Incremental policy',
'incremental.snapshot': 'Full snapshot',
'incremental.watermark': 'Watermark',
'incremental.cdc': 'CDC log',
'incremental.watermark_column': 'Watermark column',
'incremental.tie_breaker': 'Tie-breaker column',
'incremental.overlap_window': 'Overlap window (ms)',
'incremental.watermark_delivery_note': 'Watermark jobs do not yet support append semantics. InitialValue, overlap windows, and independent commit intervals are not wired to the engine and therefore have no editable controls.',
'incremental.watermark_mixed_note': 'This task has per-object watermark differences. The first is shown; editing either field unifies all object mappings.',
'incremental.initial_snapshot': 'Run a full snapshot before the first stream',
'incremental.cdc_adapter': 'CDC adapter',
'incremental.select_cdc_adapter': 'Choose an adapter',
'incremental.start_position': 'Start position',
'incremental.position.latest': 'Latest position',
'incremental.position.earliest': 'Earliest position',
'incremental.position.checkpoint': 'Last checkpoint',
'incremental.cdc_safety_title': 'CDC start-position boundary',
'incremental.cdc_safety_note': 'The current guarantee is at-least-once consumption after a newly created latest barrier, or continuation from this task\'s existing checkpoint.',
'incremental.cdc_snapshot_gap_warning': 'A separate snapshot followed by latest leaves a change window and may miss changes in that window. Seamless handoff is not guaranteed.',
'incremental.cdc_checkpoint_unavailable': 'This task has no usable checkpoint, so checkpoint start is unavailable.',
'preflight.title': 'Preflight',
'preflight.stale': 'Configuration changed; run preflight again',
'preflight.not_run': 'Preflight has not run',
'preflight.running': 'Checking endpoints, mappings, and execution policy',
'preflight.blocked': '{count} blockers',
'preflight.warning': '{count} warnings',
'preflight.passed': 'Preflight passed',
'preflight.empty': 'Complete the configuration and run preflight. Issues link back to their stage.',
'preflight.open_issue': 'Locate',
'preflight.current_revision': 'Based on task revision {revision}',
'preflight.approval_required': 'Production write approval required',
'preflight.approval_not_required': 'No production write approval required',
'preflight.approval_fail_closed': 'Save-to-production and run stay disabled until countdown confirmation grants a one-time token.',
'preflight.approval_granted': 'One-time production authorization granted',
'preflight.approval_begin_countdown': 'Begin server 10-second confirmation',
'preflight.approval_beginning': 'Starting server confirmation',
'preflight.approval_countdown': 'Wait {seconds} seconds',
'preflight.approval_confirm': 'Confirm production write and grant token',
'preflight.approving': 'Requesting authorization',
'preflight.approval_expires': 'The token is memory-only, expires at {expiresAt}, and is invalidated after save or run.',
'preflight.severity.blocker': 'Blocker',
'preflight.severity.warning': 'Warning',
'preflight.severity.info': 'Info',
'preflight.index_remediation.title': 'Unmigrated indexes ({count})',
'preflight.index_remediation.columns': 'Columns: {columns}',
'preflight.index_remediation.copy': 'Copy remediation DDL',
'preflight.index_remediation.copy_failed': 'Copy failed. Copy the DDL manually from the list below.',
'runs.title': 'Run history',
'runs.subtitle': 'Run instances come from the gateway; persisted history and checkpoints plug in later.',
'runs.empty_title': 'No runs yet',
'runs.empty_desc': 'After a task runs, throughput, error rows, and checkpoints appear here.',
'runs.id': 'Run ID',
'runs.task': 'Task',
'runs.status': 'Status',
'runs.started_at': 'Started',
'runs.rows_written': 'Rows written',
'runs.rows_failed': 'Error rows',
'runs.checkpoint': 'Checkpoint',
'runs.view_errors': 'View error rows',
'runs.actions': 'Actions',
'runs.cancel': 'Cancel',
'runs.resume': 'Resume',
'runs.retry': 'Retry run',
'errors.title': 'Error rows',
'errors.empty_title': 'No quarantined rows',
'errors.empty_desc': 'Choose a failed run to inspect, retry, or export bad rows.',
'errors.source': 'Source object',
'errors.reason': 'Reason',
'errors.payload': 'Payload preview',
'errors.retryable': 'Retryable',
'errors.retry': 'Retry row',
'errors.retry_unavailable': 'The backend does not expose an error-row retry API, so this action stays disabled.',
'errors.discard': 'Discard',
'errors.discarded': 'Discarded',
'checkpoint.title': 'Checkpoint',
'checkpoint.empty': 'The selected run has no durable checkpoint.',
'checkpoint.kind': 'Kind',
'checkpoint.phase': 'Phase',
'checkpoint.updated_at': 'Updated',
'checkpoint.cursor': 'Cursor',
'checkpoint.reset': 'Reset checkpoint',
'checkpoint.reset_warning': 'Reset removes the resume position. CDC can then start only from a new latest barrier.',
'common.yes': 'Yes',
'common.no': 'No',
'common.refresh': 'Refresh',
'common.dismiss': 'Dismiss',
'common.cancel': 'Cancel',
'schedules.title': 'Schedules',
'schedules.subtitle': 'Review timezones, Cron expressions, and next runs in one place.',
'schedules.empty_title': 'No enabled schedules',
'schedules.empty_desc': 'Choose a one-time or Cron trigger in the task editor.',
'cdc.title': 'CDC source status',
'cdc.subtitle': 'Status comes from adapter probes and task checkpoints. Lag is never inferred when the backend does not report it.',
'cdc.empty_title': 'No CDC sources to monitor',
'cdc.empty_desc': 'Create a CDC task and probe its permissions to see source health here.',
'cdc.lag_unknown': 'Lag not reported',
'cdc.status.ready': 'Adapter ready',
'cdc.status.probing': 'Probing',
'cdc.status.lagging': 'Lagging',
'cdc.status.offline': 'Source offline',
'cdc.status.unsupported': 'Unsupported',
'cdc.status.unknown': 'Unknown',
'status.queued': 'Queued',
'status.running': 'Running',
'status.cancelling': 'Cancelling',
'status.preflighting': 'Preflighting',
'status.snapshotting': 'Snapshotting',
'status.catching_up': 'Catching up',
'status.streaming': 'Streaming',
'status.paused': 'Paused',
'status.succeeded': 'Succeeded',
'status.partial': 'Partial',
'status.failed': 'Failed',
'status.canceled': 'Canceled',
'status.cancelled': 'Cancelled',
'status.interrupted': 'Interrupted',
'validation.definition_invalid': 'The task definition is invalid. Check required fields, object mappings, and execution policies.',
'validation.definition_hash_failed': 'The task definition fingerprint could not be generated. Check the task configuration.',
'validation.task_name_required': 'Enter a task name.',
'validation.source_connection_required': 'Choose a source connection.',
'validation.target_connection_required': 'Choose a target connection.',
'validation.source_connection_failed': 'The source saved connection could not be resolved. Verify that it still exists and is complete.',
'validation.target_connection_failed': 'The target saved connection could not be resolved. Verify that it still exists and is complete.',
'validation.source_connect_failed': 'The source database connection could not be initialized.',
'validation.source_ping_failed': 'The source database connectivity check failed.',
'validation.target_connect_failed': 'The target database connection could not be initialized.',
'validation.target_ping_failed': 'The target database connectivity check failed.',
'validation.same_endpoint': 'Source and target point to the same location. Confirm that source data cannot be overwritten.',
'validation.same_object': 'Source and target resolve to the same physical object, so this sync cannot run.',
'validation.route_unsupported': 'The selected source-target route cannot execute this sync task.',
'validation.source_query_required': 'Enter the source SQL query.',
'validation.source_query_not_read_only': 'The source SQL must be one read-only query.',
'validation.mapping_required': 'Enable at least one object mapping.',
'validation.source_object_required': 'Enter a source object name.',
'validation.target_object_required': 'Enter a target object name.',
'validation.duplicate_source_object': 'Each source object can be added only once.',
'validation.duplicate_target_object': 'Multiple mappings target the same object.',
'validation.mapping_compile_failed': 'The object or field mapping could not be compiled. Check mappings and transforms.',
'validation.source_columns_failed': 'Source fields could not be read. Check the object name and metadata permissions.',
'validation.target_columns_failed': 'Target fields could not be read. Check the object name and metadata permissions.',
'validation.source_column_missing': 'A configured source field does not exist.',
'validation.target_column_missing': 'A configured target field does not exist.',
'validation.key_column_missing': 'A configured source key field does not exist.',
'validation.watermark_column_missing': 'The configured watermark field does not exist on the source object.',
'validation.target_table_check_failed': 'The target table existence check failed.',
'validation.target_table_missing': 'The target table does not exist and this task cannot create it automatically.',
'validation.target_table_will_be_created': 'The target table does not exist and will be created by the migration planner.',
'validation.key_columns_required': 'Difference sync and CDC require a primary or unique key.',
'validation.batch_size_invalid': 'Batch size must be an integer from 1 to 10000.',
'validation.commit_every_invalid': 'Commit interval must be at least the batch size.',
'validation.target_protection_blocked': 'The target connection protection policy blocks this write.',
'validation.row_error_isolation_unsupported': 'This task does not meet the safety requirements for row skip or quarantine.',
'validation.append_retry_unsupported': 'Append writes cannot retry automatically because that could duplicate rows.',
'validation.append_retry_unsafe': 'Append writes cannot retry automatically because committed rows could be duplicated.',
'validation.append_resume_unsafe': 'Append jobs must disable resume because committed batches cannot be replayed safely.',
'validation.full_overwrite_non_atomic': 'Persistent jobs cannot use non-atomic full overwrite because failure could leave an empty or partial table.',
'validation.write_mode_required': 'Executable sync tasks require an explicit write mode.',
'validation.watermark_append_unsupported': 'Watermark jobs do not yet support append delivery semantics.',
'validation.watermark_tie_breaker_required': 'Watermark jobs require a stable tie-breaker field or key.',
'validation.watermark_initial_value_unsupported': 'Watermark initial values are not implemented. Remove this setting.',
'validation.watermark_runtime_unsupported': 'The selected source, target, or execution policy cannot run watermark sync.',
'validation.watermark_overwrite_unsupported': 'Watermark jobs cannot use full overwrite.',
'validation.watermark_delete_unsupported': 'Watermark jobs cannot infer source deletes. Use CDC or snapshot reconcile.',
'validation.query_sink_single_mapping_required': 'A SQL result sink must have exactly one target mapping.',
'validation.query_key_required': 'SQL result upsert requires exactly one stable key.',
'validation.query_target_pk_mismatch': 'The SQL result stable key must map to the target table\'s single primary key.',
'validation.query_schema_runtime_validation': 'SQL result field names will be checked against the mapping when the read-only query runs.',
'validation.watermark_column_required': 'Watermark mode requires a watermark column.',
'validation.cron_expression_required': 'Enter a Cron expression.',
'validation.timezone_required': 'Enter a scheduling timezone.',
'validation.interval_invalid': 'Fixed intervals must be at least 60 seconds.',
'validation.cdc_incremental_required': 'CDC tasks must use the CDC incremental policy.',
'validation.cdc_trigger_required': 'CDC tasks must run continuously.',
'validation.cdc_adapter_required': 'Choose a CDC adapter.',
'validation.cdc_initial_snapshot_unsupported': 'The current CDC reader cannot safely hand off from an initial snapshot.',
'validation.cdc_initial_snapshot_handoff_unsupported': 'The current CDC reader cannot guarantee a gap-free initial snapshot handoff. Disable initial snapshot.',
'validation.cdc_earliest_unsupported': 'The current CDC adapter cannot start from the earliest position.',
'validation.cdc_probe_failed': 'CDC capability and permission probing failed.',
'validation.cdc_adapter_not_ready': 'The selected CDC adapter is not ready.',
'validation.cdc_existing_target_required': 'CDC jobs currently require existing target tables.',
'validation.cdc_upsert_required': 'CDC jobs must use upsert delivery so events can be replayed safely.',
'validation.cdc_target_non_atomic': 'CDC row isolation and checkpoint ordering require an atomic relational target.',
'validation.cdc_authoritative_columns_required': 'CDC jobs require explicit source-to-target field mappings.',
'validation.cdc_checkpoint_unavailable': 'The CDC checkpoint could not be read.',
'validation.cdc_checkpoint_required': 'Checkpoint start requires a compatible durable checkpoint for this task.',
'validation.cdc_checkpoint_incompatible': 'The stored CDC checkpoint is incompatible with this task. Pause the task and reset it explicitly.',
'validation.compare_route_unsupported': 'The selected source-target route cannot execute compare tasks.',
'validation.index_inspection_failed': 'Source index metadata could not be read, so complete index migration cannot be verified.',
'validation.unmigrated_index': 'An index could not be migrated automatically. Review the remediation DDL before execution.',
'validation.capability_unverified': 'This task uses the static gateway. The backend must still verify the source-target capability before execution.',
'validation.unknown': 'Preflight found an unrecognized configuration issue.',
};
export type DataSyncWorkbenchLocale = 'zh-CN' | 'en-US';
export const resolveDataSyncWorkbenchLocale = (
language?: string,
): DataSyncWorkbenchLocale =>
String(language || '').toLowerCase().startsWith('zh') ? 'zh-CN' : 'en-US';
export type DataSyncWorkbenchTranslate = (
key: DataSyncWorkbenchTextKey,
params?: Record<string, string | number>,
) => string;
export const createDataSyncWorkbenchTranslate = (
language?: string,
): DataSyncWorkbenchTranslate => {
const catalog = resolveDataSyncWorkbenchLocale(language) === 'zh-CN' ? zhCN : enUS;
return (key, params) => {
let value = catalog[key] || key;
Object.entries(params || {}).forEach(([name, replacement]) => {
value = value.split(`{${name}}`).join(String(replacement));
});
return value;
};
};
/**
* Stable validation codes are the localization contract. Backend messages are
* retained only as a diagnostic fallback for unknown driver/runtime errors.
*/
export const dataSyncValidationIssueText = (
issue: { code: string; message?: string },
t: DataSyncWorkbenchTranslate,
): string => {
const key = `validation.${issue.code}` as DataSyncWorkbenchTextKey;
const localized = t(key);
if (localized !== key) return localized;
return String(issue.message || '').trim() || t('validation.unknown');
};