Skip to content

Commit fd002fd

Browse files
authored
Merge pull request #521 from RobPasMue/ci/autoupdate-translation-stats
enh: autoupdating translation stats during build
2 parents ee4bfea + cbd0f73 commit fd002fd

File tree

3 files changed

+115
-229
lines changed

3 files changed

+115
-229
lines changed

_ext/translation_graph.py

Lines changed: 115 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
from pathlib import Path
22
import json
3-
from typing import TypeAlias, TypedDict, Annotated as A
3+
from typing import TYPE_CHECKING, TypeAlias, TypedDict, Annotated as A
44

5+
from babel.messages import pofile
56
from docutils import nodes
67
from docutils.parsers.rst import Directive
78
import plotly.graph_objects as go
89
from plotly.offline import plot
910
import numpy as np
1011

12+
if TYPE_CHECKING:
13+
from sphinx.application import Sphinx
14+
15+
16+
BASE_DIR = Path(__file__).resolve().parent.parent # Repository base directory
17+
LOCALES_DIR = BASE_DIR / "locales" # Locales directory
18+
STATIC_DIR = BASE_DIR / "_static" # Static directory
1119

1220
class ModuleStats(TypedDict):
1321
total: int
@@ -35,10 +43,7 @@ class TranslationGraph(Directive):
3543
Completed: %{customdata.percentage}%
3644
"""
3745
def run(self):
38-
# Read the JSON file containing translation statistics
39-
json_path = Path(__file__).parent.parent / "_static" / "translation_stats.json"
40-
with json_path.open("r") as f:
41-
data: TranslationStats = json.load(f)
46+
data = get_translation_stats()
4247

4348
# Sort data by locale and module
4449
data = {locale: dict(sorted(loc_stats.items())) for locale, loc_stats in sorted(data.items())}
@@ -122,8 +127,113 @@ def run(self):
122127
)
123128
return [nodes.raw("", div, format="html")]
124129

130+
def calculate_translation_percentage(po_path : Path, locale : str) -> ModuleStats:
131+
"""
132+
Calculate the translation percentage for a given .po file.
133+
134+
Parameters
135+
----------
136+
po_path : Path
137+
Path to the .po file.
138+
locale : str
139+
Locale code (e.g., 'es', 'fr').
140+
141+
Returns
142+
-------
143+
dict
144+
A dictionary containing the total number of strings, translated strings,
145+
fuzzy strings, untranslated strings, and the translation percentage.
146+
"""
147+
with open(po_path, "r", encoding="utf-8") as f:
148+
catalog = pofile.read_po(f, locale=locale)
149+
150+
total = 0
151+
translated = 0
152+
fuzzy = 0
153+
154+
for message in catalog:
155+
if message.id:
156+
total += 1
157+
# Check if the message is fuzzy
158+
# Fuzzy messages are not considered translated
159+
if message.fuzzy:
160+
fuzzy += 1
161+
break
162+
# Check if the message is translated
163+
if message.string:
164+
translated += 1
165+
166+
percentage = (translated / total * 100) if total > 0 else 0
167+
168+
return {
169+
"total": total,
170+
"translated": translated,
171+
"fuzzy": fuzzy,
172+
"untranslated": total - translated - fuzzy,
173+
"percentage": round(percentage, 2)
174+
}
175+
176+
177+
def get_translation_stats() -> TranslationStats:
178+
# Get all .po files in the locales directory
179+
po_files = list(LOCALES_DIR.rglob("*.po"))
180+
181+
# Let's use a dictionary to store the results
182+
#
183+
# We will store the info as
184+
# {
185+
# "es": {
186+
# "file1": {
187+
# "total": 100,
188+
# "translated": 50,
189+
# "fuzzy": 0,
190+
# "untranslated": 50,
191+
# "percentage": 50.0
192+
# },
193+
# ...
194+
# },
195+
# "fr": {
196+
# "file1": {
197+
# "total": 100,
198+
# "translated": 50,
199+
# "fuzzy": 0,
200+
# "untranslated": 50,
201+
# "percentage": 50.0
202+
# },
203+
# ...
204+
# }
205+
results = {}
206+
207+
# Calculate translation percentages for each file
208+
for po_file in po_files:
209+
# Get the locale from the file path
210+
locale = po_file.parent.parent.name
211+
stats = calculate_translation_percentage(po_file, locale)
212+
213+
# Store the results in the dictionary
214+
if locale not in results:
215+
results[locale] = {}
216+
217+
results[locale][po_file.stem] = stats
218+
219+
return results
220+
221+
def write_translation_stats(app: "Sphinx", exception: Exception | None) -> None:
222+
from sphinx.util import logging
223+
logger = logging.getLogger("_ext.translation_graph")
224+
225+
stats = get_translation_stats()
226+
out_path = app.outdir / "_static" / "translation_stats.json"
227+
with open(out_path, "w") as f:
228+
json.dump(stats, f, indent=2)
229+
230+
logger.info("Wrote translation stats to %s", out_path)
231+
232+
125233
def setup(app):
126234
app.add_directive("translation-graph", TranslationGraph)
235+
app.connect("build-finished", write_translation_stats)
236+
127237
return {
128238
"version": "0.1",
129239
"parallel_read_safe": True,

_static/translation_stats.json

Lines changed: 0 additions & 118 deletions
This file was deleted.

scripts/translation_stats.py

Lines changed: 0 additions & 106 deletions
This file was deleted.

0 commit comments

Comments
 (0)