import os from django.conf import settings from django.core.management.base import BaseCommand class Command(BaseCommand): help = ( "Traverse all .po files under BASE_DIR (or a given base-dir), " "remove 'fuzzy' flags, drop '#| msgid' comments, and reset msgstr to empty." ) def add_arguments(self, parser): parser.add_argument( "-b", "--base-dir", default=settings.BASE_DIR, help="Root directory to start searching for .po files (default: settings.BASE_DIR).", ) def handle(self, *args, **options): base_dir = options["base_dir"] for root, _dirs, files in os.walk(base_dir): for fname in files: if not fname.endswith(".po"): continue path = os.path.join(root, fname) self.stdout.write(f"→ Processing {path}") self._clean_po_file(path) def _clean_po_file(self, filepath): with open(filepath, encoding="utf-8") as f: lines = f.readlines() entries, curr = [], [] for line in lines: if line.strip() == "": if curr: entries.append(curr) curr = [] else: curr.append(line) if curr: entries.append(curr) new_lines = [] changed = False for ent in entries: if ent and ent[0].startswith('msgid ""'): new_lines.extend(ent) new_lines.append("\n") continue if any( line.startswith("#~") or (line.startswith("#,") and line.lstrip("#, ").startswith("msgid ")) for line in ent ): changed = True continue fuzzy_idx = next( ( i for i, line in enumerate(ent) if line.startswith("#,") and "fuzzy" in line ), None, ) if fuzzy_idx is not None: flags = [ f.strip() for f in ent[fuzzy_idx][2:].split(",") if f.strip() != "fuzzy" ] if flags: ent[fuzzy_idx] = "#, " + ", ".join(flags) + "\n" else: del ent[fuzzy_idx] ent = [line for line in ent if not line.startswith("#| msgid")] ent = [ 'msgstr ""\n' if line.startswith("msgstr") else line for line in ent ] changed = True new_lines.extend(ent) new_lines.append("\n") if changed: with open(filepath, "w", encoding="utf-8") as f: f.writelines(new_lines) self.stdout.write(self.style.SUCCESS(f" → Updated {filepath}")) else: self.stdout.write(" (no changes)")