使用 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_count
        self.processed_count += 1

        message_content = match.group(1)

        # extract source content
        source_match = re.search(r'<source>(.*?)</source>', message_content, re.DOTALL)
        if not source_match:
            return message_content

        source_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 translate
        translate_result = self.translate_text(source_text)
        if translate_result is None:
            # can not translate, just add the original text to missing set
            self.missings.add(source_text.strip())
            return message_content

        self.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_text
        translation_preview = translate_result[:50] + '...' if len(translate_result) > 50 else translate_result
        logger.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 matching
        stripped_text = english_text.strip()

        # Convert character entity references to plain characters for matching
        compare_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 untranslatable
        return 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 中。需要源码的自行获取。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值