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
@@ -89,29 +92,51 @@ def recreate_tx_config():
8992 )
9093
9194
95+ @dataclass
96+ class ResourceLanguageStatistics :
97+ name : str
98+ total_words : int
99+ translated_words : int
100+ total_strings : int
101+ translated_strings : int
102+
103+ @classmethod
104+ def from_api_v3_entry (cls , data : dict ) -> Self :
105+ return cls (
106+ name = search ('r:([^:]*)' , data ['id' ]).group (1 ),
107+ total_words = data ['attributes' ]['total_words' ],
108+ translated_words = data ['attributes' ]['translated_words' ],
109+ total_strings = data ['attributes' ]['total_strings' ],
110+ translated_strings = data ['attributes' ]['translated_strings' ],
111+ )
112+
113+
92114def _get_resources ():
93115 from requests import get
94116
95117 resources = []
96- offset = 0
118+ cursor = None
97119 if os .path .exists ('.tx/api-key' ):
98120 with open ('.tx/api-key' ) as f :
99121 transifex_api_key = f .read ()
100122 else :
101123 transifex_api_key = os .getenv ('TX_TOKEN' )
102124 while True :
103125 response = get (
104- f'https://api.transifex.com/organizations/python-doc/projects/{ PROJECT_SLUG } /resources/' ,
105- params = {'language_code' : LANGUAGE , 'offset' : offset },
106- auth = ('api' , transifex_api_key ),
126+ 'https://rest.api.transifex.com/resource_language_stats' ,
127+ params = {
128+ 'filter[project]' : f'o:python-doc:p:{ PROJECT_SLUG } ' , 'filter[language]' : f'l:{ LANGUAGE } '
129+ } | ({'page[cursor]' : cursor } if cursor else {}),
130+ headers = {'Authorization' : f'Bearer { transifex_api_key } ' }
107131 )
108132 response .raise_for_status ()
109- response_list = response .json ()
133+ response_json = response .json ()
134+ response_list = response_json ['data' ]
110135 resources .extend (response_list )
111- if len ( response_list ) < 100 :
136+ if 'next' not in response_json [ 'links' ] :
112137 break
113- offset += len ( response_list )
114- return resources
138+ cursor = unquote ( search ( 'page\[cursor]=([^&]*)' , response_json [ 'links' ][ 'next' ]). group ( 1 ) )
139+ return [ ResourceLanguageStatistics . from_api_v3_entry ( entry ) for entry in resources ]
115140
116141
117142def _get_number_of_translators ():
@@ -128,18 +153,18 @@ def _get_number_of_translators():
128153def recreate_readme ():
129154 def language_switcher (entry ):
130155 return (
131- entry [ ' name' ] .startswith ('bugs' )
132- or entry [ ' name' ] .startswith ('tutorial' )
133- or entry [ ' name' ] .startswith ('library--functions' )
156+ entry . name .startswith ('bugs' )
157+ or entry . name .startswith ('tutorial' )
158+ or entry . name .startswith ('library--functions' )
134159 )
135160
136161 def average (averages , weights ):
137162 return sum ([a * w for a , w in zip (averages , weights )]) / sum (weights )
138163
139164 resources = _get_resources ()
140165 filtered = list (filter (language_switcher , resources ))
141- average_list = [e [ 'stats' ][ 'translated' ][ 'percentage' ] for e in filtered ]
142- weights_list = [e [ 'wordcount' ] for e in filtered ]
166+ average_list = [e . translated_words / e . total_words for e in filtered ]
167+ weights_list = [e . total_words for e in filtered ]
143168
144169 language_switcher_status = average (average_list , weights = weights_list ) * 100
145170 number_of_translators = _get_number_of_translators ()
0 commit comments