cocoapods-aqara-localzedLoader 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 795d106ed32e894b1e09d27b5ea84afda20ba23d4e8e11f8ae0fe6a6fe1ec1e5
4
- data.tar.gz: 3da5d0f1c604a3c805dbcc3fbdb9ef127199778c9e74899407d785dd958b366e
3
+ metadata.gz: b7fdeaa4c9af99d6d9d4530f324362ab1c5e467f49390465282cd9df5147e74f
4
+ data.tar.gz: 50c4a8eb1f2c97d91ecff0973a607c2d787eaa3f355fbd80408d0b96b4b97ca9
5
5
  SHA512:
6
- metadata.gz: 312c90c5f9bfa427d653eba01c8345f05457b16ab2527987991cf19427b5f0deacaf88a08a37c7485a270eaed2ccbeeab96fa6ce28821f1a5816bd8e6bfd123b
7
- data.tar.gz: 6331e59b66c6f13d7a35eb0a55a2087cf608be23a609422dd2d1b85318d9ed4d49581a8448699568777d6493f6a5750e873fc7ecfa414b4ad49db86ad1806e2e
6
+ metadata.gz: 9e39d70e6c65937d9c2a7537cb33764481b3c0ed29dbf83c7092720d233100865ac20b1053dcb374f5ae12629db29b191b6ca4aa0367a952d06a410b516b5e65
7
+ data.tar.gz: d8717544101f5bdf4955ae4512a7019dc4e6f6233eb7c5b295b93ed8fde7bee36c4fa0e64653d284874282c31177cd6d4f39fda068a48583a80211c33dc2e96f
@@ -2,6 +2,7 @@ import shutil
2
2
  import os, sys, stat
3
3
  import time
4
4
  import requests
5
+ import zipfile
5
6
  from typing import Optional
6
7
 
7
8
 
@@ -170,136 +171,85 @@ class CrowdinPlatform():
170
171
  "Content-Type": "application/json"
171
172
  }
172
173
 
173
- def _get_project_files(self) -> dict:
174
- """获取项目文件列表
174
+ def _get_directories(self) -> dict:
175
+ url = f"{self.base_url}/projects/{self.project_id}/directories"
176
+ resp = requests.get(url, headers=self._get_headers(), params={"limit": 500})
177
+ resp.raise_for_status()
178
+ return resp.json()
175
179
 
176
- Returns:
177
- dict: API 返回的文件列表数据
178
- """
179
- url = f"{self.base_url}/projects/{self.project_id}/files"
180
- headers = self._get_headers()
181
- params = {"limit": 500}
182
- print(f"Request: GET {url} with params {params}")
183
- response = requests.get(url, headers=headers, params=params)
184
- #print(f"Response: {response.status_code}")
185
- # print(f"Response Body: {response.text}")
186
- if response.status_code != 200:
187
- raise Exception(f"获取项目文件列表失败: {response.status_code}, {response.text}")
188
- return response.json()
189
-
190
- def _find_file_id_by_name(self, files_data: dict, file_name: str) -> Optional[int]:
191
- """从文件列表中查找指定文件名的 fileId
180
+ def _find_directory_id_by_path(self, directory_path: str) -> int:
181
+ dirs = self._get_directories()
182
+ for item in dirs["data"]:
183
+ data = item["data"]
184
+ if data.get("path") == directory_path:
185
+ return data["id"]
186
+ raise Exception(f"未找到目录: {directory_path}")
192
187
 
193
- Args:
194
- files_data: get_project_files 返回的数据
195
- file_name: 要查找的文件名
188
+ def build_directory_all_languages(self, directory_path: str) -> int:
196
189
 
197
- Returns:
198
- int: 文件的 ID,如果未找到则返回 None
199
- """
200
- if "data" not in files_data:
201
- raise Exception("文件列表数据格式错误: 缺少 'data' 字段")
202
- for file_item in files_data["data"]:
203
- if "data" in file_item and file_item["data"]["name"] == file_name:
204
- return file_item["data"]["id"]
205
- return None
190
+ print("开始获取 /APP 目录的directory_id...")
191
+ directory_id = self._find_directory_id_by_path(directory_path)
192
+ print(f"开始构建directory_id:{directory_id}的翻译文件")
193
+ url = f"{self.base_url}/projects/{self.project_id}/translations/builds/directories/{directory_id}"
206
194
 
