#!/usr/bin/env python3 import sys import re # see man 3 printf reIndex = r"([1-9][0-9]*\$)?" reFlags = r"([-#0+I']|' ')*" reWidth = rf"([1-9][0-9]*|\*{reIndex})?" rePrecision = rf"(\.{reWidth})?" reLenghtMod = r"(hh|h|l|ll|q|L|j|z|Z|t)?" reConversion = r"[diouxXeEfFgGaAcspnm%]" reCFormat = "".join([ r"%", rf"(?P{reIndex})", rf"(?P{reFlags})", rf"(?P{reWidth})", rf"(?P{rePrecision})", rf"(?P{reLenghtMod})", rf"(?P{reConversion})"]) def translateFormat(fmt, idx, m): groups = m.groupdict() if groups["index"] or groups["conversion"] == "%": print(f"Ignoring c-format '{fmt}'") return idx, fmt for field in "width", "precision": if "*" in groups[field]: groups[field] = f"{groups[field]}{idx}$" idx += 1 newFmt = f"%{idx}${''.join(groups.values())}" idx += 1 return idx, newFmt def process(ids, strs, fuzzy): regex = rf"(.*?)({reCFormat})(.*)" fmts = [] idx = 1 newIds = [] for s in ids: new = [] m = re.search(regex, s) while m is not None: new.append(m.group(1)) oldFmt = m.group(2) idx, newFmt = translateFormat(oldFmt, idx, m) fmts.append((oldFmt, newFmt)) new.append(newFmt) s = m.group(m.lastindex) m = re.search(regex, s) new.append(s) newIds.append("".join(new)) if fuzzy: return newIds, strs n = 0 newStrs = [] for s in strs: new = [] m = re.search(regex, s) while m is not None: new.append(m.group(1)) if n < len(fmts) and fmts[n][0] == m.group(2): new.append(fmts[n][1]) n += 1 else: print("Ignoring translation", strs) print(" for id", newIds) return newIds, strs s = m.group(m.lastindex) m = re.search(regex, s) new.append(s) newStrs.append("".join(new)) return newIds, newStrs def writeMsg(po, header, strs): if len(strs) == 0: return po.write(header) po.write(" ") for s in strs: po.write('"') po.write(s) po.write('"\n') if len(sys.argv) != 2: print(f"usage: {sys.argv[0]} PO-FILE", file=sys.stderr) sys.exit(1) pofile = sys.argv[1] with open(pofile, "r") as po: polines = po.readlines() with open(pofile, "w") as po: current = None cfmt = False fuzzy = False ids = [] strs = [] for line in polines: m = re.search(r'^(([a-z]+) )?"(.*)"', line) if m is None: if cfmt: ids, strs = process(ids, strs, fuzzy) writeMsg(po, "msgid", ids) writeMsg(po, "msgstr", strs) po.write(line) cfmt = line.startswith("#,") and " c-format" in line fuzzy = line.startswith("#,") and " fuzzy" in line current = None ids = [] strs = [] continue if m.group(2): current = m.group(2) if current == "msgid": ids.append(m.group(3)) elif current == "msgstr": strs.append(m.group(3)) if cfmt: ids, strs = process(ids, strs, fuzzy) writeMsg(po, "msgid", ids) writeMsg(po, "msgstr", strs)