前言
之前应朋友要求,帮其对 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 '%1'": "TODO",
"All Files (*)": "TODO",
"Receiving signal. Perform range test & confirm.": "TODO",
输出示例:
"Forward": """前进""",
"Frame Class": """机架类别""",
"Currently set to frame class '%1'": """当前设置为机架类别 '%1'""",
"All Files (*)": """所有文件 (*)""",
"Receiving signal. Perform range test & confirm.": """正在接收信号。执行距离测试 & 确认""",
以下是对应要翻译部分的列表:
源码
- 目前已经创建 PR#13411 , 尝试将其合并到 QGC 中。需要源码的自行获取。
986

被折叠的 条评论
为什么被折叠?



