1515from argparse import ArgumentParser
1616from collections import Counter
1717import os
18- from re import match
18+ from dataclasses import dataclass
19+ from re import match , search
1920from subprocess import call , run
2021import sys
22+ from typing import Self
23+ from urllib .parse import unquote
2124
2225LANGUAGE = 'pl'
2326
@@ -91,29 +94,51 @@ def recreate_tx_config():
9194 )
9295
9396
97+ @dataclass
98+ class ResourceLanguageStatistics :
99+ name : str
100+ total_words : int
101+ translated_words : int
102+ total_strings : int
103+ translated_strings : int
104+
105+ @classmethod
106+ def from_api_v3_entry (cls , data : dict ) -> Self :
107+ return cls (
108+ name = search ('r:([^:]*)' , data ['id' ]).group (1 ),
109+ total_words = data ['attributes' ]['total_words' ],
110+ translated_words = data ['attributes' ]['translated_words' ],
111+ total_strings = data ['attributes' ]['total_strings' ],
112+ translated_strings = data ['attributes' ]['translated_strings' ],
113+ )
114+
115+
94116def _get_resources ():
95117 from requests import get
96118
97119 resources = []
98- offset = 0
120+ cursor = None
99121 if os .path .exists ('.tx/api-key' ):
100122 with open ('.tx/api-key' ) as f :
101123 transifex_api_key = f .read ()
102124 else :
103125 transifex_api_key = os .getenv ('TX_TOKEN' )
104126 while True :
105127 response = get (
106- f'https://api.transifex.com/organizations/python-doc/projects/{ PROJECT_SLUG } /resources/' ,
107- params = {'language_code' : LANGUAGE , 'offset' : offset },
108- auth = ('api' , transifex_api_key ),
128+ 'https://rest.api.transifex.com/resource_language_stats' ,
129+ params = {
130+ 'filter[project]' : f'o:python-doc:p:{ PROJECT_SLUG } ' , 'filter[language]' : f'l:{ LANGUAGE } '
131+ } | ({'page[cursor]' : cursor } if cursor else {}),
132+ headers = {'Authorization' : f'Bearer { transifex_api_key } ' }
109133 )
110134 response .raise_for_status ()
111- response_list = response .json ()
135+ response_json = response .json ()
136+ response_list = response_json ['data' ]
112137 resources .extend (response_list )
113- if len ( response_list ) < 100 :
138+ if 'next' not in response_json [ 'links' ] :
114139 break
115- offset += len ( response_list )
116- return resources
140+ cursor = unquote ( search ( 'page\[cursor]=([^&]*)' , response_json [ 'links' ][ 'next' ]). group ( 1 ) )
141+ return [ ResourceLanguageStatistics . from_api_v3_entry ( entry ) for entry in resources ]
117142
118143
119144def _get_number_of_translators ():
@@ -130,18 +155,18 @@ def _get_number_of_translators():
130155def recreate_readme ():
131156 def language_switcher (entry ):
132157 return (
133- entry [ ' name' ] .startswith ('bugs' )
134- or entry [ ' name' ] .startswith ('tutorial' )
135- or entry [ ' name' ] .startswith ('library--functions' )
158+ entry . name .startswith ('bugs' )
159+ or entry . name .startswith ('tutorial' )
160+ or entry . name .startswith ('library--functions' )
136161 )
137162
138163 def average (averages , weights ):
139164 return sum ([a * w for a , w in zip (averages , weights )]) / sum (weights )
140165
141166 resources = _get_resources ()
142167 filtered = list (filter (language_switcher , resources ))
143- average_list = [e [ 'stats' ][ 'translated' ][ 'percentage' ] for e in filtered ]
144- weights_list = [e [ 'wordcount' ] for e in filtered ]
168+ average_list = [e . translated_words / e . total_words for e in filtered ]
169+ weights_list = [e . total_words for e in filtered ]
145170
146171 language_switcher_status = average (average_list , weights = weights_list ) * 100
147172 number_of_translators = _get_number_of_translators ()
0 commit comments