forked from FoldingCommunity/Translate
-
Notifications
You must be signed in to change notification settings - Fork 0
/
generate_report.py
executable file
·125 lines (109 loc) · 5.32 KB
/
generate_report.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python3
from pathlib import Path
from typing import TextIO
class POHeaderData:
def __init__(self, header_fields: dict):
self.header_fields = header_fields
class ReportGenerator:
"""
Reads .po files from a folder (see ROOT_FOLDER) and locates the original files (see SOURCE_LANGUAGE)
to compare them to the other available translations. Then it will render out a Markdown-formatted
report of the current status of those available translations.
To retrieve the report, just call `get_report()`.
"""
ROOT_FOLDER = 'Localization/'
SOURCE_LANGUAGE = 'en-US'
def get_report(self) -> str:
translations = {}
original_files = self._find_po_files(Path(f'{self.ROOT_FOLDER}{self.SOURCE_LANGUAGE}'))
languages = self._find_languages()
for (language, directory) in sorted(languages.items(), key=lambda item: item[0]):
translations[language] = {'files': {}}
files = self._find_po_files(directory)
for file in sorted(original_files.keys()):
if file in files:
translations[language]['files'][file] = self._verify_translation(original_files[file], files[file], language)
else:
translations[language]['files'][file] = {'error': 'missing'}
return self._render_report(translations)
def _find_po_files(self, path: Path) -> dict:
files = {}
for file in path.glob('*.po'):
with file.open('r', encoding='UTF-8') as fh:
files[file.name] = self._extract_po_header(fh)
return files
@staticmethod
def _extract_po_header(file_handler: TextIO) -> POHeaderData:
in_header = False
header_fields = {}
header_string = ""
for line in file_handler:
if line.startswith('msgid ""') and not in_header:
in_header = True
elif line.startswith('msgid ""') and in_header:
break
elif line.startswith('msgstr "'):
header_string += line[8:-2]
elif line.startswith('"'):
header_string += line[1:-2]
for line in header_string.split("\\n"):
fields = line.split(':')
if len(fields) == 2:
header_fields[fields[0].strip()] = fields[1].strip()
return POHeaderData(header_fields)
def _find_languages(self) -> dict:
root_folder = Path(self.ROOT_FOLDER)
languages = {}
for directory in root_folder.glob('*-*'):
if directory.name != self.SOURCE_LANGUAGE:
languages[directory.name] = directory
return languages
@staticmethod
def _verify_translation(original_file: POHeaderData, translated_file: POHeaderData, language: str) -> dict:
details = {}
if translated_file.header_fields['Target-Language'] == language:
details['Target-Language'] = '✔'
else:
details['Target-Language'] = f"""is "{translated_file.header_fields['Target-Language']}" but should be "{language}" """
if translated_file.header_fields['Source-Version'] == original_file.header_fields['Source-Version']:
details['Source-Version'] = '✔'
else:
details['Source-Version'] = f"""not up-to-date ({translated_file.header_fields['Source-Version']} vs {original_file.header_fields['Source-Version']})"""
return details
@staticmethod
def _render_report(translations: dict):
details = """## Details\n"""
overview = {}
for (language, files) in translations.items():
details += f"""### {language}\n"""
details += """| File | Target-Language | Source-Version | Error |\n"""
details += """| ---- | --------------- | -------------- | ----- |\n"""
errors = 0
updates_needed = 0
for (file, file_info) in files['files'].items():
if 'error' in file_info:
details += f"""| {file} | ? | ? | {file_info['error']} |\n"""
errors += 1
else:
details += f"""| {file} | {file_info['Target-Language']} | {file_info['Source-Version']} | - |\n"""
if file_info['Target-Language'] != '✔' or file_info['Source-Version'] != '✔':
updates_needed += 1
details += """\n[↑ Back to the overview](#overview)\n"""
overview[language] = {'percentage_done': round((len(files['files']) - errors) / len(files['files']) * 100), 'updates_needed': updates_needed}
result = """# Translation Status Report\n"""
result += """## Overview\n"""
result += """| Language | Done % | Updates Needed |\n"""
result += """| -------- | -----: | -------------: |\n"""
for (language, stats) in overview.items():
result += f"""| [{language}](#{language}) | """
if stats['percentage_done'] >= 100:
result += '✔ '
result += f"""{stats['percentage_done']}% | """
if stats['updates_needed'] == 0:
result += '✔ '
result += f"""{stats['updates_needed']} |\n"""
result += details
return result
with open('translation_report.md', 'w', encoding='UTF-8') as fh:
report = (ReportGenerator()).get_report()
fh.write(report)