#!/usr/bin/env python3 import ast import struct import sys from pathlib import Path def read_po(path): messages = {} current = None buffers = {"msgid": [], "msgstr": []} def flush(): if buffers["msgid"] or buffers["msgstr"]: messages["".join(buffers["msgid"])] = "".join(buffers["msgstr"]) buffers["msgid"] = [] buffers["msgstr"] = [] for raw_line in path.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#"): continue if line.startswith("msgid "): flush() current = "msgid" buffers[current].append(ast.literal_eval(line[6:].strip())) continue if line.startswith("msgstr "): current = "msgstr" buffers[current].append(ast.literal_eval(line[7:].strip())) continue if line.startswith('"') and current: buffers[current].append(ast.literal_eval(line)) flush() return messages def write_mo(messages, path): keys = sorted(messages) ids = b"\x00".join(key.encode("utf-8") for key in keys) + b"\x00" strs = b"\x00".join(messages[key].encode("utf-8") for key in keys) + b"\x00" keystart = 7 * 4 + len(keys) * 16 valuestart = keystart + len(ids) koffsets = [] voffsets = [] offset = keystart for key in keys: encoded = key.encode("utf-8") koffsets.append((len(encoded), offset)) offset += len(encoded) + 1 offset = valuestart for key in keys: encoded = messages[key].encode("utf-8") voffsets.append((len(encoded), offset)) offset += len(encoded) + 1 output = [ struct.pack("Iiiiiii", 0x950412DE, 0, len(keys), 7 * 4, 7 * 4 + len(keys) * 8, 0, 0) ] output.extend(struct.pack("ii", length, offset) for length, offset in koffsets) output.extend(struct.pack("ii", length, offset) for length, offset in voffsets) output.append(ids) output.append(strs) path.write_bytes(b"".join(output)) def main(): root = Path(sys.argv[1] if len(sys.argv) > 1 else "locale") for po in root.glob("*/LC_MESSAGES/*.po"): mo = po.with_suffix(".mo") write_mo(read_po(po), mo) print(mo) if __name__ == "__main__": main()