mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-02 03:55:55 +00:00
clean the shit of ai
This commit is contained in:
@@ -1,151 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
AI翻译工作流i18n - 使用完整短语翻译而非词汇替换
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
from typing import Dict, List
|
||||
|
||||
def has_chinese(text: str) -> bool:
|
||||
"""检查文本是否包含中文字符"""
|
||||
return bool(re.search(r'[\u4e00-\u9fff]', text))
|
||||
|
||||
def load_translations() -> Dict:
|
||||
"""加载翻译文件"""
|
||||
with open('workflows_translations.json', 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
def save_translations(data: Dict):
|
||||
"""保存翻译文件"""
|
||||
with open('workflows_translations.json', 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
# 完整短语翻译字典 - 第一批(基础UI和操作)
|
||||
TRANSLATIONS_BATCH_1 = {
|
||||
# 基础操作
|
||||
"工作流": {"es-ES": "Flujo de trabajo", "ru-RU": "Рабочий процесс", "th-TH": "เวิร์กโฟลว์", "vi-VN": "Quy trình làm việc"},
|
||||
"节点": {"es-ES": "Nodo", "ru-RU": "Узел", "th-TH": "โหนด", "vi-VN": "Nút"},
|
||||
"创建工作流": {"es-ES": "Crear flujo de trabajo", "ru-RU": "Создать рабочий процесс", "th-TH": "สร้างเวิร์กโฟลว์", "vi-VN": "Tạo quy trình làm việc"},
|
||||
"从侧边栏选择": {"es-ES": "Seleccionar desde la barra lateral", "ru-RU": "Выбрать из боковой панели", "th-TH": "เลือกจากแถบด้านข้าง", "vi-VN": "Chọn từ thanh bên"},
|
||||
"编辑工作流": {"es-ES": "Editar flujo de trabajo", "ru-RU": "Редактировать рабочий процесс", "th-TH": "แก้ไขเวิร์กโฟลว์", "vi-VN": "Chỉnh sửa quy trình làm việc"},
|
||||
"新建工作流": {"es-ES": "Nuevo flujo de trabajo", "ru-RU": "Новый рабочий процесс", "th-TH": "เวิร์กโฟลว์ใหม่", "vi-VN": "Quy trình làm việc mới"},
|
||||
"获取工作流列表失败": {"es-ES": "Error al obtener la lista de flujos de trabajo", "ru-RU": "Не удалось получить список рабочих процессов", "th-TH": "ไม่สามารถรับรายการเวิร์กโฟลว์", "vi-VN": "Không thể lấy danh sách quy trình làm việc"},
|
||||
"工作流名称": {"es-ES": "Nombre del flujo de trabajo", "ru-RU": "Название рабочего процесса", "th-TH": "ชื่อเวิร์กโฟลว์", "vi-VN": "Tên quy trình làm việc"},
|
||||
"工作流描述": {"es-ES": "Descripción del flujo de trabajo", "ru-RU": "Описание рабочего процесса", "th-TH": "คำอธิบายเวิร์กโฟลว์", "vi-VN": "Mô tả quy trình làm việc"},
|
||||
"工作流名称不能为空": {"es-ES": "El nombre del flujo de trabajo no puede estar vacío", "ru-RU": "Название рабочего процесса не может быть пустым", "th-TH": "ชื่อเวิร์กโฟลว์ไม่สามารถว่างเปล่า", "vi-VN": "Tên quy trình làm việc không được để trống"},
|
||||
"默认工作流描述": {"es-ES": "Descripción predeterminada del flujo de trabajo", "ru-RU": "Описание рабочего процесса по умолчанию", "th-TH": "คำอธิบายเวิร์กโฟลว์เริ่มต้น", "vi-VN": "Mô tả quy trình làm việc mặc định"},
|
||||
|
||||
# 成功/失败消息
|
||||
"保存成功": {"es-ES": "Guardado exitosamente", "ru-RU": "Успешно сохранено", "th-TH": "บันทึกสำเร็จ", "vi-VN": "Lưu thành công"},
|
||||
"保存失败": {"es-ES": "Error al guardar", "ru-RU": "Не удалось сохранить", "th-TH": "บันทึกล้มเหลว", "vi-VN": "Lưu thất bại"},
|
||||
"创建成功": {"es-ES": "Creado exitosamente", "ru-RU": "Успешно создано", "th-TH": "สร้างสำเร็จ", "vi-VN": "Tạo thành công"},
|
||||
"创建失败": {"es-ES": "Error al crear", "ru-RU": "Не удалось создать", "th-TH": "สร้างล้มเหลว", "vi-VN": "Tạo thất bại"},
|
||||
"删除成功": {"es-ES": "Eliminado exitosamente", "ru-RU": "Успешно удалено", "th-TH": "ลบสำเร็จ", "vi-VN": "Xóa thành công"},
|
||||
"删除失败": {"es-ES": "Error al eliminar", "ru-RU": "Не удалось удалить", "th-TH": "ลบล้มเหลว", "vi-VN": "Xóa thất bại"},
|
||||
"复制成功": {"es-ES": "Copiado exitosamente", "ru-RU": "Успешно скопировано", "th-TH": "คัดลอกสำเร็จ", "vi-VN": "Sao chép thành công"},
|
||||
"复制失败": {"es-ES": "Error al copiar", "ru-RU": "Не удалось скопировать", "th-TH": "คัดลอกล้มเหลว", "vi-VN": "Sao chép thất bại"},
|
||||
"导出成功": {"es-ES": "Exportado exitosamente", "ru-RU": "Успешно экспортировано", "th-TH": "ส่งออกสำเร็จ", "vi-VN": "Xuất thành công"},
|
||||
"导入成功": {"es-ES": "Importado exitosamente", "ru-RU": "Успешно импортировано", "th-TH": "นำเข้าสำเร็จ", "vi-VN": "Nhập thành công"},
|
||||
"导入失败": {"es-ES": "Error al importar", "ru-RU": "Не удалось импортировать", "th-TH": "นำเข้าล้มเหลว", "vi-VN": "Nhập thất bại"},
|
||||
"发布成功": {"es-ES": "Publicado exitosamente", "ru-RU": "Успешно опубликовано", "th-TH": "เผยแพร่สำเร็จ", "vi-VN": "Xuất bản thành công"},
|
||||
"发布失败": {"es-ES": "Error al publicar", "ru-RU": "Не удалось опубликовать", "th-TH": "เผยแพร่ล้มเหลว", "vi-VN": "Xuất bản thất bại"},
|
||||
"获取工作流失败": {"es-ES": "Error al obtener el flujo de trabajo", "ru-RU": "Не удалось получить рабочий процесс", "th-TH": "ไม่สามารถรับเวิร์กโฟลว์", "vi-VN": "Không thể lấy quy trình làm việc"},
|
||||
"加载失败": {"es-ES": "Error al cargar", "ru-RU": "Не удалось загрузить", "th-TH": "โหลดล้มเหลว", "vi-VN": "Tải thất bại"},
|
||||
|
||||
# 确认对话框
|
||||
"确认删除": {"es-ES": "Confirmar eliminación", "ru-RU": "Подтвердить удаление", "th-TH": "ยืนยันการลบ", "vi-VN": "Xác nhận xóa"},
|
||||
"确认删除此工作流吗?": {"es-ES": "¿Confirmar la eliminación de este flujo de trabajo?", "ru-RU": "Подтвердить удаление этого рабочего процесса?", "th-TH": "ยืนยันการลบเวิร์กโฟลว์นี้หรือไม่?", "vi-VN": "Xác nhận xóa quy trình làm việc này?"},
|
||||
|
||||
# 基本操作
|
||||
"导出": {"es-ES": "Exportar", "ru-RU": "Экспорт", "th-TH": "ส่งออก", "vi-VN": "Xuất"},
|
||||
"导入": {"es-ES": "Importar", "ru-RU": "Импорт", "th-TH": "นำเข้า", "vi-VN": "Nhập"},
|
||||
"发布": {"es-ES": "Publicar", "ru-RU": "Опубликовать", "th-TH": "เผยแพร่", "vi-VN": "Xuất bản"},
|
||||
"配置": {"es-ES": "Configuración", "ru-RU": "Конфигурация", "th-TH": "การกำหนดค่า", "vi-VN": "Cấu hình"},
|
||||
"执行记录": {"es-ES": "Registros de ejecución", "ru-RU": "Записи выполнения", "th-TH": "บันทึกการดำเนินการ", "vi-VN": "Bản ghi thực thi"},
|
||||
"编辑器": {"es-ES": "Editor", "ru-RU": "Редактор", "th-TH": "ตัวแก้ไข", "vi-VN": "Trình chỉnh sửa"},
|
||||
"调试聊天": {"es-ES": "Chat de depuración", "ru-RU": "Отладочный чат", "th-TH": "แชทดีบัก", "vi-VN": "Chat gỡ lỗi"},
|
||||
|
||||
# 配置部分
|
||||
"基本信息": {"es-ES": "Información básica", "ru-RU": "Основная информация", "th-TH": "ข้อมูลพื้นฐาน", "vi-VN": "Thông tin cơ bản"},
|
||||
"基本信息描述": {"es-ES": "Descripción de información básica", "ru-RU": "Описание основной информации", "th-TH": "คำอธิบายข้อมูลพื้นฐาน", "vi-VN": "Mô tả thông tin cơ bản"},
|
||||
"危险区域": {"es-ES": "Zona peligrosa", "ru-RU": "Опасная зона", "th-TH": "พื้นที่อันตราย", "vi-VN": "Khu vực nguy hiểm"},
|
||||
"危险区域描述": {"es-ES": "Descripción de zona peligrosa", "ru-RU": "Описание опасной зоны", "th-TH": "คำอธิบายพื้นที่อันตราย", "vi-VN": "Mô tả khu vực nguy hiểm"},
|
||||
"删除工作流操作": {"es-ES": "Eliminar operación de flujo de trabajo", "ru-RU": "Удалить операцию рабочего процесса", "th-TH": "ลบการดำเนินการเวิร์กโฟลว์", "vi-VN": "Xóa thao tác quy trình làm việc"},
|
||||
"删除工作流提示": {"es-ES": "Sugerencia de eliminación de flujo de trabajo", "ru-RU": "Подсказка удаления рабочего процесса", "th-TH": "คำแนะนำการลบเวิร์กโฟลว์", "vi-VN": "Gợi ý xóa quy trình làm việc"},
|
||||
"删除工作流": {"es-ES": "Eliminar flujo de trabajo", "ru-RU": "Удалить рабочий процесс", "th-TH": "ลบเวิร์กโฟลว์", "vi-VN": "Xóa quy trình làm việc"},
|
||||
"删除确认描述": {"es-ES": "Descripción de confirmación de eliminación", "ru-RU": "Описание подтверждения удаления", "th-TH": "คำอธิบายการยืนยันการลบ", "vi-VN": "Mô tả xác nhận xóa"},
|
||||
|
||||
# 表单字段
|
||||
"名称": {"es-ES": "Nombre", "ru-RU": "Название", "th-TH": "ชื่อ", "vi-VN": "Tên"},
|
||||
"名称占位符": {"es-ES": "Marcador de posición de nombre", "ru-RU": "Заполнитель имени", "th-TH": "ตัวยึดตำแหน่งชื่อ", "vi-VN": "Trình giữ chỗ tên"},
|
||||
"描述占位符": {"es-ES": "Marcador de posición de descripción", "ru-RU": "Заполнитель описания", "th-TH": "ตัวยึดตำแหน่งคำอธิบาย", "vi-VN": "Trình giữ chỗ mô tả"},
|
||||
"已启用": {"es-ES": "Habilitado", "ru-RU": "Включено", "th-TH": "เปิดใช้งาน", "vi-VN": "Đã bật"},
|
||||
"已启用描述": {"es-ES": "Descripción habilitada", "ru-RU": "Описание включено", "th-TH": "คำอธิบายเปิดใช้งาน", "vi-VN": "Mô tả đã bật"},
|
||||
"加载中": {"es-ES": "Cargando", "ru-RU": "Загрузка", "th-TH": "กำลังโหลด", "vi-VN": "Đang tải"},
|
||||
"信息": {"es-ES": "Información", "ru-RU": "Информация", "th-TH": "ข้อมูล", "vi-VN": "Thông tin"},
|
||||
|
||||
# 统计信息
|
||||
"版本": {"es-ES": "Versión", "ru-RU": "Версия", "th-TH": "เวอร์ชัน", "vi-VN": "Phiên bản"},
|
||||
"创建时间": {"es-ES": "Tiempo de creación", "ru-RU": "Время создания", "th-TH": "เวลาสร้าง", "vi-VN": "Thời gian tạo"},
|
||||
"更新时间": {"es-ES": "Tiempo de actualización", "ru-RU": "Время обновления", "th-TH": "เวลาอัปเดต", "vi-VN": "Thời gian cập nhật"},
|
||||
"总执行次数": {"es-ES": "Total de ejecuciones", "ru-RU": "Всего выполнений", "th-TH": "จำนวนการดำเนินการทั้งหมด", "vi-VN": "Tổng số lần thực thi"},
|
||||
"统计": {"es-ES": "Estadísticas", "ru-RU": "Статистика", "th-TH": "สถิติ", "vi-VN": "Thống kê"},
|
||||
"成功次数": {"es-ES": "Número de éxitos", "ru-RU": "Количество успехов", "th-TH": "จำนวนความสำเร็จ", "vi-VN": "Số lần thành công"},
|
||||
"成功率": {"es-ES": "Tasa de éxito", "ru-RU": "Процент успеха", "th-TH": "อัตราความสำเร็จ", "vi-VN": "Tỷ lệ thành công"},
|
||||
"平均耗时": {"es-ES": "Duración promedio", "ru-RU": "Средняя продолжительность", "th-TH": "ระยะเวลาเฉลี่ย", "vi-VN": "Thời gian trung bình"},
|
||||
"每次执行": {"es-ES": "Por ejecución", "ru-RU": "За выполнение", "th-TH": "ต่อการดำเนินการ", "vi-VN": "Mỗi lần thực thi"},
|
||||
"失败的执行": {"es-ES": "Ejecuciones fallidas", "ru-RU": "Неудачные выполнения", "th-TH": "การดำเนินการที่ล้มเหลว", "vi-VN": "Các lần thực thi thất bại"},
|
||||
"最后执行": {"es-ES": "Última ejecución", "ru-RU": "Последнее выполнение", "th-TH": "การดำเนินการล่าสุด", "vi-VN": "Lần thực thi cuối"},
|
||||
}
|
||||
|
||||
def translate_batch(data: Dict, translations: Dict[str, Dict[str, str]]):
|
||||
"""应用一批翻译"""
|
||||
count = 0
|
||||
for key, trans_obj in data['translations'].items():
|
||||
zh_text = trans_obj.get('zh-Hans', '')
|
||||
if not zh_text:
|
||||
continue
|
||||
|
||||
# 检查是否有完整短语翻译
|
||||
if zh_text in translations:
|
||||
for lang in ['es-ES', 'ru-RU', 'th-TH', 'vi-VN']:
|
||||
if trans_obj.get(lang) == 'TODO':
|
||||
trans_obj[lang] = translations[zh_text][lang]
|
||||
count += 1
|
||||
|
||||
return count
|
||||
|
||||
def main():
|
||||
print("🚀 开始AI翻译工作流i18n...")
|
||||
|
||||
# 加载数据
|
||||
data = load_translations()
|
||||
|
||||
# 应用第一批翻译
|
||||
print("\n📝 应用第一批翻译(基础UI和操作)...")
|
||||
count = translate_batch(data, TRANSLATIONS_BATCH_1)
|
||||
print(f" ✅ 已翻译 {count} 个条目")
|
||||
|
||||
# 保存
|
||||
save_translations(data)
|
||||
print("\n✅ 翻译完成并已保存")
|
||||
|
||||
# 检查是否还有中文字符
|
||||
print("\n🔍 检查翻译质量...")
|
||||
problem_count = 0
|
||||
for key, trans_obj in data['translations'].items():
|
||||
for lang in ['es-ES', 'ru-RU', 'th-TH', 'vi-VN']:
|
||||
text = trans_obj.get(lang, '')
|
||||
if text != 'TODO' and has_chinese(text):
|
||||
problem_count += 1
|
||||
print(f" ⚠️ {key} ({lang}): {text}")
|
||||
|
||||
if problem_count == 0:
|
||||
print(" ✅ 所有翻译都不包含中文字符")
|
||||
else:
|
||||
print(f" ⚠️ 发现 {problem_count} 个翻译仍包含中文字符")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,141 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
分析所有语言文件中缺失的翻译键
|
||||
对比 zh-Hans.ts(完整翻译)和其他语言文件,找出所有英文键
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Set
|
||||
|
||||
def extract_keys_from_ts(file_path: Path) -> Dict[str, str]:
|
||||
"""从 TypeScript 文件中提取所有键值对"""
|
||||
content = file_path.read_text(encoding='utf-8')
|
||||
|
||||
# 匹配键值对:key: 'value' 或 key: "value"
|
||||
pattern = r"(\w+):\s*['\"]([^'\"]+)['\"]"
|
||||
matches = re.findall(pattern, content)
|
||||
|
||||
return dict(matches)
|
||||
|
||||
def is_english(text: str) -> bool:
|
||||
"""判断文本是否主要是英文"""
|
||||
# 如果文本中英文字符占比超过50%,认为是英文
|
||||
english_chars = sum(1 for c in text if c.isascii() and c.isalpha())
|
||||
total_chars = sum(1 for c in text if c.isalpha())
|
||||
|
||||
if total_chars == 0:
|
||||
return False
|
||||
|
||||
return english_chars / total_chars > 0.5
|
||||
|
||||
def analyze_file(file_path: Path, reference_keys: Dict[str, str]) -> Dict[str, List[str]]:
|
||||
"""分析单个文件,找出需要翻译的英文键"""
|
||||
keys = extract_keys_from_ts(file_path)
|
||||
|
||||
english_keys = []
|
||||
missing_keys = []
|
||||
|
||||
for key, value in keys.items():
|
||||
if is_english(value):
|
||||
english_keys.append(f"{key}: '{value}'")
|
||||
|
||||
# 找出参考文件中有但当前文件缺失的键
|
||||
for ref_key in reference_keys:
|
||||
if ref_key not in keys:
|
||||
missing_keys.append(ref_key)
|
||||
|
||||
return {
|
||||
'english_keys': english_keys,
|
||||
'missing_keys': missing_keys,
|
||||
'total_keys': len(keys)
|
||||
}
|
||||
|
||||
def main():
|
||||
locales_dir = Path(__file__).parent / 'src' / 'i18n' / 'locales'
|
||||
|
||||
# 读取参考文件(简体中文,完整翻译)
|
||||
zh_hans_path = locales_dir / 'zh-Hans.ts'
|
||||
print(f"读取参考文件: {zh_hans_path}")
|
||||
reference_keys = extract_keys_from_ts(zh_hans_path)
|
||||
print(f"参考文件包含 {len(reference_keys)} 个键\n")
|
||||
|
||||
# 分析所有非中文语言文件
|
||||
target_files = [
|
||||
'ja-JP.ts',
|
||||
'zh-Hant.ts',
|
||||
'es-ES.ts',
|
||||
'ru-RU.ts',
|
||||
'th-TH.ts',
|
||||
'vi-VN.ts'
|
||||
]
|
||||
|
||||
results = {}
|
||||
|
||||
for filename in target_files:
|
||||
file_path = locales_dir / filename
|
||||
if not file_path.exists():
|
||||
print(f"⚠️ 文件不存在: {filename}")
|
||||
continue
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"分析文件: {filename}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
result = analyze_file(file_path, reference_keys)
|
||||
results[filename] = result
|
||||
|
||||
print(f"总键数: {result['total_keys']}")
|
||||
print(f"英文键数: {len(result['english_keys'])}")
|
||||
print(f"缺失键数: {len(result['missing_keys'])}")
|
||||
|
||||
if result['english_keys']:
|
||||
print(f"\n前10个英文键示例:")
|
||||
for key in result['english_keys'][:10]:
|
||||
print(f" - {key}")
|
||||
|
||||
if result['missing_keys']:
|
||||
print(f"\n前10个缺失键示例:")
|
||||
for key in result['missing_keys'][:10]:
|
||||
print(f" - {key}")
|
||||
|
||||
# 汇总统计
|
||||
print(f"\n\n{'='*60}")
|
||||
print("汇总统计")
|
||||
print(f"{'='*60}")
|
||||
|
||||
total_english = sum(len(r['english_keys']) for r in results.values())
|
||||
total_missing = sum(len(r['missing_keys']) for r in results.values())
|
||||
|
||||
print(f"总计需要翻译的英文键: {total_english}")
|
||||
print(f"总计缺失的键: {total_missing}")
|
||||
print(f"总计需要处理: {total_english + total_missing}")
|
||||
|
||||
# 保存详细报告
|
||||
report_path = Path(__file__).parent.parent / 'plans' / 'translation-analysis-report.txt'
|
||||
with open(report_path, 'w', encoding='utf-8') as f:
|
||||
f.write("翻译分析报告\n")
|
||||
f.write("="*60 + "\n\n")
|
||||
|
||||
for filename, result in results.items():
|
||||
f.write(f"\n文件: {filename}\n")
|
||||
f.write(f"总键数: {result['total_keys']}\n")
|
||||
f.write(f"英文键数: {len(result['english_keys'])}\n")
|
||||
f.write(f"缺失键数: {len(result['missing_keys'])}\n")
|
||||
|
||||
if result['english_keys']:
|
||||
f.write(f"\n英文键列表:\n")
|
||||
for key in result['english_keys']:
|
||||
f.write(f" {key}\n")
|
||||
|
||||
if result['missing_keys']:
|
||||
f.write(f"\n缺失键列表:\n")
|
||||
for key in result['missing_keys']:
|
||||
f.write(f" {key}\n")
|
||||
|
||||
f.write("\n" + "="*60 + "\n")
|
||||
|
||||
print(f"\n详细报告已保存到: {report_path}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,262 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
应用workflows翻译到语言文件
|
||||
|
||||
使用方法:
|
||||
1. 编辑 workflows_translations.json 文件
|
||||
2. 将 'TODO' 替换为实际翻译
|
||||
3. 运行此脚本:python3 apply_workflows_translations.py
|
||||
|
||||
脚本会:
|
||||
- 读取 workflows_translations.json
|
||||
- 识别已完成的翻译(非"TODO")
|
||||
- 应用到对应的语言文件
|
||||
- 生成进度报告
|
||||
- 支持增量应用(可以分批翻译)
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple, Set
|
||||
|
||||
|
||||
def load_translations() -> Dict:
|
||||
"""加载翻译JSON文件"""
|
||||
json_path = Path(__file__).parent / 'workflows_translations.json'
|
||||
|
||||
if not json_path.exists():
|
||||
raise FileNotFoundError(f"找不到翻译文件: {json_path}")
|
||||
|
||||
with open(json_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def get_completed_translations(translations_data: Dict) -> Dict[str, Dict[str, str]]:
|
||||
"""
|
||||
获取已完成的翻译
|
||||
|
||||
返回格式:
|
||||
{
|
||||
'ja-JP': {'title': '工作流对话', 'description': '...', ...},
|
||||
'zh-Hant': {...},
|
||||
...
|
||||
}
|
||||
"""
|
||||
translations = translations_data.get('translations', {})
|
||||
languages = ['ja-JP', 'zh-Hant', 'es-ES', 'ru-RU', 'th-TH', 'vi-VN']
|
||||
|
||||
completed = {lang: {} for lang in languages}
|
||||
|
||||
for key, values in translations.items():
|
||||
for lang in languages:
|
||||
translation = values.get(lang, 'TODO')
|
||||
if translation != 'TODO' and translation.strip():
|
||||
completed[lang][key] = translation
|
||||
|
||||
return completed
|
||||
|
||||
|
||||
def apply_translations_to_file(file_path: Path, translations: Dict[str, str], lang_code: str) -> Tuple[int, List[str]]:
|
||||
"""
|
||||
应用翻译到指定语言文件
|
||||
|
||||
返回:(成功应用的数量, 失败的键列表)
|
||||
"""
|
||||
if not file_path.exists():
|
||||
print(f"⚠️ 文件不存在: {file_path}")
|
||||
return 0, list(translations.keys())
|
||||
|
||||
# 读取文件内容
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# 找到workflows部分的起始和结束位置
|
||||
workflows_start = content.find('workflows: {')
|
||||
if workflows_start == -1:
|
||||
print(f"⚠️ 找不到workflows部分: {file_path}")
|
||||
return 0, list(translations.keys())
|
||||
|
||||
# 找到workflows部分的结束位置(匹配的闭合大括号)
|
||||
brace_count = 0
|
||||
workflows_end = workflows_start
|
||||
for i in range(workflows_start, len(content)):
|
||||
if content[i] == '{':
|
||||
brace_count += 1
|
||||
elif content[i] == '}':
|
||||
brace_count -= 1
|
||||
if brace_count == 0:
|
||||
workflows_end = i + 1
|
||||
break
|
||||
|
||||
if workflows_end == workflows_start:
|
||||
print(f"⚠️ 无法确定workflows部分的结束位置: {file_path}")
|
||||
return 0, list(translations.keys())
|
||||
|
||||
# 提取workflows部分
|
||||
before_workflows = content[:workflows_start]
|
||||
workflows_section = content[workflows_start:workflows_end]
|
||||
after_workflows = content[workflows_end:]
|
||||
|
||||
# 应用翻译
|
||||
success_count = 0
|
||||
failed_keys = []
|
||||
|
||||
for key, translation in translations.items():
|
||||
# 转义特殊字符
|
||||
escaped_key = re.escape(key)
|
||||
|
||||
# 匹配模式:key: 'value', 或 key: "value",
|
||||
# 支持多行和注释
|
||||
patterns = [
|
||||
# 单引号,可能有尾随逗号和注释
|
||||
rf"(\s+{escaped_key}:\s*)'[^']*'(,?\s*(?://.*)?(?:\n|$))",
|
||||
# 双引号,可能有尾随逗号和注释
|
||||
rf'(\s+{escaped_key}:\s*)"[^"]*"(,?\s*(?://.*)?(?:\n|$))',
|
||||
]
|
||||
|
||||
replaced = False
|
||||
for pattern in patterns:
|
||||
if re.search(pattern, workflows_section):
|
||||
# 转义翻译文本中的单引号
|
||||
escaped_translation = translation.replace("'", "\\'")
|
||||
replacement = rf"\1'{escaped_translation}'\2"
|
||||
workflows_section = re.sub(pattern, replacement, workflows_section)
|
||||
replaced = True
|
||||
success_count += 1
|
||||
break
|
||||
|
||||
if not replaced:
|
||||
failed_keys.append(key)
|
||||
|
||||
# 重新组合文件内容
|
||||
new_content = before_workflows + workflows_section + after_workflows
|
||||
|
||||
# 写回文件
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(new_content)
|
||||
|
||||
return success_count, failed_keys
|
||||
|
||||
|
||||
def update_progress_in_json(json_path: Path, completed_by_lang: Dict[str, int]):
|
||||
"""更新JSON文件中的进度信息"""
|
||||
with open(json_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
# 计算总的已翻译键数(取所有语言的平均值)
|
||||
total_translated = sum(completed_by_lang.values()) // len(completed_by_lang) if completed_by_lang else 0
|
||||
total_keys = data.get('_progress', {}).get('total_keys', 0)
|
||||
|
||||
data['_progress']['translated_keys'] = total_translated
|
||||
data['_progress']['remaining_keys'] = total_keys - total_translated
|
||||
data['_progress']['by_language'] = completed_by_lang
|
||||
|
||||
with open(json_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
def generate_report(results: Dict[str, Tuple[int, List[str]]], total_keys: int):
|
||||
"""生成应用报告"""
|
||||
print("\n" + "="*80)
|
||||
print("📊 Workflows翻译应用报告")
|
||||
print("="*80)
|
||||
|
||||
total_applied = 0
|
||||
|
||||
for lang, (success_count, failed_keys) in results.items():
|
||||
total_applied += success_count
|
||||
success_rate = (success_count / total_keys * 100) if total_keys > 0 else 0
|
||||
|
||||
print(f"\n【{lang}】")
|
||||
print(f" ✅ 成功应用: {success_count}/{total_keys} ({success_rate:.1f}%)")
|
||||
|
||||
if failed_keys:
|
||||
print(f" ❌ 失败: {len(failed_keys)} 个键")
|
||||
if len(failed_keys) <= 10:
|
||||
print(f" 失败的键: {', '.join(failed_keys)}")
|
||||
else:
|
||||
print(f" 失败的键(前10个): {', '.join(failed_keys[:10])}...")
|
||||
|
||||
print("\n" + "-"*80)
|
||||
avg_applied = total_applied // len(results) if results else 0
|
||||
avg_rate = (avg_applied / total_keys * 100) if total_keys > 0 else 0
|
||||
print(f"📈 总体进度: {avg_applied}/{total_keys} ({avg_rate:.1f}%)")
|
||||
print(f"📝 剩余待翻译: {total_keys - avg_applied} 个键")
|
||||
print("="*80)
|
||||
|
||||
|
||||
def main():
|
||||
print("🚀 开始应用workflows翻译...")
|
||||
|
||||
# 加载翻译数据
|
||||
print("\n📖 读取翻译文件...")
|
||||
translations_data = load_translations()
|
||||
total_keys = translations_data.get('_progress', {}).get('total_keys', 0)
|
||||
print(f" 总键数: {total_keys}")
|
||||
|
||||
# 获取已完成的翻译
|
||||
print("\n🔍 识别已完成的翻译...")
|
||||
completed = get_completed_translations(translations_data)
|
||||
|
||||
for lang, trans in completed.items():
|
||||
print(f" {lang}: {len(trans)} 个键已翻译")
|
||||
|
||||
# 如果没有任何翻译,提示用户
|
||||
if all(len(trans) == 0 for trans in completed.values()):
|
||||
print("\n⚠️ 没有发现任何已完成的翻译(所有值都是'TODO')")
|
||||
print("💡 请先编辑 workflows_translations.json 文件,将 'TODO' 替换为实际翻译")
|
||||
return
|
||||
|
||||
# 应用翻译到各个语言文件
|
||||
print("\n✏️ 应用翻译到语言文件...")
|
||||
|
||||
locales_dir = Path(__file__).parent / 'src' / 'i18n' / 'locales'
|
||||
|
||||
language_files = {
|
||||
'ja-JP': locales_dir / 'ja-JP.ts',
|
||||
'zh-Hant': locales_dir / 'zh-Hant.ts',
|
||||
'es-ES': locales_dir / 'es-ES.ts',
|
||||
'ru-RU': locales_dir / 'ru-RU.ts',
|
||||
'th-TH': locales_dir / 'th-TH.ts',
|
||||
'vi-VN': locales_dir / 'vi-VN.ts',
|
||||
}
|
||||
|
||||
results = {}
|
||||
completed_by_lang = {}
|
||||
|
||||
for lang, file_path in language_files.items():
|
||||
translations = completed[lang]
|
||||
if not translations:
|
||||
print(f" ⏭️ 跳过 {lang}(没有已完成的翻译)")
|
||||
results[lang] = (0, [])
|
||||
completed_by_lang[lang] = 0
|
||||
continue
|
||||
|
||||
print(f" 📝 处理 {lang}...")
|
||||
success_count, failed_keys = apply_translations_to_file(file_path, translations, lang)
|
||||
results[lang] = (success_count, failed_keys)
|
||||
completed_by_lang[lang] = success_count
|
||||
|
||||
if success_count > 0:
|
||||
print(f" ✅ 成功应用 {success_count} 个翻译")
|
||||
if failed_keys:
|
||||
print(f" ⚠️ {len(failed_keys)} 个键应用失败")
|
||||
|
||||
# 更新JSON文件中的进度
|
||||
print("\n📊 更新进度信息...")
|
||||
json_path = Path(__file__).parent / 'workflows_translations.json'
|
||||
update_progress_in_json(json_path, completed_by_lang)
|
||||
|
||||
# 生成报告
|
||||
generate_report(results, total_keys)
|
||||
|
||||
print("\n✅ 翻译应用完成!")
|
||||
print("\n💡 提示:")
|
||||
print(" 1. 继续编辑 workflows_translations.json 翻译更多键")
|
||||
print(" 2. 再次运行此脚本应用新的翻译")
|
||||
print(" 3. 重复以上步骤直到所有翻译完成")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,351 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
批量翻译workflows的多语言文件
|
||||
支持:西班牙语(es-ES)、俄语(ru-RU)、泰语(th-TH)、越南语(vi-VN)
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
# 翻译映射表 - 基于中文原文的专业翻译
|
||||
TRANSLATIONS = {
|
||||
# 基础UI文本
|
||||
"title": {
|
||||
"es-ES": "Conversación de Flujo de Trabajo",
|
||||
"ru-RU": "Диалог Рабочего Процесса",
|
||||
"th-TH": "การสนทนาเวิร์กโฟลว์",
|
||||
"vi-VN": "Hội thoại Quy trình"
|
||||
},
|
||||
"description": {
|
||||
"es-ES": "Descripción",
|
||||
"ru-RU": "Описание",
|
||||
"th-TH": "คำอธิบาย",
|
||||
"vi-VN": "Mô tả"
|
||||
},
|
||||
"createWorkflow": {
|
||||
"es-ES": "Crear Flujo de Trabajo",
|
||||
"ru-RU": "Создать Рабочий Процесс",
|
||||
"th-TH": "สร้างเวิร์กโฟลว์",
|
||||
"vi-VN": "Tạo Quy trình"
|
||||
},
|
||||
"selectFromSidebar": {
|
||||
"es-ES": "Seleccione un flujo de trabajo de la barra lateral",
|
||||
"ru-RU": "Выберите рабочий процесс из боковой панели",
|
||||
"th-TH": "เลือกเวิร์กโฟลว์จากแถบด้านข้าง",
|
||||
"vi-VN": "Chọn một quy trình từ thanh bên"
|
||||
},
|
||||
"editWorkflow": {
|
||||
"es-ES": "Editar Flujo de Trabajo",
|
||||
"ru-RU": "Редактировать Рабочий Процесс",
|
||||
"th-TH": "แก้ไขเวิร์กโฟลว์",
|
||||
"vi-VN": "Chỉnh sửa Quy trình"
|
||||
},
|
||||
"newWorkflow": {
|
||||
"es-ES": "Nuevo Flujo de Trabajo",
|
||||
"ru-RU": "Новый Рабочий Процесс",
|
||||
"th-TH": "เวิร์กโฟลว์ใหม่",
|
||||
"vi-VN": "Quy trình Mới"
|
||||
},
|
||||
"getWorkflowListError": {
|
||||
"es-ES": "Error al obtener la lista de flujos de trabajo:",
|
||||
"ru-RU": "Ошибка получения списка рабочих процессов:",
|
||||
"th-TH": "ไม่สามารถรับรายการเวิร์กโฟลว์:",
|
||||
"vi-VN": "Lỗi khi lấy danh sách quy trình:"
|
||||
},
|
||||
"workflowName": {
|
||||
"es-ES": "Nombre del Flujo de Trabajo",
|
||||
"ru-RU": "Название Рабочего Процесса",
|
||||
"th-TH": "ชื่อเวิร์กโฟลว์",
|
||||
"vi-VN": "Tên Quy trình"
|
||||
},
|
||||
"workflowDescription": {
|
||||
"es-ES": "Descripción del Flujo de Trabajo",
|
||||
"ru-RU": "Описание Рабочего Процесса",
|
||||
"th-TH": "คำอธิบายเวิร์กโฟลว์",
|
||||
"vi-VN": "Mô tả Quy trình"
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def load_translations_json():
|
||||
"""加载翻译JSON文件"""
|
||||
json_path = Path(__file__).parent / 'workflows_translations.json'
|
||||
|
||||
if not json_path.exists():
|
||||
raise FileNotFoundError(f"找不到翻译文件: {json_path}")
|
||||
|
||||
with open(json_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def save_translations_json(data):
|
||||
"""保存翻译JSON文件"""
|
||||
json_path = Path(__file__).parent / 'workflows_translations.json'
|
||||
|
||||
with open(json_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
def translate_text(text: str, target_lang: str) -> str:
|
||||
"""
|
||||
翻译文本到目标语言
|
||||
使用规则和模式匹配进行翻译
|
||||
"""
|
||||
# 如果有预定义翻译,直接使用
|
||||
if text in TRANSLATIONS and target_lang in TRANSLATIONS[text]:
|
||||
return TRANSLATIONS[text][target_lang]
|
||||
|
||||
# 通用翻译规则
|
||||
common_translations = {
|
||||
"es-ES": {
|
||||
# 常用词汇
|
||||
"工作流": "Flujo de Trabajo",
|
||||
"节点": "Nodo",
|
||||
"触发器": "Disparador",
|
||||
"执行": "Ejecutar",
|
||||
"调试": "Depurar",
|
||||
"配置": "Configuración",
|
||||
"变量": "Variable",
|
||||
"条件": "Condición",
|
||||
"循环": "Bucle",
|
||||
"等待": "Esperar",
|
||||
"结束": "Fin",
|
||||
"开始": "Inicio",
|
||||
"消息": "Mensaje",
|
||||
"发送": "Enviar",
|
||||
"接收": "Recibir",
|
||||
"错误": "Error",
|
||||
"成功": "Éxito",
|
||||
"失败": "Fallo",
|
||||
"保存": "Guardar",
|
||||
"取消": "Cancelar",
|
||||
"删除": "Eliminar",
|
||||
"编辑": "Editar",
|
||||
"添加": "Agregar",
|
||||
"创建": "Crear",
|
||||
"名称": "Nombre",
|
||||
"描述": "Descripción",
|
||||
"类型": "Tipo",
|
||||
"值": "Valor",
|
||||
"参数": "Parámetro",
|
||||
"输入": "Entrada",
|
||||
"输出": "Salida",
|
||||
"请": "Por favor",
|
||||
"选择": "Seleccionar",
|
||||
"确认": "Confirmar",
|
||||
"提示": "Aviso",
|
||||
"警告": "Advertencia",
|
||||
"信息": "Información",
|
||||
},
|
||||
"ru-RU": {
|
||||
"工作流": "Рабочий Процесс",
|
||||
"节点": "Узел",
|
||||
"触发器": "Триггер",
|
||||
"执行": "Выполнить",
|
||||
"调试": "Отладка",
|
||||
"配置": "Конфигурация",
|
||||
"变量": "Переменная",
|
||||
"条件": "Условие",
|
||||
"循环": "Цикл",
|
||||
"等待": "Ожидание",
|
||||
"结束": "Конец",
|
||||
"开始": "Начало",
|
||||
"消息": "Сообщение",
|
||||
"发送": "Отправить",
|
||||
"接收": "Получить",
|
||||
"错误": "Ошибка",
|
||||
"成功": "Успех",
|
||||
"失败": "Неудача",
|
||||
"保存": "Сохранить",
|
||||
"取消": "Отмена",
|
||||
"删除": "Удалить",
|
||||
"编辑": "Редактировать",
|
||||
"添加": "Добавить",
|
||||
"创建": "Создать",
|
||||
"名称": "Название",
|
||||
"描述": "Описание",
|
||||
"类型": "Тип",
|
||||
"值": "Значение",
|
||||
"参数": "Параметр",
|
||||
"输入": "Вход",
|
||||
"输出": "Выход",
|
||||
"请": "Пожалуйста",
|
||||
"选择": "Выбрать",
|
||||
"确认": "Подтвердить",
|
||||
"提示": "Подсказка",
|
||||
"警告": "Предупреждение",
|
||||
"信息": "Информация",
|
||||
},
|
||||
"th-TH": {
|
||||
"工作流": "เวิร์กโฟลว์",
|
||||
"节点": "โหนด",
|
||||
"触发器": "ทริกเกอร์",
|
||||
"执行": "ดำเนินการ",
|
||||
"调试": "ดีบัก",
|
||||
"配置": "การกำหนดค่า",
|
||||
"变量": "ตัวแปร",
|
||||
"条件": "เงื่อนไข",
|
||||
"循环": "วนซ้ำ",
|
||||
"等待": "รอ",
|
||||
"结束": "สิ้นสุด",
|
||||
"开始": "เริ่มต้น",
|
||||
"消息": "ข้อความ",
|
||||
"发送": "ส่ง",
|
||||
"接收": "รับ",
|
||||
"错误": "ข้อผิดพลาด",
|
||||
"成功": "สำเร็จ",
|
||||
"失败": "ล้มเหลว",
|
||||
"保存": "บันทึก",
|
||||
"取消": "ยกเลิก",
|
||||
"删除": "ลบ",
|
||||
"编辑": "แก้ไข",
|
||||
"添加": "เพิ่ม",
|
||||
"创建": "สร้าง",
|
||||
"名称": "ชื่อ",
|
||||
"描述": "คำอธิบาย",
|
||||
"类型": "ประเภท",
|
||||
"值": "ค่า",
|
||||
"参数": "พารามิเตอร์",
|
||||
"输入": "อินพุต",
|
||||
"输出": "เอาต์พุต",
|
||||
"请": "กรุณา",
|
||||
"选择": "เลือก",
|
||||
"确认": "ยืนยัน",
|
||||
"提示": "คำแนะนำ",
|
||||
"警告": "คำเตือน",
|
||||
"信息": "ข้อมูล",
|
||||
},
|
||||
"vi-VN": {
|
||||
"工作流": "Quy trình",
|
||||
"节点": "Nút",
|
||||
"触发器": "Trình kích hoạt",
|
||||
"执行": "Thực thi",
|
||||
"调试": "Gỡ lỗi",
|
||||
"配置": "Cấu hình",
|
||||
"变量": "Biến",
|
||||
"条件": "Điều kiện",
|
||||
"循环": "Vòng lặp",
|
||||
"等待": "Chờ",
|
||||
"结束": "Kết thúc",
|
||||
"开始": "Bắt đầu",
|
||||
"消息": "Tin nhắn",
|
||||
"发送": "Gửi",
|
||||
"接收": "Nhận",
|
||||
"错误": "Lỗi",
|
||||
"成功": "Thành công",
|
||||
"失败": "Thất bại",
|
||||
"保存": "Lưu",
|
||||
"取消": "Hủy",
|
||||
"删除": "Xóa",
|
||||
"编辑": "Chỉnh sửa",
|
||||
"添加": "Thêm",
|
||||
"创建": "Tạo",
|
||||
"名称": "Tên",
|
||||
"描述": "Mô tả",
|
||||
"类型": "Loại",
|
||||
"值": "Giá trị",
|
||||
"参数": "Tham số",
|
||||
"输入": "Đầu vào",
|
||||
"输出": "Đầu ra",
|
||||
"请": "Vui lòng",
|
||||
"选择": "Chọn",
|
||||
"确认": "Xác nhận",
|
||||
"提示": "Gợi ý",
|
||||
"警告": "Cảnh báo",
|
||||
"信息": "Thông tin",
|
||||
}
|
||||
}
|
||||
|
||||
# 尝试使用通用翻译规则
|
||||
if target_lang in common_translations:
|
||||
result = text
|
||||
for zh, translation in common_translations[target_lang].items():
|
||||
result = result.replace(zh, translation)
|
||||
if result != text:
|
||||
return result
|
||||
|
||||
# 如果没有匹配的翻译规则,返回原文
|
||||
return text
|
||||
|
||||
|
||||
def batch_translate():
|
||||
"""批量翻译所有TODO项"""
|
||||
print("🚀 开始批量翻译workflows...")
|
||||
print("=" * 80)
|
||||
|
||||
# 加载翻译数据
|
||||
data = load_translations_json()
|
||||
translations = data.get('translations', {})
|
||||
|
||||
target_languages = ['es-ES', 'ru-RU', 'th-TH', 'vi-VN']
|
||||
|
||||
stats = {lang: {'total': 0, 'translated': 0} for lang in target_languages}
|
||||
|
||||
# 遍历所有键进行翻译
|
||||
for key, values in translations.items():
|
||||
zh_hans = values.get('zh-Hans', '')
|
||||
|
||||
if not zh_hans or zh_hans == 'TODO':
|
||||
continue
|
||||
|
||||
for lang in target_languages:
|
||||
stats[lang]['total'] += 1
|
||||
|
||||
current_value = values.get(lang, 'TODO')
|
||||
|
||||
# 如果已经翻译过,跳过
|
||||
if current_value != 'TODO' and current_value.strip():
|
||||
stats[lang]['translated'] += 1
|
||||
continue
|
||||
|
||||
# 执行翻译
|
||||
translated = translate_text(zh_hans, lang)
|
||||
|
||||
# 更新翻译
|
||||
if translated and translated != zh_hans:
|
||||
values[lang] = translated
|
||||
stats[lang]['translated'] += 1
|
||||
print(f"✅ [{lang}] {key}: {zh_hans} -> {translated}")
|
||||
|
||||
# 保存更新后的数据
|
||||
save_translations_json(data)
|
||||
|
||||
# 显示统计信息
|
||||
print("\n" + "=" * 80)
|
||||
print("📊 翻译统计:")
|
||||
print("=" * 80)
|
||||
|
||||
for lang in target_languages:
|
||||
total = stats[lang]['total']
|
||||
translated = stats[lang]['translated']
|
||||
percentage = (translated / total * 100) if total > 0 else 0
|
||||
|
||||
lang_names = {
|
||||
'es-ES': '西班牙语',
|
||||
'ru-RU': '俄语',
|
||||
'th-TH': '泰语',
|
||||
'vi-VN': '越南语'
|
||||
}
|
||||
|
||||
print(f"\n【{lang_names[lang]} ({lang})】")
|
||||
print(f" 总计: {total}")
|
||||
print(f" 已翻译: {translated}")
|
||||
print(f" 完成度: {percentage:.1f}%")
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
print("✅ 批量翻译完成!")
|
||||
print("\n💡 下一步:")
|
||||
print(" 1. 运行 python3 check_translation_progress.py 查看进度")
|
||||
print(" 2. 运行 python3 apply_workflows_translations.py 应用翻译")
|
||||
print("=" * 80)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
batch_translate()
|
||||
except Exception as e:
|
||||
print(f"\n❌ 错误: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
@@ -1,280 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
批量翻译繁体中文workflows部分
|
||||
基于简体中文进行繁体转换和台湾用语调整
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
# 简繁转换映射(常用词汇)
|
||||
SIMPLIFIED_TO_TRADITIONAL = {
|
||||
# 基础词汇
|
||||
'工作流': '工作流程',
|
||||
'创建': '建立',
|
||||
'编辑': '編輯',
|
||||
'删除': '刪除',
|
||||
'保存': '儲存',
|
||||
'加载': '載入',
|
||||
'导出': '匯出',
|
||||
'导入': '匯入',
|
||||
'发布': '發佈',
|
||||
'配置': '設定',
|
||||
'执行': '執行',
|
||||
'记录': '記錄',
|
||||
'编辑器': '編輯器',
|
||||
'调试': '除錯',
|
||||
'基础': '基礎',
|
||||
'信息': '資訊',
|
||||
'设置': '設定',
|
||||
'图标': '圖示',
|
||||
'描述': '描述',
|
||||
'危险': '危險',
|
||||
'区域': '區域',
|
||||
'操作': '操作',
|
||||
'确认': '確認',
|
||||
'名称': '名稱',
|
||||
'输入': '輸入',
|
||||
'启用': '啟用',
|
||||
'加载中': '載入中',
|
||||
'版本': '版本',
|
||||
'创建时间': '建立時間',
|
||||
'更新时间': '更新時間',
|
||||
'统计': '統計',
|
||||
'分析': '分析',
|
||||
'成功': '成功',
|
||||
'失败': '失敗',
|
||||
'平均': '平均',
|
||||
'耗时': '耗時',
|
||||
'筛选': '篩選',
|
||||
'状态': '狀態',
|
||||
'手动': '手動',
|
||||
'触发': '觸發',
|
||||
'开始': '開始',
|
||||
'时间': '時間',
|
||||
'详情': '詳情',
|
||||
'错误': '錯誤',
|
||||
'节点': '節點',
|
||||
'结果': '結果',
|
||||
'等待': '等待',
|
||||
'执行中': '執行中',
|
||||
'已完成': '已完成',
|
||||
'已取消': '已取消',
|
||||
'面板': '面板',
|
||||
'属性': '屬性',
|
||||
'放大': '放大',
|
||||
'缩小': '縮小',
|
||||
'适应': '適應',
|
||||
'视图': '檢視',
|
||||
'未保存': '未儲存',
|
||||
'更改': '變更',
|
||||
'粘贴': '貼上',
|
||||
'已删除': '已刪除',
|
||||
'复制': '複製',
|
||||
'剪贴板': '剪貼簿',
|
||||
'搜索': '搜尋',
|
||||
'正在加载': '正在載入',
|
||||
'类型': '類型',
|
||||
'未找到': '找不到',
|
||||
'清除': '清除',
|
||||
'拖拽': '拖曳',
|
||||
'画布': '畫布',
|
||||
'选择': '選擇',
|
||||
'连线': '連線',
|
||||
'点击': '點擊',
|
||||
'查看': '檢視',
|
||||
'条件': '條件',
|
||||
'已设置': '已設定',
|
||||
'表达式': '運算式',
|
||||
'变量': '變數',
|
||||
'引用': '參照',
|
||||
'上下文': '上下文',
|
||||
'显示': '顯示',
|
||||
'标签': '標籤',
|
||||
'输出': '輸出',
|
||||
'可用': '可用',
|
||||
'全局': '全域',
|
||||
'消息': '訊息',
|
||||
'内容': '內容',
|
||||
'发送者': '發送者',
|
||||
'平台': '平台',
|
||||
'会话': '工作階段',
|
||||
'时间戳': '時間戳記',
|
||||
'无': '無',
|
||||
'选项': '選項',
|
||||
# 节点类型
|
||||
'触发器': '觸發器',
|
||||
'定时': '定時',
|
||||
'事件': '事件',
|
||||
'处理': '處理',
|
||||
'调用': '呼叫',
|
||||
'代码': '程式碼',
|
||||
'模板': '範本',
|
||||
'请求': '請求',
|
||||
'转换': '轉換',
|
||||
'分类器': '分類器',
|
||||
'提取器': '擷取器',
|
||||
'检索': '檢索',
|
||||
'知识库': '知識庫',
|
||||
'聚合': '彙總',
|
||||
'分割': '分割',
|
||||
'赋值': '指派',
|
||||
'控制流': '控制流程',
|
||||
'分支': '分支',
|
||||
'多路': '多路',
|
||||
'循环': '迴圈',
|
||||
'迭代器': '迭代器',
|
||||
'并行': '並行',
|
||||
'延迟': '延遲',
|
||||
'合并': '合併',
|
||||
'聚合器': '彙總器',
|
||||
'动作': '動作',
|
||||
'回复': '回覆',
|
||||
'存储': '儲存',
|
||||
'数据': '資料',
|
||||
'数据库': '資料庫',
|
||||
'集成': '整合',
|
||||
'第三方': '第三方',
|
||||
'查询': '查詢',
|
||||
'缓存': '快取',
|
||||
'工具': '工具',
|
||||
'记忆': '記憶',
|
||||
# 配置字段
|
||||
'关键词': '關鍵字',
|
||||
'过滤': '篩選',
|
||||
'正则': '正規表示式',
|
||||
'长度': '長度',
|
||||
'提及': '提及',
|
||||
'群': '群組',
|
||||
'响应': '回應',
|
||||
'规则': '規則',
|
||||
'访问': '存取',
|
||||
'控制': '控制',
|
||||
'表达式': '運算式',
|
||||
'时区': '時區',
|
||||
'路径': '路徑',
|
||||
'允许': '允許',
|
||||
'方法': '方法',
|
||||
'认证': '驗證',
|
||||
'密钥': '金鑰',
|
||||
'验证': '驗證',
|
||||
'超时': '逾時',
|
||||
'防抖': '防抖',
|
||||
'模型': '模型',
|
||||
'提示词': '提示詞',
|
||||
'系统': '系統',
|
||||
'温度': '溫度',
|
||||
'惩罚': '懲罰',
|
||||
'令牌': '權杖',
|
||||
'序列': '序列',
|
||||
'种子': '種子',
|
||||
'流式': '串流',
|
||||
'历史': '歷史',
|
||||
'语言': '語言',
|
||||
'程序': '程式',
|
||||
'指令': '指令',
|
||||
'参数': '參數',
|
||||
'定义': '定義',
|
||||
'返回': '傳回',
|
||||
'阈值': '閾值',
|
||||
'相似度': '相似度',
|
||||
'引用': '引用',
|
||||
'运算符': '運算子',
|
||||
'迭代': '迭代',
|
||||
'中断': '中斷',
|
||||
'并发': '並行',
|
||||
'等待': '等待',
|
||||
'所有': '所有',
|
||||
'快速': '快速',
|
||||
'单位': '單位',
|
||||
'策略': '策略',
|
||||
'映射': '對應',
|
||||
'模式': '模式',
|
||||
'目标': '目標',
|
||||
'长文本': '長文字',
|
||||
'强制': '強制',
|
||||
'继承': '繼承',
|
||||
'过期': '過期',
|
||||
'前缀': '前置詞',
|
||||
'作用域': '範圍',
|
||||
'建议': '建議',
|
||||
'问题': '問題',
|
||||
'格式': '格式',
|
||||
'连接': '連線',
|
||||
'字符串': '字串',
|
||||
'哈希': '雜湊',
|
||||
'字段': '欄位',
|
||||
'服务器': '伺服器',
|
||||
'应用': '應用程式',
|
||||
'数据集': '資料集',
|
||||
'流程': '流程',
|
||||
'机器人': '機器人',
|
||||
}
|
||||
|
||||
def convert_to_traditional(text: str) -> str:
|
||||
"""将简体中文转换为繁体中文"""
|
||||
result = text
|
||||
for simp, trad in SIMPLIFIED_TO_TRADITIONAL.items():
|
||||
result = result.replace(simp, trad)
|
||||
return result
|
||||
|
||||
def main():
|
||||
print("繁体中文批量转换工具")
|
||||
print("=" * 60)
|
||||
print("此脚本将简体中文翻译转换为繁体中文")
|
||||
print("=" * 60)
|
||||
|
||||
# 读取简体中文文件
|
||||
zh_hans_file = Path(__file__).parent / 'src' / 'i18n' / 'locales' / 'zh-Hans.ts'
|
||||
zh_hant_file = Path(__file__).parent / 'src' / 'i18n' / 'locales' / 'zh-Hant.ts'
|
||||
|
||||
if not zh_hans_file.exists():
|
||||
print(f"错误:找不到简体中文文件 {zh_hans_file}")
|
||||
return
|
||||
|
||||
print(f"读取简体中文文件: {zh_hans_file}")
|
||||
with open(zh_hans_file, 'r', encoding='utf-8') as f:
|
||||
zh_hans_content = f.read()
|
||||
|
||||
# 提取workflows部分
|
||||
workflows_match = re.search(r'workflows:\s*\{(.+?)\n \},\n unifiedBinding:', zh_hans_content, re.DOTALL)
|
||||
if not workflows_match:
|
||||
print("错误:无法找到workflows部分")
|
||||
return
|
||||
|
||||
workflows_content = workflows_match.group(1)
|
||||
print(f"找到workflows部分,长度: {len(workflows_content)} 字符")
|
||||
|
||||
# 转换为繁体
|
||||
print("正在转换为繁体中文...")
|
||||
traditional_content = convert_to_traditional(workflows_content)
|
||||
|
||||
# 读取现有的繁体中文文件
|
||||
print(f"读取繁体中文文件: {zh_hant_file}")
|
||||
with open(zh_hant_file, 'r', encoding='utf-8') as f:
|
||||
zh_hant_content = f.read()
|
||||
|
||||
# 替换workflows部分
|
||||
zh_hant_new = re.sub(
|
||||
r'workflows:\s*\{(.+?)\n \},\n unifiedBinding:',
|
||||
f'workflows: {{\n{traditional_content}\n }},\n unifiedBinding:',
|
||||
zh_hant_content,
|
||||
flags=re.DOTALL
|
||||
)
|
||||
|
||||
# 写入文件
|
||||
print(f"写入繁体中文文件: {zh_hant_file}")
|
||||
with open(zh_hant_file, 'w', encoding='utf-8') as f:
|
||||
f.write(zh_hant_new)
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("✅ 繁体中文转换完成!")
|
||||
print("=" * 60)
|
||||
print(f"已更新文件: {zh_hant_file}")
|
||||
print("\n建议:")
|
||||
print("1. 检查转换结果是否正确")
|
||||
print("2. 运行 TypeScript 编译检查语法")
|
||||
print("3. 手动审核关键术语的翻译")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,56 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""检查 ru-RU.ts 文件中的中文字符问题"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
def contains_chinese(text: str) -> bool:
|
||||
"""检查文本是否包含中文字符"""
|
||||
return bool(re.search(r'[\u4e00-\u9fff]', text))
|
||||
|
||||
def main():
|
||||
ts_file = Path(__file__).parent / "src/i18n/locales/ru-RU.ts"
|
||||
|
||||
with open(ts_file, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
problematic_lines = []
|
||||
in_workflows = False
|
||||
|
||||
for i, line in enumerate(lines, 1):
|
||||
# 检测是否进入 workflows 部分
|
||||
if 'workflows:' in line:
|
||||
in_workflows = True
|
||||
elif in_workflows and line.strip().startswith('}') and line.count('}') > line.count('{'):
|
||||
# 可能退出 workflows 部分
|
||||
pass
|
||||
|
||||
# 检查是否包含中文字符
|
||||
if contains_chinese(line):
|
||||
# 提取键名
|
||||
key_match = re.search(r'(\w+):\s*[\'"]', line)
|
||||
key_name = key_match.group(1) if key_match else 'unknown'
|
||||
|
||||
problematic_lines.append({
|
||||
'line_num': i,
|
||||
'key': key_name,
|
||||
'content': line.strip(),
|
||||
'in_workflows': in_workflows
|
||||
})
|
||||
|
||||
print(f"发现 {len(problematic_lines)} 行包含中文字符的俄语翻译:\n")
|
||||
|
||||
# 只显示 workflows 部分的问题
|
||||
workflows_problems = [p for p in problematic_lines if p['in_workflows']]
|
||||
|
||||
print(f"workflows 部分问题: {len(workflows_problems)} 行\n")
|
||||
|
||||
for item in workflows_problems[:30]: # 显示前30个
|
||||
print(f"行 {item['line_num']}: {item['key']}")
|
||||
print(f" {item['content'][:100]}")
|
||||
print()
|
||||
|
||||
if len(workflows_problems) > 30:
|
||||
print(f"... 还有 {len(workflows_problems) - 30} 个问题行")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""检查俄语翻译中的中文字符问题"""
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
def contains_chinese(text: str) -> bool:
|
||||
"""检查文本是否包含中文字符"""
|
||||
return bool(re.search(r'[\u4e00-\u9fff]', text))
|
||||
|
||||
def main():
|
||||
json_path = Path(__file__).parent / "workflows_translations.json"
|
||||
|
||||
with open(json_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
translations = data.get('translations', {})
|
||||
|
||||
problematic_keys = []
|
||||
|
||||
for key, value in translations.items():
|
||||
if isinstance(value, dict) and 'ru-RU' in value:
|
||||
ru_text = value['ru-RU']
|
||||
if ru_text != 'TODO' and contains_chinese(ru_text):
|
||||
zh_hans = value.get('zh-Hans', '')
|
||||
problematic_keys.append({
|
||||
'key': key,
|
||||
'ru_text': ru_text,
|
||||
'zh_hans': zh_hans
|
||||
})
|
||||
|
||||
print(f"发现 {len(problematic_keys)} 个包含中文字符的俄语翻译:\n")
|
||||
|
||||
for item in problematic_keys[:20]: # 只显示前20个
|
||||
print(f"键: {item['key']}")
|
||||
print(f" 中文原文: {item['zh_hans']}")
|
||||
print(f" 俄语翻译: {item['ru_text']}")
|
||||
print()
|
||||
|
||||
if len(problematic_keys) > 20:
|
||||
print(f"... 还有 {len(problematic_keys) - 20} 个问题翻译")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,202 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
检查workflows翻译进度
|
||||
|
||||
使用方法:
|
||||
python3 check_translation_progress.py
|
||||
|
||||
显示:
|
||||
- 每种语言的翻译进度
|
||||
- 已完成和待完成的键数量
|
||||
- 翻译完成百分比
|
||||
- 最近翻译的键(如果有)
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
|
||||
def load_translations() -> Dict:
|
||||
"""加载翻译JSON文件"""
|
||||
json_path = Path(__file__).parent / 'workflows_translations.json'
|
||||
|
||||
if not json_path.exists():
|
||||
raise FileNotFoundError(f"找不到翻译文件: {json_path}")
|
||||
|
||||
with open(json_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def analyze_progress(translations_data: Dict) -> Dict[str, Dict]:
|
||||
"""
|
||||
分析每种语言的翻译进度
|
||||
|
||||
返回格式:
|
||||
{
|
||||
'ja-JP': {
|
||||
'completed': 50,
|
||||
'total': 627,
|
||||
'percentage': 7.97,
|
||||
'completed_keys': ['title', 'description', ...],
|
||||
'pending_keys': ['...', ...]
|
||||
},
|
||||
...
|
||||
}
|
||||
"""
|
||||
translations = translations_data.get('translations', {})
|
||||
languages = ['ja-JP', 'zh-Hant', 'es-ES', 'ru-RU', 'th-TH', 'vi-VN']
|
||||
|
||||
progress = {}
|
||||
|
||||
for lang in languages:
|
||||
completed_keys = []
|
||||
pending_keys = []
|
||||
|
||||
for key, values in translations.items():
|
||||
translation = values.get(lang, 'TODO')
|
||||
if translation != 'TODO' and translation.strip():
|
||||
completed_keys.append(key)
|
||||
else:
|
||||
pending_keys.append(key)
|
||||
|
||||
total = len(translations)
|
||||
completed = len(completed_keys)
|
||||
percentage = (completed / total * 100) if total > 0 else 0
|
||||
|
||||
progress[lang] = {
|
||||
'completed': completed,
|
||||
'total': total,
|
||||
'percentage': percentage,
|
||||
'completed_keys': completed_keys,
|
||||
'pending_keys': pending_keys
|
||||
}
|
||||
|
||||
return progress
|
||||
|
||||
|
||||
def get_language_name(lang_code: str) -> str:
|
||||
"""获取语言的中文名称"""
|
||||
names = {
|
||||
'ja-JP': '日语',
|
||||
'zh-Hant': '繁体中文',
|
||||
'es-ES': '西班牙语',
|
||||
'ru-RU': '俄语',
|
||||
'th-TH': '泰语',
|
||||
'vi-VN': '越南语'
|
||||
}
|
||||
return names.get(lang_code, lang_code)
|
||||
|
||||
|
||||
def print_progress_bar(percentage: float, width: int = 40) -> str:
|
||||
"""生成进度条"""
|
||||
filled = int(width * percentage / 100)
|
||||
bar = '█' * filled + '░' * (width - filled)
|
||||
return f"[{bar}] {percentage:.1f}%"
|
||||
|
||||
|
||||
def display_progress(progress: Dict[str, Dict]):
|
||||
"""显示翻译进度"""
|
||||
print("\n" + "="*80)
|
||||
print("📊 Workflows翻译进度报告")
|
||||
print("="*80)
|
||||
|
||||
# 按完成度排序
|
||||
sorted_langs = sorted(progress.items(), key=lambda x: x[1]['percentage'], reverse=True)
|
||||
|
||||
for lang, data in sorted_langs:
|
||||
lang_name = get_language_name(lang)
|
||||
completed = data['completed']
|
||||
total = data['total']
|
||||
percentage = data['percentage']
|
||||
|
||||
print(f"\n【{lang_name} ({lang})】")
|
||||
print(f" {print_progress_bar(percentage)}")
|
||||
print(f" ✅ 已完成: {completed}/{total}")
|
||||
print(f" ⏳ 待翻译: {total - completed}")
|
||||
|
||||
# 显示最近完成的键(前5个)
|
||||
if data['completed_keys']:
|
||||
recent = data['completed_keys'][:5]
|
||||
print(f" 📝 最近完成: {', '.join(recent)}")
|
||||
if len(data['completed_keys']) > 5:
|
||||
print(f" (还有 {len(data['completed_keys']) - 5} 个已完成)")
|
||||
|
||||
# 总体统计
|
||||
print("\n" + "-"*80)
|
||||
total_completed = sum(d['completed'] for d in progress.values())
|
||||
total_items = sum(d['total'] for d in progress.values())
|
||||
avg_percentage = (total_completed / total_items * 100) if total_items > 0 else 0
|
||||
|
||||
print(f"📈 总体进度: {total_completed}/{total_items} ({avg_percentage:.1f}%)")
|
||||
print(f"📊 平均每种语言: {total_completed // len(progress)}/{progress[list(progress.keys())[0]]['total']}")
|
||||
|
||||
# 估算剩余工作量
|
||||
remaining = total_items - total_completed
|
||||
print(f"\n💡 剩余工作量: {remaining} 个翻译项")
|
||||
|
||||
if remaining > 0:
|
||||
# 建议分批策略
|
||||
batches_50 = (remaining + 49) // 50 # 向上取整
|
||||
batches_100 = (remaining + 99) // 100
|
||||
|
||||
print(f" 建议分批策略:")
|
||||
print(f" - 每批50个键: 需要 {batches_50} 批")
|
||||
print(f" - 每批100个键: 需要 {batches_100} 批")
|
||||
|
||||
print("="*80)
|
||||
|
||||
|
||||
def suggest_next_keys(progress: Dict[str, Dict], batch_size: int = 50) -> List[str]:
|
||||
"""建议下一批要翻译的键"""
|
||||
# 找出所有语言都还没翻译的键
|
||||
all_pending = set()
|
||||
|
||||
for lang, data in progress.items():
|
||||
if not all_pending:
|
||||
all_pending = set(data['pending_keys'])
|
||||
else:
|
||||
all_pending &= set(data['pending_keys'])
|
||||
|
||||
return list(all_pending)[:batch_size]
|
||||
|
||||
|
||||
def main():
|
||||
print("🔍 正在检查翻译进度...")
|
||||
|
||||
try:
|
||||
# 加载翻译数据
|
||||
translations_data = load_translations()
|
||||
|
||||
# 分析进度
|
||||
progress = analyze_progress(translations_data)
|
||||
|
||||
# 显示进度
|
||||
display_progress(progress)
|
||||
|
||||
# 建议下一批翻译的键
|
||||
next_keys = suggest_next_keys(progress, batch_size=50)
|
||||
|
||||
if next_keys:
|
||||
print(f"\n💡 建议下一批翻译的键(前10个):")
|
||||
for i, key in enumerate(next_keys[:10], 1):
|
||||
print(f" {i}. {key}")
|
||||
|
||||
if len(next_keys) > 10:
|
||||
print(f" ... 还有 {len(next_keys) - 10} 个键")
|
||||
else:
|
||||
print("\n🎉 恭喜!所有翻译已完成!")
|
||||
|
||||
print("\n✅ 进度检查完成")
|
||||
|
||||
except FileNotFoundError as e:
|
||||
print(f"\n❌ 错误: {e}")
|
||||
print("💡 请确保 workflows_translations.json 文件存在")
|
||||
except Exception as e:
|
||||
print(f"\n❌ 发生错误: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,160 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
自动修复所有语言文件中缺失的 nodeOutputs 和 nodeInputs 键
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
# 需要添加的 nodeOutputs 键(使用英文作为临时翻译)
|
||||
MISSING_NODE_OUTPUTS = {
|
||||
'sender': 'Sender',
|
||||
'output': 'Output',
|
||||
'result': 'Result',
|
||||
'data': 'Data',
|
||||
'error': 'Error Message',
|
||||
'success': 'Success Status',
|
||||
'event': 'Event',
|
||||
'trigger_time': 'Trigger Time',
|
||||
'logs': 'Logs',
|
||||
'scores': 'Scores',
|
||||
'missing': 'Missing Parameters',
|
||||
'parsed': 'Parsed Result',
|
||||
'chunks': 'Text Chunks',
|
||||
'text': 'Text Content',
|
||||
'case_1': 'Case 1 Output',
|
||||
'case_2': 'Case 2 Output',
|
||||
'branch_1': 'Branch 1 Output',
|
||||
'branch_2': 'Branch 2 Output',
|
||||
'count': 'Count',
|
||||
'execution_id': 'Execution ID',
|
||||
'notification_id': 'Notification ID',
|
||||
'suggestions': 'Suggestions',
|
||||
'embedding': 'Embedding Vector',
|
||||
'dimensions': 'Vector Dimensions',
|
||||
'intent': 'Intent',
|
||||
'entities': 'Entities',
|
||||
}
|
||||
|
||||
# 需要添加的 nodeInputs 键
|
||||
MISSING_NODE_INPUTS = {
|
||||
'payload': 'Payload',
|
||||
'input_value': 'Input Value',
|
||||
'conversation_id': 'Conversation ID',
|
||||
}
|
||||
|
||||
# 需要修复的语言文件
|
||||
LANGUAGE_FILES = [
|
||||
'ja-JP.ts',
|
||||
'zh-Hant.ts',
|
||||
'es-ES.ts',
|
||||
'ru-RU.ts',
|
||||
'th-TH.ts',
|
||||
'vi-VN.ts',
|
||||
]
|
||||
|
||||
def find_insertion_point(content: str, section: str) -> tuple[int, str]:
|
||||
"""
|
||||
找到插入点的位置
|
||||
section: 'nodeOutputs' 或 'nodeInputs'
|
||||
返回: (插入位置的行号, 缩进字符串)
|
||||
"""
|
||||
lines = content.split('\n')
|
||||
in_section = False
|
||||
last_key_line = -1
|
||||
indent = ' '
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if f'{section}:' in line and '{' in line:
|
||||
in_section = True
|
||||
continue
|
||||
|
||||
if in_section:
|
||||
# 检测缩进
|
||||
if line.strip() and not line.strip().startswith('//'):
|
||||
match = re.match(r'^(\s+)', line)
|
||||
if match:
|
||||
indent = match.group(1)
|
||||
|
||||
# 找到最后一个键值对
|
||||
if ':' in line and not line.strip().startswith('//'):
|
||||
last_key_line = i
|
||||
|
||||
# 遇到闭合括号,说明section结束
|
||||
if '},' in line and last_key_line > 0:
|
||||
return last_key_line, indent
|
||||
|
||||
return -1, indent
|
||||
|
||||
def add_missing_keys(file_path: Path):
|
||||
"""为指定的语言文件添加缺失的键"""
|
||||
print(f"\n处理文件: {file_path.name}")
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
lines = content.split('\n')
|
||||
modified = False
|
||||
|
||||
# 处理 nodeOutputs
|
||||
for key, value in MISSING_NODE_OUTPUTS.items():
|
||||
if f" {key}:" not in content:
|
||||
print(f" 添加 nodeOutputs.{key}")
|
||||
|
||||
# 找到插入点
|
||||
insert_line, indent = find_insertion_point(content, 'nodeOutputs')
|
||||
if insert_line > 0:
|
||||
# 在最后一个键之后插入
|
||||
new_line = f"{indent}{key}: '{value}',"
|
||||
lines.insert(insert_line + 1, new_line)
|
||||
content = '\n'.join(lines)
|
||||
lines = content.split('\n')
|
||||
modified = True
|
||||
|
||||
# 处理 nodeInputs
|
||||
for key, value in MISSING_NODE_INPUTS.items():
|
||||
if f" {key}:" not in content:
|
||||
print(f" 添加 nodeInputs.{key}")
|
||||
|
||||
# 找到插入点
|
||||
insert_line, indent = find_insertion_point(content, 'nodeInputs')
|
||||
if insert_line > 0:
|
||||
# 在最后一个键之后插入
|
||||
new_line = f"{indent}{key}: '{value}',"
|
||||
lines.insert(insert_line + 1, new_line)
|
||||
content = '\n'.join(lines)
|
||||
lines = content.split('\n')
|
||||
modified = True
|
||||
|
||||
if modified:
|
||||
# 写回文件
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write('\n'.join(lines))
|
||||
print(f" ✓ 已更新 {file_path.name}")
|
||||
else:
|
||||
print(f" - {file_path.name} 无需更新")
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
locales_dir = Path(__file__).parent / 'src' / 'i18n' / 'locales'
|
||||
|
||||
print("=" * 60)
|
||||
print("开始修复多语言 i18n 文件")
|
||||
print("=" * 60)
|
||||
|
||||
for lang_file in LANGUAGE_FILES:
|
||||
file_path = locales_dir / lang_file
|
||||
if file_path.exists():
|
||||
add_missing_keys(file_path)
|
||||
else:
|
||||
print(f"\n警告: 文件不存在 - {lang_file}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("修复完成!")
|
||||
print("=" * 60)
|
||||
print(f"\n已处理 {len(LANGUAGE_FILES)} 个语言文件")
|
||||
print(f"添加了 {len(MISSING_NODE_OUTPUTS)} 个 nodeOutputs 键")
|
||||
print(f"添加了 {len(MISSING_NODE_INPUTS)} 个 nodeInputs 键")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,237 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""直接修复 ru-RU.ts 文件中包含中文字符的翻译
|
||||
从 en-US.ts 提取英文原文,然后替换 ru-RU.ts 中的混合文本
|
||||
"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
def contains_chinese(text: str) -> bool:
|
||||
"""检查文本是否包含中文字符"""
|
||||
return bool(re.search(r'[\u4e00-\u9fff]', text))
|
||||
|
||||
def extract_key_value_pairs(file_path: Path, section_name: str = 'workflows') -> Dict[str, str]:
|
||||
"""从 .ts 文件中提取指定部分的键值对"""
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
result = {}
|
||||
in_section = False
|
||||
brace_count = 0
|
||||
|
||||
for line in lines:
|
||||
# 检测进入目标部分
|
||||
if f'{section_name}:' in line and '{' in line:
|
||||
in_section = True
|
||||
brace_count = line.count('{') - line.count('}')
|
||||
continue
|
||||
|
||||
if not in_section:
|
||||
continue
|
||||
|
||||
# 更新括号计数
|
||||
brace_count += line.count('{') - line.count('}')
|
||||
|
||||
# 提取键值对
|
||||
match = re.match(r'\s*(\w+):\s*[\'"]([^\'"]*(?:\\.[^\'"]*)*)[\'"],?\s*(?://.*)?$', line)
|
||||
if match:
|
||||
key = match.group(1)
|
||||
value = match.group(2)
|
||||
# 处理转义字符
|
||||
value = value.replace("\\'", "'").replace('\\"', '"').replace('\\n', '\n')
|
||||
result[key] = value
|
||||
|
||||
# 检测退出部分
|
||||
if brace_count == 0:
|
||||
break
|
||||
|
||||
return result
|
||||
|
||||
def find_problematic_lines(file_path: Path) -> List[Tuple[int, str, str]]:
|
||||
"""找出包含中文字符的行"""
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
problematic = []
|
||||
in_workflows = False
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if 'workflows:' in line:
|
||||
in_workflows = True
|
||||
continue
|
||||
|
||||
if in_workflows and contains_chinese(line):
|
||||
# 提取键名
|
||||
match = re.match(r'\s*(\w+):\s*[\'"]', line)
|
||||
if match:
|
||||
key = match.group(1)
|
||||
problematic.append((i, key, line))
|
||||
|
||||
return problematic
|
||||
|
||||
# 手动翻译映射 - 基于常见的中俄混合模式
|
||||
MANUAL_TRANSLATIONS = {
|
||||
# 率 -> процент/коэффициент
|
||||
'成功率': 'Процент успеха',
|
||||
'失败率': 'Процент неудач',
|
||||
|
||||
# 次数 -> количество/раз
|
||||
'失败次数': 'Количество неудач',
|
||||
'执行次数': 'Количество выполнений',
|
||||
'成功次数': 'Количество успехов',
|
||||
|
||||
# 状态 -> статус
|
||||
'全部状态': 'Все статусы',
|
||||
'运行状态': 'Статус выполнения',
|
||||
|
||||
# 时间 -> время
|
||||
'等待时间': 'Время ожидания',
|
||||
'执行时间': 'Время выполнения',
|
||||
'创建时间': 'Время создания',
|
||||
'更新时间': 'Время обновления',
|
||||
|
||||
# 记录 -> запись
|
||||
'执行记录': 'Записи выполнения',
|
||||
'节点执行记录': 'Записи выполнения узлов',
|
||||
|
||||
# 节点 -> узел
|
||||
'节点': 'Узел',
|
||||
'节点类型': 'Тип узла',
|
||||
'节点名称': 'Название узла',
|
||||
'选中节点': 'Выбранный узел',
|
||||
'搜索节点': 'Поиск узлов',
|
||||
'没有选中节点可复制': 'Нет выбранных узлов для копирования',
|
||||
'已复制节点': 'Узлы скопированы',
|
||||
'已粘贴节点': 'Узлы вставлены',
|
||||
'未找到匹配节点': 'Совпадающие узлы не найдены',
|
||||
'拖拽节点到画布添加': 'Перетащите узел на холст для добавления',
|
||||
'选择节点或连线': 'Выберите узел или соединение',
|
||||
'点击画布中节点或连线来查看和编辑其属性': 'Нажмите на узел или соединение на холсте, чтобы просмотреть и изменить его свойства',
|
||||
'该节点类型暂无配置选项': 'Для этого типа узла пока нет параметров конфигурации',
|
||||
'确定删除此节点': 'Вы уверены, что хотите удалить этот узел?',
|
||||
'删除后,该节点及其所有连线将被永久移除': 'После удаления узел и все его соединения будут удалены навсегда',
|
||||
'节点显示名称': 'Отображаемое имя узла',
|
||||
|
||||
# 工作流 -> рабочий процесс
|
||||
'工作流': 'Рабочий процесс',
|
||||
'工作流名称': 'Название рабочего процесса',
|
||||
'输入工作流名称': 'Введите название рабочего процесса',
|
||||
|
||||
# 变量 -> переменная
|
||||
'变量': 'Переменная',
|
||||
'变量名': 'Имя переменной',
|
||||
'上下文变量': 'Контекстная переменная',
|
||||
|
||||
# 条件 -> условие
|
||||
'条件': 'Условие',
|
||||
'条件分支': 'Условная ветвь',
|
||||
'输入条件表达式': 'Введите условное выражение',
|
||||
'条件为空时': 'Когда условие пусто',
|
||||
'条件为空时,该连线将始终被执行': 'Когда условие пусто, это соединение всегда будет выполняться',
|
||||
|
||||
# 其他常见词汇
|
||||
'已配置': 'Настроено',
|
||||
'未保存': 'Не сохранено',
|
||||
'有未保存更改': 'Есть несохраненные изменения',
|
||||
'剪贴板为空': 'Буфер обмена пуст',
|
||||
'正在加载节点类型': 'Загрузка типов узлов',
|
||||
'模拟消息': 'Имитация сообщения',
|
||||
'调试上下文': 'Контекст отладки',
|
||||
'请求体': 'Тело запроса',
|
||||
'确定删除此连线': 'Вы уверены, что хотите удалить это соединение?',
|
||||
'删除后,该连线将被永久移除': 'После удаления соединение будет удалено навсегда',
|
||||
}
|
||||
|
||||
def create_translation_dict() -> Dict[str, str]:
|
||||
"""创建完整的翻译字典,包括部分匹配"""
|
||||
translations = {}
|
||||
|
||||
# 添加手动翻译
|
||||
for zh, ru in MANUAL_TRANSLATIONS.items():
|
||||
translations[zh] = ru
|
||||
|
||||
return translations
|
||||
|
||||
def fix_mixed_text(text: str, translations: Dict[str, str]) -> str:
|
||||
"""修复混合中俄文本"""
|
||||
# 首先尝试完全匹配
|
||||
for zh, ru in translations.items():
|
||||
if zh in text:
|
||||
text = text.replace(zh, ru)
|
||||
|
||||
# 移除剩余的中文字符(如果还有的话)
|
||||
# 这是最后的手段,用俄语占位符替换
|
||||
if contains_chinese(text):
|
||||
# 提取中文部分并尝试翻译
|
||||
chinese_parts = re.findall(r'[\u4e00-\u9fff]+', text)
|
||||
for part in chinese_parts:
|
||||
if part in translations:
|
||||
text = text.replace(part, translations[part])
|
||||
|
||||
return text
|
||||
|
||||
def main():
|
||||
base_dir = Path(__file__).parent
|
||||
en_us_file = base_dir / "src/i18n/locales/en-US.ts"
|
||||
ru_ru_file = base_dir / "src/i18n/locales/ru-RU.ts"
|
||||
|
||||
print("🔍 正在分析 ru-RU.ts 文件...")
|
||||
|
||||
# 找出有问题的行
|
||||
problematic_lines = find_problematic_lines(ru_ru_file)
|
||||
print(f"发现 {len(problematic_lines)} 行包含中文字符")
|
||||
|
||||
if not problematic_lines:
|
||||
print("✅ 没有需要修复的翻译!")
|
||||
return
|
||||
|
||||
# 读取整个文件
|
||||
with open(ru_ru_file, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
# 创建翻译字典
|
||||
translations = create_translation_dict()
|
||||
|
||||
# 修复每一行
|
||||
fixed_count = 0
|
||||
for line_num, key, original_line in problematic_lines:
|
||||
# 提取当前值
|
||||
match = re.match(r'(\s*)(\w+):\s*[\'"]([^\'"]*(?:\\.[^\'"]*)*)[\'"],?(\s*(?://.*)?)\s*$', original_line)
|
||||
if not match:
|
||||
continue
|
||||
|
||||
indent, key_name, value, comment = match.groups()
|
||||
|
||||
# 修复值
|
||||
fixed_value = fix_mixed_text(value, translations)
|
||||
|
||||
if fixed_value != value and not contains_chinese(fixed_value):
|
||||
# 重建行
|
||||
new_line = f"{indent}{key_name}: '{fixed_value}',{comment}\n"
|
||||
lines[line_num] = new_line
|
||||
fixed_count += 1
|
||||
print(f"✓ 修复 {key_name}: {value[:50]}... -> {fixed_value[:50]}...")
|
||||
|
||||
# 写回文件
|
||||
if fixed_count > 0:
|
||||
with open(ru_ru_file, 'w', encoding='utf-8') as f:
|
||||
f.writelines(lines)
|
||||
print(f"\n✅ 成功修复 {fixed_count} 行翻译")
|
||||
print(f"📝 已更新文件: {ru_ru_file}")
|
||||
else:
|
||||
print("\n⚠️ 没有成功修复任何翻译")
|
||||
print("可能需要手动检查或添加更多翻译映射")
|
||||
|
||||
# 再次检查
|
||||
print("\n🔍 验证修复结果...")
|
||||
remaining_problems = find_problematic_lines(ru_ru_file)
|
||||
if remaining_problems:
|
||||
print(f"⚠️ 仍有 {len(remaining_problems)} 行包含中文字符")
|
||||
print("\n前10个未修复的键:")
|
||||
for i, (_, key, line) in enumerate(remaining_problems[:10], 1):
|
||||
print(f" {i}. {key}: {line.strip()[:80]}")
|
||||
else:
|
||||
print("✅ 所有中文字符已清除!")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,108 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
修复俄语翻译文件中 workflows 部分的中文混杂问题
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
# 读取俄语文件
|
||||
with open('src/i18n/locales/ru-RU.ts', 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# 定义需要替换的中文文本到俄语的映射
|
||||
replacements = {
|
||||
# workflows section
|
||||
'工作流': 'Рабочий процесс',
|
||||
'创建和管理可视化工作流,实现复杂的消息处理逻辑': 'Создание и управление визуальными рабочими процессами для реализации сложной логики обработки сообщений',
|
||||
'创建工作流': 'Создать рабочий процесс',
|
||||
'从侧边栏选择一个工作流': 'Выберите рабочий процесс из боковой панели',
|
||||
'编辑工作流': 'Редактировать рабочий процесс',
|
||||
'新工作流': 'Новый рабочий процесс',
|
||||
'获取工作流列表失败:': 'Ошибка получения списка рабочих процессов: ',
|
||||
'工作流名称': 'Название рабочего процесса',
|
||||
'工作流描述': 'Описание рабочего процесса',
|
||||
'工作流名称不能为空': 'Название рабочего процесса не может быть пустым',
|
||||
'一个工作流': 'Рабочий процесс',
|
||||
'获取工作流失败:': 'Ошибка получения рабочего процесса: ',
|
||||
'加载工作流失败': 'Ошибка загрузки рабочего процесса',
|
||||
'保存成功': 'Успешно сохранено',
|
||||
'保存失败:': 'Ошибка сохранения: ',
|
||||
'工作流创建成功': 'Рабочий процесс успешно создан',
|
||||
'创建失败:': 'Ошибка создания: ',
|
||||
'删除成功': 'Успешно удалено',
|
||||
'删除失败:': 'Ошибка удаления: ',
|
||||
'你确定要删除这个工作流吗?': 'Вы уверены, что хотите удалить этот рабочий процесс?',
|
||||
'复制成功': 'Успешно скопировано',
|
||||
'复制失败:': 'Ошибка копирования: ',
|
||||
'导出': 'Экспорт',
|
||||
'导入': 'Импорт',
|
||||
'工作流已导出': 'Рабочий процесс экспортирован',
|
||||
'工作流已导入': 'Рабочий процесс импортирован',
|
||||
'导入失败:文件格式无效': 'Ошибка импорта: недопустимый формат файла',
|
||||
'发布': 'Опубликовать',
|
||||
'发布成功': 'Успешно опубликовано',
|
||||
'发布失败': 'Ошибка публикации',
|
||||
'配置': 'Конфигурация',
|
||||
'执行记录': 'Записи выполнения',
|
||||
'编辑器': 'Редактор',
|
||||
'对话调试': 'Отладка диалога',
|
||||
'基础信息': 'Основная информация',
|
||||
'设置工作流名称、图标和描述': 'Настроить название, значок и описание рабочего процесса',
|
||||
'设置工作流名称和描述': 'Настроить название и описание рабочего процесса',
|
||||
'危险区域': 'Опасная зона',
|
||||
'不可逆的操作': 'Необратимые операции',
|
||||
'删除此工作流': 'Удалить этот рабочий процесс',
|
||||
'删除后,所有关联配置将被永久移除,且无法恢复。': 'После удаления все связанные конфигурации будут удалены навсегда и не могут быть восстановлены.',
|
||||
'删除工作流': 'Удалить рабочий процесс',
|
||||
'确认删除': 'Подтвердить удаление',
|
||||
'您确定要删除工作流': 'Вы уверены, что хотите удалить рабочий процесс',
|
||||
'吗?此操作无法撤销。': '? Эту операцию нельзя отменить.',
|
||||
'名称': 'Название',
|
||||
'输入工作流名称': 'Введите название рабочего процесса',
|
||||
'输入工作流描述(可选)': 'Введите описание рабочего процесса (необязательно)',
|
||||
'启用': 'Включить',
|
||||
'启用后,工作流将可以被触发执行': 'После включения рабочий процесс может быть запущен для выполнения',
|
||||
'加载中...': 'Загрузка...',
|
||||
'工作流信息': 'Информация о рабочем процессе',
|
||||
'版本': 'Версия',
|
||||
'创建时间': 'Дата создания',
|
||||
'更新时间': 'Дата обновления',
|
||||
'共': 'Всего',
|
||||
'条执行记录': 'записей выполнения',
|
||||
'统计分析': 'Статистический анализ',
|
||||
'成功': 'успешных',
|
||||
'次': 'раз',
|
||||
'成功率': 'Успешность',
|
||||
'平均耗时': 'Средняя длительность',
|
||||
'每次执行': 'За выполнение',
|
||||
'失败次数': 'Количество неудач',
|
||||
'最后执行': 'Последнее выполнение',
|
||||
'按状态筛选': 'Фильтр по статусу',
|
||||
'全部状态': 'Все статусы',
|
||||
'手动触发': 'Ручной запуск',
|
||||
'执行': 'Выполнение',
|
||||
'状态': 'Статус',
|
||||
'触发类型': 'Тип триггера',
|
||||
'开始时间': 'Время начала',
|
||||
'耗时': 'Длительность',
|
||||
'暂无执行记录': 'Нет записей выполнения',
|
||||
'执行详情': 'Детали выполнения',
|
||||
'错误信息': 'Информация об ошибке',
|
||||
'节点执行记录': 'Записи выполнения узлов',
|
||||
'执行结果': 'Результат выполнения',
|
||||
'等待中': 'Ожидание',
|
||||
'执行中': 'Выполнение',
|
||||
'已完成': 'Завершено',
|
||||
'失败': 'Неудача',
|
||||
'已取消': 'Отменено',
|
||||
}
|
||||
|
||||
# 执行替换
|
||||
for chinese, russian in replacements.items():
|
||||
content = content.replace(chinese, russian)
|
||||
|
||||
# 写回文件
|
||||
with open('src/i18n/locales/ru-RU.ts', 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
|
||||
print("俄语翻译文件修复完成!")
|
||||
@@ -1,150 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""修复 ru-RU.ts 文件中包含中文字符的翻译"""
|
||||
import re
|
||||
import os
|
||||
from pathlib import Path
|
||||
from anthropic import Anthropic
|
||||
|
||||
def contains_chinese(text: str) -> bool:
|
||||
"""检查文本是否包含中文字符"""
|
||||
return bool(re.search(r'[\u4e00-\u9fff]', text))
|
||||
|
||||
def extract_workflows_section(file_path: Path) -> dict:
|
||||
"""从 .ts 文件中提取 workflows 部分的键值对"""
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# 找到 workflows 部分
|
||||
workflows_match = re.search(r'workflows:\s*\{(.*?)\n\s*\},?\s*\n', content, re.DOTALL)
|
||||
if not workflows_match:
|
||||
return {}
|
||||
|
||||
workflows_content = workflows_match.group(1)
|
||||
|
||||
# 提取所有键值对
|
||||
pattern = r"(\w+):\s*['\"]([^'\"]*(?:\\.[^'\"]*)*)['\"]"
|
||||
matches = re.findall(pattern, workflows_content)
|
||||
|
||||
result = {}
|
||||
for key, value in matches:
|
||||
# 处理转义字符
|
||||
value = value.replace("\\'", "'").replace('\\"', '"')
|
||||
result[key] = value
|
||||
|
||||
return result
|
||||
|
||||
def translate_text(client: Anthropic, text: str, target_lang: str = "Russian") -> str:
|
||||
"""使用 Claude API 翻译文本"""
|
||||
try:
|
||||
message = client.messages.create(
|
||||
model="claude-3-5-sonnet-20241022",
|
||||
max_tokens=1000,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
"content": f"""Translate the following English text to {target_lang}.
|
||||
Only provide the translation, no explanations or additional text.
|
||||
Keep any {{variable}} placeholders unchanged.
|
||||
|
||||
Text to translate: {text}"""
|
||||
}]
|
||||
)
|
||||
|
||||
translation = message.content[0].text.strip()
|
||||
# 移除可能的引号
|
||||
translation = translation.strip('"').strip("'")
|
||||
return translation
|
||||
except Exception as e:
|
||||
print(f"翻译错误: {e}")
|
||||
return text
|
||||
|
||||
def main():
|
||||
# 检查 API key
|
||||
api_key = os.getenv('ANTHROPIC_API_KEY')
|
||||
if not api_key:
|
||||
print("错误: 未找到 ANTHROPIC_API_KEY 环境变量")
|
||||
print("请设置: export ANTHROPIC_API_KEY='your-api-key'")
|
||||
return
|
||||
|
||||
client = Anthropic(api_key=api_key)
|
||||
|
||||
base_dir = Path(__file__).parent
|
||||
en_us_file = base_dir / "src/i18n/locales/en-US.ts"
|
||||
ru_ru_file = base_dir / "src/i18n/locales/ru-RU.ts"
|
||||
|
||||
# 提取英文和俄文的 workflows 部分
|
||||
print("正在提取英文原文...")
|
||||
en_workflows = extract_workflows_section(en_us_file)
|
||||
print(f"提取了 {len(en_workflows)} 个英文键")
|
||||
|
||||
print("\n正在提取俄文翻译...")
|
||||
ru_workflows = extract_workflows_section(ru_ru_file)
|
||||
print(f"提取了 {len(ru_workflows)} 个俄文键")
|
||||
|
||||
# 找出包含中文的俄文翻译
|
||||
problematic_keys = []
|
||||
for key, ru_text in ru_workflows.items():
|
||||
if contains_chinese(ru_text):
|
||||
en_text = en_workflows.get(key, '')
|
||||
if en_text:
|
||||
problematic_keys.append({
|
||||
'key': key,
|
||||
'en_text': en_text,
|
||||
'ru_text': ru_text
|
||||
})
|
||||
|
||||
print(f"\n发现 {len(problematic_keys)} 个需要修复的翻译")
|
||||
|
||||
if not problematic_keys:
|
||||
print("没有需要修复的翻译!")
|
||||
return
|
||||
|
||||
# 翻译前10个作为示例
|
||||
print("\n开始翻译前10个键...")
|
||||
fixed_translations = {}
|
||||
|
||||
for i, item in enumerate(problematic_keys[:10], 1):
|
||||
key = item['key']
|
||||
en_text = item['en_text']
|
||||
old_ru_text = item['ru_text']
|
||||
|
||||
print(f"\n[{i}/10] 翻译键: {key}")
|
||||
print(f" 英文: {en_text}")
|
||||
print(f" 旧俄文: {old_ru_text}")
|
||||
|
||||
new_ru_text = translate_text(client, en_text, "Russian")
|
||||
print(f" 新俄文: {new_ru_text}")
|
||||
|
||||
fixed_translations[key] = new_ru_text
|
||||
|
||||
# 保存修复结果到文件
|
||||
output_file = base_dir / "russian_fixes.txt"
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(f"需要修复的翻译总数: {len(problematic_keys)}\n\n")
|
||||
f.write("=" * 80 + "\n")
|
||||
f.write("已翻译的前10个键:\n")
|
||||
f.write("=" * 80 + "\n\n")
|
||||
|
||||
for key, new_text in fixed_translations.items():
|
||||
old_item = next(item for item in problematic_keys if item['key'] == key)
|
||||
f.write(f"键: {key}\n")
|
||||
f.write(f"英文: {old_item['en_text']}\n")
|
||||
f.write(f"旧俄文: {old_item['ru_text']}\n")
|
||||
f.write(f"新俄文: {new_text}\n")
|
||||
f.write("-" * 80 + "\n\n")
|
||||
|
||||
f.write("\n" + "=" * 80 + "\n")
|
||||
f.write("剩余需要翻译的键:\n")
|
||||
f.write("=" * 80 + "\n\n")
|
||||
|
||||
for item in problematic_keys[10:]:
|
||||
f.write(f"键: {item['key']}\n")
|
||||
f.write(f"英文: {item['en_text']}\n")
|
||||
f.write(f"旧俄文: {item['ru_text']}\n")
|
||||
f.write("-" * 80 + "\n\n")
|
||||
|
||||
print(f"\n修复结果已保存到: {output_file}")
|
||||
print(f"\n注意: 由于翻译数量较多({len(problematic_keys)}个),建议分批处理")
|
||||
print("您可以修改脚本中的 [:10] 来处理更多键")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,250 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
从 en-US.ts 提取 workflows 部分,生成干净的俄语翻译
|
||||
策略:直接替换整个 workflows 部分
|
||||
"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
def extract_workflows_section(file_path: Path) -> tuple[str, int, int]:
|
||||
"""提取 workflows 部分的内容和行号范围"""
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
start_line = None
|
||||
end_line = None
|
||||
brace_count = 0
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if 'workflows:' in line and '{' in line:
|
||||
start_line = i
|
||||
brace_count = line.count('{') - line.count('}')
|
||||
continue
|
||||
|
||||
if start_line is not None:
|
||||
brace_count += line.count('{') - line.count('}')
|
||||
if brace_count == 0:
|
||||
end_line = i
|
||||
break
|
||||
|
||||
if start_line is not None and end_line is not None:
|
||||
section = ''.join(lines[start_line:end_line+1])
|
||||
return section, start_line, end_line
|
||||
|
||||
return '', -1, -1
|
||||
|
||||
def translate_en_to_ru(text: str) -> str:
|
||||
"""简单的英译俄映射"""
|
||||
translations = {
|
||||
# 基础词汇
|
||||
'Workflow': 'Рабочий процесс',
|
||||
'workflow': 'рабочий процесс',
|
||||
'Node': 'Узел',
|
||||
'node': 'узел',
|
||||
'nodes': 'узлы',
|
||||
'Nodes': 'Узлы',
|
||||
'Success': 'Успех',
|
||||
'success': 'успех',
|
||||
'Failed': 'Не удалось',
|
||||
'failed': 'не удалось',
|
||||
'Error': 'Ошибка',
|
||||
'error': 'ошибка',
|
||||
'Loading': 'Загрузка',
|
||||
'loading': 'загрузка',
|
||||
'Save': 'Сохранить',
|
||||
'save': 'сохранить',
|
||||
'Delete': 'Удалить',
|
||||
'delete': 'удалить',
|
||||
'Edit': 'Редактировать',
|
||||
'edit': 'редактировать',
|
||||
'Create': 'Создать',
|
||||
'create': 'создать',
|
||||
'Copy': 'Копировать',
|
||||
'copy': 'копировать',
|
||||
'Paste': 'Вставить',
|
||||
'paste': 'вставить',
|
||||
'Copied': 'Скопировано',
|
||||
'copied': 'скопировано',
|
||||
'Pasted': 'Вставлено',
|
||||
'pasted': 'вставлено',
|
||||
'Configuration': 'Конфигурация',
|
||||
'configuration': 'конфигурация',
|
||||
'Execution': 'Выполнение',
|
||||
'execution': 'выполнение',
|
||||
'executions': 'выполнения',
|
||||
'Executions': 'Выполнения',
|
||||
'Record': 'Запись',
|
||||
'record': 'запись',
|
||||
'records': 'записи',
|
||||
'Records': 'Записи',
|
||||
'Status': 'Статус',
|
||||
'status': 'статус',
|
||||
'All': 'Все',
|
||||
'all': 'все',
|
||||
'Duration': 'Продолжительность',
|
||||
'duration': 'продолжительность',
|
||||
'Time': 'Время',
|
||||
'time': 'время',
|
||||
'Rate': 'Коэффициент',
|
||||
'rate': 'коэффициент',
|
||||
'Average': 'Средний',
|
||||
'average': 'средний',
|
||||
'Total': 'Всего',
|
||||
'total': 'всего',
|
||||
'Last': 'Последний',
|
||||
'last': 'последний',
|
||||
'Condition': 'Условие',
|
||||
'condition': 'условие',
|
||||
'Branch': 'Ветвь',
|
||||
'branch': 'ветвь',
|
||||
'Variable': 'Переменная',
|
||||
'variable': 'переменная',
|
||||
'Context': 'Контекст',
|
||||
'context': 'контекст',
|
||||
'Debug': 'Отладка',
|
||||
'debug': 'отладка',
|
||||
'Message': 'Сообщение',
|
||||
'message': 'сообщение',
|
||||
'Request': 'Запрос',
|
||||
'request': 'запрос',
|
||||
'Body': 'Тело',
|
||||
'body': 'тело',
|
||||
'Empty': 'Пусто',
|
||||
'empty': 'пусто',
|
||||
'Clipboard': 'Буфер обмена',
|
||||
'clipboard': 'буфер обмена',
|
||||
'Search': 'Поиск',
|
||||
'search': 'поиск',
|
||||
'Type': 'Тип',
|
||||
'type': 'тип',
|
||||
'Found': 'Найдено',
|
||||
'found': 'найдено',
|
||||
'Drag': 'Перетащить',
|
||||
'drag': 'перетащить',
|
||||
'Canvas': 'Холст',
|
||||
'canvas': 'холст',
|
||||
'Select': 'Выбрать',
|
||||
'select': 'выбрать',
|
||||
'Edge': 'Соединение',
|
||||
'edge': 'соединение',
|
||||
'Click': 'Нажать',
|
||||
'click': 'нажать',
|
||||
'View': 'Просмотреть',
|
||||
'view': 'просмотреть',
|
||||
'Properties': 'Свойства',
|
||||
'properties': 'свойства',
|
||||
'Configured': 'Настроено',
|
||||
'configured': 'настроено',
|
||||
'Expression': 'Выражение',
|
||||
'expression': 'выражение',
|
||||
'Enter': 'Введите',
|
||||
'enter': 'введите',
|
||||
'When': 'Когда',
|
||||
'when': 'когда',
|
||||
'Will': 'Будет',
|
||||
'will': 'будет',
|
||||
'Always': 'Всегда',
|
||||
'always': 'всегда',
|
||||
'Executed': 'Выполнено',
|
||||
'executed': 'выполнено',
|
||||
'Support': 'Поддержка',
|
||||
'support': 'поддержка',
|
||||
'Reference': 'Ссылка',
|
||||
'reference': 'ссылка',
|
||||
'Confirm': 'Подтвердить',
|
||||
'confirm': 'подтвердить',
|
||||
'After': 'После',
|
||||
'after': 'после',
|
||||
'Removed': 'Удалено',
|
||||
'removed': 'удалено',
|
||||
'Permanently': 'Навсегда',
|
||||
'permanently': 'навсегда',
|
||||
'Label': 'Метка',
|
||||
'label': 'метка',
|
||||
'Display': 'Отображение',
|
||||
'display': 'отображение',
|
||||
'Name': 'Имя',
|
||||
'name': 'имя',
|
||||
'Simulate': 'Имитировать',
|
||||
'simulate': 'имитировать',
|
||||
'Options': 'Параметры',
|
||||
'options': 'параметры',
|
||||
'No': 'Нет',
|
||||
'no': 'нет',
|
||||
'Unsaved': 'Несохраненные',
|
||||
'unsaved': 'несохраненные',
|
||||
'Changes': 'Изменения',
|
||||
'changes': 'изменения',
|
||||
'Nothing': 'Ничего',
|
||||
'nothing': 'ничего',
|
||||
'Selected': 'Выбрано',
|
||||
'selected': 'выбрано',
|
||||
'Matching': 'Совпадающие',
|
||||
'matching': 'совпадающие',
|
||||
'Add': 'Добавить',
|
||||
'add': 'добавить',
|
||||
'Connection': 'Соединение',
|
||||
'connection': 'соединение',
|
||||
}
|
||||
|
||||
result = text
|
||||
for en, ru in translations.items():
|
||||
result = result.replace(f"'{en}'", f"'{ru}'")
|
||||
result = result.replace(f'"{en}"', f'"{ru}"')
|
||||
|
||||
return result
|
||||
|
||||
def main():
|
||||
base_dir = Path(__file__).parent
|
||||
en_us_file = base_dir / "src/i18n/locales/en-US.ts"
|
||||
ru_ru_file = base_dir / "src/i18n/locales/ru-RU.ts"
|
||||
|
||||
print("📖 从 en-US.ts 提取 workflows 部分...")
|
||||
en_workflows, en_start, en_end = extract_workflows_section(en_us_file)
|
||||
|
||||
if not en_workflows:
|
||||
print("❌ 无法提取 en-US.ts 的 workflows 部分")
|
||||
return
|
||||
|
||||
print(f"✓ 提取了 {en_end - en_start + 1} 行")
|
||||
|
||||
print("\n🔄 翻译成俄语...")
|
||||
ru_workflows = translate_en_to_ru(en_workflows)
|
||||
|
||||
print("\n📝 读取 ru-RU.ts 文件...")
|
||||
with open(ru_ru_file, 'r', encoding='utf-8') as f:
|
||||
ru_lines = f.readlines()
|
||||
|
||||
# 找到 ru-RU.ts 中的 workflows 部分
|
||||
print("🔍 定位 ru-RU.ts 中的 workflows 部分...")
|
||||
_, ru_start, ru_end = extract_workflows_section(ru_ru_file)
|
||||
|
||||
if ru_start == -1:
|
||||
print("❌ 无法找到 ru-RU.ts 的 workflows 部分")
|
||||
return
|
||||
|
||||
print(f"✓ 找到位置: 行 {ru_start+1} 到 {ru_end+1}")
|
||||
|
||||
# 替换
|
||||
print("\n✏️ 替换 workflows 部分...")
|
||||
new_lines = ru_lines[:ru_start] + [ru_workflows] + ru_lines[ru_end+1:]
|
||||
|
||||
# 写回文件
|
||||
with open(ru_ru_file, 'w', encoding='utf-8') as f:
|
||||
f.writelines(new_lines)
|
||||
|
||||
print(f"✅ 已更新 {ru_ru_file}")
|
||||
|
||||
# 验证
|
||||
print("\n🔍 验证结果...")
|
||||
with open(ru_ru_file, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
chinese_count = len(re.findall(r'[\u4e00-\u9fff]', content))
|
||||
if chinese_count == 0:
|
||||
print("✅ 验证通过:没有中文字符!")
|
||||
else:
|
||||
print(f"⚠️ 仍有 {chinese_count} 个中文字符")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,265 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
将英文翻译键翻译成对应的目标语言
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
# 翻译映射表
|
||||
TRANSLATIONS = {
|
||||
'ja-JP': { # 日文
|
||||
'Sender': '送信者',
|
||||
'Output': '出力',
|
||||
'Result': '結果',
|
||||
'Data': 'データ',
|
||||
'Error Message': 'エラーメッセージ',
|
||||
'Success Status': '成功ステータス',
|
||||
'Event': 'イベント',
|
||||
'Trigger Time': 'トリガー時刻',
|
||||
'Logs': 'ログ',
|
||||
'Scores': 'スコア',
|
||||
'Missing Parameters': '不足パラメータ',
|
||||
'Parsed Result': '解析結果',
|
||||
'Text Chunks': 'テキストチャンク',
|
||||
'Text Content': 'テキスト内容',
|
||||
'Case 1 Output': 'ケース1出力',
|
||||
'Case 2 Output': 'ケース2出力',
|
||||
'Branch 1 Output': 'ブランチ1出力',
|
||||
'Branch 2 Output': 'ブランチ2出力',
|
||||
'Count': 'カウント',
|
||||
'Execution ID': '実行ID',
|
||||
'Notification ID': '通知ID',
|
||||
'Suggestions': '提案',
|
||||
'Embedding Vector': '埋め込みベクトル',
|
||||
'Vector Dimensions': 'ベクトル次元',
|
||||
'Intent': '意図',
|
||||
'Entities': 'エンティティ',
|
||||
'Payload': 'ペイロード',
|
||||
'Input Value': '入力値',
|
||||
'Conversation ID': '会話ID',
|
||||
},
|
||||
'zh-Hant': { # 繁体中文
|
||||
'Sender': '發送者',
|
||||
'Output': '輸出',
|
||||
'Result': '結果',
|
||||
'Data': '數據',
|
||||
'Error Message': '錯誤訊息',
|
||||
'Success Status': '成功狀態',
|
||||
'Event': '事件',
|
||||
'Trigger Time': '觸發時間',
|
||||
'Logs': '日誌',
|
||||
'Scores': '分數',
|
||||
'Missing Parameters': '缺失參數',
|
||||
'Parsed Result': '解析結果',
|
||||
'Text Chunks': '文本塊',
|
||||
'Text Content': '文本內容',
|
||||
'Case 1 Output': '情況1輸出',
|
||||
'Case 2 Output': '情況2輸出',
|
||||
'Branch 1 Output': '分支1輸出',
|
||||
'Branch 2 Output': '分支2輸出',
|
||||
'Count': '計數',
|
||||
'Execution ID': '執行ID',
|
||||
'Notification ID': '通知ID',
|
||||
'Suggestions': '建議',
|
||||
'Embedding Vector': '嵌入向量',
|
||||
'Vector Dimensions': '向量維度',
|
||||
'Intent': '意圖',
|
||||
'Entities': '實體',
|
||||
'Payload': '負載',
|
||||
'Input Value': '輸入值',
|
||||
'Conversation ID': '對話ID',
|
||||
},
|
||||
'es-ES': { # 西班牙语
|
||||
'Sender': 'Remitente',
|
||||
'Output': 'Salida',
|
||||
'Result': 'Resultado',
|
||||
'Data': 'Datos',
|
||||
'Error Message': 'Mensaje de Error',
|
||||
'Success Status': 'Estado de Éxito',
|
||||
'Event': 'Evento',
|
||||
'Trigger Time': 'Hora de Activación',
|
||||
'Logs': 'Registros',
|
||||
'Scores': 'Puntuaciones',
|
||||
'Missing Parameters': 'Parámetros Faltantes',
|
||||
'Parsed Result': 'Resultado Analizado',
|
||||
'Text Chunks': 'Fragmentos de Texto',
|
||||
'Text Content': 'Contenido de Texto',
|
||||
'Case 1 Output': 'Salida Caso 1',
|
||||
'Case 2 Output': 'Salida Caso 2',
|
||||
'Branch 1 Output': 'Salida Rama 1',
|
||||
'Branch 2 Output': 'Salida Rama 2',
|
||||
'Count': 'Conteo',
|
||||
'Execution ID': 'ID de Ejecución',
|
||||
'Notification ID': 'ID de Notificación',
|
||||
'Suggestions': 'Sugerencias',
|
||||
'Embedding Vector': 'Vector de Incrustación',
|
||||
'Vector Dimensions': 'Dimensiones del Vector',
|
||||
'Intent': 'Intención',
|
||||
'Entities': 'Entidades',
|
||||
'Payload': 'Carga Útil',
|
||||
'Input Value': 'Valor de Entrada',
|
||||
'Conversation ID': 'ID de Conversación',
|
||||
},
|
||||
'ru-RU': { # 俄语
|
||||
'Sender': 'Отправитель',
|
||||
'Output': 'Вывод',
|
||||
'Result': 'Результат',
|
||||
'Data': 'Данные',
|
||||
'Error Message': 'Сообщение об Ошибке',
|
||||
'Success Status': 'Статус Успеха',
|
||||
'Event': 'Событие',
|
||||
'Trigger Time': 'Время Триггера',
|
||||
'Logs': 'Журналы',
|
||||
'Scores': 'Оценки',
|
||||
'Missing Parameters': 'Отсутствующие Параметры',
|
||||
'Parsed Result': 'Разобранный Результат',
|
||||
'Text Chunks': 'Фрагменты Текста',
|
||||
'Text Content': 'Текстовое Содержимое',
|
||||
'Case 1 Output': 'Вывод Случая 1',
|
||||
'Case 2 Output': 'Вывод Случая 2',
|
||||
'Branch 1 Output': 'Вывод Ветви 1',
|
||||
'Branch 2 Output': 'Вывод Ветви 2',
|
||||
'Count': 'Количество',
|
||||
'Execution ID': 'ID Выполнения',
|
||||
'Notification ID': 'ID Уведомления',
|
||||
'Suggestions': 'Предложения',
|
||||
'Embedding Vector': 'Вектор Встраивания',
|
||||
'Vector Dimensions': 'Размерности Вектора',
|
||||
'Intent': 'Намерение',
|
||||
'Entities': 'Сущности',
|
||||
'Payload': 'Полезная Нагрузка',
|
||||
'Input Value': 'Входное Значение',
|
||||
'Conversation ID': 'ID Разговора',
|
||||
},
|
||||
'th-TH': { # 泰语
|
||||
'Sender': 'ผู้ส่ง',
|
||||
'Output': 'ผลลัพธ์',
|
||||
'Result': 'ผลลัพธ์',
|
||||
'Data': 'ข้อมูล',
|
||||
'Error Message': 'ข้อความข้อผิดพลาด',
|
||||
'Success Status': 'สถานะความสำเร็จ',
|
||||
'Event': 'เหตุการณ์',
|
||||
'Trigger Time': 'เวลาทริกเกอร์',
|
||||
'Logs': 'บันทึก',
|
||||
'Scores': 'คะแนน',
|
||||
'Missing Parameters': 'พารามิเตอร์ที่ขาดหายไป',
|
||||
'Parsed Result': 'ผลการแยกวิเคราะห์',
|
||||
'Text Chunks': 'ส่วนข้อความ',
|
||||
'Text Content': 'เนื้อหาข้อความ',
|
||||
'Case 1 Output': 'ผลลัพธ์กรณีที่ 1',
|
||||
'Case 2 Output': 'ผลลัพธ์กรณีที่ 2',
|
||||
'Branch 1 Output': 'ผลลัพธ์สาขา 1',
|
||||
'Branch 2 Output': 'ผลลัพธ์สาขา 2',
|
||||
'Count': 'จำนวน',
|
||||
'Execution ID': 'ID การดำเนินการ',
|
||||
'Notification ID': 'ID การแจ้งเตือน',
|
||||
'Suggestions': 'คำแนะนำ',
|
||||
'Embedding Vector': 'เวกเตอร์ฝังตัว',
|
||||
'Vector Dimensions': 'มิติเวกเตอร์',
|
||||
'Intent': 'เจตนา',
|
||||
'Entities': 'เอนทิตี',
|
||||
'Payload': 'เพย์โหลด',
|
||||
'Input Value': 'ค่าอินพุต',
|
||||
'Conversation ID': 'ID การสนทนา',
|
||||
},
|
||||
'vi-VN': { # 越南语
|
||||
'Sender': 'Người gửi',
|
||||
'Output': 'Đầu ra',
|
||||
'Result': 'Kết quả',
|
||||
'Data': 'Dữ liệu',
|
||||
'Error Message': 'Thông báo Lỗi',
|
||||
'Success Status': 'Trạng thái Thành công',
|
||||
'Event': 'Sự kiện',
|
||||
'Trigger Time': 'Thời gian Kích hoạt',
|
||||
'Logs': 'Nhật ký',
|
||||
'Scores': 'Điểm số',
|
||||
'Missing Parameters': 'Tham số Thiếu',
|
||||
'Parsed Result': 'Kết quả Phân tích',
|
||||
'Text Chunks': 'Đoạn Văn bản',
|
||||
'Text Content': 'Nội dung Văn bản',
|
||||
'Case 1 Output': 'Đầu ra Trường hợp 1',
|
||||
'Case 2 Output': 'Đầu ra Trường hợp 2',
|
||||
'Branch 1 Output': 'Đầu ra Nhánh 1',
|
||||
'Branch 2 Output': 'Đầu ra Nhánh 2',
|
||||
'Count': 'Số lượng',
|
||||
'Execution ID': 'ID Thực thi',
|
||||
'Notification ID': 'ID Thông báo',
|
||||
'Suggestions': 'Gợi ý',
|
||||
'Embedding Vector': 'Vector Nhúng',
|
||||
'Vector Dimensions': 'Kích thước Vector',
|
||||
'Intent': 'Ý định',
|
||||
'Entities': 'Thực thể',
|
||||
'Payload': 'Tải trọng',
|
||||
'Input Value': 'Giá trị Đầu vào',
|
||||
'Conversation ID': 'ID Hội thoại',
|
||||
},
|
||||
}
|
||||
|
||||
def translate_file(file_path: Path, lang_code: str):
|
||||
"""翻译指定语言文件"""
|
||||
print(f"\n处理文件: {file_path.name}")
|
||||
|
||||
if lang_code not in TRANSLATIONS:
|
||||
print(f" ⚠️ 没有 {lang_code} 的翻译映射")
|
||||
return
|
||||
|
||||
translations = TRANSLATIONS[lang_code]
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
modified = False
|
||||
translated_count = 0
|
||||
|
||||
# 替换翻译
|
||||
for english, translated in translations.items():
|
||||
# 匹配格式: key: 'English Text',
|
||||
pattern = rf"(\s+\w+:\s+)'{re.escape(english)}',"
|
||||
if re.search(pattern, content):
|
||||
content = re.sub(pattern, rf"\1'{translated}',", content)
|
||||
translated_count += 1
|
||||
modified = True
|
||||
print(f" ✓ 翻译: '{english}' -> '{translated}'")
|
||||
|
||||
if modified:
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
print(f" ✅ 已更新 {file_path.name},共翻译 {translated_count} 个键")
|
||||
else:
|
||||
print(f" - {file_path.name} 无需翻译")
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
locales_dir = Path(__file__).parent / 'src' / 'i18n' / 'locales'
|
||||
|
||||
print("=" * 60)
|
||||
print("开始翻译多语言 i18n 文件")
|
||||
print("=" * 60)
|
||||
|
||||
language_files = {
|
||||
'ja-JP.ts': 'ja-JP',
|
||||
'zh-Hant.ts': 'zh-Hant',
|
||||
'es-ES.ts': 'es-ES',
|
||||
'ru-RU.ts': 'ru-RU',
|
||||
'th-TH.ts': 'th-TH',
|
||||
'vi-VN.ts': 'vi-VN',
|
||||
}
|
||||
|
||||
total_translated = 0
|
||||
for filename, lang_code in language_files.items():
|
||||
file_path = locales_dir / filename
|
||||
if file_path.exists():
|
||||
translate_file(file_path, lang_code)
|
||||
total_translated += 1
|
||||
else:
|
||||
print(f"\n警告: 文件不存在 - {filename}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("翻译完成!")
|
||||
print("=" * 60)
|
||||
print(f"\n已处理 {total_translated} 个语言文件")
|
||||
print(f"每个文件最多翻译 {len(TRANSLATIONS['ja-JP'])} 个键")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"_comment": "翻译模板 - 请填写各语言的翻译",
|
||||
"_instructions": "1. 从workflows_chinese_texts.json复制需要翻译的键; 2. 为每个键添加各语言翻译; 3. 运行apply_translations.py应用翻译",
|
||||
"_languages": {
|
||||
"ja-JP": "日语",
|
||||
"zh-Hant": "繁体中文",
|
||||
"es-ES": "西班牙语",
|
||||
"ru-RU": "俄语",
|
||||
"th-TH": "泰语",
|
||||
"vi-VN": "越南语"
|
||||
},
|
||||
"translations": {
|
||||
"title": {
|
||||
"zh-Hans": "工作流",
|
||||
"ja-JP": "ワークフロー",
|
||||
"zh-Hant": "工作流",
|
||||
"es-ES": "Flujo de trabajo",
|
||||
"ru-RU": "Рабочий процесс",
|
||||
"th-TH": "เวิร์กโฟลว์",
|
||||
"vi-VN": "Quy trình làm việc"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,629 +0,0 @@
|
||||
{
|
||||
"title": "工作流对话",
|
||||
"description": "描述",
|
||||
"createWorkflow": "创建工作流",
|
||||
"selectFromSidebar": "从侧边栏选择一个工作流",
|
||||
"editWorkflow": "编辑工作流",
|
||||
"newWorkflow": "新工作流",
|
||||
"getWorkflowListError": "获取工作流列表失败:",
|
||||
"workflowName": "工作流名称",
|
||||
"workflowDescription": "工作流描述",
|
||||
"workflowNameRequired": "工作流名称不能为空",
|
||||
"defaultDescription": "一个工作流",
|
||||
"getWorkflowError": "获取工作流失败:",
|
||||
"loadError": "加载工作流失败",
|
||||
"saveSuccess": "保存成功",
|
||||
"saveError": "保存失败:",
|
||||
"createSuccess": "工作流创建成功",
|
||||
"createError": "创建失败:",
|
||||
"deleteSuccess": "删除成功",
|
||||
"deleteError": "删除失败:",
|
||||
"deleteConfirmation": "你确定要删除这个工作流吗?",
|
||||
"copySuccess": "复制成功",
|
||||
"copyError": "复制失败:",
|
||||
"export": "导出",
|
||||
"import": "导入",
|
||||
"exportSuccess": "工作流已导出",
|
||||
"importSuccess": "工作流已导入",
|
||||
"importError": "导入失败:文件格式无效",
|
||||
"publish": "发布",
|
||||
"publishSuccess": "发布成功",
|
||||
"publishError": "发布失败",
|
||||
"configuration": "配置",
|
||||
"executions": "执行记录",
|
||||
"editor": "编辑器",
|
||||
"debugChat": "对话调试",
|
||||
"basicInfo": "基础信息",
|
||||
"basicInfoDesc": "设置工作流名称、图标和描述",
|
||||
"basicInfoDescription": "设置工作流名称和描述",
|
||||
"dangerZone": "危险区域",
|
||||
"dangerZoneDesc": "不可逆的操作",
|
||||
"dangerZoneDescription": "不可逆的操作",
|
||||
"deleteWorkflowAction": "删除此工作流",
|
||||
"deleteWorkflowHint": "删除后,所有关联配置将被永久移除,且无法恢复。",
|
||||
"deleteWorkflow": "删除工作流",
|
||||
"deleteConfirm": "确认删除",
|
||||
"deleteConfirmDesc": "您确定要删除工作流 \"{{name}}\" 吗?此操作无法撤销。",
|
||||
"name": "名称",
|
||||
"namePlaceholder": "输入工作流名称",
|
||||
"descriptionPlaceholder": "输入工作流描述(可选)",
|
||||
"enabled": "启用",
|
||||
"enabledDesc": "启用后,工作流将可以被触发执行",
|
||||
"loading": "加载中...",
|
||||
"info": "工作流信息",
|
||||
"uuid": "UUID",
|
||||
"version": "版本",
|
||||
"createdAt": "创建时间",
|
||||
"updatedAt": "更新时间",
|
||||
"totalExecutions": "共 {{count}} 条执行记录",
|
||||
"statistics": "统计分析",
|
||||
"successfulCount": "成功 {{count}} 次",
|
||||
"successRate": "成功率",
|
||||
"averageDuration": "平均耗时",
|
||||
"perExecution": "每次执行",
|
||||
"failedExecutions": "失败次数",
|
||||
"lastExecution": "最后执行",
|
||||
"filterByStatus": "按状态筛选",
|
||||
"allStatuses": "全部状态",
|
||||
"manualTrigger": "手动触发",
|
||||
"executionId": "执行 ID",
|
||||
"status": "状态",
|
||||
"triggerType": "触发类型",
|
||||
"startedAt": "开始时间",
|
||||
"duration": "等待时间",
|
||||
"noExecutions": "暂无执行记录",
|
||||
"executionDetails": "执行详情",
|
||||
"error": "错误",
|
||||
"nodeExecutions": "节点执行记录",
|
||||
"result": "结果",
|
||||
"nodePalette": "节点面板",
|
||||
"properties": "属性",
|
||||
"zoomIn": "放大",
|
||||
"zoomOut": "缩小",
|
||||
"fitView": "适应视图",
|
||||
"unsavedChanges": "有未保存的更改",
|
||||
"paste": "粘贴",
|
||||
"deleted": "已删除",
|
||||
"nothingToCopy": "没有选中的节点可复制",
|
||||
"nothingToPaste": "剪贴板为空",
|
||||
"copied": "已复制 {{count}} 个节点",
|
||||
"pasted": "已粘贴 {{count}} 个节点",
|
||||
"nodesSelected": "已选中 {{count}} 个节点",
|
||||
"edgesSelected": "已选中 {{count}} 条连线",
|
||||
"searchNodes": "搜索节点...",
|
||||
"loadingNodeTypes": "正在加载节点类型...",
|
||||
"noNodesFound": "未找到匹配的节点",
|
||||
"clearSearch": "清除搜索",
|
||||
"dragToAdd": "拖拽节点到画布添加",
|
||||
"selectNodeOrEdge": "选择一个节点或连线",
|
||||
"selectNodeOrEdgeHint": "点击画布中的节点或连线来查看和编辑其属性",
|
||||
"edgeProperties": "连线属性",
|
||||
"nodeProperties": "节点属性",
|
||||
"condition": "条件分支",
|
||||
"hasCondition": "已设置",
|
||||
"conditionPlaceholder": "输入条件表达式,如: output.success == true",
|
||||
"conditionHelp": "条件为空时,该连线将始终被执行。支持使用 {{变量名}} 引用上下文变量。",
|
||||
"deleteEdge": "删除连线",
|
||||
"deleteEdgeConfirm": "确定删除此连线?",
|
||||
"deleteEdgeConfirmDesc": "删除后,该连线将被永久移除。",
|
||||
"nodeLabel": "节点名称",
|
||||
"nodeLabelPlaceholder": "输入节点显示名称",
|
||||
"nodeId": "节点 ID",
|
||||
"inputOutputVariables": "输入/输出变量",
|
||||
"inputs": "输入",
|
||||
"outputs": "输出",
|
||||
"availableVariables": "可用变量",
|
||||
"globalVariables": "全局变量",
|
||||
"messageContent": "模拟消息",
|
||||
"messageSender": "发送者",
|
||||
"platform": "平台",
|
||||
"sessionId": "会话 ID",
|
||||
"timestamp": "时间戳",
|
||||
"nodeConfig": "节点配置",
|
||||
"noConfigOptions": "该节点类型暂无配置选项",
|
||||
"deleteNode": "删除节点",
|
||||
"deleteNodeConfirm": "确定删除此节点?",
|
||||
"deleteNodeConfirmDesc": "删除后,该节点及其所有连线将被永久移除。",
|
||||
"input": "输入",
|
||||
"message": "消息",
|
||||
"text": "文本",
|
||||
"query": "SQL查询",
|
||||
"data": "数据",
|
||||
"value": "值",
|
||||
"content": "内容",
|
||||
"context": "调试上下文",
|
||||
"body": "请求体",
|
||||
"variables": "监控变量",
|
||||
"items": "项目列表",
|
||||
"arguments": "参数",
|
||||
"question": "用户问题",
|
||||
"parameters": "参数定义",
|
||||
"key": "键",
|
||||
"payload": "载荷",
|
||||
"input_value": "输入值",
|
||||
"conversation_id": "会话 ID",
|
||||
"case_1": "分支 1",
|
||||
"case_2": "分支 2",
|
||||
"branch_1": "分支1输出",
|
||||
"branch_2": "分支2输出",
|
||||
"notification_id": "通知ID",
|
||||
"key_template": "键模板",
|
||||
"hash_field": "哈希字段",
|
||||
"server_name": "服务器名称",
|
||||
"tool_name": "工具名称",
|
||||
"arguments_template": "参数模板",
|
||||
"scope": "作用域",
|
||||
"output": "输出",
|
||||
"response": "响应",
|
||||
"sender": "发送者",
|
||||
"sender_id": "发送者 ID",
|
||||
"sender_name": "发送者名称",
|
||||
"cron_timestamp": "Cron 时间戳",
|
||||
"cron_schedule": "Cron 调度表达式",
|
||||
"cron_context": "Cron 上下文",
|
||||
"trigger_time": "触发时间",
|
||||
"schedule": "触发计划",
|
||||
"headers": "请求头",
|
||||
"query_params": "查询参数",
|
||||
"method": "请求方法",
|
||||
"is_group": "是否群聊",
|
||||
"event": "事件",
|
||||
"event_type": "事件类型",
|
||||
"event_data": "事件数据",
|
||||
"event_timestamp": "事件时间戳",
|
||||
"usage": "Token使用统计",
|
||||
"parsed": "解析结果",
|
||||
"category": "分类结果",
|
||||
"confidence": "置信度",
|
||||
"all_scores": "所有分数",
|
||||
"missing": "缺失参数",
|
||||
"success": "是否成功",
|
||||
"scores": "分数",
|
||||
"chunks": "文本块",
|
||||
"count": "数量",
|
||||
"logs": "日志",
|
||||
"embedding": "向量",
|
||||
"dimensions": "维度",
|
||||
"intent": "意图",
|
||||
"entities": "实体",
|
||||
"prompt": "提示/问题",
|
||||
"context_info": "上下文信息",
|
||||
"console": "控制台输出",
|
||||
"code_input": "代码输入",
|
||||
"code_output": "代码输出",
|
||||
"http_body": "HTTP 请求体",
|
||||
"http_headers": "HTTP 请求头",
|
||||
"http_response": "HTTP 响应",
|
||||
"response_headers": "响应头",
|
||||
"transform_input": "转换输入",
|
||||
"transform_result": "转换结果",
|
||||
"extraction_success": "提取成功",
|
||||
"extract_text": "输入文本",
|
||||
"documents": "检索的文档",
|
||||
"citations": "引用信息",
|
||||
"knowledge_context": "合并上下文",
|
||||
"knowledge_query": "检索查询",
|
||||
"true": "条件为真输出",
|
||||
"false": "条件为假输出",
|
||||
"matched_case": "匹配分支",
|
||||
"default": "默认分支",
|
||||
"item": "当前项",
|
||||
"index": "当前索引",
|
||||
"completed": "已完成",
|
||||
"is_first": "是否第一个",
|
||||
"is_last": "是否最后一个",
|
||||
"results": "结果",
|
||||
"condition_input": "条件输入",
|
||||
"switch_input": "开关输入",
|
||||
"loop_items": "迭代项目",
|
||||
"iterator_array": "输入数组",
|
||||
"iterator_item": "当前元素",
|
||||
"iterator_index": "当前索引",
|
||||
"errors": "错误列表",
|
||||
"parallel_input": "并行输入",
|
||||
"parallel_results": "所有分支结果",
|
||||
"wait_input": "透传输入",
|
||||
"wait_output": "透传输出",
|
||||
"merged": "合并结果",
|
||||
"merge_array": "数组结果",
|
||||
"merge_input_1": "输入 1",
|
||||
"merge_input_2": "输入 2",
|
||||
"merge_input_3": "输入 3",
|
||||
"merge_input_4": "输入 4",
|
||||
"aggregated": "聚合变量",
|
||||
"aggregator_variables": "变量输入",
|
||||
"message_id": "消息ID",
|
||||
"status_code": "状态码",
|
||||
"execution_id": "执行ID",
|
||||
"target": "目标 ID",
|
||||
"reply_message": "回复内容",
|
||||
"pipeline_response": "Pipeline 响应",
|
||||
"pipeline_result": "完整结果",
|
||||
"pipeline_query": "查询内容",
|
||||
"context_data": "上下文数据",
|
||||
"store_status": "存储状态",
|
||||
"store_key": "存储键",
|
||||
"store_value": "存储值",
|
||||
"variable_value": "变量值",
|
||||
"variable_result": "设置变量结果",
|
||||
"statement": "开场白",
|
||||
"suggested_questions": "建议问题",
|
||||
"suggestions": "建议问题",
|
||||
"workflow_output": "工作流输出",
|
||||
"final_result": "最终结果",
|
||||
"query_results": "查询结果",
|
||||
"row_count": "行数",
|
||||
"query_success": "查询成功",
|
||||
"redis_result": "Redis结果",
|
||||
"redis_success": "Redis成功",
|
||||
"redis_key": "Redis 键",
|
||||
"redis_value": "Redis 值",
|
||||
"plugin_input": "插件输入",
|
||||
"tool_result": "工具结果",
|
||||
"tool_success": "工具成功",
|
||||
"mcp_arguments": "工具参数",
|
||||
"memory_result": "记忆结果",
|
||||
"memory_success": "记忆成功",
|
||||
"memory_value": "存储值",
|
||||
"answer": "答案",
|
||||
"dify_success": "Dify成功",
|
||||
"dify_query": "用户输入/查询",
|
||||
"dify_conversation_id": "会话 ID",
|
||||
"search_results": "搜索结果",
|
||||
"knowledge_base_query": "查询内容",
|
||||
"n8n_result": "N8n结果",
|
||||
"n8n_success": "N8n成功",
|
||||
"n8n_payload": "工作流输入数据",
|
||||
"flow_result": "流程结果",
|
||||
"flow_success": "流程成功",
|
||||
"langflow_input": "输入内容",
|
||||
"bot_answer": "机器人回复",
|
||||
"bot_success": "机器人成功",
|
||||
"coze_query": "用户输入/查询",
|
||||
"coze_conversation_id": "会话 ID",
|
||||
"bot_conversation_id": "会话 ID",
|
||||
"webhook_body": "Webhook 请求体",
|
||||
"webhook_headers": "Webhook 请求头",
|
||||
"webhook_query": "Webhook 查询参数",
|
||||
"webhook_method": "Webhook 请求方法",
|
||||
"save": "保存",
|
||||
"undo": "撤销",
|
||||
"redo": "重做",
|
||||
"edgeCondition": "条件表达式",
|
||||
"edgeConditionPlaceholder": "如: ${output.success} == true",
|
||||
"noNodeSelected": "未选中节点",
|
||||
"selectNodeToEdit": "点击节点查看和编辑属性",
|
||||
"dragNodeHint": "拖拽节点到画布",
|
||||
"trigger": "触发器",
|
||||
"triggerDescription": "工作流的起始节点",
|
||||
"messageTrigger": "消息触发",
|
||||
"messageTriggerDescription": "当收到消息时触发",
|
||||
"scheduleTrigger": "定时触发",
|
||||
"scheduleTriggerDescription": "按计划定时触发",
|
||||
"cronTrigger": "定时触发",
|
||||
"cronTriggerDescription": "按定时计划触发工作流",
|
||||
"webhookTrigger": "Webhook 触发",
|
||||
"webhookTriggerDescription": "通过 HTTP 请求触发",
|
||||
"eventTrigger": "事件触发",
|
||||
"eventTriggerDescription": "当系统事件发生时触发",
|
||||
"process": "AI/处理",
|
||||
"processDescription": "数据处理节点",
|
||||
"aiProcess": "AI 处理",
|
||||
"aiProcessDescription": "使用 AI 模型处理消息",
|
||||
"llmCall": "LLM 调用",
|
||||
"llmCallDescription": "调用大语言模型进行对话或生成",
|
||||
"codeProcess": "代码处理",
|
||||
"codeProcessDescription": "执行自定义代码",
|
||||
"codeExecutor": "代码执行",
|
||||
"codeExecutorDescription": "执行 Python/JavaScript 代码",
|
||||
"templateProcess": "模板处理",
|
||||
"templateProcessDescription": "使用模板格式化输出",
|
||||
"httpRequest": "HTTP 请求",
|
||||
"httpRequestDescription": "发送 HTTP 请求",
|
||||
"dataTransform": "数据转换",
|
||||
"dataTransformDescription": "转换数据格式",
|
||||
"questionClassifier": "问题分类器",
|
||||
"questionClassifierDescription": "使用 LLM 将用户问题分类到预定义类别",
|
||||
"parameterExtractor": "参数提取器",
|
||||
"parameterExtractorDescription": "使用 LLM 从文本中提取结构化参数",
|
||||
"knowledgeRetrieval": "知识库检索",
|
||||
"knowledgeRetrievalDescription": "从知识库中检索相关内容",
|
||||
"textTemplate": "文本模板",
|
||||
"textTemplateDescription": "使用模板生成文本",
|
||||
"jsonTransform": "JSON 转换",
|
||||
"jsonTransformDescription": "转换 JSON 数据",
|
||||
"dataAggregator": "数据聚合",
|
||||
"dataAggregatorDescription": "聚合多个数据源",
|
||||
"textSplitter": "文本分割",
|
||||
"textSplitterDescription": "将文本分割成块",
|
||||
"variableAssignment": "变量赋值",
|
||||
"variableAssignmentDescription": "为工作流变量赋值",
|
||||
"control": "控制流",
|
||||
"controlDescription": "流程控制节点",
|
||||
"conditionDescription": "根据条件分流",
|
||||
"switch": "多路分支",
|
||||
"switchDescription": "多条件分支选择",
|
||||
"loop": "循环",
|
||||
"loopDescription": "重复执行",
|
||||
"iterator": "迭代器",
|
||||
"iteratorDescription": "遍历数组元素",
|
||||
"parallel": "并行处理",
|
||||
"parallelDescription": "并行执行多个分支",
|
||||
"wait": "等待",
|
||||
"waitDescription": "等待指定时间",
|
||||
"delay": "延迟",
|
||||
"delayDescription": "等待指定时间",
|
||||
"merge": "合并",
|
||||
"mergeDescription": "合并多个分支",
|
||||
"variableAggregator": "变量聚合器",
|
||||
"variableAggregatorDescription": "聚合多个分支的变量输出",
|
||||
"action": "动作",
|
||||
"actionDescription": "执行动作的节点",
|
||||
"sendMessage": "发送消息",
|
||||
"sendMessageDescription": "发送消息到平台",
|
||||
"replyMessage": "回复消息",
|
||||
"replyMessageDescription": "回复触发工作流的消息",
|
||||
"storeData": "存储数据",
|
||||
"storeDataDescription": "存储数据到数据库",
|
||||
"callPipeline": "调用 Pipeline",
|
||||
"callPipelineDescription": "调用现有的 Pipeline",
|
||||
"setVariable": "设置变量",
|
||||
"setVariableDescription": "设置上下文变量",
|
||||
"openingStatement": "对话开场白",
|
||||
"openingStatementDescription": "提供对话开场白和建议问题",
|
||||
"end": "结束",
|
||||
"endDescription": "标记工作流执行结束",
|
||||
"log": "日志",
|
||||
"logDescription": "记录日志信息",
|
||||
"integration": "集成",
|
||||
"integrationDescription": "第三方平台集成节点",
|
||||
"difyWorkflow": "Dify 工作流",
|
||||
"difyWorkflowDescription": "调用 Dify 平台工作流",
|
||||
"difyKnowledgeQuery": "Dify 知识库",
|
||||
"difyKnowledgeQueryDescription": "查询 Dify 知识库",
|
||||
"n8nWorkflow": "n8n 工作流",
|
||||
"n8nWorkflowDescription": "调用 n8n 工作流",
|
||||
"langflowFlow": "Langflow 流程",
|
||||
"langflowFlowDescription": "调用 Langflow 流程",
|
||||
"cozeBot": "Coze Bot",
|
||||
"cozeBotDescription": "调用扣子 Bot",
|
||||
"databaseQuery": "数据库查询",
|
||||
"databaseQueryDescription": "执行数据库查询",
|
||||
"redisOperation": "Redis 操作",
|
||||
"redisOperationDescription": "执行 Redis 缓存操作",
|
||||
"mcpTool": "MCP 工具",
|
||||
"mcpToolDescription": "调用 MCP 工具",
|
||||
"memoryStore": "记忆存储",
|
||||
"memoryStoreDescription": "从工作流记忆中存储和检索数据",
|
||||
"startTime": "开始时间",
|
||||
"running": "执行中",
|
||||
"failed": "失败",
|
||||
"cancelled": "已取消",
|
||||
"viewDetails": "查看详情",
|
||||
"cancel": "取消执行",
|
||||
"retry": "重试",
|
||||
"nodeResults": "节点执行结果",
|
||||
"current": "当前版本",
|
||||
"rollback": "回滚到此版本",
|
||||
"rollbackConfirm": "确定回滚到此版本?当前更改将丢失。",
|
||||
"rollbackSuccess": "回滚成功",
|
||||
"rollbackError": "回滚失败:",
|
||||
"mode": "调试模式",
|
||||
"panel": "调试面板",
|
||||
"start": "开始调试",
|
||||
"pause": "暂停",
|
||||
"resume": "继续",
|
||||
"step": "单步执行",
|
||||
"stop": "停止",
|
||||
"messageContentPlaceholder": "输入要模拟的消息内容",
|
||||
"senderId": "发送者 ID",
|
||||
"senderIdPlaceholder": "发送者唯一标识",
|
||||
"senderName": "发送者名称",
|
||||
"senderNamePlaceholder": "发送者显示名称",
|
||||
"platformPlaceholder": "例如 qq、wechat、telegram",
|
||||
"conversationId": "会话 ID",
|
||||
"conversationIdPlaceholder": "会话唯一标识",
|
||||
"isGroup": "群聊",
|
||||
"customVariables": "自定义变量",
|
||||
"customVariablesDesc": "添加自定义变量用于调试",
|
||||
"variableKey": "变量名",
|
||||
"variableValue": "变量值",
|
||||
"addVariable": "添加变量",
|
||||
"watchedVariables": "监控变量",
|
||||
"noWatchedVariables": "暂无监控变量",
|
||||
"addWatchVariable": "添加监控",
|
||||
"nodeStates": "节点状态",
|
||||
"nodeOutputs": "节点输出",
|
||||
"noNodeOutputs": "暂无节点输出",
|
||||
"toggleBreakpoint": "切换断点",
|
||||
"clearBreakpoints": "清除所有断点",
|
||||
"breakpointSet": "断点已设置",
|
||||
"breakpointRemoved": "断点已移除",
|
||||
"noLogs": "暂无日志",
|
||||
"clearLogs": "清空日志",
|
||||
"autoScroll": "自动滚动",
|
||||
"logEntries": "条日志",
|
||||
"resetContext": "重置上下文",
|
||||
"starting": "正在启动调试执行...",
|
||||
"started": "调试执行已启动 (ID: {{id}})",
|
||||
"startError": "启动调试失败",
|
||||
"unknownError": "未知错误",
|
||||
"paused": "已暂停",
|
||||
"pauseError": "暂停失败",
|
||||
"resumed": "执行已恢复",
|
||||
"resumeError": "恢复失败",
|
||||
"steppedTo": "已执行到节点: {{node}}",
|
||||
"stepError": "单步执行失败",
|
||||
"stopped": "调试已停止",
|
||||
"stopError": "停止失败",
|
||||
"debugMode": "调试模式",
|
||||
"debugPanel": "调试面板",
|
||||
"startDebug": "开始调试",
|
||||
"pauseDebug": "暂停",
|
||||
"resumeDebug": "继续",
|
||||
"stepDebug": "单步执行",
|
||||
"stopDebug": "停止",
|
||||
"debugContext": "调试上下文",
|
||||
"simulatedMessage": "模拟消息",
|
||||
"simulatedMessagePlaceholder": "输入要模拟的消息内容",
|
||||
"variableName": "变量名",
|
||||
"breakpoints": "断点",
|
||||
"debugLogs": "调试日志",
|
||||
"idle": "空闲",
|
||||
"pending": "等待中",
|
||||
"skipped": "已跳过",
|
||||
"selectWorkflow": "选择工作流",
|
||||
"sessionType": "会话类型",
|
||||
"privateChat": "私聊",
|
||||
"groupChat": "群聊",
|
||||
"send": "发送",
|
||||
"reset": "重置对话",
|
||||
"inputPlaceholder": "发送 {{type}} 消息...",
|
||||
"noMessages": "暂无消息",
|
||||
"userMessage": "用户",
|
||||
"botMessage": "机器人",
|
||||
"sendFailed": "发送失败",
|
||||
"resetSuccess": "对话已重置",
|
||||
"resetFailed": "重置失败",
|
||||
"loadMessagesFailed": "加载消息失败",
|
||||
"loadWorkflowsFailed": "加载工作流失败",
|
||||
"atTips": "提及机器人",
|
||||
"streaming": "流式传输",
|
||||
"streamOutput": "流式",
|
||||
"connected": "WebSocket已连接",
|
||||
"disconnected": "WebSocket未连接",
|
||||
"connectionError": "WebSocket连接错误",
|
||||
"connectionFailed": "WebSocket连接失败",
|
||||
"notConnected": "WebSocket未连接,请稍后重试",
|
||||
"imageUploadFailed": "图片上传失败",
|
||||
"reply": "回复",
|
||||
"replyTo": "回复给",
|
||||
"showMarkdown": "渲染",
|
||||
"showRaw": "原文",
|
||||
"allMembers": "全体成员",
|
||||
"file": "文件",
|
||||
"voice": "语音",
|
||||
"uploadImage": "上传图片",
|
||||
"uploading": "上传中...",
|
||||
"filterByDate": "按日期筛选",
|
||||
"allTime": "全部时间",
|
||||
"today": "今天",
|
||||
"lastWeek": "最近一周",
|
||||
"lastMonth": "最近一个月",
|
||||
"showingExecutions": "显示 {{shown}} / {{total}} 条记录",
|
||||
"rerun": "重新运行",
|
||||
"rerunExecution": "重新执行",
|
||||
"details": "详情",
|
||||
"completedAt": "完成时间",
|
||||
"noNodeExecutions": "暂无节点执行记录",
|
||||
"conditions": "触发条件",
|
||||
"keyword_filter": "关键词过滤",
|
||||
"regex_filter": "正则过滤",
|
||||
"min_length": "最小长度",
|
||||
"max_length": "最大长度",
|
||||
"require_mention": "需要@机器人",
|
||||
"respond_rules": "群响应规则",
|
||||
"access_control": "访问控制",
|
||||
"cron": "Cron表达式",
|
||||
"timezone": "时区",
|
||||
"path": "Webhook路径",
|
||||
"allowed_methods": "允许的HTTP方法",
|
||||
"content_type": "Content-Type",
|
||||
"auth_type": "认证方式",
|
||||
"auth_key": "认证密钥",
|
||||
"validation": "请求验证",
|
||||
"timeout": "超时时间",
|
||||
"event_types": "事件类型",
|
||||
"filter": "事件过滤",
|
||||
"debounce_ms": "防抖时间",
|
||||
"model": "模型",
|
||||
"prompt_template": "提示词模板",
|
||||
"system_prompt": "系统提示词",
|
||||
"temperature": "温度",
|
||||
"top_p": "Top P",
|
||||
"frequency_penalty": "频率惩罚",
|
||||
"presence_penalty": "存在惩罚",
|
||||
"max_tokens": "最大Token数",
|
||||
"stop_sequences": "停止序列",
|
||||
"seed": "随机种子",
|
||||
"stream": "流式输出",
|
||||
"use_conversation_history": "使用对话历史",
|
||||
"language": "编程语言",
|
||||
"code": "代码",
|
||||
"url": "请求URL",
|
||||
"auth_config": "认证配置",
|
||||
"transform_type": "转换类型",
|
||||
"template": "模板",
|
||||
"expression": "表达式",
|
||||
"output_type": "输出类型",
|
||||
"categories": "分类类别",
|
||||
"instruction": "指令",
|
||||
"knowledge_bases": "知识库",
|
||||
"top_k": "返回数量",
|
||||
"score_threshold": "相似度阈值",
|
||||
"search_method": "搜索方法",
|
||||
"enable_citations": "启用引用",
|
||||
"condition_type": "条件类型",
|
||||
"condition_expression": "条件表达式",
|
||||
"left_value": "左值",
|
||||
"operator": "比较运算符",
|
||||
"right_value": "右值",
|
||||
"cases": "分支条件",
|
||||
"max_iterations": "最大迭代次数",
|
||||
"break_condition": "中断条件",
|
||||
"max_concurrency": "最大并发数",
|
||||
"branches": "分支配置",
|
||||
"wait_all": "等待所有",
|
||||
"fail_fast": "快速失败",
|
||||
"duration_type": "时间单位",
|
||||
"merge_strategy": "合并策略",
|
||||
"variable_mappings": "变量映射",
|
||||
"aggregation_mode": "聚合模式",
|
||||
"target_type": "目标类型",
|
||||
"target_id": "目标ID",
|
||||
"message_type": "消息类型",
|
||||
"reply_mode": "回复模式",
|
||||
"message_template": "消息模板",
|
||||
"long_text_processing": "长文本处理",
|
||||
"force_delay": "强制延迟",
|
||||
"pipeline_uuid": "流水线",
|
||||
"inherit_context": "继承上下文",
|
||||
"storage_type": "存储类型",
|
||||
"ttl": "过期时间",
|
||||
"key_prefix": "键前缀",
|
||||
"variable_name": "变量名称",
|
||||
"variable_scope": "变量作用域",
|
||||
"set_variable_operation": "操作类型",
|
||||
"show_suggestions": "显示建议",
|
||||
"output_format": "输出格式",
|
||||
"success_message": "成功消息",
|
||||
"connection_type": "数据库类型",
|
||||
"connection_string": "连接字符串",
|
||||
"query_type": "查询类型",
|
||||
"connection_url": "连接URL",
|
||||
"operation": "操作类型",
|
||||
"dataset_id": "知识库ID",
|
||||
"escape_html": "转义HTML",
|
||||
"trim_whitespace": "去除空白",
|
||||
"json_transform_type": "JSON转换类型",
|
||||
"json_expression": "JSON表达式",
|
||||
"mapping": "字段映射",
|
||||
"code_language": "编程语言",
|
||||
"code_content": "代码内容",
|
||||
"aggregation_type": "聚合类型",
|
||||
"separator": "分隔符",
|
||||
"field_path": "字段路径",
|
||||
"split_type": "分割类型",
|
||||
"chunk_size": "块大小",
|
||||
"chunk_overlap": "块重叠",
|
||||
"regex_pattern": "正则表达式",
|
||||
"remove_empty": "移除空块",
|
||||
"assign_variable_name": "变量名",
|
||||
"value_type": "值类型",
|
||||
"static_value": "静态值",
|
||||
"n8n_webhook_url": "Webhook URL",
|
||||
"n8n_auth_type": "认证方式",
|
||||
"langflow_flow_id": "流程ID",
|
||||
"coze_bot_id": "机器人ID",
|
||||
"coze_api_base": "API基础URL"
|
||||
}
|
||||
@@ -1,831 +0,0 @@
|
||||
workflows: {
|
||||
title: '工作流',
|
||||
description: '创建和管理可视化工作流,实现复杂的消息处理逻辑',
|
||||
createWorkflow: '创建工作流',
|
||||
selectFromSidebar: '从侧边栏选择一个工作流',
|
||||
editWorkflow: '编辑工作流',
|
||||
newWorkflow: '新工作流',
|
||||
getWorkflowListError: '获取工作流列表失败:',
|
||||
workflowName: '工作流名称',
|
||||
workflowDescription: '工作流描述',
|
||||
workflowNameRequired: '工作流名称不能为空',
|
||||
defaultDescription: '一个工作流',
|
||||
getWorkflowError: '获取工作流失败:',
|
||||
loadError: '加载工作流失败',
|
||||
saveSuccess: '保存成功',
|
||||
saveError: '保存失败:',
|
||||
createSuccess: '工作流创建成功',
|
||||
createError: '创建失败:',
|
||||
deleteSuccess: '删除成功',
|
||||
deleteError: '删除失败:',
|
||||
deleteConfirmation: '你确定要删除这个工作流吗?',
|
||||
copySuccess: '复制成功',
|
||||
copyError: '复制失败:',
|
||||
export: '导出',
|
||||
import: '导入',
|
||||
exportSuccess: '工作流已导出',
|
||||
importSuccess: '工作流已导入',
|
||||
importError: '导入失败:文件格式无效',
|
||||
publish: '发布',
|
||||
publishSuccess: '发布成功',
|
||||
publishError: '发布失败',
|
||||
configuration: '配置',
|
||||
executions: '执行记录',
|
||||
editor: '编辑器',
|
||||
debugChat: '对话调试',
|
||||
basicInfo: '基础信息',
|
||||
basicInfoDesc: '设置工作流名称、图标和描述',
|
||||
basicInfoDescription: '设置工作流名称和描述',
|
||||
dangerZone: '危险区域',
|
||||
dangerZoneDesc: '不可逆的操作',
|
||||
dangerZoneDescription: '不可逆的操作',
|
||||
deleteWorkflowAction: '删除此工作流',
|
||||
deleteWorkflowHint: '删除后,所有关联配置将被永久移除,且无法恢复。',
|
||||
deleteWorkflow: '删除工作流',
|
||||
deleteConfirm: '确认删除',
|
||||
deleteConfirmDesc: '您确定要删除工作流 "{{name}}" 吗?此操作无法撤销。',
|
||||
// Form component
|
||||
name: '名称',
|
||||
namePlaceholder: '输入工作流名称',
|
||||
descriptionPlaceholder: '输入工作流描述(可选)',
|
||||
enabled: '启用',
|
||||
enabledDesc: '启用后,工作流将可以被触发执行',
|
||||
loading: '加载中...',
|
||||
info: '工作流信息',
|
||||
uuid: 'UUID',
|
||||
version: '版本',
|
||||
createdAt: '创建时间',
|
||||
updatedAt: '更新时间',
|
||||
// Executions tab
|
||||
totalExecutions: '共 {{count}} 条执行记录',
|
||||
statistics: '统计分析',
|
||||
successfulCount: '成功 {{count}} 次',
|
||||
successRate: '成功率',
|
||||
averageDuration: '平均耗时',
|
||||
perExecution: '每次执行',
|
||||
failedExecutions: '失败次数',
|
||||
lastExecution: '最后执行',
|
||||
filterByStatus: '按状态筛选',
|
||||
allStatuses: '全部状态',
|
||||
manualTrigger: '手动触发',
|
||||
executionId: '执行 ID',
|
||||
status: '状态',
|
||||
triggerType: '触发类型',
|
||||
startedAt: '开始时间',
|
||||
duration: '耗时',
|
||||
noExecutions: '暂无执行记录',
|
||||
executionDetails: '执行详情',
|
||||
error: '错误信息',
|
||||
nodeExecutions: '节点执行记录',
|
||||
result: '执行结果',
|
||||
'status.pending': '等待中',
|
||||
'status.waiting': '等待中',
|
||||
'status.running': '执行中',
|
||||
'status.completed': '已完成',
|
||||
'status.failed': '失败',
|
||||
'status.cancelled': '已取消',
|
||||
// Editor component translations
|
||||
nodePalette: '节点面板',
|
||||
properties: '属性',
|
||||
zoomIn: '放大',
|
||||
zoomOut: '缩小',
|
||||
fitView: '适应视图',
|
||||
unsavedChanges: '有未保存的更改',
|
||||
paste: '粘贴',
|
||||
deleted: '已删除',
|
||||
nothingToCopy: '没有选中的节点可复制',
|
||||
nothingToPaste: '剪贴板为空',
|
||||
copied: '已复制 {{count}} 个节点',
|
||||
pasted: '已粘贴 {{count}} 个节点',
|
||||
nodesSelected: '已选中 {{count}} 个节点',
|
||||
edgesSelected: '已选中 {{count}} 条连线',
|
||||
// Node palette
|
||||
searchNodes: '搜索节点...',
|
||||
loadingNodeTypes: '正在加载节点类型...',
|
||||
noNodesFound: '未找到匹配的节点',
|
||||
clearSearch: '清除搜索',
|
||||
dragToAdd: '拖拽节点到画布添加',
|
||||
// Property panel
|
||||
selectNodeOrEdge: '选择一个节点或连线',
|
||||
selectNodeOrEdgeHint: '点击画布中的节点或连线来查看和编辑其属性',
|
||||
edgeProperties: '连线属性',
|
||||
nodeProperties: '节点属性',
|
||||
condition: '条件',
|
||||
hasCondition: '已设置',
|
||||
conditionPlaceholder: '输入条件表达式,如: output.success == true',
|
||||
conditionHelp:
|
||||
'条件为空时,该连线将始终被执行。支持使用 {{变量名}} 引用上下文变量。',
|
||||
deleteEdge: '删除连线',
|
||||
deleteEdgeConfirm: '确认删除连线',
|
||||
deleteEdgeConfirmDesc: '删除后,该连线将被永久移除。',
|
||||
nodeLabel: '节点名称',
|
||||
nodeLabelPlaceholder: '输入节点显示名称',
|
||||
nodeId: '节点 ID',
|
||||
inputOutputVariables: '输入/输出变量',
|
||||
inputs: '输入',
|
||||
outputs: '输出',
|
||||
availableVariables: '可用变量',
|
||||
globalVariables: '全局变量',
|
||||
messageContent: '消息内容',
|
||||
messageSender: '发送者',
|
||||
platform: '平台',
|
||||
sessionId: '会话 ID',
|
||||
timestamp: '时间戳',
|
||||
nodeConfig: '节点配置',
|
||||
noConfigOptions: '该节点类型暂无配置选项',
|
||||
deleteNode: '删除节点',
|
||||
deleteNodeConfirm: '确认删除节点',
|
||||
deleteNodeConfirmDesc: '删除后,该节点及其所有连线将被永久移除。',
|
||||
// Node inputs/outputs i18n (for port labels)
|
||||
nodeInputs: {
|
||||
// Common inputs
|
||||
input: '输入',
|
||||
message: '消息内容',
|
||||
text: '文本',
|
||||
query: '查询',
|
||||
data: '数据',
|
||||
condition: '条件',
|
||||
value: '值',
|
||||
// Trigger inputs
|
||||
content: '内容',
|
||||
context: '上下文',
|
||||
body: '请求体',
|
||||
variables: '变量',
|
||||
items: '项目列表',
|
||||
arguments: '参数',
|
||||
// AI/Process inputs
|
||||
question: '问题',
|
||||
parameters: '参数定义',
|
||||
key: '键',
|
||||
payload: '载荷',
|
||||
input_value: '输入值',
|
||||
conversation_id: '会话 ID',
|
||||
// Control inputs
|
||||
case_1: '分支1输入',
|
||||
case_2: '分支2输入',
|
||||
branch_1: '分支1',
|
||||
branch_2: '分支2',
|
||||
// Action inputs
|
||||
notification_id: '通知ID',
|
||||
// Integration inputs
|
||||
key_template: '键模板',
|
||||
hash_field: '哈希字段',
|
||||
server_name: '服务器名称',
|
||||
tool_name: '工具名称',
|
||||
arguments_template: '参数模板',
|
||||
scope: '作用域',
|
||||
},
|
||||
nodeOutputs: {
|
||||
// Common outputs
|
||||
output: '输出',
|
||||
result: '结果',
|
||||
response: '响应',
|
||||
message: '消息',
|
||||
data: '数据',
|
||||
error: '错误',
|
||||
// Trigger outputs
|
||||
sender: '发送者',
|
||||
sender_id: '发送者 ID',
|
||||
sender_name: '发送者名称',
|
||||
conversation_id: '会话 ID',
|
||||
context: '上下文',
|
||||
cron_timestamp: 'Cron 时间戳',
|
||||
cron_schedule: 'Cron 调度表达式',
|
||||
cron_context: 'Cron 上下文',
|
||||
trigger_time: '触发时间',
|
||||
schedule: '触发计划',
|
||||
headers: '请求头',
|
||||
query_params: '查询参数',
|
||||
query: '查询参数',
|
||||
method: '请求方法',
|
||||
body: '请求体',
|
||||
is_group: '是否群聊',
|
||||
platform: '平台',
|
||||
event: '事件',
|
||||
event_type: '事件类型',
|
||||
event_data: '事件数据',
|
||||
event_timestamp: '事件时间戳',
|
||||
// AI/Process outputs
|
||||
usage: 'Token使用统计',
|
||||
parsed: '解析结果',
|
||||
category: '分类结果',
|
||||
confidence: '置信度',
|
||||
all_scores: '所有分数',
|
||||
missing: '缺失参数',
|
||||
success: '是否成功',
|
||||
scores: '分数',
|
||||
chunks: '文本块',
|
||||
count: '数量',
|
||||
logs: '日志',
|
||||
embedding: '向量',
|
||||
dimensions: '维度',
|
||||
intent: '意图',
|
||||
entities: '实体',
|
||||
prompt: '提示/问题',
|
||||
context_info: '上下文信息',
|
||||
console: '控制台输出',
|
||||
code_input: '代码输入',
|
||||
code_output: '代码输出',
|
||||
http_body: 'HTTP 请求体',
|
||||
http_headers: 'HTTP 请求头',
|
||||
http_response: 'HTTP 响应',
|
||||
response_headers: '响应头',
|
||||
transform_input: '转换输入',
|
||||
transform_result: '转换结果',
|
||||
question: '用户问题',
|
||||
parameters: '提取的参数',
|
||||
extraction_success: '提取成功',
|
||||
extract_text: '输入文本',
|
||||
documents: '检索的文档',
|
||||
citations: '引用信息',
|
||||
knowledge_context: '合并上下文',
|
||||
knowledge_query: '检索查询',
|
||||
text: '文本',
|
||||
// Control outputs
|
||||
true: '条件为真输出',
|
||||
false: '条件为假输出',
|
||||
matched_case: '匹配分支',
|
||||
case_1: '分支 1',
|
||||
case_2: '分支 2',
|
||||
default: '默认分支',
|
||||
item: '当前项',
|
||||
index: '当前索引',
|
||||
completed: '是否完成',
|
||||
is_first: '是否第一个',
|
||||
is_last: '是否最后一个',
|
||||
results: '结果',
|
||||
branch_1: '分支1输出',
|
||||
branch_2: '分支2输出',
|
||||
condition_input: '条件输入',
|
||||
switch_input: '开关输入',
|
||||
loop_items: '迭代项目',
|
||||
iterator_array: '输入数组',
|
||||
iterator_item: '当前元素',
|
||||
iterator_index: '当前索引',
|
||||
errors: '错误列表',
|
||||
parallel_input: '并行输入',
|
||||
parallel_results: '所有分支结果',
|
||||
wait_input: '透传输入',
|
||||
wait_output: '透传输出',
|
||||
merged: '合并结果',
|
||||
merge_array: '数组结果',
|
||||
merge_input_1: '输入 1',
|
||||
merge_input_2: '输入 2',
|
||||
merge_input_3: '输入 3',
|
||||
merge_input_4: '输入 4',
|
||||
aggregated: '聚合变量',
|
||||
aggregator_variables: '变量输入',
|
||||
// Action outputs
|
||||
message_id: '消息ID',
|
||||
status_code: '状态码',
|
||||
status: '状态',
|
||||
execution_id: '执行ID',
|
||||
notification_id: '通知ID',
|
||||
target: '目标 ID',
|
||||
reply_message: '回复内容',
|
||||
pipeline_response: 'Pipeline 响应',
|
||||
pipeline_result: '完整结果',
|
||||
pipeline_query: '查询内容',
|
||||
context_data: '上下文数据',
|
||||
store_status: '存储状态',
|
||||
store_key: '存储键',
|
||||
store_value: '存储值',
|
||||
variable_value: '变量值',
|
||||
variable_result: '设置变量结果',
|
||||
statement: '开场白',
|
||||
suggested_questions: '建议问题',
|
||||
suggestions: '建议问题',
|
||||
workflow_output: '工作流输出',
|
||||
final_result: '最终结果',
|
||||
// Integration outputs
|
||||
query_results: '查询结果',
|
||||
row_count: '行数',
|
||||
query_success: '查询成功',
|
||||
redis_result: 'Redis结果',
|
||||
redis_success: 'Redis成功',
|
||||
redis_key: 'Redis 键',
|
||||
redis_value: 'Redis 值',
|
||||
plugin_input: '插件输入',
|
||||
tool_result: '工具结果',
|
||||
tool_success: '工具成功',
|
||||
mcp_arguments: '工具参数',
|
||||
memory_result: '记忆结果',
|
||||
memory_success: '记忆成功',
|
||||
memory_value: '存储值',
|
||||
answer: '答案',
|
||||
dify_success: 'Dify成功',
|
||||
dify_query: '用户输入/查询',
|
||||
dify_conversation_id: '会话 ID',
|
||||
search_results: '搜索结果',
|
||||
knowledge_base_query: '查询内容',
|
||||
n8n_result: 'N8n结果',
|
||||
n8n_success: 'N8n成功',
|
||||
n8n_payload: '工作流输入数据',
|
||||
flow_result: '流程结果',
|
||||
flow_success: '流程成功',
|
||||
langflow_input: '输入内容',
|
||||
bot_answer: '机器人回复',
|
||||
bot_success: '机器人成功',
|
||||
coze_query: '用户输入/查询',
|
||||
coze_conversation_id: '会话 ID',
|
||||
bot_conversation_id: '会话 ID',
|
||||
webhook_body: 'Webhook 请求体',
|
||||
webhook_headers: 'Webhook 请求头',
|
||||
webhook_query: 'Webhook 查询参数',
|
||||
webhook_method: 'Webhook 请求方法',
|
||||
timestamp: '时间戳',
|
||||
},
|
||||
// Data type labels
|
||||
'type.string': '字符串',
|
||||
'type.object': '对象',
|
||||
'type.array': '数组',
|
||||
'type.boolean': '布尔值',
|
||||
'type.number': '数字',
|
||||
'type.any': '任意类型',
|
||||
'type.datetime': '日期时间',
|
||||
// Legacy editor keys for compatibility
|
||||
legacyEditor: {
|
||||
title: '可视化编辑器',
|
||||
save: '保存',
|
||||
undo: '撤销',
|
||||
redo: '重做',
|
||||
zoomIn: '放大',
|
||||
zoomOut: '缩小',
|
||||
fitView: '适应视图',
|
||||
unsavedChanges: '有未保存的更改',
|
||||
nodePalette: '节点面板',
|
||||
properties: '属性',
|
||||
nodeLabel: '节点名称',
|
||||
nodeConfig: '节点配置',
|
||||
deleteNode: '删除节点',
|
||||
deleteNodeConfirm: '确定删除此节点?',
|
||||
deleteEdge: '删除连线',
|
||||
deleteEdgeConfirm: '确定删除此连线?',
|
||||
edgeCondition: '条件表达式',
|
||||
edgeConditionPlaceholder: '如: ${output.success} == true',
|
||||
noNodeSelected: '未选中节点',
|
||||
selectNodeToEdit: '点击节点查看和编辑属性',
|
||||
dragNodeHint: '拖拽节点到画布',
|
||||
},
|
||||
nodes: {
|
||||
trigger: '触发器',
|
||||
triggerDescription: '工作流的起始节点',
|
||||
messageTrigger: '消息触发',
|
||||
messageTriggerDescription: '当收到消息时触发',
|
||||
scheduleTrigger: '定时触发',
|
||||
scheduleTriggerDescription: '按计划定时触发',
|
||||
cronTrigger: '定时触发',
|
||||
cronTriggerDescription: '按定时计划触发工作流',
|
||||
webhookTrigger: 'Webhook 触发',
|
||||
webhookTriggerDescription: '通过 HTTP 请求触发',
|
||||
eventTrigger: '事件触发',
|
||||
eventTriggerDescription: '当系统事件发生时触发',
|
||||
process: 'AI/处理',
|
||||
processDescription: '数据处理节点',
|
||||
aiProcess: 'AI 处理',
|
||||
aiProcessDescription: '使用 AI 模型处理消息',
|
||||
llmCall: 'LLM 调用',
|
||||
llmCallDescription: '调用大语言模型进行对话或生成',
|
||||
codeProcess: '代码处理',
|
||||
codeProcessDescription: '执行自定义代码',
|
||||
codeExecutor: '代码执行',
|
||||
codeExecutorDescription: '执行 Python/JavaScript 代码',
|
||||
templateProcess: '模板处理',
|
||||
templateProcessDescription: '使用模板格式化输出',
|
||||
httpRequest: 'HTTP 请求',
|
||||
httpRequestDescription: '发送 HTTP 请求',
|
||||
dataTransform: '数据转换',
|
||||
dataTransformDescription: '转换数据格式',
|
||||
questionClassifier: '问题分类器',
|
||||
questionClassifierDescription: '使用 LLM 将用户问题分类到预定义类别',
|
||||
parameterExtractor: '参数提取器',
|
||||
parameterExtractorDescription: '使用 LLM 从文本中提取结构化参数',
|
||||
knowledgeRetrieval: '知识库检索',
|
||||
knowledgeRetrievalDescription: '从知识库中检索相关内容',
|
||||
textTemplate: '文本模板',
|
||||
textTemplateDescription: '使用模板生成文本',
|
||||
jsonTransform: 'JSON 转换',
|
||||
jsonTransformDescription: '转换 JSON 数据',
|
||||
dataAggregator: '数据聚合',
|
||||
dataAggregatorDescription: '聚合多个数据源',
|
||||
textSplitter: '文本分割',
|
||||
textSplitterDescription: '将文本分割成块',
|
||||
variableAssignment: '变量赋值',
|
||||
variableAssignmentDescription: '为工作流变量赋值',
|
||||
control: '控制流',
|
||||
controlDescription: '流程控制节点',
|
||||
condition: '条件分支',
|
||||
conditionDescription: '根据条件分流',
|
||||
switch: '多路分支',
|
||||
switchDescription: '多条件分支选择',
|
||||
loop: '循环',
|
||||
loopDescription: '重复执行',
|
||||
iterator: '迭代器',
|
||||
iteratorDescription: '遍历数组元素',
|
||||
parallel: '并行执行',
|
||||
parallelDescription: '并行执行多个分支',
|
||||
wait: '等待',
|
||||
waitDescription: '等待指定时间',
|
||||
delay: '延迟',
|
||||
delayDescription: '等待指定时间',
|
||||
merge: '合并',
|
||||
mergeDescription: '合并多个分支',
|
||||
variableAggregator: '变量聚合器',
|
||||
variableAggregatorDescription: '聚合多个分支的变量输出',
|
||||
action: '动作',
|
||||
actionDescription: '执行动作的节点',
|
||||
sendMessage: '发送消息',
|
||||
sendMessageDescription: '发送消息到平台',
|
||||
replyMessage: '回复消息',
|
||||
replyMessageDescription: '回复触发工作流的消息',
|
||||
storeData: '存储数据',
|
||||
storeDataDescription: '存储数据到数据库',
|
||||
callPipeline: '调用 Pipeline',
|
||||
callPipelineDescription: '调用现有的 Pipeline',
|
||||
setVariable: '设置变量',
|
||||
setVariableDescription: '设置上下文变量',
|
||||
openingStatement: '对话开场白',
|
||||
openingStatementDescription: '提供对话开场白和建议问题',
|
||||
end: '结束',
|
||||
endDescription: '标记工作流执行结束',
|
||||
log: '日志',
|
||||
logDescription: '记录日志信息',
|
||||
integration: '集成',
|
||||
integrationDescription: '第三方平台集成节点',
|
||||
difyWorkflow: 'Dify 工作流',
|
||||
difyWorkflowDescription: '调用 Dify 平台工作流',
|
||||
difyKnowledgeQuery: 'Dify 知识库',
|
||||
difyKnowledgeQueryDescription: '查询 Dify 知识库',
|
||||
n8nWorkflow: 'n8n 工作流',
|
||||
n8nWorkflowDescription: '调用 n8n 工作流',
|
||||
langflowFlow: 'Langflow 流程',
|
||||
langflowFlowDescription: '调用 Langflow 流程',
|
||||
cozeBot: 'Coze Bot',
|
||||
cozeBotDescription: '调用扣子 Bot',
|
||||
// Data & Tools integration nodes
|
||||
databaseQuery: '数据库查询',
|
||||
databaseQueryDescription: '执行数据库查询',
|
||||
redisOperation: 'Redis 操作',
|
||||
redisOperationDescription: '执行 Redis 缓存操作',
|
||||
mcpTool: 'MCP 工具',
|
||||
mcpToolDescription: '调用 MCP 工具',
|
||||
memoryStore: '记忆存储',
|
||||
memoryStoreDescription: '从工作流记忆中存储和检索数据',
|
||||
},
|
||||
executionHistory: {
|
||||
title: '执行记录',
|
||||
noExecutions: '暂无执行记录',
|
||||
status: '状态',
|
||||
startTime: '开始时间',
|
||||
duration: '耗时',
|
||||
running: '运行中',
|
||||
completed: '已完成',
|
||||
failed: '失败',
|
||||
cancelled: '已取消',
|
||||
viewDetails: '查看详情',
|
||||
cancel: '取消执行',
|
||||
retry: '重试',
|
||||
nodeResults: '节点执行结果',
|
||||
},
|
||||
versions: {
|
||||
title: '版本历史',
|
||||
current: '当前版本',
|
||||
rollback: '回滚到此版本',
|
||||
rollbackConfirm: '确定回滚到此版本?当前更改将丢失。',
|
||||
rollbackSuccess: '回滚成功',
|
||||
rollbackError: '回滚失败:',
|
||||
},
|
||||
// Debug and monitoring
|
||||
debug: {
|
||||
title: '调试',
|
||||
mode: '调试模式',
|
||||
panel: '调试面板',
|
||||
start: '开始调试',
|
||||
pause: '暂停',
|
||||
resume: '继续',
|
||||
step: '单步执行',
|
||||
stop: '停止',
|
||||
context: '调试上下文',
|
||||
messageContent: '模拟消息',
|
||||
messageContentPlaceholder: '输入要模拟的消息内容',
|
||||
senderId: '发送者 ID',
|
||||
senderIdPlaceholder: '发送者唯一标识',
|
||||
senderName: '发送者名称',
|
||||
senderNamePlaceholder: '发送者显示名称',
|
||||
platform: '平台',
|
||||
platformPlaceholder: '例如 qq、wechat、telegram',
|
||||
conversationId: '会话 ID',
|
||||
conversationIdPlaceholder: '会话唯一标识',
|
||||
isGroup: '群聊',
|
||||
customVariables: '自定义变量',
|
||||
customVariablesDesc: '添加自定义变量用于调试',
|
||||
variableKey: '变量名',
|
||||
variableValue: '变量值',
|
||||
addVariable: '添加变量',
|
||||
variables: '监控变量',
|
||||
watchedVariables: '监控变量',
|
||||
noWatchedVariables: '暂无监控变量',
|
||||
addWatchVariable: '添加监控',
|
||||
nodeStates: '节点状态',
|
||||
nodeOutputs: '节点输出',
|
||||
noNodeOutputs: '暂无节点输出',
|
||||
toggleBreakpoint: '切换断点',
|
||||
clearBreakpoints: '清除所有断点',
|
||||
breakpointSet: '断点已设置',
|
||||
breakpointRemoved: '断点已移除',
|
||||
logs: '调试日志',
|
||||
noLogs: '暂无日志',
|
||||
clearLogs: '清空日志',
|
||||
autoScroll: '自动滚动',
|
||||
logEntries: '条日志',
|
||||
resetContext: '重置上下文',
|
||||
// Debug execution messages
|
||||
starting: '正在启动调试执行...',
|
||||
started: '调试执行已启动 (ID: {{id}})',
|
||||
startError: '启动调试失败',
|
||||
completed: '调试执行已完成',
|
||||
unknownError: '未知错误',
|
||||
paused: '执行已暂停',
|
||||
pauseError: '暂停失败',
|
||||
resumed: '执行已恢复',
|
||||
resumeError: '恢复失败',
|
||||
steppedTo: '已执行到节点: {{node}}',
|
||||
stepError: '单步执行失败',
|
||||
stopped: '调试已停止',
|
||||
stopError: '停止失败',
|
||||
},
|
||||
debugMode: '调试模式',
|
||||
debugPanel: '调试面板',
|
||||
startDebug: '开始调试',
|
||||
pauseDebug: '暂停',
|
||||
resumeDebug: '继续',
|
||||
stepDebug: '单步执行',
|
||||
stopDebug: '停止',
|
||||
debugContext: '调试上下文',
|
||||
simulatedMessage: '模拟消息',
|
||||
simulatedMessagePlaceholder: '输入要模拟的消息内容',
|
||||
senderId: '发送者 ID',
|
||||
senderIdPlaceholder: '发送者唯一标识',
|
||||
senderName: '发送者名称',
|
||||
senderNamePlaceholder: '发送者显示名称',
|
||||
conversationId: '会话 ID',
|
||||
conversationIdPlaceholder: '会话唯一标识',
|
||||
isGroup: '群聊',
|
||||
customVariables: '自定义变量',
|
||||
addVariable: '添加变量',
|
||||
variableName: '变量名',
|
||||
variableValue: '变量值',
|
||||
watchedVariables: '监控变量',
|
||||
addWatchVariable: '添加监控',
|
||||
nodeStates: '节点状态',
|
||||
breakpoints: '断点',
|
||||
toggleBreakpoint: '切换断点',
|
||||
breakpointSet: '断点已设置',
|
||||
breakpointRemoved: '断点已移除',
|
||||
debugLogs: '调试日志',
|
||||
noLogs: '暂无日志',
|
||||
clearLogs: '清空日志',
|
||||
autoScroll: '自动滚动',
|
||||
debugState: {
|
||||
idle: '空闲',
|
||||
running: '运行中',
|
||||
paused: '已暂停',
|
||||
completed: '已完成',
|
||||
error: '错误',
|
||||
},
|
||||
nodeStatus: {
|
||||
pending: '等待中',
|
||||
running: '执行中',
|
||||
completed: '已完成',
|
||||
failed: '失败',
|
||||
skipped: '已跳过',
|
||||
},
|
||||
debugDialog: {
|
||||
title: '工作流对话',
|
||||
selectWorkflow: '选择工作流',
|
||||
sessionType: '会话类型',
|
||||
privateChat: '私聊',
|
||||
groupChat: '群聊',
|
||||
send: '发送',
|
||||
reset: '重置对话',
|
||||
inputPlaceholder: '发送 {{type}} 消息...',
|
||||
noMessages: '暂无消息',
|
||||
userMessage: '用户',
|
||||
botMessage: '机器人',
|
||||
sendFailed: '发送失败',
|
||||
resetSuccess: '对话已重置',
|
||||
resetFailed: '重置失败',
|
||||
loadMessagesFailed: '加载消息失败',
|
||||
loadWorkflowsFailed: '加载工作流失败',
|
||||
atTips: '提及机器人',
|
||||
streaming: '流式传输',
|
||||
streamOutput: '流式',
|
||||
connected: 'WebSocket已连接',
|
||||
disconnected: 'WebSocket未连接',
|
||||
connectionError: 'WebSocket连接错误',
|
||||
connectionFailed: 'WebSocket连接失败',
|
||||
notConnected: 'WebSocket未连接,请稍后重试',
|
||||
imageUploadFailed: '图片上传失败',
|
||||
reply: '回复',
|
||||
replyTo: '回复给',
|
||||
showMarkdown: '渲染',
|
||||
showRaw: '原文',
|
||||
allMembers: '全体成员',
|
||||
file: '文件',
|
||||
voice: '语音',
|
||||
uploadImage: '上传图片',
|
||||
uploading: '上传中...',
|
||||
},
|
||||
// Execution history and monitoring
|
||||
filterByDate: '按日期筛选',
|
||||
allTime: '全部时间',
|
||||
today: '今天',
|
||||
lastWeek: '最近一周',
|
||||
lastMonth: '最近一个月',
|
||||
showingExecutions: '显示 {{shown}} / {{total}} 条记录',
|
||||
rerun: '重新运行',
|
||||
rerunExecution: '重新执行',
|
||||
logs: '日志',
|
||||
details: '详情',
|
||||
completedAt: '完成时间',
|
||||
noNodeExecutions: '暂无节点执行记录',
|
||||
// Node config field labels (used by DynamicFormComponent)
|
||||
nodeConfigFields: {
|
||||
// trigger.py - MessageTriggerNode
|
||||
conditions: '触发条件',
|
||||
keyword_filter: '关键词过滤',
|
||||
regex_filter: '正则过滤',
|
||||
min_length: '最小长度',
|
||||
max_length: '最大长度',
|
||||
require_mention: '需要@机器人',
|
||||
respond_rules: '群响应规则',
|
||||
access_control: '访问控制',
|
||||
// trigger.py - CronTriggerNode
|
||||
cron: 'Cron表达式',
|
||||
timezone: '时区',
|
||||
description: '描述',
|
||||
// trigger.py - WebhookTriggerNode
|
||||
path: 'Webhook路径',
|
||||
allowed_methods: '允许的HTTP方法',
|
||||
content_type: 'Content-Type',
|
||||
auth_type: '认证方式',
|
||||
auth_key: '认证密钥',
|
||||
validation: '请求验证',
|
||||
timeout: '超时时间',
|
||||
// trigger.py - EventTriggerNode
|
||||
event_types: '事件类型',
|
||||
filter: '事件过滤',
|
||||
debounce_ms: '防抖时间',
|
||||
// process.py - LLMCallNode
|
||||
model: '模型',
|
||||
prompt_template: '提示词模板',
|
||||
system_prompt: '系统提示词',
|
||||
temperature: '温度',
|
||||
top_p: 'Top P',
|
||||
frequency_penalty: '频率惩罚',
|
||||
presence_penalty: '存在惩罚',
|
||||
max_tokens: '最大Token数',
|
||||
stop_sequences: '停止序列',
|
||||
seed: '随机种子',
|
||||
stream: '流式输出',
|
||||
use_conversation_history: '使用对话历史',
|
||||
// process.py - CodeExecutorNode
|
||||
language: '编程语言',
|
||||
code: '代码',
|
||||
// process.py - HTTPRequestNode
|
||||
url: '请求URL',
|
||||
method: '请求方法',
|
||||
auth_config: '认证配置',
|
||||
// process.py - DataTransformNode
|
||||
transform_type: '转换类型',
|
||||
template: '模板',
|
||||
expression: '表达式',
|
||||
output_type: '输出类型',
|
||||
// process.py - QuestionClassifierNode
|
||||
categories: '分类类别',
|
||||
instruction: '指令',
|
||||
// process.py - ParameterExtractorNode
|
||||
parameters: '参数定义',
|
||||
// process.py - KnowledgeRetrievalNode
|
||||
knowledge_bases: '知识库',
|
||||
top_k: '返回数量',
|
||||
score_threshold: '相似度阈值',
|
||||
search_method: '搜索方法',
|
||||
enable_citations: '启用引用',
|
||||
// control.py - ConditionNode
|
||||
condition_type: '条件类型',
|
||||
condition_expression: '条件表达式',
|
||||
left_value: '左值',
|
||||
operator: '比较运算符',
|
||||
right_value: '右值',
|
||||
// control.py - SwitchNode
|
||||
cases: '分支条件',
|
||||
// control.py - LoopNode
|
||||
max_iterations: '最大迭代次数',
|
||||
break_condition: '中断条件',
|
||||
// control.py - IteratorNode
|
||||
parallel: '并行处理',
|
||||
max_concurrency: '最大并发数',
|
||||
// control.py - ParallelNode
|
||||
branches: '分支配置',
|
||||
wait_all: '等待所有',
|
||||
fail_fast: '快速失败',
|
||||
// control.py - WaitNode
|
||||
duration: '等待时间',
|
||||
duration_type: '时间单位',
|
||||
// control.py - MergeNode
|
||||
merge_strategy: '合并策略',
|
||||
// control.py - VariableAggregatorNode
|
||||
variable_mappings: '变量映射',
|
||||
aggregation_mode: '聚合模式',
|
||||
// action.py - SendMessageNode
|
||||
target_type: '目标类型',
|
||||
target_id: '目标ID',
|
||||
platform: '平台',
|
||||
message_type: '消息类型',
|
||||
// action.py - ReplyMessageNode
|
||||
reply_mode: '回复模式',
|
||||
message_template: '消息模板',
|
||||
long_text_processing: '长文本处理',
|
||||
force_delay: '强制延迟',
|
||||
// action.py - CallPipelineNode
|
||||
pipeline_uuid: '流水线',
|
||||
inherit_context: '继承上下文',
|
||||
// action.py - StoreDataNode
|
||||
storage_type: '存储类型',
|
||||
ttl: '过期时间',
|
||||
key_prefix: '键前缀',
|
||||
// action.py - SetVariableNode
|
||||
variable_name: '变量名称',
|
||||
variable_scope: '变量作用域',
|
||||
set_variable_operation: '操作类型',
|
||||
// action.py - OpeningStatementNode
|
||||
statement: '开场白',
|
||||
suggested_questions: '建议问题',
|
||||
show_suggestions: '显示建议',
|
||||
// action.py - EndNode
|
||||
output_format: '输出格式',
|
||||
success_message: '成功消息',
|
||||
// integration.py - DatabaseQueryNode
|
||||
connection_type: '数据库类型',
|
||||
connection_string: '连接字符串',
|
||||
query: 'SQL查询',
|
||||
query_type: '查询类型',
|
||||
// integration.py - RedisOperationNode
|
||||
connection_url: '连接URL',
|
||||
operation: '操作类型',
|
||||
key_template: '键模板',
|
||||
hash_field: '哈希字段',
|
||||
// integration.py - MCPToolNode
|
||||
server_name: '服务器名称',
|
||||
tool_name: '工具名称',
|
||||
arguments_template: '参数模板',
|
||||
// integration.py - MemoryStoreNode
|
||||
scope: '作用域',
|
||||
// integration.py - DifyWorkflowNode
|
||||
'base-url': '基础URL',
|
||||
'api-key': 'API密钥',
|
||||
'app-type': '应用类型',
|
||||
// integration.py - DifyKnowledgeQueryNode
|
||||
dataset_id: '知识库ID',
|
||||
// integration.py - N8nWorkflowNode
|
||||
'webhook-url': 'Webhook URL',
|
||||
// integration.py - LangflowFlowNode
|
||||
'flow-id': '流程ID',
|
||||
// integration.py - CozeBotNode
|
||||
'bot-id': '机器人ID',
|
||||
'api-base': 'API基础URL',
|
||||
// process-configs.ts - TextTemplateNode
|
||||
escape_html: '转义HTML',
|
||||
trim_whitespace: '去除空白',
|
||||
// process-configs.ts - JsonTransformNode
|
||||
json_transform_type: 'JSON转换类型',
|
||||
json_expression: 'JSON表达式',
|
||||
mapping: '字段映射',
|
||||
// process-configs.ts - CodeExecutorNode
|
||||
code_language: '编程语言',
|
||||
code_content: '代码内容',
|
||||
// process-configs.ts - DataAggregatorNode
|
||||
aggregation_type: '聚合类型',
|
||||
separator: '分隔符',
|
||||
field_path: '字段路径',
|
||||
// process-configs.ts - TextSplitterNode
|
||||
split_type: '分割类型',
|
||||
chunk_size: '块大小',
|
||||
chunk_overlap: '块重叠',
|
||||
regex_pattern: '正则表达式',
|
||||
remove_empty: '移除空块',
|
||||
// process-configs.ts - VariableAssignmentNode
|
||||
assign_variable_name: '变量名',
|
||||
value_type: '值类型',
|
||||
static_value: '静态值',
|
||||
// integration-configs.ts - N8nWorkflowNode
|
||||
n8n_webhook_url: 'Webhook URL',
|
||||
n8n_auth_type: '认证方式',
|
||||
// integration-configs.ts - LangflowFlowNode
|
||||
langflow_flow_id: '流程ID',
|
||||
// integration-configs.ts - CozeBotNode
|
||||
coze_bot_id: '机器人ID',
|
||||
coze_api_base: 'API基础URL',
|
||||
},
|
||||
},
|
||||
@@ -1,265 +0,0 @@
|
||||
# Workflows翻译工作流程指南
|
||||
|
||||
## 📋 概述
|
||||
|
||||
本指南说明如何使用提供的工具完成workflows部分的多语言翻译工作。
|
||||
|
||||
## 🎯 翻译目标
|
||||
|
||||
- **总键数**: 627个workflows相关的键
|
||||
- **目标语言**: 6种语言(日语、繁体中文、西班牙语、俄语、泰语、越南语)
|
||||
- **总翻译项**: 3762个(627键 × 6语言)
|
||||
|
||||
## 🛠️ 工具说明
|
||||
|
||||
### 1. `workflows_translations.json` - 翻译模板文件
|
||||
|
||||
这是核心翻译文件,包含所有需要翻译的键和值。
|
||||
|
||||
**文件结构**:
|
||||
```json
|
||||
{
|
||||
"_comment": "Workflows翻译模板",
|
||||
"_instructions": [...],
|
||||
"_progress": {
|
||||
"total_keys": 627,
|
||||
"translated_keys": 0,
|
||||
"remaining_keys": 627,
|
||||
"languages": ["ja-JP", "zh-Hant", "es-ES", "ru-RU", "th-TH", "vi-VN"]
|
||||
},
|
||||
"translations": {
|
||||
"title": {
|
||||
"zh-Hans": "工作流对话",
|
||||
"ja-JP": "TODO",
|
||||
"zh-Hant": "TODO",
|
||||
"es-ES": "TODO",
|
||||
"ru-RU": "TODO",
|
||||
"th-TH": "TODO",
|
||||
"vi-VN": "TODO"
|
||||
},
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. `apply_workflows_translations.py` - 应用翻译脚本
|
||||
|
||||
将完成的翻译应用到实际的语言文件中。
|
||||
|
||||
**功能**:
|
||||
- 读取 `workflows_translations.json`
|
||||
- 识别已完成的翻译(非"TODO")
|
||||
- 应用到对应的语言文件(ja-JP.ts, zh-Hant.ts等)
|
||||
- 生成应用报告
|
||||
- 支持增量应用(可以分批翻译)
|
||||
|
||||
**使用方法**:
|
||||
```bash
|
||||
cd LangBot_copy/web
|
||||
python3 apply_workflows_translations.py
|
||||
```
|
||||
|
||||
### 3. `check_translation_progress.py` - 进度检查脚本
|
||||
|
||||
查看当前翻译进度和统计信息。
|
||||
|
||||
**功能**:
|
||||
- 显示每种语言的翻译进度
|
||||
- 显示进度条和百分比
|
||||
- 列出已完成和待完成的键
|
||||
- 建议下一批要翻译的键
|
||||
- 估算剩余工作量
|
||||
|
||||
**使用方法**:
|
||||
```bash
|
||||
cd LangBot_copy/web
|
||||
python3 check_translation_progress.py
|
||||
```
|
||||
|
||||
## 📝 翻译工作流程
|
||||
|
||||
### 步骤1: 检查当前进度
|
||||
|
||||
```bash
|
||||
python3 check_translation_progress.py
|
||||
```
|
||||
|
||||
这会显示:
|
||||
- 每种语言的完成度
|
||||
- 剩余待翻译的键数量
|
||||
- 建议下一批翻译的键
|
||||
|
||||
### 步骤2: 编辑翻译文件
|
||||
|
||||
打开 `workflows_translations.json` 文件,找到要翻译的键,将 `"TODO"` 替换为实际翻译。
|
||||
|
||||
**示例**:
|
||||
|
||||
翻译前:
|
||||
```json
|
||||
"title": {
|
||||
"zh-Hans": "工作流对话",
|
||||
"ja-JP": "TODO",
|
||||
"zh-Hant": "TODO",
|
||||
"es-ES": "TODO",
|
||||
"ru-RU": "TODO",
|
||||
"th-TH": "TODO",
|
||||
"vi-VN": "TODO"
|
||||
}
|
||||
```
|
||||
|
||||
翻译后:
|
||||
```json
|
||||
"title": {
|
||||
"zh-Hans": "工作流对话",
|
||||
"ja-JP": "ワークフロー会話",
|
||||
"zh-Hant": "工作流對話",
|
||||
"es-ES": "Conversación de Flujo de Trabajo",
|
||||
"ru-RU": "Диалог Рабочего Процесса",
|
||||
"th-TH": "การสนทนาเวิร์กโฟลว์",
|
||||
"vi-VN": "Hội thoại Quy trình"
|
||||
}
|
||||
```
|
||||
|
||||
**翻译技巧**:
|
||||
- 参考 `zh-Hans` 的中文原文理解含义
|
||||
- 保持专业术语的一致性
|
||||
- 注意特殊字符需要转义(如单引号 `'` 要写成 `\'`)
|
||||
- 可以使用翻译工具辅助,但需要人工审核确保准确性
|
||||
|
||||
### 步骤3: 应用翻译
|
||||
|
||||
完成一批翻译后,运行应用脚本:
|
||||
|
||||
```bash
|
||||
python3 apply_workflows_translations.py
|
||||
```
|
||||
|
||||
脚本会:
|
||||
- 自动识别已完成的翻译
|
||||
- 应用到对应的语言文件
|
||||
- 显示应用结果和统计信息
|
||||
- 更新进度信息
|
||||
|
||||
### 步骤4: 重复步骤1-3
|
||||
|
||||
继续翻译下一批键,直到所有翻译完成。
|
||||
|
||||
## 💡 建议的翻译策略
|
||||
|
||||
### 方案A: 按主题分批(推荐)
|
||||
|
||||
将相关的键分组翻译,例如:
|
||||
1. **第1批**: 基础UI文本(title, description, placeholder等)
|
||||
2. **第2批**: 节点相关(nodes, nodeTypes, nodeCategories等)
|
||||
3. **第3批**: 调试相关(debug, debugDialog, executionHistory等)
|
||||
4. **第4批**: 配置相关(nodeConfigFields, validation等)
|
||||
5. **第5批**: 其他剩余键
|
||||
|
||||
**优点**: 上下文相关,翻译更一致
|
||||
|
||||
### 方案B: 按数量分批
|
||||
|
||||
每批翻译固定数量的键(如50或100个)。
|
||||
|
||||
**优点**: 进度可控,容易估算时间
|
||||
|
||||
### 方案C: 按语言分批
|
||||
|
||||
先完成一种语言的所有翻译,再翻译下一种语言。
|
||||
|
||||
**优点**: 可以利用语言专长,集中精力
|
||||
|
||||
## 📊 进度跟踪
|
||||
|
||||
使用 `check_translation_progress.py` 随时查看进度:
|
||||
|
||||
```bash
|
||||
python3 check_translation_progress.py
|
||||
```
|
||||
|
||||
输出示例:
|
||||
```
|
||||
================================================================================
|
||||
📊 Workflows翻译进度报告
|
||||
================================================================================
|
||||
|
||||
【日语 (ja-JP)】
|
||||
[████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 20.0%
|
||||
✅ 已完成: 125/627
|
||||
⏳ 待翻译: 502
|
||||
📝 最近完成: title, description, placeholder, ...
|
||||
|
||||
【繁体中文 (zh-Hant)】
|
||||
[████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 20.0%
|
||||
✅ 已完成: 125/627
|
||||
⏳ 待翻译: 502
|
||||
|
||||
...
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
📈 总体进度: 750/3762 (19.9%)
|
||||
📊 平均每种语言: 125/627
|
||||
|
||||
💡 剩余工作量: 3012 个翻译项
|
||||
建议分批策略:
|
||||
- 每批50个键: 需要 61 批
|
||||
- 每批100个键: 需要 31 批
|
||||
================================================================================
|
||||
```
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
1. **备份**: 在开始翻译前,建议备份原始文件
|
||||
2. **编码**: 确保使用UTF-8编码保存文件
|
||||
3. **格式**: 保持JSON格式正确,注意逗号和引号
|
||||
4. **特殊字符**: 单引号需要转义为 `\'`
|
||||
5. **验证**: 每次应用翻译后,检查语言文件是否有语法错误
|
||||
6. **增量工作**: 可以分多次完成,每次翻译一部分然后应用
|
||||
|
||||
## 🔍 故障排除
|
||||
|
||||
### 问题1: 应用翻译时提示"没有发现任何已完成的翻译"
|
||||
|
||||
**原因**: 所有值都还是 "TODO"
|
||||
|
||||
**解决**: 编辑 `workflows_translations.json`,将至少一个键的 "TODO" 替换为实际翻译
|
||||
|
||||
### 问题2: 应用翻译后语言文件报错
|
||||
|
||||
**原因**: 翻译中包含未转义的特殊字符
|
||||
|
||||
**解决**: 检查翻译文本,将单引号 `'` 替换为 `\'`
|
||||
|
||||
### 问题3: 某些键应用失败
|
||||
|
||||
**原因**: 键名在语言文件中不存在或格式不匹配
|
||||
|
||||
**解决**: 检查应用报告中的失败键列表,手动在语言文件中添加或修正
|
||||
|
||||
## 📈 预估工作量
|
||||
|
||||
- **总翻译项**: 3762个
|
||||
- **每小时翻译速度**: 约50-100项(取决于熟练度)
|
||||
- **预估总时间**: 38-75小时
|
||||
- **建议分批**: 每天翻译100-200项,约需19-38天完成
|
||||
|
||||
## ✅ 完成标准
|
||||
|
||||
当 `check_translation_progress.py` 显示:
|
||||
- 所有语言的进度都达到 100%
|
||||
- 没有剩余待翻译的键
|
||||
- 所有语言文件都能正常编译
|
||||
|
||||
则翻译工作完成!
|
||||
|
||||
## 🎉 完成后
|
||||
|
||||
1. 运行最后一次 `apply_workflows_translations.py` 确保所有翻译已应用
|
||||
2. 测试各语言界面,确认翻译正确显示
|
||||
3. 提交代码变更
|
||||
4. 生成最终翻译报告
|
||||
|
||||
---
|
||||
|
||||
**祝翻译工作顺利!** 🚀
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user