@@ -24,56 +24,70 @@ class TranslationGraph(Directive):
2424 # and has no content
2525 has_content = False
2626
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+ """
2737 def run (self ):
2838 # Read the JSON file containing translation statistics
2939 json_path = Path (__file__ ).parent .parent / "_static" / "translation_stats.json"
3040 with json_path .open ("r" ) as f :
3141 data : TranslationStats = json .load (f )
3242
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+ )
6673 # Create figure
67- fig = go .Figure (data = traces )
74+ fig = go .Figure (data = heatmap )
6875 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" ,
7590 )
76-
7791 div = plot (fig , output_type = "div" , include_plotlyjs = True )
7892 return [nodes .raw ("" , div , format = "html" )]
7993
0 commit comments