i18n/posplit
author Matt Harbison <matt_harbison@yahoo.com>
Fri, 04 Nov 2022 17:35:44 -0400
changeset 49572 c4f07a011714
parent 48875 6000f5b25c9b
child 51863 f4733654f144
permissions -rwxr-xr-x
util: implement `writelines()` on atomictempfile With typehints on the vfs objects, pytype will flag this: FAILED: /mnt/c/Users/Matt/hg/.pytype/pyi/mercurial/patch.pyi /usr/bin/python3.8 -m pytype.single --imports_info /mnt/c/Users/Matt/hg/.pytype/imports/mercurial.patch.imports --module-name mercurial.patch -V 3.7 -o /mnt/c/Users/Matt/hg/.pytype/pyi/mercurial/patch.pyi --analyze-annotated --nofail --quick /mnt/c/Users/Matt/hg/mercurial/patch.py File "/mnt/c/Users/Matt/hg/mercurial/patch.py", line 535, in writerej: No attribute 'writelines' on mercurial.util.atomictempfile [attribute-error] In Union[ mercurial.util.atomictempfile, mercurial.vfs.checkambigatclosing, mercurial.vfs.delayclosedfile, mercurial.windows.fdproxy, mercurial.windows.mixedfilemodewrapper ] It's not a real problem there (atomictempfile is only created by passing different args), but it's reasonable for this to implement the function and behave like a normal file. There are other functions missing that can be added if/when needed.

#!/usr/bin/env python3
#
# posplit - split messages in paragraphs on .po/.pot files
#
# license: MIT/X11/Expat
#


import polib
import re
import sys


def addentry(po, entry, cache):
    e = cache.get(entry.msgid)
    if e:
        e.occurrences.extend(entry.occurrences)

        # merge comments from entry
        for comment in entry.comment.split('\n'):
            if comment and comment not in e.comment:
                if not e.comment:
                    e.comment = comment
                else:
                    e.comment += '\n' + comment
    else:
        po.append(entry)
        cache[entry.msgid] = entry


def mkentry(orig, delta, msgid, msgstr):
    entry = polib.POEntry()
    entry.merge(orig)
    entry.msgid = msgid or orig.msgid
    entry.msgstr = msgstr or orig.msgstr
    entry.occurrences = [(p, int(l) + delta) for (p, l) in orig.occurrences]
    return entry


if __name__ == "__main__":
    po = polib.pofile(sys.argv[1])

    cache = {}
    entries = po[:]
    po[:] = []
    findd = re.compile(r' *\.\. (\w+)::')  # for finding directives
    for entry in entries:
        msgids = entry.msgid.split(u'\n\n')
        if entry.msgstr:
            msgstrs = entry.msgstr.split(u'\n\n')
        else:
            msgstrs = [u''] * len(msgids)

        if len(msgids) != len(msgstrs):
            # places the whole existing translation as a fuzzy
            # translation for each paragraph, to give the
            # translator a chance to recover part of the old
            # translation - erasing extra paragraphs is
            # probably better than retranslating all from start
            if 'fuzzy' not in entry.flags:
                entry.flags.append('fuzzy')
            msgstrs = [entry.msgstr] * len(msgids)

        delta = 0
        for msgid, msgstr in zip(msgids, msgstrs):
            if msgid and msgid != '::':
                newentry = mkentry(entry, delta, msgid, msgstr)
                mdirective = findd.match(msgid)
                if mdirective:
                    if not msgid[mdirective.end() :].rstrip():
                        # only directive, nothing to translate here
                        delta += 2
                        continue
                    directive = mdirective.group(1)
                    if directive in ('container', 'include'):
                        if msgid.rstrip('\n').count('\n') == 0:
                            # only rst syntax, nothing to translate
                            delta += 2
                            continue
                        else:
                            # lines following directly, unexpected
                            print(
                                'Warning: text follows line with directive'
                                ' %s' % directive
                            )
                    comment = 'do not translate: .. %s::' % directive
                    if not newentry.comment:
                        newentry.comment = comment
                    elif comment not in newentry.comment:
                        newentry.comment += '\n' + comment
                addentry(po, newentry, cache)
            delta += 2 + msgid.count('\n')
    po.save()