3

我需要合并/更新/删除 .po 文件消息并需要一些 Python 包,它允许我完全解析 .po 文件,包括:消息、复数、位置、上下文和注释。

我想做一个简单的工具来检查文件之间的差异。我也可以使用一些已经完成的 GUI,但不确定是否有这样的工具会添加新的翻译或删除未使用的翻译。

我正在搜索一些文章,但没有找到如何去做。请推荐一些完全解析 .po 的 Python 包(可能是其他语言)或工具来完成如此重要的任务以保持良好的翻译。

4

3 回答 3

5

polib非常好。它解析文件并提供几种访问数据的方法,包括一个迭代器来循环遍历 msgid、msgstr 对以执行您需要的任何操作。这是快速入门文档

如果 .po 不可用,它还可以解析 .mo,特别处理过时的消息字符串,仅迭代已翻译的字符串,以及其他不错的功能。

于 2013-08-15T15:59:33.617 回答
2

您不需要花哨的工具来读取.po文件;它们是纯文本文件,基本上包含消息/翻译对:

#: buttons.c:425
msgid "Extra"
msgstr "Thêm"

#: buttons.c:433
msgid "Help"
msgstr "Trợ giúp"

对于比较它们的简单工具,我建议使用diff -u.

有一个带有.mo扩展名的二进制格式。您可以使用msgunfmtgettext-tools 包中的程序将它们转换回纯文本。

从文件中提取 id/translation 对.po并不困难:

In [1]: po = '''#: buttons.c:425
   ...: msgid "Extra"
   ...: msgstr "Thêm"
   ...: 
   ...: #: buttons.c:433
   ...: msgid "Help"
   ...: msgstr "Trợ giúp"
   ...: 
   ...: '''

In [2]: import re

In [3]: re.findall('^msgid \"(.*)\"', po, re.MULTILINE)
Out[3]: ['Extra', 'Help']

In [4]: re.findall('^msgstr \"(.*)\"', po, re.MULTILINE)
Out[4]: ['Th\xc3\xaam', 'Tr\xe1\xbb\xa3 gi\xc3\xbap']

In [5]: zip(re.findall('^msgid \"(.*)\"[^\"]*', po, re.MULTILINE), re.findall('^msgstr \"(.*)\"[^\"]*', po, re.MULTILINE))
Out[5]: [('Extra', 'Th\xc3\xaam'), ('Help', 'Tr\xe1\xbb\xa3 gi\xc3\xbap')]

我正在使用^andre.MULTILINE来防止注释掉的消息出现在这里。作为健全性检查,确保包含消息 ID 和消息字符串的列表长度相等。

编辑:你有一个关于随机排序和使用的有效观点diff。但是您可以使用上面的代码为旧文件和新.po文件创建 (message-id, translation) 元组列表。如果您按消息 ID 对这些列表进行排序,您可以使用它difflib.unified_diff来打印差异。

例如:

In [1]: import re, itertools, difflib

#I've used cpaste to input two pieces of a .po file, the latter with some changes

In [4]: orig_po
Out[4]: '#: mixedgauge.c:64\nmsgid "Passed"\nmsgstr "\xc4\x90\xe1\xbb\x97"\n\n#: mixedgauge.c:67\nmsgid "Completed"\nmsgstr "Ho\xc3\xa0n to\xc3\xa0n"\n\n#: mixedgauge.c:70\nmsgid "Checked"\nmsgstr "\xc4\x90\xc3\xa3 ki\xe1\xbb\x83m tra"\n\n#: mixedgauge.c:73\nmsgid "Done"\nmsgstr "Ho\xc3\xa0n t\xe1\xba\xa5t"\n\n#: mixedgauge.c:76\nmsgid "Skipped"\nmsgstr "B\xe1\xbb\x8b b\xe1\xbb\x8f qua"\n\n#: mixedgauge.c:79\nmsgid "In Progress"\nmsgstr "\xc4\x90ang ch\xe1\xba\xa1y"\n\n#: mixedgauge.c:85\nmsgid "N/A"\nmsgstr "Kh\xc3\xb4ng c\xc3\xb3"\n\n#: mixedgauge.c:193\nmsgid "Overall Progress"\nmsgstr "To\xc3\xa0n ti\xe1\xba\xbfn h\xc3\xa0nh"\n'

