wesnoth/utils/po_stat.py
Steve Cotton 1ad78a0442 Fix the po stats script to recognise "es_419"
The failure mode caused it to overwrite the es_ES stats
with the es_419 ones. Skipping the CI step, as this script
is only run by the pot-update targets.

[ci_skip]

(cherry picked from commit ec7bd83721)
2022-01-17 21:51:02 +01:00

221 lines
6.4 KiB
Python
Executable File

#!/usr/bin/env python3
# encoding: utf-8
import sys
import os
import glob
import subprocess
import re
verbose = False
update_cfg = False
textdomains = []
class Stats:
def __init__(self):
self.stats = [0, 0, 0]
def parse(self, line):
m = re.search(r'(\d+)\s*translated', line)
if m:
self.stats[0] = int(m.group(1))
m = re.search(r'(\d+)\s*fuzzy', line)
if m:
self.stats[1] = int(m.group(1))
m = re.search(r'(\d+)\s*untranslated', line)
if m:
self.stats[2] = int(m.group(1))
def __iadd__(self, other):
for i in range(3):
self.stats[i] += other.stats[i]
return self
def __add__(self, other):
s = Stats()
s.stats = list(self.stats)
s += other
return s
def translated_percent(self):
s = sum(self.stats)
return self.stats[0] * 100 // s if s else 0
def usage(file=sys.stdout):
file.write(
'Usage: {} [--verbose] [--update-cfg] [--help]\n'
'Calculates the translated% (non-fuzzy) of Wesnoth\'s po files, prints it to stdout.\n'
' --update-cfg: writes the result into data/languages/*.cfg\n'
' --verbose: prints extra status messages\n'
' --textdomains <comma-separated list>: use only these textdomains.\n'
' --help: prints this text\n'
'po/*/<locale_name>.po files must exist.'.format(sys.argv[0]))
def do_stats(po_files):
env = dict(os.environ)
env['LC_MESSAGES'] = 'C'
env.pop('LC_ALL', None)
total = Stats()
for po_file in po_files:
command_args = ['msgfmt', '-o', '/dev/null', '--statistics', po_file]
try:
# print('running {}'.format(' '.join(command_args)))
byte_output = subprocess.check_output(command_args, env=env, stderr=subprocess.STDOUT)
# print('output: {}'.format(output))
str_output = byte_output.decode("utf-8")
current = Stats()
current.parse(str_output)
total += current
if verbose:
print('File {}: {} strings translated'.format(po_file, current.translated_percent()))
except subprocess.CalledProcessError as e:
print('yo {}'.format(e.returncode))
break
return total.translated_percent()
def write_percentage_wml(wml_file, percent):
text = ''
with open(wml_file) as f:
text = f.read()
percent_line = 'percent={}'.format(percent)
if 'percent=' in text:
text = re.sub(r'percent=\d+', percent_line, text)
else:
text = re.sub(r'\[/locale\]', ' {}\n[/locale]'.format(percent_line), text)
with open(wml_file, 'w') as f:
f.write(text)
def get_wml_cfg(wml_dir, locale):
match = re.match(r'([a-z]+)(_([A-Z0-9]+))?(@([a-z]+))?', locale)
if not match:
return None
lang, script, region = match.group(1, 3, 5)
candidates = [
'{}.cfg'.format(lang),
]
if region:
if script:
candidates.append('{}_{}@{}.cfg'.format(lang, script, region))
else:
candidates.append('{}@{}.cfg'.format(lang, region))
candidates.append('{}_{}@{}.cfg'.format(lang, lang.upper(), region))
candidates.append('{}_*@{}.cfg'.format(lang, region))
else:
if script:
candidates.append('{}_{}.cfg'.format(lang, script))
candidates.append('{}_{}@*.cfg'.format(lang, script))
else:
candidates.append('{}_{}.cfg'.format(lang, lang.upper()))
candidates.append('{}_*.cfg'.format(lang))
candidates.append('{}@*.cfg'.format(lang))
candidates.append('{}_*@*.cfg'.format(lang))
candidate_files = {
file: glob.glob(os.path.join(wml_dir, file))
for file in candidates
}
for current_index, current in enumerate(candidates):
for previous in range(0, current_index-1):
# Remove more specialized candidates from more general one's list
for file in candidate_files[current]:
if file in candidate_files[candidates[previous]]:
candidate_files[candidates[previous]].remove(file)
for current in candidates:
files = candidate_files[current]
if files:
if len(files) > 1:
print('Warning: too many candidates for {}: {}'.format(locale, files))
return files[0]
return None
def get_pos(wesnoth_dir, locale_name):
po_files = []
if not textdomains:
po_mask = '*/{}.po'.format(locale_name)
pos_mask = os.path.join(wesnoth_dir, 'po', po_mask)
po_files = glob.glob(pos_mask)
if not po_files:
sys.stderr.write('Error: Cannot find {}\n'.format(pos_mask))
exit(1)
else:
for d in textdomains:
po_file = os.path.join(wesnoth_dir, 'po', d, locale_name + '.po')
if os.path.isfile(po_file):
po_files.append(po_file)
else:
sys.stderr.write('Warning: cannot find {}\n'.format(po_file))
return po_files
def stat_one_locale(wesnoth_dir, locale_name):
wml_dir = os.path.join(wesnoth_dir, 'data/languages')
po_files = get_pos(wesnoth_dir, locale_name)
if not os.path.isdir(wml_dir):
sys.stderr.write('File {} not found\n'.format(wml_dir))
exit(1)
percent = do_stats(po_files)
print('{} {}'.format(locale_name, percent))
if not update_cfg:
return
wml_cfg = get_wml_cfg(wml_dir, locale_name)
if not wml_cfg:
exit(1)
try:
write_percentage_wml(wml_cfg, percent)
except IOError as whoopsie:
sys.stderr.write(whoopsie)
if __name__ == '__main__':
for arg in sys.argv:
if arg == '--verbose':
verbose = True
elif arg == '--help':
usage()
elif arg == '--update-cfg':
update_cfg = True
elif arg.startswith('--textdomains='):
arg = arg[14:]
# Is supposed to be:
# wesnoth,wesnoth-editor,wesnoth-help,wesnoth-lib,wesnoth-multiplayer,wesnoth-tutorial,wesnoth-units
textdomains = re.split(r'[;, ]', arg)
wesnoth_dir = os.path.realpath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
with open(os.path.join(wesnoth_dir, 'po/LINGUAS')) as f:
da_langs = f.read().split()
for lang in da_langs:
stat_one_locale(wesnoth_dir, lang)