当前位置: 首页 > news >正文

使用 AI 对 QT应用程序进行翻译

前言

之前应朋友要求,帮其对 QGC 进行二次开发,其中一个要求是“汉化”。看了一下,虽然官方也有翻译,但还有很多没有翻译,如果要人工来做的话,纯属体力劳动。不如让 AI 帮着翻译。

经过一番调查和测试,找到了翻译 QT.ts 文件的方法和流程。总共不到两天时间就将95%以上的文字翻译成功。大大节省我的工作量。而且该方法可以适用于 任意 QT 程序的 任意语言翻译

之后虽然因为朋友有其他的解决方案,最后没有采用QGC。因此我也就不再需要对其保密,因此将相关信息共享并开源。

核心步骤

  • 使用 python 程序将 .ts 文件中对应 translation type="unfinished" (未翻译) 的文字全部提取出来,整理出 "原始文字":"TODO" 格式的原始 key-value 对;
  • key-value 对丢给 AI(如 deepseek), 让其翻译。由于这个时候只有需要翻译的文本,AI 能高效的完成。
  • 将翻译以后的文本 key-value 对, 放置到代码中定义的 dict 变量中,再用 python 代码处理, 将其写回 .ts 文件对应的地方, 并去除 translation type="unfinished" 部分(表示翻译成功)。
  • 以上步骤,循环多次以后,即可将需要的文字大部分翻译成功。有部分原始文字是多行的,处理起来比较麻烦,而且考虑到不多,可以手动处理。

核心代码

  • 通过正则处理 .ts 文件的内容,解析出 key-value
 def process_message(self, match):# nonlocal processed_count, translated_countself.processed_count += 1message_content = match.group(1)# extract source contentsource_match = re.search(r'<source>(.*?)</source>', message_content, re.DOTALL)if not source_match:return message_contentsource_text = source_match.group(1).strip()# logger.info(f"handle source_text={source_text}")if 'type="unfinished"' not in message_content:return message_content  # already translate# try translatetranslate_result = self.translate_text(source_text)if translate_result is None:# can not translate, just add the original text to missing setself.missings.add(source_text.strip())return message_contentself.translated_count += 1# Display only the first 50 characters to avoid overly long output.source_preview = source_text[:50] + '...' if len(source_text) > 50 else source_texttranslation_preview = translate_result[:50] + '...' if len(translate_result) > 50 else translate_resultlogger.info(f"[{self.translated_count}]: '{source_preview}' => '{translation_preview}'")# Replace the content of the translation and remove type="unfinished"return re.sub(r'<translation type="unfinished">.*?</translation>',f'<translation>{translate_result}</translation>',message_content,flags=re.DOTALL)
  • 翻译部分: 传入原始的英文key, 从翻译的词典中找是否有匹配项,找到就进行翻译
 def translate_text(self, english_text: str, keep_space: bool = False):if not self.dictionary:d = self.get_dict()self.dictionary = {}for k, v in d.items():self.dictionary[k.strip()] = v.strip()# Remove leading and trailing spaces for matchingstripped_text = english_text.strip()# Convert character entity references to plain characters for matchingcompare_text = self.decode_html_entities(stripped_text)if compare_text in self.dictionary:if  keep_space:leading_spaces = len(english_text) - len(english_text.lstrip())trailing_spaces = len(english_text) - len(english_text.rstrip())translation = self.dictionary[compare_text]return self.encode_html_entities(' ' * leading_spaces + translation + ' ' * trailing_spaces)return self.encode_html_entities(self.dictionary[compare_text])# return None to indicate untranslatablereturn None
  • 放置 AI 翻译后生成的 原文-翻译 对的变量。注意:不是单词,而是整个翻译句子对应的部分。
class DictZhCN(DictBase):def get_dict(self) -> dict[str, str]:""" Return translate items """return {"""Help""": """帮助""",}

翻译提示词

  • 需要告诉 AI 合适的提示词,不然他会乱改格式,尤其是 .ts 中的分隔符等.
  • 测试了几个AI进行翻译, 发现 deepseek 最慢,但相对来说准确率高一些。而豆包、元宝等虽然速度快了很多,但有明显的错误。
以下文本都是 "英文":"TODO", 的形式, 这些英文是无人机相关的英文, 将他们翻译成中文, 并替换成 "英文": """中文""", 的格式.
注意:
1.不要更改原始输入英文的格式,在输出的中文中也保留对应的格式字符,只要 txt 的纯文本格式, 不要转换成其他格式.输入示例:
"Forward": "TODO",
"Frame Class": "TODO",
"Currently set to frame class &apos;%1&apos;": "TODO",
"All Files (*)": "TODO",
"Receiving signal. Perform range test &amp; confirm.": "TODO",输出示例:
"Forward": """前进""",
"Frame Class": """机架类别""",
"Currently set to frame class &apos;%1&apos;": """当前设置为机架类别 &apos;%1&apos;""",
"All Files (*)": """所有文件 (*)""",
"Receiving signal. Perform range test &amp; confirm.": """正在接收信号。执行距离测试 &amp; 确认""",以下是对应要翻译部分的列表:

源码

  • 目前已经创建 PR#13411 , 尝试将其合并到 QGC 中。需要源码的自行获取。
http://www.dtcms.com/a/394060.html

相关文章:

  • Windows下游戏闪退?软件崩溃?游戏环境缺失?软件运行缺少依赖?这个免费工具一键帮您自动修复(DLL文件/DirectX/运行库等问题一键搞定)
  • 【从入门到精通Spring Cloud】统一服务入口Spring Cloud Gateway
  • setfacl 命令
  • Photoshop - Photoshop 分享作品和设计
  • 【Agent 设计模式与工程化】如何做出好一个可持续发展的agent需要考虑的架构
  • 【Camera开发】疑难杂症记录
  • 如何提高自己的Java并发编程能力?
  • Polkadot - ELVES Protocol详解
  • springBoot图片本地存储
  • 蝉镜-AI数字人视频创作平台
  • Linux入门(五)
  • MySqL-day4_03(索引)
  • Vue 深度选择器(:deep)完全指北:从“能用”到“用好”
  • [Nodejs+LangChain+Ollama] 1.第一个案例
  • 设计模式2.【备忘录模式】
  • Spring Boot 入门:快速构建现代 Java 应用的利器
  • Redis 实例 CPU 飙高到 90%,如何排查和解决?
  • 中国女篮备战全运会,宫鲁鸣重点培养年轻核心
  • 【Qt】常用控件1——QWidget
  • 9.21关于大模型推理未来的思考
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘uvicorn’ 问题
  • 变分自编码器(VAE):生成模型的另一条技术路线
  • 【LVS入门宝典】LVS NAT模式实战指南:ip_forward、iptables与SNAT、DNAT规则配置详解
  • 【Android】BottomSheet的三种使用
  • Spring MVC 九大组件源码深度剖析(八):RequestToViewNameTranslator - 视图名转换的奥秘
  • 在Linux环境下安装和卸载DMETL5数据迁移工具
  • 《计算》第五六章读书笔记
  • daily notes[47]
  • 模电基础:放大电路的分析方法---图解法
  • Windows10系统Web UI自动化测试学习系列1--介绍(序章-万事开头难)