const TRANSLATION_PAIRS = [ { zh: '正在检查登录状态...', en: 'Checking login status...' }, { zh: '请稍候,系统正在验证会话。', en: 'Please wait, verifying your session.' }, { zh: 'InSAR 自动化管理系统', en: 'InSAR Automation Management System' }, { zh: '科研工程模式', en: 'Research Engineering Mode' }, { zh: '已授权', en: 'Licensed' }, { zh: '未授权', en: 'Unlicensed' }, { zh: '管理员', en: 'Admin' }, { zh: '只读账号', en: 'Read-only account' }, { zh: '任务', en: 'Tasks' }, { zh: '授权至', en: 'License until' }, { zh: '刷新自检状态', en: 'Refresh health status' }, { zh: '自检中...', en: 'Checking...' }, { zh: '刷新自检', en: 'Refresh Health' }, { zh: '退出登录', en: 'Sign Out' }, { zh: '数据管理', en: 'Data' }, { zh: '生产规划', en: 'Production' }, { zh: 'D-InSAR 分析', en: 'D-InSAR Analysis' }, { zh: '水体监测(旧)', en: 'Water Monitoring (Legacy)' }, { zh: '运行维护', en: 'Operations' }, { zh: '入库监控', en: 'Ingest Monitor' }, { zh: '数据列表', en: 'Data List' }, { zh: '灾害点', en: 'Hazard Points' }, { zh: '配对规划', en: 'Pair Planning' }, { zh: '任务规划', en: 'Task Planning' }, { zh: '任务批次', en: 'Task Batches' }, { zh: '数据分发', en: 'Data Distribution' }, { zh: 'D-InSAR生产', en: 'D-InSAR Production' }, { zh: 'D-InSAR 结果', en: 'D-InSAR Results' }, { zh: 'AI 质量评估', en: 'AI Quality Assessment' }, { zh: '运维自检', en: 'Health Check' }, { zh: '用户管理', en: 'User Management' }, { zh: '审计日志', en: 'Audit Logs' }, { zh: '刷新源数据', en: 'Refresh Source Data' }, { zh: '统计', en: 'Statistics' }, { zh: '源数据检索', en: 'Source Data Search' }, { zh: '卫星:全部', en: 'Satellite: All' }, { zh: '成像模式:全部', en: 'Imaging Mode: All' }, { zh: '成像时间起:不限', en: 'Imaging Date From: Any' }, { zh: '成像时间止:不限', en: 'Imaging Date To: Any' }, { zh: '极化方式:全部', en: 'Polarization: All' }, { zh: '产品级别:全部', en: 'Product Level: All' }, { zh: 'AOI: 不限', en: 'AOI: Any' }, { zh: 'AOI: 行政区', en: 'AOI: Region' }, { zh: 'AOI: 上传SHP', en: 'AOI: Upload SHP' }, { zh: '搜索', en: 'Search' }, { zh: '重置', en: 'Reset' }, { zh: '选择省份', en: 'Select Province' }, { zh: '选择地市(可选)', en: 'Select City (Optional)' }, { zh: '高级字段', en: 'Advanced Fields' }, { zh: '卫星模式:全部', en: 'Satellite Mode: All' }, { zh: '接收站:全部', en: 'Receiving Station: All' }, { zh: '轨道圈号:全部', en: 'Orbit Circle: All' }, { zh: '采集时间:全部', en: 'Acquisition Time: All' }, { zh: '产品类型:全部', en: 'Product Type: All' }, { zh: '产品唯一ID:全部', en: 'Product Unique ID: All' }, { zh: '轨道方向:全部', en: 'Orbit Direction: All' }, { zh: '有精轨:全部', en: 'Precise Orbit: All' }, { zh: '有精轨:是', en: 'Precise Orbit: Yes' }, { zh: '有精轨:否', en: 'Precise Orbit: No' }, { zh: 'ENVI已处理:全部', en: 'ENVI Processed: All' }, { zh: 'ENVI已处理:是', en: 'ENVI Processed: Yes' }, { zh: 'ENVI已处理:否', en: 'ENVI Processed: No' }, { zh: '源数据检索选项加载中...', en: 'Loading source data search options...' }, { zh: '无源数据', en: 'No source data.' }, { zh: '覆盖面全部显示/隐藏', en: 'Toggle all coverage' }, { zh: '源影像一键显示', en: 'Show All Source Previews' }, { zh: '源影像一键隐藏', en: 'Hide All Source Previews' }, { zh: '上一页', en: 'Previous' }, { zh: '下一页', en: 'Next' }, { zh: '每页', en: 'Per page' }, { zh: '条', en: 'items' }, { zh: '跳到', en: 'Go to' }, { zh: '页', en: 'page' }, { zh: '跳转', en: 'Jump' }, { zh: '提示:可跳转页码范围为', en: 'Tip: valid page range is' }, { zh: '按 Enter 可快速跳转。', en: 'Press Enter to jump.' }, { zh: '未找到 Dinsar 结果。', en: 'No D-InSAR results found.' }, { zh: '清除筛选', en: 'Clear Filter' }, { zh: '一键显示', en: 'Show All' }, { zh: '一键隐藏', en: 'Hide All' }, { zh: '隐藏日期', en: 'Hide Dates' }, { zh: '显示日期', en: 'Show Dates' }, { zh: 'AI 评分过滤', en: 'AI Score Filter' }, { zh: '过滤低于此分数的低质量结果', en: 'Filter low-quality results below this score' }, { zh: '主影像日期', en: 'Master date' }, { zh: '辅影像日期', en: 'Slave date' }, { zh: '标记为高质量', en: 'Mark as high quality' }, { zh: '标记为低质量', en: 'Mark as low quality' }, { zh: '良好', en: 'Good' }, { zh: '欠佳', en: 'Poor' }, { zh: '使用 AI 自动分析此结果', en: 'Use AI to analyze this result' }, { zh: 'AI 诊断', en: 'AI Diagnose' }, { zh: '在地图上显示/隐藏', en: 'Show/hide on map' }, { zh: 'AI 质量评分', en: 'AI quality score' }, { zh: '影像信息', en: 'Image Information' }, { zh: '卫星:', en: 'Satellite:' }, { zh: '卫星模式:', en: 'Satellite Mode:' }, { zh: '接收站:', en: 'Receiving Station:' }, { zh: '成像日期:', en: 'Imaging Date:' }, { zh: '成像模式:', en: 'Imaging Mode:' }, { zh: '轨道圈号:', en: 'Orbit Circle:' }, { zh: '场景中心经度:', en: 'Scene Center Lon:' }, { zh: '场景中心纬度:', en: 'Scene Center Lat:' }, { zh: '采集时间:', en: 'Acquisition Time:' }, { zh: '产品类型:', en: 'Product Type:' }, { zh: '极化方式:', en: 'Polarization:' }, { zh: '产品级别:', en: 'Product Level:' }, { zh: '产品唯一ID:', en: 'Product Unique ID:' }, { zh: '轨道方向:', en: 'Orbit Direction:' }, { zh: '有精轨:', en: 'Has Orbit:' }, { zh: '轨道文件:', en: 'Orbit File:' }, { zh: 'ENVI已处理:', en: 'ENVI Processed:' }, { zh: '关闭', en: 'Close' }, { zh: '是', en: 'Yes' }, { zh: '否', en: 'No' }, { zh: '未知', en: 'Unknown' }, { zh: '加载中', en: 'Loading' }, { zh: '失败', en: 'Failed' }, { zh: '成功', en: 'Succeeded' }, // AiQualityPanel { zh: '基于标注结果训练随机森林模型,并对所有结果进行质量预测。', en: 'Train a random forest model based on labeled results and predict quality for all results.' }, { zh: '已标注', en: 'Labeled' }, { zh: '良好', en: 'Good' }, { zh: '欠佳', en: 'Poor' }, { zh: '处理中...', en: 'Processing...' }, { zh: '训练模型', en: 'Train Model' }, { zh: '至少需要2个样本 (包含好和坏) 才能训练。', en: 'At least 2 samples (good and bad) are required to train.' }, { zh: '预测所有结果', en: 'Predict All Results' }, { zh: '请先训练模型。', en: 'Please train the model first.' }, // PairingPanel { zh: '基于时间基线、footprint 中心距与两景 footprint 最小重叠率筛选干涉对,可选 AOI 限定范围。', en: 'Filter interferometric pairs by temporal baseline, footprint center distance, and pair footprint overlap ratio. Optional AOI constraint.' }, { zh: '配对', en: 'Pair' }, { zh: '时序准备', en: 'Timeseries Prep' }, { zh: '结果与刷新', en: 'Results & Refresh' }, { zh: '已生成配对', en: 'Generated Pairs' }, { zh: '已选中', en: 'Selected' }, { zh: '刷新当前检索', en: 'Refresh Current Search' }, { zh: '刷新结果', en: 'Refresh Results' }, // BatchPanel { zh: '刷新中...', en: 'Refreshing...' }, { zh: '刷新批次', en: 'Refresh Batches' }, { zh: '-- 选择批次 --', en: '-- Select Batch --' }, { zh: '全部完成', en: 'Mark All Done' }, { zh: '请选择一个批次查看明细。', en: 'Select a batch to view details.' }, { zh: '该批次暂无明细。', en: 'No items in this batch.' }, { zh: '未审核', en: 'Pending' }, { zh: '审核中', en: 'In Review' }, { zh: '可下发', en: 'Approved' }, { zh: '不宜下发', en: 'Rejected' }, { zh: '备注', en: 'Remark' }, { zh: '保存', en: 'Save' }, // --- Base layers (appConstants) --- { zh: 'Google 影像', en: 'Google Imagery' }, { zh: '高德 影像', en: 'Gaode Imagery' }, { zh: '高德 矢量', en: 'Gaode Vector' }, // --- Preview status (appUiHelpers) --- { zh: '回退', en: 'Fallback' }, { zh: '纠正', en: 'Ortho' }, { zh: '未建', en: 'None' }, // --- App.jsx: map & region --- { zh: '区域定位', en: 'Region Locator' }, { zh: '底图', en: 'Base Map' }, { zh: '日志', en: 'Logs' }, { zh: '暂无日志。', en: 'No logs.' }, { zh: '收起', en: 'Collapse' }, { zh: '当前定位', en: 'Current Location' }, { zh: '定位中...', en: 'Locating...' }, { zh: '定位到选中区域', en: 'Zoom to Region' }, { zh: '清除定位高亮', en: 'Clear Highlight' }, { zh: '可只选到省/市级进行定位。', en: 'Select province or city to locate.' }, { zh: '可只选到省/市级,系统将自动使用当前选中层级边界。', en: 'Select province or city level; the system will use the selected boundary.' }, // --- App.jsx: pairing modal --- { zh: 'D-InSAR 配对参数', en: 'D-InSAR Pairing Parameters' }, { zh: '配对提示', en: 'Pairing Info' }, { zh: '回退模式', en: 'Fallback Mode' }, { zh: '已选择', en: 'Selected' }, { zh: '保存批次', en: 'Save Batch' }, { zh: '清空结果', en: 'Clear Results' }, { zh: '预览', en: 'Preview' }, { zh: '全选', en: 'Select All' }, { zh: '起始日期 (只考虑此日期后的影像)', en: 'Start Date (only images after this date)' }, { zh: 'AOI 来源:', en: 'AOI Source:' }, { zh: '上传SHP', en: 'Upload SHP' }, { zh: '行政区选择', en: 'Region Selection' }, { zh: '限定范围 (Shapefile,可选):', en: 'AOI Constraint (Shapefile, optional):' }, { zh: '选择文件...', en: 'Select File...' }, { zh: '行政区范围:', en: 'Region Boundary:' }, { zh: 'AOI 覆盖率阈值 (0 表示不限制):', en: 'AOI Coverage Threshold (0 = unlimited):' }, { zh: '成像模式一致', en: 'Consistent Imaging Mode' }, { zh: '极化一致', en: 'Consistent Polarization' }, { zh: '仅使用有精轨数据的影像', en: 'Only Precise-orbit Images' }, { zh: '开始配对', en: 'Start Pairing' }, { zh: '取消', en: 'Cancel' }, // --- App.jsx: PS modal --- { zh: '准备时序InSAR候选栈', en: 'Prepare Time-series InSAR Stack' }, { zh: '研究区域来源:', en: 'Study Area Source:' }, { zh: '研究区域 (Shapefile):', en: 'Study Area (Shapefile):' }, { zh: '准备并导出', en: 'Prepare & Export' }, // --- App.jsx: province/city selects --- { zh: '-- 省级 --', en: '-- Province --' }, { zh: '-- 地市 --', en: '-- City --' }, // --- App.jsx: misc UI --- { zh: '仅管理员可访问用户管理。', en: 'Admin access only.' }, { zh: '仅管理员可访问审计日志。', en: 'Admin access only.' }, { zh: '当前账号为只读用户,无法执行写操作。', en: 'Read-only account, no write access.' }, { zh: '当前账号为只读权限,无法执行此操作。如需操作,请联系管理员升级权限。', en: 'Read-only account. Contact admin to request write access.' }, { zh: '任务已入队,等待处理...', en: 'Task queued, pending...' }, // --- IDLAutomationPanel --- { zh: 'SARscape 处理中心', en: 'SARscape Processing Center' }, { zh: '已安装', en: 'Installed' }, { zh: '未检测到', en: 'Not Detected' }, { zh: '运行中', en: 'Running' }, { zh: '引擎', en: 'Engine' }, { zh: '任务运行中', en: 'Task Running' }, { zh: '强制解锁', en: 'Force Unlock' }, { zh: '输入管理员密码', en: 'Enter admin password' }, { zh: '确认取消', en: 'Confirm Cancel' }, { zh: '按钮已锁定,等待任务完成', en: 'Buttons locked, waiting for task completion' }, { zh: 'Task 状态总览', en: 'Task Status Overview' }, { zh: '加载中...', en: 'Loading...' }, { zh: '刷新', en: 'Refresh' }, { zh: '填写下方数据目录后点击刷新', en: 'Enter data directory below and click Refresh' }, { zh: '已导入', en: 'Imported' }, { zh: '已处理', en: 'Processed' }, { zh: '已提取', en: 'Extracted' }, { zh: '结构', en: 'Structure' }, { zh: '修改时间', en: 'Modified' }, { zh: 'Step 1: 数据导入 (Import)', en: 'Step 1: Data Import' }, { zh: '扫描目录下的 LuTan-1 原始数据 (*.meta.xml),转换为 ENVI SARscape 格式 (*.sml)。', en: 'Scan LuTan-1 raw data (*.meta.xml) and convert to ENVI SARscape format (*.sml).' }, { zh: '支持 Task_*/master|slave 结构和平铺目录。', en: 'Supports Task_*/master|slave structure and flat directories.' }, { zh: '数据目录 (root_dir)', en: 'Data Directory (root_dir)' }, { zh: '最大处理数', en: 'Max Items' }, { zh: '0 = 不限制', en: '0 = No limit' }, { zh: '预检查', en: 'Pre-check' }, { zh: '开始导入', en: 'Start Import' }, { zh: 'Import 检查结果', en: 'Import Check Results' }, { zh: 'Step 2: D-InSAR 生产', en: 'Step 2: D-InSAR Processing' }, { zh: '对 Task_* 目录执行 D-InSAR 位移生成。', en: 'Execute D-InSAR displacement processing on Task_* directories.' }, { zh: '未导入的数据将自动先执行 Import,再进行 D-InSAR 处理。', en: 'Unimported data will be auto-imported before D-InSAR processing.' }, { zh: 'DEM 路径由系统配置管理,无需手动指定。', en: 'DEM path is managed by system configuration.' }, { zh: '默认处理', en: 'Default Processing' }, { zh: '自定义处理', en: 'Custom Processing' }, { zh: '调用 ENVI SARscape metatask 一键执行全流程。参数:3×3 多视、默认自适应滤波、自动 GCP 精配准。', en: 'Runs ENVI SARscape metatask end-to-end: 3×3 multilooking, adaptive filtering, auto GCP co-registration.' }, { zh: '逐步调用各处理模块,参数可控。多视:动态计算、GOLDSTEIN 滤波、自动 GCP、相干阈值 coh=0.05。', en: 'Step-by-step modules: dynamic multilooking, Goldstein filtering, auto GCP, coherence threshold 0.05.' }, { zh: 'D-InSAR 检查结果', en: 'D-InSAR Check Results' }, { zh: 'Step 3: 结果提取', en: 'Step 3: Result Extraction' }, { zh: '将 D-InSAR 生产结果中的 disp 文件提取到扫描目录,以便系统识别。', en: 'Extract displacement files from D-InSAR results to the scan directory.' }, { zh: '提取 Disp 结果', en: 'Extract Disp Results' }, { zh: '目标目录', en: 'Target Directory' }, { zh: '新增', en: 'Added' }, { zh: '更新', en: 'Updated' }, { zh: '跳过', en: 'Skipped' }, { zh: '处理', en: 'Processed' }, { zh: '任务历史', en: 'Run History' }, { zh: '暂无运行记录', en: 'No run records' }, { zh: '自动导入', en: 'Auto-imported' }, { zh: '自定义', en: 'Custom' }, { zh: '从列表移除', en: 'Remove' }, { zh: '消息', en: 'Message' }, { zh: '处理统计', en: 'Processing Statistics' }, { zh: '近期运行结果', en: 'Recent Run Results' }, { zh: '平均耗时 (秒)', en: 'Avg Duration (s)' }, { zh: '平均耗时 (s)', en: 'Avg Duration (s)' }, { zh: '结果入库趋势', en: 'Result Import Trend' }, { zh: '入库数量', en: 'Imported Count' }, { zh: '其他', en: 'Other' }, { zh: '就绪', en: 'Ready' }, { zh: '未就绪', en: 'Not Ready' }, { zh: '状态', en: 'Status' }, { zh: '查看日志', en: 'View Log' }, { zh: '文件大小', en: 'File Size' }, { zh: '已截断,仅显示末尾', en: 'Truncated, showing last' }, // --- IDLAutomationPanel: dynamic messages --- { zh: '执行失败', en: 'Execution failed' }, { zh: '未知错误', en: 'Unknown error' }, { zh: '只读账号无法提交任务。', en: 'Read-only account cannot submit tasks.' }, { zh: '请填写数据目录。', en: 'Please enter data directory.' }, { zh: '只读账号无法执行提取。', en: 'Read-only account cannot run extraction.' }, { zh: '已自动触发结果扫描入库', en: 'Auto-triggered result scan' }, { zh: '扫描入库触发失败', en: 'Result scan trigger failed' }, { zh: '提取完成', en: 'Extraction complete' }, { zh: '总览加载失败', en: 'Overview load failed' }, { zh: '任务已强制取消,前端已解锁。', en: 'Task force-cancelled, UI unlocked.' }, { zh: '强制解锁失败', en: 'Force unlock failed' }, { zh: '任务已入队', en: 'Task queued' }, // --- HazardPointPanel --- { zh: '地质灾害点监测', en: 'Geological Hazard Monitoring' }, { zh: '隐藏全部', en: 'Hide All' }, { zh: '显示全部', en: 'Show All' }, { zh: '同步中...', en: 'Syncing...' }, { zh: '同步 Shapefile 数据', en: 'Sync Shapefile' }, { zh: '搜索编号、名称、市县...', en: 'Search ID, name, city...' }, { zh: '未找到匹配的灾害点', en: 'No matching hazard points' }, { zh: '获取灾害点失败', en: 'Failed to load hazard points' }, { zh: '当前账号为只读模式,无法同步灾害点。', en: 'Read-only account cannot sync hazard points.' }, { zh: '正在发起灾害点同步任务...', en: 'Starting hazard point sync...' }, { zh: '正在同步灾害点数据...', en: 'Syncing hazard point data...' }, { zh: '同步失败', en: 'Sync failed' }, // --- DataMonitorPanel --- { zh: '数据监控面板', en: 'Data Monitor' }, { zh: '路径摘要', en: 'Path Summary' }, { zh: '未配置', en: 'Not configured' }, { zh: '监控模式', en: 'Monitor Mode' }, { zh: '手动', en: 'Manual' }, { zh: '配置', en: 'Config' }, { zh: '归档解包', en: 'Archive Unpack' }, { zh: '来源目录', en: 'Source Dir' }, { zh: '轨道', en: 'Orbit' }, { zh: '活动任务', en: 'Active Tasks' }, { zh: '当前无活动任务。', en: 'No active tasks.' }, { zh: '扫描雷达数据', en: 'Scan Radar Data' }, { zh: '扫描精轨数据', en: 'Scan Orbit Data' }, { zh: '扫描D-InSAR结果', en: 'Scan D-InSAR Results' }, { zh: '实时日志', en: 'Live Logs' }, { zh: '暂无日志...', en: 'No logs...' }, { zh: '运行中...', en: 'Running...' }, { zh: '运行解包', en: 'Run Unpack' }, { zh: '只读模式', en: 'Read-only' }, { zh: '当前账号为只读模式,无法触发扫描。', en: 'Read-only account cannot trigger scans.' }, { zh: '当前账号为只读模式,无法触发解包任务。', en: 'Read-only account cannot trigger unpack.' }, { zh: '解包任务启动中...', en: 'Starting unpack task...' }, { zh: '解包任务已启动', en: 'Unpack task started' }, { zh: '雷达数据', en: 'Radar data' }, { zh: '精轨数据', en: 'Orbit data' }, { zh: 'D-InSAR结果', en: 'D-InSAR results' }, { zh: '仅手动模式。路径从 .env 读取;如需修改请更新 .env 并重启后端。', en: 'Manual mode. Paths loaded from .env; update .env and restart backend to modify.' }, { zh: '未加载到监控状态,请检查后端 /api/monitor/status。', en: 'Monitor status not loaded. Check backend /api/monitor/status.' }, { zh: '触发失败', en: 'Trigger failed' }, // --- DataCopierPanel --- { zh: '已完成', en: 'Completed' }, { zh: 'PS 分发', en: 'PS Distribution' }, { zh: 'D-InSAR 分发', en: 'D-InSAR Distribution' }, { zh: '当前账号为只读模式,无法发起复制任务。', en: 'Read-only account cannot run copy tasks.' }, { zh: '当前账号为只读模式,无法执行复制任务。', en: 'Read-only account cannot run copy tasks.' }, { zh: '请选择批次并设置目标目录。', en: 'Select batch and set target directory.' }, { zh: '请至少选择一个任务状态。', en: 'Select at least one task status.' }, { zh: '启动失败', en: 'Start failed' }, { zh: '选择批次', en: 'Select Batch' }, { zh: '-- 请选择 --', en: '-- Select --' }, { zh: '任务状态筛选', en: 'Task Status Filter' }, { zh: '目标目录', en: 'Target Directory' }, { zh: '复制中...', en: 'Copying...' }, { zh: '开始复制', en: 'Start Copy' }, { zh: '等待任务...', en: 'Waiting for task...' }, { zh: '默认仅复制"已完成"项。', en: 'Only "Completed" items are copied by default.' }, // --- WaterMonitorPanel (status labels) --- { zh: '等待中', en: 'Pending' }, { zh: '完成', en: 'Done' }, { zh: '共', en: 'Total' }, // --- App.jsx: log messages --- { zh: '搜索全部源数据', en: 'Search All' }, ]; const ZH_TO_EN = [...TRANSLATION_PAIRS].sort((a, b) => b.zh.length - a.zh.length); const EN_TO_ZH = [...TRANSLATION_PAIRS].sort((a, b) => b.en.length - a.en.length); const EXCEPTION_HINT_PATTERNS = [ /\btraceback\b/i, /\b(?:[A-Za-z_]\w*)(?:Error|Exception)\b/, /\bNoneType\b/, /\bobject is not callable\b/i, /File "[^"]+", line \d+/, /\bat\s+\S+\s+\([^)]*:\d+:\d+\)/, /\bASGI\b/, /\buvicorn\b/i, /\bstatus_code\b/i, /\bSQLSTATE\b/i, ]; const escapeForRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const shouldBypassTranslation = (text) => EXCEPTION_HINT_PATTERNS.some((pattern) => pattern.test(text)); const replaceAllPairs = (text, pairs, fromKey, toKey) => { let output = text; pairs.forEach((item) => { const source = item[fromKey]; const target = item[toKey]; if (!source) return; output = output.replace(new RegExp(escapeForRegExp(source), 'g'), target); }); return output; }; export const translateText = (text, language) => { if (typeof text !== 'string' || !text) return text; if (shouldBypassTranslation(text)) return text; if (language === 'en') { return replaceAllPairs(text, ZH_TO_EN, 'zh', 'en'); } return replaceAllPairs(text, EN_TO_ZH, 'en', 'zh'); }; export const SUPPORTED_LANGUAGES = ['zh', 'en'];