1+ #!/usr/bin/env python3
2+ """
3+ scripts/generate_status_table.py
4+
5+ Regenerate the per-file translation status table between marker comments in
6+ a markdown file (default: RESOURCE.md) from the current state of all .po
7+ files. Meant to run on a schedule so the table never goes stale, replacing
8+ the old Transifex-exported report.
9+
10+ Requires: pip install polib
11+
12+ Usage:
13+ python3 scripts/generate_status_table.py
14+ python3 scripts/generate_status_table.py --file RESOURCE.md
15+ """
16+ import argparse
17+ import re
18+ import sys
19+ from datetime import date
20+ from pathlib import Path
21+
22+ import polib
23+
24+ REPO_ROOT = Path (__file__ ).resolve ().parent .parent
25+ START_MARKER = "<!-- TRANSLATION_STATUS_START -->"
26+ END_MARKER = "<!-- TRANSLATION_STATUS_END -->"
27+
28+
29+ def file_stats (path : Path ):
30+ po = polib .pofile (str (path ))
31+ return len (po .translated_entries ()), len (po .fuzzy_entries ()), len (po .untranslated_entries ())
32+
33+
34+ def build_table () -> str :
35+ files = sorted (REPO_ROOT .rglob ("*.po" ))
36+ rows = []
37+ for f in files :
38+ if ".cpython-src" in f .parts or ".git" in f .parts :
39+ continue
40+ t , fz , u = file_stats (f )
41+ total = t + fz + u
42+ translated_pct = (t / total * 100 ) if total else 100.0
43+ fuzzy_pct = (fz / total * 100 ) if total else 0.0
44+ rel = f .relative_to (REPO_ROOT )
45+ rows .append ((str (rel ), translated_pct , fuzzy_pct ))
46+
47+ # most-complete files first, matching the old report's ordering
48+ rows .sort (key = lambda r : (- r [1 ], r [0 ]))
49+
50+ lines = [
51+ "| File | Translated | Fuzzy |" ,
52+ "|:-----|:-----------:|:-----------:|" ,
53+ ]
54+ for name , t_pct , f_pct in rows :
55+ lines .append (f"| { name } | { t_pct :.1f} % | { f_pct :.1f} % |" )
56+ return "\n " .join (lines )
57+
58+
59+ def main ():
60+ parser = argparse .ArgumentParser (description = __doc__ )
61+ parser .add_argument ("--file" , default = "RESOURCE.md" ,
62+ help = "Markdown file containing the marker block to update" )
63+ args = parser .parse_args ()
64+
65+ target = REPO_ROOT / args .file
66+ text = target .read_text (encoding = "utf-8" )
67+
68+ if START_MARKER not in text or END_MARKER not in text :
69+ print (f"Markers { START_MARKER } / { END_MARKER } not found in { args .file } ." )
70+ print ("Add them around the table you want auto-generated, then re-run." )
71+ sys .exit (1 )
72+
73+ table = build_table ()
74+ block = (
75+ f"{ START_MARKER } \n "
76+ f"### وضعیت ترجمه فایلها\n "
77+ f"(بهروزرسانی: { date .today ().isoformat ()} )\n \n "
78+ f"{ table } \n "
79+ f"{ END_MARKER } "
80+ )
81+
82+ new_text = re .sub (
83+ re .escape (START_MARKER ) + r".*?" + re .escape (END_MARKER ),
84+ lambda _ : block , # avoid backslash-escape surprises from re.sub
85+ text ,
86+ flags = re .DOTALL ,
87+ )
88+ target .write_text (new_text , encoding = "utf-8" )
89+ print (f"Updated { args .file } ." )
90+
91+
92+ if __name__ == "__main__" :
93+ main ()
0 commit comments