背景描述
最近在参与OCA模块的中文翻译,在线操作Weblate逐条不够丝滑,遂下载po文件使用poedit进行翻译;
但是用poedit操作几次之后发现几乎都是重复劳动,本着程序员一个活重复干三遍以上就自动化的原则,驱动通义千问去编写脚本调用AI的接口进行自动化的翻译。
LLM API Provider
用的月之暗面的免费接口,可以去申请一下
https://platform.moonshot.cn/console/pay-detail
上代码
import argparse
import os
import json
import time
from openai import OpenAI
from polib import pofile
CHAT_API_URL = '*****'
CHAT_API_KEY = '*****'
CHAT_MODEL = 'moonshot-v1-8k'
def _read_po(filename):
def _po_to_json_batches(po_filepath, batch_size=30):
"""
从PO文件读取翻译项,并按批次转换为JSON字符串。
:param po_filepath: PO文件路径
:param batch_size: 每个批次包含的条目数
:return: 一个生成器,每次迭代返回一个批次的JSON字符串
"""
try:
po = pofile(po_filepath)
except Exception as ex:
raise ValueError(f'解析po文件{po_filepath}失败,错误如下:\n{ex}')
entries = list(po)
total_entries = len(entries)
batchs = []
for i in range(0, total_entries, batch_size):
batch_data = {}
for j in range(i, min(i + batch_size, total_entries)):
entry = entries[j]
if not entry.translated():
batch_data[str(j)] = {
'en_US': entry.msgid,
'zh_ZN': ''
}
if len(batch_data) > 0:
batchs.append(json.dumps(batch_data, ensure_ascii=False))
return batchs
msg_batchs = _po_to_json_batches(filename)
for i in range(len(msg_batchs)):
msg_batch = msg_batchs[i]
print(f'正在处理翻译:{i+1} / {len(msg_batchs)}')
_translate_with_ai(filename, msg_batch)
time.sleep(5)
def _translate_with_ai(filename, msgs):
client = OpenAI(api_key=CHAT_API_KEY, base_url=CHAT_API_URL)
response = client.chat.completions.create(
model="moonshot-v1-8k",
messages=[
{
"role": "system",
"content": '''你是一个翻译专家,擅长信息化系统的中英文翻译;
在后续的对话中请帮助我处理一些翻译工作,要求如下:
将输入的JSON格式中的en_US的词条进行翻译后回填到zh_CN字段中
按原格式同时返回源词条,注意标点符号的一致性''',
},
{"role": "user", "content": msgs},
],
temperature=0.3,
stream=False,
)
if len(response.choices) == 1:
res = response.choices[0].message.content
try:
res_msgs = json.loads(res)
# print(res_msgs)
except Exception as ex:
print('解析返回JSON失败:', ex, '\n', res)
_save_translations(filename, res_msgs)
else:
raise ValueError('未知错误')
def _save_translations(filename, msgs):
po = pofile(filename)
for i in list(msgs.keys()):
entry = po[int(i)]
entry.msgstr = msgs[str(i)]['zh_CN']
po.save()
print('翻译完成!~~')
def main():
parser = argparse.ArgumentParser(description='Translate the po file')
parser.add_argument("-f", "--file", help="po文件的路径", type=str, required=True)
# parser.add_argument("-f", "--file", help="po文件的路径", type=str, default='zh_CN.po')
args = parser.parse_args()
filename = args.file
print(f"po文件的路径: {args.file}")
if os.path.exists(filename):
_read_po(filename)
else:
raise FileNotFoundError(f'文件{filename}不存在!')
if __name__ == "__main__":
main()
半分钟翻完一个文件,效果相当哇噻