207
- def _get_file_download_url(self, file_id: int) -> str:
208
- """获取文件下载 URL
209
195
 
210
- Args:
211
- file_id: 文件 ID
196
+ resp = requests.post(url, headers=self._get_headers())
197
+ resp.raise_for_status()
212
198
 
213
- Returns:
214
- str: 下载 URL
215
- """
216
- url = f"{self.base_url}/projects/{self.project_id}/files/{file_id}/download"
217
- headers = self._get_headers()
218
- print(f"Request: GET {url}")
219
- response = requests.get(url, headers=headers)
220
- #print(f"Response: {response.status_code}")
221
- # print(f"Response Body: {response.text}")
222
- if response.status_code != 200:
223
- raise Exception(f"获取文件下载 URL 失败: {response.status_code}, {response.text}")
224
- data = response.json()
225
- if "data" not in data or "url" not in data["data"]:
226
- raise Exception(f"下载 URL 数据格式错误: {data}")
227
- return data["data"]["url"]
228
-
229
- def _download_file_from_url(self, download_url: str, save_path: str, max_retries: int = 3) -> None:
230
- """从 URL 下载文件
199
+ build_id = resp.json()["data"]["id"]
200
+ return build_id
231
201
 
232
- Args:
233
- download_url: 文件下载 URL
234
- save_path: 保存路径
235
- max_retries: 最大重试次数
236
- """
237
- for attempt in range(max_retries):
238
- try:
239
- # print(f"Request: GET {download_url} (Attempt {attempt + 1}/{max_retries})")
240
- response = requests.get(download_url, stream=True, timeout=60)
241
- #print(f"Response: {response.status_code}")
242
- if response.status_code != 200:
243
- raise Exception(f"下载文件失败: {response.status_code}, {response.text}")
244
-
245
- os.makedirs(os.path.dirname(save_path) if os.path.dirname(save_path) else ".", exist_ok=True)
246
- with open(save_path, "wb") as f:
247
- for chunk in response.iter_content(chunk_size=8192):
248
- if chunk:
249
- f.write(chunk)
250
- #print(f"文件下载成功: {save_path}")
251
- return
252
- except (requests.exceptions.ChunkedEncodingError, requests.exceptions.RequestException, Exception) as e:
253
- print(f"下载失败 (Attempt {attempt + 1}/{max_retries}): {e}")
254
- if attempt < max_retries - 1:
255
- wait_time = (attempt + 1) * 2
256
- print(f"等待 {wait_time} 秒后重试...")
257
- time.sleep(wait_time)
258
- else:
259
- raise Exception(f"文件下载最终失败,已重试 {max_retries} 次: {e}")
260
-
261
- def download_file(self, target_file_name: str, output_path: str, **kwargs) -> None:
262
- """从 Crowdin 下载指定文件
263
-
264
- Args:
265
- target_file_name: 目标文件名
266
- output_path: 输出文件路径
267
- **kwargs: 其他参数(未使用)
268
- """
269
- print(f"开始从 Crowdin 下载文件: {target_file_name}")
270
- # 1. 获取项目文件列表
271
- print("正在获取项目文件列表...")
272
- files_data = self._get_project_files()
273
- # 2. 查找目标文件的 fileId
274
- print(f"正在查找文件: {target_file_name}")
275
- file_id = self._find_file_id_by_name(files_data, target_file_name)
276
- if file_id is None:
277
- raise Exception(f"未找到文件: {target_file_name}")
278
- print(f"找到文件 ID: {file_id}")
279
- # 3. 获取下载 URL
280
- print("正在获取下载 URL...")
281
- download_url = self._get_file_download_url(file_id)
282
- print("下载 URL 获取成功")
283
- # 4. 下载文件
284
- print("正在下载文件...")
285
- self._download_file_from_url(download_url, output_path)
286
- print("文件下载完成")
287
-
288
- def update_source_language(self, target_file_name: str, output_path: str, **kwargs) -> None:
289
- """从 Crowdin 更新源语言文件
290
-
291
- Args:
292
- target_file_name: 目标文件名
293
- output_path: 输出文件路径(最终保存位置)
294
- **kwargs: 其他参数(未使用)
295
- """
296
- temp_file = "./APP.xlsx"
297
- self.download_file(target_file_name, temp_file, **kwargs)
298
- os.makedirs(os.path.dirname(output_path), exist_ok=True)
299
- shutil.copy(temp_file, output_path)
300
- os.remove(temp_file)
301
- print(f"源语言文件已更新: {output_path}")
302
202
 
