diff --git a/Lib/test/test_tools/test_msgfmt.py b/Lib/test/test_tools/test_msgfmt.py index ea10d4693df75a..eb93f55b4a1286 100644 --- a/Lib/test/test_tools/test_msgfmt.py +++ b/Lib/test/test_tools/test_msgfmt.py @@ -169,6 +169,17 @@ def test_no_input_file(self): def test_nonexistent_file(self): assert_python_failure(msgfmt, 'nonexistent.po') + def test_statistics(self): + with temp_cwd(): + res = assert_python_ok(msgfmt, '--statistics', data_dir / "general.po") + out = res.out.decode('utf-8').strip() + self.assertEqual('8 translated messages, 1 untranslated message.', out) + # Multiple input files + res = assert_python_ok(msgfmt, '--statistics', '-o', 'temp.mo', data_dir / "general.po", data_dir / "fuzzy.po") + out = res.out.decode('utf-8').strip() + self.assertIn('general.po: 8 translated messages, 1 untranslated message.', out) + self.assertIn('fuzzy.po: 0 translated messages.', out) + def update_catalog_snapshots(): for po_file in data_dir.glob('*.po'): diff --git a/Misc/NEWS.d/next/Tools-Demos/2025-04-05-18-13-00.gh-issue-77393.msgid28.rst b/Misc/NEWS.d/next/Tools-Demos/2025-04-05-18-13-00.gh-issue-77393.msgid28.rst new file mode 100644 index 00000000000000..454dab452527d6 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2025-04-05-18-13-00.gh-issue-77393.msgid28.rst @@ -0,0 +1 @@ +Added ``--statistics`` option to :program:`msgfmt`. diff --git a/Tools/i18n/msgfmt.py b/Tools/i18n/msgfmt.py index 878d3e290778c6..887cf6db22dd1c 100755 --- a/Tools/i18n/msgfmt.py +++ b/Tools/i18n/msgfmt.py @@ -23,6 +23,9 @@ -V --version Display version information and exit. + + --statistics + Print statistics about translations. """ import os @@ -38,6 +41,7 @@ MESSAGES = {} +empty_translations = 0 # Counter for empty translations for --statistics def usage(code, msg=''): @@ -49,12 +53,14 @@ def usage(code, msg=''): def add(ctxt, id, str, fuzzy): "Add a non-fuzzy translation to the dictionary." - global MESSAGES + global MESSAGES, empty_translations if not fuzzy and str: if ctxt is None: MESSAGES[id] = str else: MESSAGES[b"%b\x04%b" % (ctxt, id)] = str + elif not fuzzy and not str: + empty_translations += 1 def generate(): @@ -99,6 +105,11 @@ def generate(): def make(filename, outfile): + # see gh-issue: 53950 + global MESSAGES, empty_translations + MESSAGES.clear() + empty_translations = 0 + ID = 1 STR = 2 CTXT = 3 @@ -229,11 +240,12 @@ def make(filename, outfile): def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'hVo:', - ['help', 'version', 'output-file=']) + ['help', 'version', 'output-file=', 'statistics']) except getopt.error as msg: usage(1, msg) outfile = None + print_statistics = False # parse options for opt, arg in opts: if opt in ('-h', '--help'): @@ -243,6 +255,8 @@ def main(): sys.exit(0) elif opt in ('-o', '--output-file'): outfile = arg + elif opt in ('--statistics',): + print_statistics = True # do it if not args: print('No input file given', file=sys.stderr) @@ -252,6 +266,25 @@ def main(): for filename in args: make(filename, outfile) + if print_statistics: + _print_statistics(filename, args) + +# Utility to print --statistics +def _print_statistics(filename, args): + translated = 0 + for msgid, msgstr in MESSAGES.items(): + if not msgid: + continue + if msgstr: + translated += 1 + + message = (f"{os.path.basename(filename) + ': ' if len(args) > 1 else ''}" + f"{translated} translated message{'s' if translated != 1 else ''}") + if empty_translations > 0: + message += f", {empty_translations} untranslated message{'s' if empty_translations != 1 else ''}" + message += "." + print(message) + if __name__ == '__main__': main()