@@ -24,56 +24,70 @@ class TranslationGraph(Directive):
24
24
# and has no content
25
25
has_content = False
26
26
27
+ # oddly, this is evaluated in the js not python,
28
+ # so we treat customdata like a json object
29
+ HOVER_TEMPLATE = """
30
+ <b>%{customdata.module}</b><br>
31
+ Translated: %{customdata.translated}<br>
32
+ Fuzzy: %{customdata.fuzzy}<br>
33
+ Untranslated: %{customdata.untranslated}<br>
34
+ Total: %{customdata.total}<br>
35
+ Completed: %{customdata.percentage}%
36
+ """
27
37
def run (self ):
28
38
# Read the JSON file containing translation statistics
29
39
json_path = Path (__file__ ).parent .parent / "_static" / "translation_stats.json"
30
40
with json_path .open ("r" ) as f :
31
41
data : TranslationStats = json .load (f )
32
42
33
- # Collect all module names -- iterates over the JSON data in 2 levels
34
- all_modules = {module for stats in data .values () for module in stats }
35
- all_modules = sorted (all_modules )
36
-
37
- # Build one trace per locale with full hover info
38
- traces = []
39
-
40
- for locale , modules in data .items ():
41
- y_vals = []
42
- hover_texts = []
43
-
44
- for module in all_modules :
45
- stats = modules .get (module )
46
- y_vals .append (stats ["percentage" ])
47
-
48
- hover_text = (
49
- f"<b>{ module } </b><br>"
50
- f"Translated: { stats ['translated' ]} <br>"
51
- f"Fuzzy: { stats ['fuzzy' ]} <br>"
52
- f"Untranslated: { stats ['untranslated' ]} <br>"
53
- f"Total: { stats ['total' ]} <br>"
54
- f"Completed: { stats ['percentage' ]} %"
55
- )
56
- hover_texts .append (hover_text )
57
-
58
- traces .append (go .Bar (
59
- name = locale ,
60
- x = all_modules ,
61
- y = y_vals ,
62
- hovertext = hover_texts ,
63
- hoverinfo = "text"
64
- ))
65
-
43
+ # Sort data by locale and module
44
+ data = {locale : dict (sorted (loc_stats .items ())) for locale , loc_stats in sorted (data .items ())}
45
+
46
+ # prepend english, everything set to 100%
47
+ en = {module : ModuleStats (total = stats ['total' ], translated = stats ['total' ], fuzzy = stats ['total' ], untranslated = 0 , percentage = 100 ) for module , stats in next (iter (data .values ())).items ()}
48
+ data = {'en' : en } | data
49
+
50
+ # extract data to plot
51
+ locales = list (data .keys ())
52
+ modules = list (data [locales [- 1 ]].keys ())
53
+ values = [[stats ['percentage' ] for stats in loc_stats .values ()] for loc_stats in data .values ()]
54
+ hoverdata = [[{'module' : module } | stats for module , stats in loc_stats .items ()] for loc_stats in data .values ()]
55
+ heatmap = go .Heatmap (
56
+ x = modules ,
57
+ y = locales ,
58
+ z = values ,
59
+ xgap = 5 ,
60
+ ygap = 5 ,
61
+ customdata = np .array (hoverdata ),
62
+ hovertemplate = self .HOVER_TEMPLATE ,
63
+ colorbar = {
64
+ 'orientation' : 'h' ,
65
+ 'y' : 0 ,
66
+ "yanchor" : "bottom" ,
67
+ "yref" : "container" ,
68
+ "title" : "Completion %" ,
69
+ "thickness" : 10 ,
70
+ },
71
+ colorscale = "Plotly3" ,
72
+ )
66
73
# Create figure
67
- fig = go .Figure (data = traces )
74
+ fig = go .Figure (data = heatmap )
68
75
fig .update_layout (
69
- barmode = "group" ,
70
- title = "Translation Coverage by Module and Locale" ,
71
- xaxis_title = "Module" ,
72
- yaxis_title = "Percentage Translated" ,
73
- height = 600 ,
74
- margin = dict (l = 40 , r = 40 , t = 40 , b = 40 )
76
+ paper_bgcolor = "rgba(0,0,0,0)" ,
77
+ plot_bgcolor = "rgba(0,0,0,0)" ,
78
+ font_color = "var(--bs-body-color)" ,
79
+ margin = dict (l = 40 , r = 40 , t = 40 , b = 40 ),
80
+ xaxis_showgrid = False ,
81
+ xaxis_side = "top" ,
82
+ xaxis_tickangle = - 45 ,
83
+ xaxis_tickfont = {
84
+ "family" : "var(--bs-font-monospace)" ,
85
+ "color" : "#fff"
86
+ },
87
+ yaxis_showgrid = False ,
88
+ yaxis_title = "Locale" ,
89
+ yaxis_autorange = "reversed" ,
75
90
)
76
-
77
91
div = plot (fig , output_type = "div" , include_plotlyjs = True )
78
92
return [nodes .raw ("" , div , format = "html" )]
79
93
0 commit comments