Fix code style: use tabs and reformat xgettext arguments

Align check_pot_freshness.py and pot_tools.py with project
indentation (tabs) and ruff format requirements.

Sorry :-)
This commit is contained in:
Softer 2026-05-04 23:41:33 +03:00
parent 1f4ebd9414
commit 5a95a122b8
2 changed files with 127 additions and 121 deletions

View File

@ -4,8 +4,8 @@
Used by CI. Fails if any translatable string is missing from the committed pot.
Usage:
xgettext ... -o /tmp/generated.pot
python3 check_pot_freshness.py /tmp/generated.pot locales/base.pot
xgettext ... -o /tmp/generated.pot
python3 check_pot_freshness.py /tmp/generated.pot locales/base.pot
"""
import re
@ -14,43 +14,43 @@ from pathlib import Path
def extract_msgids(path: str) -> set[str]:
content = Path(path).read_text()
ids: set[str] = set()
current: str | None = None
content = Path(path).read_text()
ids: set[str] = set()
current: str | None = None
for line in content.splitlines():
if line.startswith('msgid '):
m = re.search(r'"(.*)"', line)
current = m.group(1) if m else ''
elif current is not None and line.startswith('"'):
m = re.search(r'"(.*)"', line)
if m:
current += m.group(1)
else:
if current is not None and current:
ids.add(current)
current = None
for line in content.splitlines():
if line.startswith('msgid '):
m = re.search(r'"(.*)"', line)
current = m.group(1) if m else ''
elif current is not None and line.startswith('"'):
m = re.search(r'"(.*)"', line)
if m:
current += m.group(1)
else:
if current is not None and current:
ids.add(current)
current = None
if current:
ids.add(current)
if current:
ids.add(current)
return ids
return ids
def main() -> None:
generated = extract_msgids(sys.argv[1])
committed = extract_msgids(sys.argv[2])
generated = extract_msgids(sys.argv[1])
committed = extract_msgids(sys.argv[2])
missing = sorted(generated - committed)
missing = sorted(generated - committed)
if missing:
print('::error::New tr() strings not in base.pot - run locales_generator.sh:')
for s in missing:
print(f' {s}')
sys.exit(1)
if missing:
print('::error::New tr() strings not in base.pot - run locales_generator.sh:')
for s in missing:
print(f' {s}')
sys.exit(1)
print('All tr() strings are present in base.pot')
print('All tr() strings are present in base.pot')
if __name__ == '__main__':
main()
main()

View File

@ -2,9 +2,9 @@
"""Tools for managing base.pot: find and add missing translatable strings.
Usage (from repo root):
scripts/pot_tools.py stats
scripts/pot_tools.py list
scripts/pot_tools.py add_missing [--dry-run]
scripts/pot_tools.py stats
scripts/pot_tools.py list
scripts/pot_tools.py add_missing [--dry-run]
Requires: gettext (xgettext) installed.
"""
@ -22,124 +22,130 @@ BASE_POT = ARCHINSTALL_DIR / 'locales' / 'base.pot'
def extract_msgids(path: Path) -> set[str]:
content = path.read_text()
ids: set[str] = set()
current: str | None = None
content = path.read_text()
ids: set[str] = set()
current: str | None = None
for line in content.splitlines():
if line.startswith('msgid '):
m = re.search(r'"(.*)"', line)
current = m.group(1) if m else ''
elif current is not None and line.startswith('"'):
m = re.search(r'"(.*)"', line)
if m:
current += m.group(1)
else:
if current is not None and current:
ids.add(current)
current = None
for line in content.splitlines():
if line.startswith('msgid '):
m = re.search(r'"(.*)"', line)
current = m.group(1) if m else ''
elif current is not None and line.startswith('"'):
m = re.search(r'"(.*)"', line)
if m:
current += m.group(1)
else:
if current is not None and current:
ids.add(current)
current = None
if current:
ids.add(current)
if current:
ids.add(current)
return ids
return ids
def generate_fresh_pot() -> Path:
fd, tmp_path = tempfile.mkstemp(suffix='.pot')
os.close(fd)
tmp = Path(tmp_path)
py_files = sorted(str(p) for p in ARCHINSTALL_DIR.rglob('*.py'))
fd, tmp_path = tempfile.mkstemp(suffix='.pot')
os.close(fd)
tmp = Path(tmp_path)
py_files = sorted(str(p) for p in ARCHINSTALL_DIR.rglob('*.py'))
subprocess.run(
['xgettext', '--no-location', '--omit-header',
'--keyword=tr', '-d', 'base', '-o', str(tmp)] + py_files,
check=True,
capture_output=True,
)
return tmp
cmd = [
'xgettext',
'--no-location',
'--omit-header',
'--keyword=tr',
'-d',
'base',
'-o',
str(tmp),
] + py_files
subprocess.run(cmd, check=True, capture_output=True)
return tmp
def get_missing(fresh_pot: Path) -> set[str]:
generated = extract_msgids(fresh_pot)
committed = extract_msgids(BASE_POT)
return generated - committed
generated = extract_msgids(fresh_pot)
committed = extract_msgids(BASE_POT)
return generated - committed
def cmd_stats() -> None:
fresh_pot = generate_fresh_pot()
try:
generated = extract_msgids(fresh_pot)
committed = extract_msgids(BASE_POT)
missing = generated - committed
fresh_pot = generate_fresh_pot()
try:
generated = extract_msgids(fresh_pot)
committed = extract_msgids(BASE_POT)
missing = generated - committed
print(f'Code: {len(generated)} translatable strings')
print(f'base.pot: {len(committed)} msgids')
print(f' Missing: {len(missing)}')
finally:
fresh_pot.unlink(missing_ok=True)
print(f'Code: {len(generated)} translatable strings')
print(f'base.pot: {len(committed)} msgids')
print(f' Missing: {len(missing)}')
finally:
fresh_pot.unlink(missing_ok=True)
def cmd_list() -> None:
fresh_pot = generate_fresh_pot()
try:
missing = sorted(get_missing(fresh_pot))
fresh_pot = generate_fresh_pot()
try:
missing = sorted(get_missing(fresh_pot))
if missing:
print(f'=== MISSING ({len(missing)}): in code but not in base.pot ===')
for s in missing:
print(f' + {s}')
else:
print('No missing strings')
finally:
fresh_pot.unlink(missing_ok=True)
if missing:
print(f'=== MISSING ({len(missing)}): in code but not in base.pot ===')
for s in missing:
print(f' + {s}')
else:
print('No missing strings')
finally:
fresh_pot.unlink(missing_ok=True)
def cmd_add_missing(dry_run: bool = False) -> None:
fresh_pot = generate_fresh_pot()
try:
missing = sorted(get_missing(fresh_pot))
fresh_pot = generate_fresh_pot()
try:
missing = sorted(get_missing(fresh_pot))
if not missing:
print('No missing strings, base.pot is up to date')
return
if not missing:
print('No missing strings, base.pot is up to date')
return
print(f'Adding {len(missing)} missing string(s)')
for s in missing:
print(f' + {s}')
print(f'Adding {len(missing)} missing string(s)')
for s in missing:
print(f' + {s}')
if dry_run:
print('(dry-run, no changes written)')
return
if dry_run:
print('(dry-run, no changes written)')
return
with open(BASE_POT, 'a') as f:
for s in missing:
if '{' in s:
f.write('\n#, python-brace-format')
f.write(f'\nmsgid "{s}"\nmsgstr ""\n')
with open(BASE_POT, 'a') as f:
for s in missing:
if '{' in s:
f.write('\n#, python-brace-format')
f.write(f'\nmsgid "{s}"\nmsgstr ""\n')
print(f'Done. Added to {BASE_POT}')
finally:
fresh_pot.unlink(missing_ok=True)
print(f'Done. Added to {BASE_POT}')
finally:
fresh_pot.unlink(missing_ok=True)
def main() -> None:
if len(sys.argv) < 2 or sys.argv[1] in ('-h', '--help'):
print('Usage: pot_tools.py {stats|list|add_missing} [--dry-run]')
sys.exit(0)
if len(sys.argv) < 2 or sys.argv[1] in ('-h', '--help'):
print('Usage: pot_tools.py {stats|list|add_missing} [--dry-run]')
sys.exit(0)
cmd = sys.argv[1]
if cmd == 'stats':
cmd_stats()
elif cmd == 'list':
cmd_list()
elif cmd == 'add_missing':
dry_run = '--dry-run' in sys.argv
cmd_add_missing(dry_run)
else:
print(f'Unknown command: {cmd}')
sys.exit(1)
cmd = sys.argv[1]
if cmd == 'stats':
cmd_stats()
elif cmd == 'list':
cmd_list()
elif cmd == 'add_missing':
dry_run = '--dry-run' in sys.argv
cmd_add_missing(dry_run)
else:
print(f'Unknown command: {cmd}')
sys.exit(1)
if __name__ == '__main__':
main()
main()