203
+ def wait_for_build(self, build_id: int, timeout: int = 120) -> None:
204
+ """等待构建完成"""
205
+ url = f"{self.base_url}/projects/{self.project_id}/translations/builds/{build_id}"
206
+ headers = self._get_headers()
207
+ start_time = time.time()
208
+ print("等待构建完成...")
209
+ while True:
210
+ resp = requests.get(url, headers=headers)
211
+ resp.raise_for_status()
212
+ status = resp.json()["data"]["status"]
213
+ print(f"当前构建状态: {status}")
214
+ if status == "finished":
215
+ print("构建完成")
216
+ return
217
+ elif status == "failed":
218
+ raise Exception("Crowdin 构建失败")
219
+ elif time.time() - start_time > timeout:
220
+ raise TimeoutError("等待 Crowdin 构建超时")
221
+ time.sleep(3)
222
+
223
+ def download_translations_zip(self, output_zip_path: str) -> None:
224
+ """下载整个项目的多语言文件 ZIP"""
225
+ build_id = self.build_directory_all_languages("/APP")
226
+ self.wait_for_build(build_id)
227
+ url = f"{self.base_url}/projects/{self.project_id}/translations/builds/{build_id}/download"
228
+ headers = self._get_headers()
229
+ resp = requests.get(url, headers=headers)
230
+ resp.raise_for_status()
231
+ download_url = resp.json()["data"]["url"]
232
+
233
+ # 下载 ZIP 文件
234
+ print(f"正在下载 ZIP 文件到 {output_zip_path} ...")
235
+ r = requests.get(download_url, stream=True)
236
+ r.raise_for_status()
237
+ os.makedirs(os.path.dirname(output_zip_path) or ".", exist_ok=True)
238
+ with open(output_zip_path, "wb") as f:
239
+ for chunk in r.iter_content(chunk_size=8192):
240
+ if chunk:
241
+ f.write(chunk)
242
+ print(f"多语言 ZIP 下载完成: {output_zip_path}")
243
+
244
+ def download_and_extract_translations(self, output_dir: str) -> None:
245
+ """下载并解压整个多语言文件"""
246
+ zip_path = "./crowdin_translations.zip"
247
+ self.download_translations_zip(zip_path)
248
+ print(f"正在解压 {zip_path} 到 {output_dir}")
249
+ with zipfile.ZipFile(zip_path, "r") as zip_ref:
250
+ zip_ref.extractall(output_dir)
251
+ os.remove(zip_path)
252
+ print(f"多语言文件已解压到: {output_dir}APP.xlsx")
303
253
 
304
254
  # 默认配置(需要设置)
305
255
  DEFAULT_ACCESS_TOKEN = "db0506fb755d528c7b9b750e15174d3cfa483859488da978748ad6b9e34d13dc94d8716810a2f978" # 需要设置
@@ -309,12 +259,18 @@ DEFAULT_TARGET_FILE_NAME = "APP.xlsx"
309
259
 
310
260
  ############################
311
261
 
262
+ def str_to_bool(v: str) -> bool:
263
+ return v.lower() in ("1", "true", "yes", "y", "on")
264
+
312
265
  if __name__ == '__main__':
313
266
  localizable_path = sys.argv[1]
314
- crowdin = sys.argv[2]
267
+ crowdin = False
268
+ if len(sys.argv) > 2:
269
+ crowdin = str_to_bool(sys.argv[2])
270
+
315
271
  if crowdin:
316
272
  platform = CrowdinPlatform(DEFAULT_ACCESS_TOKEN, DEFAULT_PROJECT_ID)
317
- target_path = f"{localizable_path}/APP/APP.xlsx"
318
- platform.update_source_language(DEFAULT_TARGET_FILE_NAME, target_path)
273
+ target_path = f"{localizable_path}/APP/"
274
+ platform.download_and_extract_translations(target_path)
319
275
  else:
320
276
  DownLatestLocalizableSource(localizable_path)
@@ -1,3 +1,3 @@
1
1
  module Localzedloader
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.8"
3
3
  end
@@ -63,7 +63,8 @@ class BundleGenerater
63
63
  sleep sleep_time
64
64
  end
65
65
  puts "当前进行第#{@@download_Count}次尝试下载多语言文件"
66
- system "cd #{File.dirname(__FILE__)};python3 DownloadNewLanguage.py #{project_path} #{crowdin}"
66
+ crowdin_arg = crowdin ? "true" : "false"
67
+ system "cd #{File.dirname(__FILE__)};python3 DownloadNewLanguage.py #{project_path} #{crowdin_arg}"
67
68
  @@download_Count = @@download_Count + 1
68
69
  end
69
70
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-aqara-localzedLoader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - zhaoxifan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-12-30 00:00:00.000000000 Z
11
+ date: 2025-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler