15
15
from argparse import ArgumentParser
16
16
from collections import Counter
17
17
import os
18
- from re import match
18
+ from dataclasses import dataclass
19
+ from re import match ,search
19
20
from subprocess import call ,run
20
21
import sys
22
+ from typing import Self
23
+ from urllib .parse import unquote
21
24
22
25
LANGUAGE = 'pl'
23
26
@@ -83,27 +86,50 @@ def recreate_tx_config():
83
86
))
84
87
85
88
89
+ @dataclass
90
+ class ResourceLanguageStatistics :
91
+ name :str
92
+ total_words :int
93
+ translated_words :int
94
+ total_strings :int
95
+ translated_strings :int
96
+
97
+ @classmethod
98
+ def from_api_v3_entry (cls ,data :dict )-> Self :
99
+ return cls (
100
+ name = search ('r:([^:]*)' ,data ['id' ]).group (1 ),
101
+ total_words = data ['attributes' ]['total_words' ],
102
+ translated_words = data ['attributes' ]['translated_words' ],
103
+ total_strings = data ['attributes' ]['total_strings' ],
104
+ translated_strings = data ['attributes' ]['translated_strings' ],
105
+ )
106
+
107
+
86
108
def _get_resources ():
87
109
from requests import get
88
110
resources = []
89
- offset = 0
111
+ cursor = None
90
112
if os .path .exists ('.tx/api-key' ):
91
113
with open ('.tx/api-key' )as f :
92
114
transifex_api_key = f .read ()
93
115
else :
94
116
transifex_api_key = os .getenv ('TX_TOKEN' )
95
117
while True :
96
118
response = get (
97
- f'https://api.transifex.com/organizations/python-doc/projects/{ PROJECT_SLUG } /resources/' ,
98
- params = {'language_code' :LANGUAGE ,'offset' :offset },
99
- auth = ('api' ,transifex_api_key ))
119
+ 'https://rest.api.transifex.com/resource_language_stats' ,
120
+ params = {
121
+ 'filter[project]' :f'o:python-doc:p:{ PROJECT_SLUG } ' ,'filter[language]' :f'l:{ LANGUAGE } '
122
+ }| ({'page[cursor]' :cursor }if cursor else {}),
123
+ headers = {'Authorization' :f'Bearer{ transifex_api_key } ' }
124
+ )
100
125
response .raise_for_status ()
101
- response_list = response .json ()
126
+ response_json = response .json ()
127
+ response_list = response_json ['data' ]
102
128
resources .extend (response_list )
103
- if len ( response_list ) < 100 :
129
+ if 'next' not in response_json [ 'links' ] :
104
130
break
105
- offset += len ( response_list )
106
- return resources
131
+ cursor = unquote ( search ( 'page\[cursor]=([^&]*)' , response_json [ 'links' ][ 'next' ]). group ( 1 ) )
132
+ return [ ResourceLanguageStatistics . from_api_v3_entry ( entry ) for entry in resources ]
107
133
108
134
109
135
def _get_number_of_translators ():
@@ -121,17 +147,17 @@ def _get_number_of_translators():
121
147
122
148
def recreate_readme ():
123
149
def language_switcher (entry ):
124
- return (entry [ ' name' ] .startswith ('bugs' )or
125
- entry [ ' name' ] .startswith ('tutorial' )or
126
- entry [ ' name' ] .startswith ('library--functions' ))
150
+ return (entry . name .startswith ('bugs' )or
151
+ entry . name .startswith ('tutorial' )or
152
+ entry . name .startswith ('library--functions' ))
127
153
128
154
def average (averages ,weights ):
129
155
return sum ([a * w for a ,w in zip (averages ,weights )])/ sum (weights )
130
156
131
157
resources = _get_resources ()
132
158
filtered = list (filter (language_switcher ,resources ))
133
- average_list = [e [ 'stats' ][ 'translated' ][ 'percentage' ] for e in filtered ]
134
- weights_list = [e [ 'wordcount' ] for e in filtered ]
159
+ average_list = [e . translated_words / e . total_words for e in filtered ]
160
+ weights_list = [e . total_words for e in filtered ]
135
161
136
162
language_switcher_status = average (average_list ,weights = weights_list )* 100
137
163
number_of_translators = _get_number_of_translators ()