In [5]: changed_po
Out[5]: '#: mixedgauge.c:64\nmsgid "Passed"\nmsgstr "\xc4\x90\xe1\xbb\x97"\n\n#: mixedgauge.c:193\nmsgid "Overall Progres"\nmsgstr "To\xc3\xa0n ti\xe1\xba\xbfn h\xc3\xa0nh"\n\n#: mixedgauge.c:67\nmsgid "Completed"\nmsgstr "Ho\xc3\xa0na to\xc3\xa0n"\n\n#: mixedgauge.c:76\nmsgid "Skipped"\nmsgstr "B\xe1\xbb\x8b b\xe1\xbb\x8f qua"\n\n#: mixedgauge.c:79\nmsgid "In Progress"\nmsgstr "\xc4\x90ang ch\xe1\xba\xa1y"\n\n#: mixedgauge.c:85\nmsgid "N/A"\nmsgstr "Kh\xc3\xb4ng c\xc3\xb3e"\n\n#: mixedgauge.c:70\nmsgid "Checked"\nmsgstr "\xc4\x90\xc3\xa3 ki\xe1\xbb\x83m tra"\n\n#: mixedgauge.c:73\nmsgid "Done"\nmsgstr "Ho\xc3\xa0n t\xe1\xba\xa5t"\n'

# Making a list of tuples

In [6]: orig_list = zip(re.findall('^(msgid \".*\")', orig_po, re.MULTILINE), re.findall('^(msgstr \".*\")', orig_po, re.MULTILINE))

In [7]: changed_list = zip(re.findall('^(msgid \".*\")', changed_po, re.MULTILINE), re.findall('^(msgstr \".*\")', changed_po, re.MULTILINE))

# Sort them by the message-id

In [8]: orig_list.sort(key=lambda t: t[0])

In [9]: changed_list.sort(key=lambda t: t[0])

# Now flatten the list

In [10]: orig_string_list = [i for i in itertools.chain(*orig_list)]

In [11]: changed_string_list = [i for i in itertools.chain(*changed_list)]

In [12]: orig_list[0:3]
Out[12]: [('msgid "Checked"', 'msgstr "\xc4\x90\xc3\xa3 ki\xe1\xbb\x83m tra"'), ('msgid "Completed"', 'msgstr "Ho\xc3\xa0n to\xc3\xa0n"'), ('msgid "Done"', 'msgstr "Ho\xc3\xa0n t\xe1\xba\xa5t"')]

In [13]: orig_string_list[0:6]
Out[13]: ['msgid "Checked"', 'msgstr "\xc4\x90\xc3\xa3 ki\xe1\xbb\x83m tra"', 'msgid "Completed"', 'msgstr "Ho\xc3\xa0n to\xc3\xa0n"', 'msgid "Done"', 'msgstr "Ho\xc3\xa0n t\xe1\xba\xa5t"']

# print the diff

In [14]: for l in difflib.unified_diff(orig_string_list, changed_string_list, fromfile='original', tofile='changed'):
   ....:     print l
   ....:     
--- original

+++ changed

@@ -1,14 +1,14 @@

 msgid "Checked"
 msgstr "Đã kiểm tra"
 msgid "Completed"
-msgstr "Hoàn toàn"
+msgstr "Hoàna toàn"
 msgid "Done"
 msgstr "Hoàn tất"
 msgid "In Progress"
 msgstr "Đang chạy"
 msgid "N/A"
-msgstr "Không có"
-msgid "Overall Progress"
+msgstr "Không cóe"
+msgid "Overall Progres"
 msgstr "Toàn tiến hành"
 msgid "Passed"
 msgstr "Đỗ"
于 2013-03-24T17:02:46.680 回答
2

试试babel模块。它包括一个.po解析器babel.messages.catalogbabel.messages.pofile其他东西。

于 2013-03-25T18:45:26.547 回答