mintlee commited on
Commit
58fa02f
·
1 Parent(s): b149fbe

add translate sheet_name

Browse files
excel/__pycache__/excel_translate.cpython-310.pyc CHANGED
Binary files a/excel/__pycache__/excel_translate.cpython-310.pyc and b/excel/__pycache__/excel_translate.cpython-310.pyc differ
 
excel/__pycache__/xlsx.cpython-310.pyc CHANGED
Binary files a/excel/__pycache__/xlsx.cpython-310.pyc and b/excel/__pycache__/xlsx.cpython-310.pyc differ
 
excel/xlsx.py CHANGED
@@ -10,6 +10,8 @@ import gridfs
10
  from io import BytesIO
11
  import shutil
12
  import io
 
 
13
 
14
 
15
  NS_MAIN = {'main': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'}
@@ -96,16 +98,7 @@ def extract_text_from_sheet(unzipped_folder_path: str) -> Optional[Tuple[List[Di
96
  'source_file': os.path.join("xl", "sharedStrings.xml"),
97
  'sheet_name': None
98
  })
99
- elif t_elements: # Trường hợp có <t> nhưng không có <r> nào (simple shared string)
100
- # Tìm <t> đầu tiên trực tiếp dưới <si> nếu không phải rich text
101
- # Hoặc nếu cấu trúc là <si><t>...</t></si>
102
- # Trong trường hợp này, element nên là si_element để khi apply_changes,
103
- # ta sẽ tạo cấu trúc <si><r><t>...</t></r></si> nếu có định dạng
104
- # hoặc <si><t>...</t></si> nếu không.
105
- # Tuy nhiên, để đơn giản hóa, nếu không có <r>, ta coi element là <t> đầu tiên
106
- # và không áp dụng "first_format" (vì nó sẽ là None).
107
- # Hoặc, ta có thể luôn coi <si> là element cho shared strings.
108
- # Lựa chọn hiện tại: nếu không có <r>, element là <t> đầu tiên tìm thấy.
109
  direct_t = si_element.find('./main:t', NS_MAIN)
110
  if direct_t is not None:
111
  modifiable_nodes.append({
@@ -284,17 +277,10 @@ def apply_and_save_changes(modified_nodes_data: List[Dict[str, Any]], global_dat
284
  # Tạo thẻ text mới <a:t>
285
  new_t = ET.Element(f"{{{NS_A['a']}}}t")
286
  new_t.text = modified_text
287
- # Trong DrawingML, xml:space="preserve" thường không cần thiết cho <a:t>
288
- # vì việc xuống dòng được kiểm soát bởi <a:br> hoặc các paragraph <a:p> riêng biệt.
289
- # Tuy nhiên, việc thêm nó không gây hại.
290
 
291
  new_r.append(new_t) # Thêm <a:t> vào <a:r>
292
  p_element.append(new_r) # Thêm <a:r> vào <a:p>
293
 
294
- # Một số text box có thể có <a:endParaRPr> để định dạng cuối paragraph.
295
- # Nếu muốn giữ lại, cần logic phức tạp hơn.
296
- # Hiện tại, chúng ta chỉ tạo lại với một run duy nhất.
297
-
298
  updated_files.add(node_info['source_file'])
299
  # print(f"Applied first format to Drawing Text in {node_info['source_file']}")
300
 
@@ -329,13 +315,6 @@ def apply_and_save_changes(modified_nodes_data: List[Dict[str, Any]], global_dat
329
  if drawing_relative_path in updated_files:
330
  drawing_file_path = os.path.join(drawings_folder, drawing_filename)
331
  try:
332
- # Đảm bảo namespaces được đăng ký đúng cách TRƯỚC KHI GHI
333
- # register_namespaces(drawing_file_path) # Có thể không cần nếu đã làm ở extract
334
- # Hoặc đăng ký cứng các namespace cần thiết:
335
- # ET.register_namespace('xdr', NS_DRAWING['xdr'])
336
- # ET.register_namespace('a', NS_A['a'])
337
- # (Đã chuyển lên đầu hàm apply_and_save_changes)
338
-
339
  drawing_tree.write(drawing_file_path, encoding='utf-8', xml_declaration=True)
340
  except Exception as e: print(f"Lỗi lưu {drawing_file_path}: {e}"); success = False
341
 
@@ -344,6 +323,89 @@ def apply_and_save_changes(modified_nodes_data: List[Dict[str, Any]], global_dat
344
  elif not updated_files: print("Không có file XML nào cần cập nhật.") ; return True # Vẫn coi là success nếu không có gì thay đổi
345
  return success
346
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347
  def zip_folder_to_excel_file(folder_path, file_name):
348
  try:
349
  # Nén thư mục thành file .xlsx trong RAM
@@ -421,19 +483,7 @@ def _translate_batch_helper(segments_to_translate, original_indices_1based, sour
421
 
422
 
423
  def translate_xlsx(file_id, file_name, source_lang='en', target_lang='vi', batch_size_segments=50, max_words_per_segment=100, delay_between_requests=1):
424
- """
425
- Dịch file XLSX, chia thành batch động, dịch riêng các segment quá dài.
426
-
427
- Args:
428
- input_filepath (str): Đường dẫn đến file XLSX đầu vào.
429
- output_filepath (str): Đường dẫn để lưu file XLSX đã dịch.
430
- source_lang (str): Mã ngôn ngữ nguồn.
431
- target_lang (str): Mã ngôn ngữ đích.
432
- batch_size_segments (int): Số lượng đoạn text tối đa MONG MUỐN trong mỗi lần gọi API.
433
- max_words_per_segment (int): Giới hạn từ tối đa cho một segment để được dịch theo batch.
434
- Các segment dài hơn sẽ được dịch riêng lẻ.
435
- delay_between_requests (int): Thời gian chờ (giây) giữa các lần gọi API dịch.
436
- """
437
  client = MongoClient("mongodb+srv://admin:[email protected]/?retryWrites=true&w=majority&appName=Cluster0")
438
  db = client['excel']
439
  fs = gridfs.GridFS(db, collection='root_file')
@@ -442,6 +492,8 @@ def translate_xlsx(file_id, file_name, source_lang='en', target_lang='vi', batch
442
  excel_file = BytesIO(ppt_file.read())
443
 
444
  xml_folder = unzip_office_file(excel_file)
 
 
445
 
446
  modifiable_nodes, global_data = extract_text_from_sheet(xml_folder)
447
 
 
10
  from io import BytesIO
11
  import shutil
12
  import io
13
+ import re
14
+ from typing import Dict
15
 
16
 
17
  NS_MAIN = {'main': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'}
 
98
  'source_file': os.path.join("xl", "sharedStrings.xml"),
99
  'sheet_name': None
100
  })
101
+ elif t_elements:
 
 
 
 
 
 
 
 
 
102
  direct_t = si_element.find('./main:t', NS_MAIN)
103
  if direct_t is not None:
104
  modifiable_nodes.append({
 
277
  # Tạo thẻ text mới <a:t>
278
  new_t = ET.Element(f"{{{NS_A['a']}}}t")
279
  new_t.text = modified_text
 
 
 
280
 
281
  new_r.append(new_t) # Thêm <a:t> vào <a:r>
282
  p_element.append(new_r) # Thêm <a:r> vào <a:p>
283
 
 
 
 
 
284
  updated_files.add(node_info['source_file'])
285
  # print(f"Applied first format to Drawing Text in {node_info['source_file']}")
286
 
 
315
  if drawing_relative_path in updated_files:
316
  drawing_file_path = os.path.join(drawings_folder, drawing_filename)
317
  try:
 
 
 
 
 
 
 
318
  drawing_tree.write(drawing_file_path, encoding='utf-8', xml_declaration=True)
319
  except Exception as e: print(f"Lỗi lưu {drawing_file_path}: {e}"); success = False
320
 
 
323
  elif not updated_files: print("Không có file XML nào cần cập nhật.") ; return True # Vẫn coi là success nếu không có gì thay đổi
324
  return success
325
 
326
+ def translate_sheet_names_via_regex(
327
+ workbook_xml_path: str,
328
+ source_lang: str = 'chinese',
329
+ target_lang: str = 'vietnamese'
330
+ ):
331
+
332
+ original_to_translated_map: Dict[str, str] = {}
333
+ modified_content: str = ""
334
+ file_changed_flag: bool = False # Sử dụng tên biến rõ ràng hơn
335
+
336
+ try:
337
+ with open(workbook_xml_path, 'r', encoding='utf-8-sig') as f:
338
+ content = f.read()
339
+
340
+ current_content = content
341
+
342
+ def replace_name_callback(match_obj):
343
+ nonlocal file_changed_flag # Để sửa đổi biến bên ngoài
344
+ nonlocal original_to_translated_map
345
+
346
+ attr_prefix = match_obj.group(1) # Ví dụ: '<sheet other_attr="foo" name='
347
+ opening_quote = match_obj.group(2) # Ví dụ: '"'
348
+ original_name_xml_encoded = match_obj.group(3)
349
+ attr_suffix = match_obj.group(5) # Ví dụ: ' sheetId="12" r:id="rId1"/>'
350
+
351
+ original_name = original_name_xml_encoded # Tạm thời bỏ qua unescape/escape cho đơn giản ví dụ
352
+
353
+ if not original_name.strip():
354
+ return match_obj.group(0) # Trả về chuỗi gốc nếu tên rỗng
355
+
356
+ translated_name = original_name # Mặc định giữ nguyên
357
+ if original_name in original_to_translated_map and original_to_translated_map[original_name] != original_name:
358
+ translated_name = original_to_translated_map[original_name]
359
+ # Nếu đã dịch và có thay đổi, không cần gọi API dịch nữa
360
+ if translated_name != original_name: # Cần kiểm tra lại vì map có thể lưu tên gốc nếu dịch lỗi
361
+ print(f"Regex: Sử dụng bản dịch đã có cho '{original_name}' -> '{translated_name}'")
362
+ file_changed_flag = True # Đảm bảo cờ được set nếu sử dụng bản dịch đã có mà khác gốc
363
+ else:
364
+ try:
365
+ translated_name_raw = translate_single_text(original_name, source_lang, target_lang)
366
+
367
+ if translated_name_raw and translated_name_raw.strip() and translated_name_raw != original_name:
368
+ translated_name = translated_name_raw[:31]
369
+ original_to_translated_map[original_name] = translated_name
370
+ file_changed_flag = True
371
+ print(f"Regex: Đã dịch sheet: '{original_name}' -> '{translated_name}'")
372
+ else:
373
+ original_to_translated_map[original_name] = original_name # Lưu tên gốc nếu dịch lỗi/không đổi
374
+ # translated_name vẫn là original_name
375
+ if translated_name_raw and translated_name_raw.strip() and translated_name_raw == original_name:
376
+ print(f"Bản dịch cho '{original_name}' giống hệt bản gốc, không thay đổi.")
377
+ elif not (translated_name_raw and translated_name_raw.strip()):
378
+ print(f"Bản dịch cho '{original_name}' trống hoặc không hợp lệ, giữ nguyên.")
379
+
380
+ except Exception as e_translate:
381
+ print(f"Lỗi khi gọi hàm dịch cho '{original_name}': {e_translate}")
382
+ original_to_translated_map[original_name] = original_name
383
+
384
+ translated_name_xml_encoded = translated_name # Tạm thời bỏ qua escape
385
+
386
+ return f"{attr_prefix}{opening_quote}{translated_name_xml_encoded}{opening_quote}{attr_suffix}"
387
+
388
+ sheet_name_pattern = re.compile(
389
+ r'(<sheet[^>]*?\sname=)(["\'])((?:(?!\2).)*?)(\2)([^>]*?>)'
390
+ )
391
+ modified_content = sheet_name_pattern.sub(replace_name_callback, current_content)
392
+
393
+ if file_changed_flag:
394
+ with open(workbook_xml_path, 'w', encoding='utf-8') as f:
395
+ f.write(modified_content)
396
+ print(f"Regex: Đã cập nhật thành công file: {workbook_xml_path}")
397
+ return original_to_translated_map, True
398
+ else:
399
+ print(f"Regex: Không có tên sheet nào được thay đổi trong file: {workbook_xml_path}")
400
+
401
+ except FileNotFoundError:
402
+ print(f"Lỗi: Không tìm thấy file tại '{workbook_xml_path}'")
403
+ except Exception as e:
404
+ print(f"Đã xảy ra lỗi không mong muốn khi xử lý file '{workbook_xml_path}' bằng regex: {e}")
405
+ import traceback
406
+ traceback.print_exc()
407
+
408
+
409
  def zip_folder_to_excel_file(folder_path, file_name):
410
  try:
411
  # Nén thư mục thành file .xlsx trong RAM
 
483
 
484
 
485
  def translate_xlsx(file_id, file_name, source_lang='en', target_lang='vi', batch_size_segments=50, max_words_per_segment=100, delay_between_requests=1):
486
+
 
 
 
 
 
 
 
 
 
 
 
 
487
  client = MongoClient("mongodb+srv://admin:[email protected]/?retryWrites=true&w=majority&appName=Cluster0")
488
  db = client['excel']
489
  fs = gridfs.GridFS(db, collection='root_file')
 
492
  excel_file = BytesIO(ppt_file.read())
493
 
494
  xml_folder = unzip_office_file(excel_file)
495
+ path_to_workbook_xml = os.path.join(xml_folder, "xl", "workbook.xml")
496
+ translate_sheet_names_via_regex(path_to_workbook_xml, source_lang, target_lang)
497
 
498
  modifiable_nodes, global_data = extract_text_from_sheet(xml_folder)
499
 
test.ipynb CHANGED
@@ -30,7 +30,7 @@
30
  },
31
  {
32
  "cell_type": "code",
33
- "execution_count": 3,
34
  "metadata": {},
35
  "outputs": [],
36
  "source": [
@@ -125,11 +125,11 @@
125
  },
126
  {
127
  "cell_type": "code",
128
- "execution_count": 2,
129
  "metadata": {},
130
  "outputs": [],
131
  "source": [
132
- "def download_input_from_mongodb(file_id, save_name, db_name=\"ppt\", collection_name=\"root_file\"):\n",
133
  " os.makedirs(\"D:\\Show_me_everything\\Machine Translation\\input\", exist_ok=True)\n",
134
  "\n",
135
  " full_file_path = os.path.join(\"D:\\Show_me_everything\\Machine Translation\\input\", save_name)\n",
@@ -160,7 +160,7 @@
160
  "metadata": {},
161
  "outputs": [],
162
  "source": [
163
- "def download_output_from_mongodb(file_id, save_name, db_name=\"ppt\", collection_name=\"root_file\"):\n",
164
  " os.makedirs(\"D:\\Show_me_everything\\Machine Translation\\output\", exist_ok=True)\n",
165
  "\n",
166
  " full_file_path = os.path.join(\"D:\\Show_me_everything\\Machine Translation\\output\", save_name)\n",
@@ -187,36 +187,36 @@
187
  },
188
  {
189
  "cell_type": "code",
190
- "execution_count": 4,
191
  "metadata": {},
192
  "outputs": [
193
  {
194
  "name": "stdout",
195
  "output_type": "stream",
196
  "text": [
197
- "✅ File đã được tải về: D:\\Show_me_everything\\Machine Translation\\input\\syllabus_big_data_analytics.docx\n"
198
  ]
199
  }
200
  ],
201
  "source": [
202
- "download_input_from_mongodb(file_id=\"67f725830f818c0a963a9421\", save_name=\"syllabus_big_data_analytics.docx\", db_name=\"word\", collection_name=\"root_file\")"
203
  ]
204
  },
205
  {
206
  "cell_type": "code",
207
- "execution_count": 5,
208
  "metadata": {},
209
  "outputs": [
210
  {
211
  "name": "stdout",
212
  "output_type": "stream",
213
  "text": [
214
- "✅ File đã được tải về: D:\\Show_me_everything\\Machine Translation\\output\\syllabus_big_data_analytics.docx\n"
215
  ]
216
  }
217
  ],
218
  "source": [
219
- "download_output_from_mongodb(file_id=\"67f725a10f818c0a963a9425\", save_name=\"syllabus_big_data_analytics.docx\", db_name=\"word\", collection_name=\"final_file\")"
220
  ]
221
  },
222
  {
@@ -228,17 +228,17 @@
228
  },
229
  {
230
  "cell_type": "code",
231
- "execution_count": 4,
232
  "metadata": {},
233
  "outputs": [
234
  {
235
  "name": "stdout",
236
  "output_type": "stream",
237
  "text": [
238
- "✅ Đã xóa 4 file trong collection 'root_file'\n",
239
  "✅ Đã xóa 0 file trong collection 'final_pptx'\n",
240
- "✅ Đã xóa 1 file trong collection 'original_xml'\n",
241
- "✅ Đã xóa 1 file trong collection 'final_xml'\n"
242
  ]
243
  }
244
  ],
@@ -250,21 +250,21 @@
250
  },
251
  {
252
  "cell_type": "code",
253
- "execution_count": 6,
254
  "metadata": {},
255
  "outputs": [
256
  {
257
  "name": "stdout",
258
  "output_type": "stream",
259
  "text": [
260
- "✅ Đã xóa 3 file trong collection 'root_file'\n",
261
- "✅ Đã xóa 2 file trong collection 'final_file'\n"
262
  ]
263
  }
264
  ],
265
  "source": [
266
  "for i in ['root_file', 'final_file']:\n",
267
- " delete_all_files_in_collection(i, db_name=\"word\")"
268
  ]
269
  },
270
  {
@@ -324,6 +324,404 @@
324
  "source": [
325
  "delete_pptx_from_mongodb(file_id='67d383681d4db191e51b0bd8')"
326
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327
  }
328
  ],
329
  "metadata": {
 
30
  },
31
  {
32
  "cell_type": "code",
33
+ "execution_count": 12,
34
  "metadata": {},
35
  "outputs": [],
36
  "source": [
 
125
  },
126
  {
127
  "cell_type": "code",
128
+ "execution_count": 4,
129
  "metadata": {},
130
  "outputs": [],
131
  "source": [
132
+ "def download_input_from_mongodb(file_id, save_name, db_name=\"excel\", collection_name=\"root_file\"):\n",
133
  " os.makedirs(\"D:\\Show_me_everything\\Machine Translation\\input\", exist_ok=True)\n",
134
  "\n",
135
  " full_file_path = os.path.join(\"D:\\Show_me_everything\\Machine Translation\\input\", save_name)\n",
 
160
  "metadata": {},
161
  "outputs": [],
162
  "source": [
163
+ "def download_output_from_mongodb(file_id, save_name, db_name=\"excel\", collection_name=\"root_file\"):\n",
164
  " os.makedirs(\"D:\\Show_me_everything\\Machine Translation\\output\", exist_ok=True)\n",
165
  "\n",
166
  " full_file_path = os.path.join(\"D:\\Show_me_everything\\Machine Translation\\output\", save_name)\n",
 
187
  },
188
  {
189
  "cell_type": "code",
190
+ "execution_count": 18,
191
  "metadata": {},
192
  "outputs": [
193
  {
194
  "name": "stdout",
195
  "output_type": "stream",
196
  "text": [
197
+ "✅ File đã được tải về: D:\\Show_me_everything\\Machine Translation\\input\\sample(1).xlsx\n"
198
  ]
199
  }
200
  ],
201
  "source": [
202
+ "download_input_from_mongodb(file_id=\"6836967a57ffb0e2132ae372\", save_name=\"sample(1).xlsx\", db_name=\"excel\", collection_name=\"root_file\")"
203
  ]
204
  },
205
  {
206
  "cell_type": "code",
207
+ "execution_count": 9,
208
  "metadata": {},
209
  "outputs": [
210
  {
211
  "name": "stdout",
212
  "output_type": "stream",
213
  "text": [
214
+ "✅ File đã được tải về: D:\\Show_me_everything\\Machine Translation\\output\\file_rangdong_26052025.xlsx\n"
215
  ]
216
  }
217
  ],
218
  "source": [
219
+ "download_output_from_mongodb(file_id=\"6833d51e97f852b6a2084ea8\", save_name=\"file_rangdong_26052025.xlsx\", db_name=\"excel\", collection_name=\"final_file\")"
220
  ]
221
  },
222
  {
 
228
  },
229
  {
230
  "cell_type": "code",
231
+ "execution_count": 13,
232
  "metadata": {},
233
  "outputs": [
234
  {
235
  "name": "stdout",
236
  "output_type": "stream",
237
  "text": [
238
+ "✅ Đã xóa 14 file trong collection 'root_file'\n",
239
  "✅ Đã xóa 0 file trong collection 'final_pptx'\n",
240
+ "✅ Đã xóa 0 file trong collection 'original_xml'\n",
241
+ "✅ Đã xóa 0 file trong collection 'final_xml'\n"
242
  ]
243
  }
244
  ],
 
250
  },
251
  {
252
  "cell_type": "code",
253
+ "execution_count": 40,
254
  "metadata": {},
255
  "outputs": [
256
  {
257
  "name": "stdout",
258
  "output_type": "stream",
259
  "text": [
260
+ "✅ Đã xóa 16 file trong collection 'root_file'\n",
261
+ "✅ Đã xóa 14 file trong collection 'final_file'\n"
262
  ]
263
  }
264
  ],
265
  "source": [
266
  "for i in ['root_file', 'final_file']:\n",
267
+ " delete_all_files_in_collection(i, db_name=\"excel\")"
268
  ]
269
  },
270
  {
 
324
  "source": [
325
  "delete_pptx_from_mongodb(file_id='67d383681d4db191e51b0bd8')"
326
  ]
327
+ },
328
+ {
329
+ "cell_type": "code",
330
+ "execution_count": 7,
331
+ "metadata": {},
332
+ "outputs": [],
333
+ "source": [
334
+ "from io import BytesIO\n",
335
+ "from openpyxl import load_workbook\n",
336
+ "from utils.utils import translate_single_text\n",
337
+ "from pymongo import MongoClient\n",
338
+ "from bson import ObjectId\n",
339
+ "import gridfs\n",
340
+ "from utils.utils import unzip_office_file\n",
341
+ "\n",
342
+ "\n",
343
+ "# 1. Kết nối tới MongoDB\n",
344
+ "client = MongoClient(\"mongodb+srv://admin:[email protected]/?retryWrites=true&w=majority&appName=Cluster0\")\n",
345
+ "db = client['excel']\n",
346
+ "fs = gridfs.GridFS(db, collection='root_file')\n",
347
+ "\n",
348
+ "# 2. Tải file Excel từ MongoDB\n",
349
+ "file_obj = fs.get(ObjectId('6836c69e59530f034bd86576'))\n",
350
+ "excel_file = BytesIO(file_obj.read())\n",
351
+ "\n",
352
+ "xml_folder = unzip_office_file(r\"D:\\Show_me_everything\\Machine Translation\\input\\sample.xlsx\")"
353
+ ]
354
+ },
355
+ {
356
+ "cell_type": "code",
357
+ "execution_count": 31,
358
+ "metadata": {},
359
+ "outputs": [],
360
+ "source": [
361
+ "import xml.etree.ElementTree as ET\n",
362
+ "from typing import List\n",
363
+ "from utils.utils import translate_single_text\n",
364
+ "\n",
365
+ "def _register_all_namespaces(xml_file_path):\n",
366
+ " try:\n",
367
+ " namespaces = dict([\n",
368
+ " node for _, node in ET.iterparse(xml_file_path, events=['start-ns'])\n",
369
+ " ])\n",
370
+ " for prefix, uri in namespaces.items():\n",
371
+ " ET.register_namespace(prefix, uri)\n",
372
+ " if '' in namespaces and namespaces[''] == \"http://schemas.openxmlformats.org/spreadsheetml/2006/main\":\n",
373
+ " ET.register_namespace('', \"http://schemas.openxmlformats.org/spreadsheetml/2006/main\")\n",
374
+ " if 'r' not in namespaces:\n",
375
+ " ET.register_namespace('r', \"http://schemas.openxmlformats.org/officeDocument/2006/relationships\")\n",
376
+ " if 'mc' not in namespaces:\n",
377
+ " ET.register_namespace('mc', \"http://schemas.openxmlformats.org/markup-compatibility/2006\")\n",
378
+ " if 'x15' not in namespaces:\n",
379
+ " ET.register_namespace('x15', \"http://schemas.microsoft.com/office/spreadsheetml/2010/11/main\")\n",
380
+ " return namespaces # Trả về để có thể dùng trong findall nếu cần\n",
381
+ " except Exception as e:\n",
382
+ " print(f\"Lỗi khi đăng ký namespace từ {xml_file_path}: {e}\")\n",
383
+ " return {}\n",
384
+ "\n",
385
+ "def get_all_sheet_names_from_file(workbook_xml_path, source_lang='chinese', target_lang='vietnamese') -> List[str]:\n",
386
+ " sheet_names = {}\n",
387
+ " try:\n",
388
+ " # Phân tích trực tiếp từ file\n",
389
+ " tree = ET.parse(workbook_xml_path)\n",
390
+ " root = tree.getroot()\n",
391
+ "\n",
392
+ " namespaces = {'main': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'}\n",
393
+ "\n",
394
+ " for sheet_element in root.findall('.//main:sheet', namespaces):\n",
395
+ " name = sheet_element.get('name')\n",
396
+ " if name:\n",
397
+ " sheet_names[name] = name\n",
398
+ " for k in sheet_names:\n",
399
+ " sheet_names[k] = translate_single_text(k, source_lang, target_lang)\n",
400
+ "\n",
401
+ " except FileNotFoundError:\n",
402
+ " print(f\"Lỗi: Không tìm thấy file tại '{workbook_xml_path}'\")\n",
403
+ " except ET.ParseError as e:\n",
404
+ " print(f\"Lỗi khi phân tích XML từ file '{workbook_xml_path}': {e}\")\n",
405
+ " except Exception as e:\n",
406
+ " print(f\"Đã xảy ra lỗi không mong muốn khi xử lý file '{workbook_xml_path}': {e}\")\n",
407
+ "\n",
408
+ " return sheet_names\n",
409
+ "\n",
410
+ "def translate_sheet_names_in_file(workbook_xml_path, source_lang = 'chinese', target_lang = 'vietnamese'):\n",
411
+ "\n",
412
+ " original_to_translated_map: Dict[str, str] = {}\n",
413
+ " file_modified = False\n",
414
+ "\n",
415
+ " try:\n",
416
+ " parsed_namespaces = _register_all_namespaces(workbook_xml_path)\n",
417
+ " tree = ET.parse(workbook_xml_path)\n",
418
+ " root = tree.getroot()\n",
419
+ " search_namespaces = {'main': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'}\n",
420
+ " if '' in parsed_namespaces and parsed_namespaces[''] == search_namespaces['main']:\n",
421
+ " pass # search_namespaces đã ổn\n",
422
+ "\n",
423
+ "\n",
424
+ " # Bước 3: Lặp qua các sheet, dịch và cập nhật tên\n",
425
+ " for sheet_element in root.findall('.//main:sheet', search_namespaces):\n",
426
+ " original_name = sheet_element.get('name')\n",
427
+ " if original_name and original_name.strip(): # Chỉ dịch nếu tên có nội dung\n",
428
+ " try:\n",
429
+ " # Gọi hàm dịch của bạn\n",
430
+ " translated_name = translate_single_text(original_name, source_lang, target_lang)\n",
431
+ " os.wait(5)\n",
432
+ "\n",
433
+ " if translated_name and translated_name.strip() and translated_name != original_name:\n",
434
+ " # Cập nhật thuộc tính 'name' của element trong cây XML\n",
435
+ " sheet_element.set('name', translated_name)\n",
436
+ " original_to_translated_map[original_name] = translated_name\n",
437
+ " file_modified = True\n",
438
+ " print(f\"Đã dịch sheet: '{original_name}' -> '{translated_name}'\")\n",
439
+ " else:\n",
440
+ " # Nếu dịch thất bại hoặc không thay đổi, giữ lại tên gốc trong map\n",
441
+ " original_to_translated_map[original_name] = original_name\n",
442
+ " if translated_name and translated_name != original_name :\n",
443
+ " print(f\"Bản dịch cho '{original_name}' trống hoặc không hợp lệ, không cập nhật XML.\")\n",
444
+ " elif not translated_name:\n",
445
+ " print(f\"Dịch thất bại cho '{original_name}', không cập nhật XML.\")\n",
446
+ "\n",
447
+ "\n",
448
+ " except Exception as e_translate:\n",
449
+ " print(f\"Lỗi khi dịch tên sheet '{original_name}': {e_translate}\")\n",
450
+ " original_to_translated_map[original_name] = original_name # Ghi nhận lỗi, giữ tên gốc\n",
451
+ "\n",
452
+ " # Bước 4: Nếu có thay đổi, ghi lại toàn bộ cây XML vào file\n",
453
+ " if file_modified:\n",
454
+ " # encoding='utf-8' và xml_declaration=True là quan trọng\n",
455
+ " tree.write(workbook_xml_path, encoding='utf-8', xml_declaration=True)\n",
456
+ " print(f\"Đã cập nhật thành công file: {workbook_xml_path}\")\n",
457
+ " else:\n",
458
+ " print(f\"Không có tên sheet nào được thay đổi trong file: {workbook_xml_path}\")\n",
459
+ "\n",
460
+ " except FileNotFoundError:\n",
461
+ " print(f\"Lỗi: Không tìm thấy file tại '{workbook_xml_path}'\")\n",
462
+ " except ET.ParseError as e:\n",
463
+ " print(f\"Lỗi khi phân tích XML từ file '{workbook_xml_path}': {e}\")\n",
464
+ " except Exception as e:\n",
465
+ " print(f\"Đã xảy ra lỗi không mong muốn khi xử lý file '{workbook_xml_path}': {e}\")\n",
466
+ " import traceback\n",
467
+ " traceback.print_exc()\n",
468
+ "\n",
469
+ "\n",
470
+ " return original_to_translated_map"
471
+ ]
472
+ },
473
+ {
474
+ "cell_type": "code",
475
+ "execution_count": 24,
476
+ "metadata": {},
477
+ "outputs": [
478
+ {
479
+ "name": "stdout",
480
+ "output_type": "stream",
481
+ "text": [
482
+ "Đã dịch sheet: '流程图' -> 'Lưu đồ'\n",
483
+ "Đã dịch sheet: '分割光源板' -> 'Tấm dẫn sáng phân đoạn'\n",
484
+ "Đã dịch sheet: '支架外观检验' -> 'Kiểm tra ngoại quan giá đỡ'\n",
485
+ "Đã dịch sheet: '固定驱动' -> 'Ổ đĩa cố định'\n",
486
+ "Đã dịch sheet: '固定接地线' -> 'Dây nối đất cố định'\n",
487
+ "Đã dịch sheet: '整理电源线' -> 'Sắp xếp dây nguồn'\n",
488
+ "Đã dịch sheet: '固定光源板' -> 'Bảng nguồn sáng cố định'\n",
489
+ "Đã dịch sheet: '连接光源板' -> 'Kết nối bảng nguồn sáng'\n",
490
+ "Đã dịch sheet: '焊接光源板' -> 'Hàn bảng nguồn sáng'\n",
491
+ "Đã dịch sheet: '连接驱动' -> 'Kết nối trình điều khiển'\n",
492
+ "Đã dịch sheet: '安装端头 ' -> 'Lắp đặt đầu cuối'\n",
493
+ "Đã dịch sheet: '试 亮' -> 'Thử Sáng'\n",
494
+ "Đã dịch sheet: '绝缘、接地 ' -> 'Cách điện, tiếp đất'\n",
495
+ "Đã dịch sheet: '安装透光罩 (2)' -> 'Lắp chụp đèn (2)'\n",
496
+ "Đã dịch sheet: '老练' -> 'Lão luyện'\n",
497
+ "Đã dịch sheet: '二次试亮' -> 'Thử sáng lần hai'\n",
498
+ "Đã cập nhật thành công file: D:\\Show_me_everything\\MT deploy\\MT_deploy\\unzipped_office\\xl\\workbook.xml\n"
499
+ ]
500
+ },
501
+ {
502
+ "data": {
503
+ "text/plain": [
504
+ "{'流程图': 'Lưu đồ',\n",
505
+ " '分割光源板': 'Tấm dẫn sáng phân đoạn',\n",
506
+ " '支架外观检验': 'Kiểm tra ngoại quan giá đỡ',\n",
507
+ " '固定驱动': 'Ổ đĩa cố định',\n",
508
+ " '固定接地线': 'Dây nối đất cố định',\n",
509
+ " '整理电源线': 'Sắp xếp dây nguồn',\n",
510
+ " '固定光源板': 'Bảng nguồn sáng cố định',\n",
511
+ " '连接光源板': 'Kết nối bảng nguồn sáng',\n",
512
+ " '焊接光源板': 'Hàn bảng nguồn sáng',\n",
513
+ " '连接驱动': 'Kết nối trình điều khiển',\n",
514
+ " '安装端头 ': 'Lắp đặt đầu cuối',\n",
515
+ " '试 亮': 'Thử Sáng',\n",
516
+ " '绝缘、接地 ': 'Cách điện, tiếp đất',\n",
517
+ " '安装透光罩 (2)': 'Lắp chụp đèn (2)',\n",
518
+ " '老练': 'Lão luyện',\n",
519
+ " '二次试亮': 'Thử sáng lần hai'}"
520
+ ]
521
+ },
522
+ "execution_count": 24,
523
+ "metadata": {},
524
+ "output_type": "execute_result"
525
+ }
526
+ ],
527
+ "source": [
528
+ "translate_sheet_names_in_file(r'D:\\Show_me_everything\\MT deploy\\MT_deploy\\unzipped_office\\xl\\workbook.xml')"
529
+ ]
530
+ },
531
+ {
532
+ "cell_type": "code",
533
+ "execution_count": null,
534
+ "metadata": {},
535
+ "outputs": [
536
+ {
537
+ "data": {
538
+ "text/plain": [
539
+ "{'流程图': 'Lưu đồ',\n",
540
+ " '分割光源板': 'Tấm dẫn sáng phân đoạn',\n",
541
+ " '支架外观检验': 'Kiểm tra ngoại quan của giá đỡ',\n",
542
+ " '固定驱动': 'Ổ đĩa cố định',\n",
543
+ " '固定接地线': 'Dây nối đất cố định',\n",
544
+ " '整理电源线': 'Sắp xếp dây nguồn',\n",
545
+ " '固定光源板': 'Tấm nền nguồn sáng cố định',\n",
546
+ " '连接光源板': 'Kết nối bảng nguồn sáng',\n",
547
+ " '焊接光源板': 'Hàn bảng nguồn sáng',\n",
548
+ " '连接驱动': 'Kết nối trình điều khiển',\n",
549
+ " '安装端头 ': 'Lắp đặt đầu cuối',\n",
550
+ " '试 亮': 'Thử Lượng',\n",
551
+ " '绝缘、接地 ': 'Cách điện, tiếp đất',\n",
552
+ " '安装透光罩 (2)': 'Lắp đặt chụp đèn trong suốt (2)',\n",
553
+ " '老练': 'Lão luyện',\n",
554
+ " '二次试亮': 'Thử sáng lần hai'}"
555
+ ]
556
+ },
557
+ "execution_count": 39,
558
+ "metadata": {},
559
+ "output_type": "execute_result"
560
+ }
561
+ ],
562
+ "source": [
563
+ "sheets_name_d"
564
+ ]
565
+ },
566
+ {
567
+ "cell_type": "code",
568
+ "execution_count": null,
569
+ "metadata": {},
570
+ "outputs": [],
571
+ "source": [
572
+ "import re\n",
573
+ "from typing import Dict, Callable\n",
574
+ "# Giả sử utils.utils.translate_single_text đã được import và hoạt động đúng\n",
575
+ "# từ file trước: from utils.utils import translate_single_text\n",
576
+ "\n",
577
+ "def translate_sheet_names_via_regex(\n",
578
+ " workbook_xml_path: str,\n",
579
+ " source_lang: str = 'chinese',\n",
580
+ " target_lang: str = 'vietnamese'\n",
581
+ ") -> (Dict[str, str], bool):\n",
582
+ "\n",
583
+ " original_to_translated_map: Dict[str, str] = {}\n",
584
+ " modified_content: str = \"\"\n",
585
+ " file_changed_flag: bool = False # Sử dụng tên biến rõ ràng hơn\n",
586
+ "\n",
587
+ " try:\n",
588
+ " with open(workbook_xml_path, 'r', encoding='utf-8') as f:\n",
589
+ " content = f.read()\n",
590
+ "\n",
591
+ " current_content = content\n",
592
+ "\n",
593
+ " def replace_name_callback(match_obj):\n",
594
+ " nonlocal file_changed_flag # Để sửa đổi biến bên ngoài\n",
595
+ " nonlocal original_to_translated_map\n",
596
+ "\n",
597
+ " attr_prefix = match_obj.group(1) # Ví dụ: '<sheet other_attr=\"foo\" name='\n",
598
+ " opening_quote = match_obj.group(2) # Ví dụ: '\"'\n",
599
+ " original_name_xml_encoded = match_obj.group(3)\n",
600
+ " attr_suffix = match_obj.group(5) # Ví dụ: ' sheetId=\"12\" r:id=\"rId1\"/>'\n",
601
+ "\n",
602
+ " original_name = original_name_xml_encoded # Tạm thời bỏ qua unescape/escape cho đơn giản ví dụ\n",
603
+ "\n",
604
+ " if not original_name.strip():\n",
605
+ " return match_obj.group(0) # Trả về chuỗi gốc nếu tên rỗng\n",
606
+ "\n",
607
+ " translated_name = original_name # Mặc định giữ nguyên\n",
608
+ " if original_name in original_to_translated_map and original_to_translated_map[original_name] != original_name:\n",
609
+ " translated_name = original_to_translated_map[original_name]\n",
610
+ " # Nếu đã dịch và có thay đổi, không cần gọi API dịch nữa\n",
611
+ " if translated_name != original_name: # Cần kiểm tra lại vì map có thể lưu tên gốc nếu dịch lỗi\n",
612
+ " print(f\"Regex: Sử dụng bản dịch đã có cho '{original_name}' -> '{translated_name}'\")\n",
613
+ " file_changed_flag = True # Đảm bảo cờ được set nếu sử dụng bản dịch đã có mà khác gốc\n",
614
+ " else:\n",
615
+ " try:\n",
616
+ " translated_name_raw = translate_single_text(original_name, source_lang, target_lang)\n",
617
+ "\n",
618
+ " if translated_name_raw and translated_name_raw.strip() and translated_name_raw != original_name:\n",
619
+ " translated_name = translated_name_raw[:31]\n",
620
+ " original_to_translated_map[original_name] = translated_name\n",
621
+ " file_changed_flag = True\n",
622
+ " print(f\"Regex: Đã dịch sheet: '{original_name}' -> '{translated_name}'\")\n",
623
+ " else:\n",
624
+ " original_to_translated_map[original_name] = original_name # Lưu tên gốc nếu dịch lỗi/không đổi\n",
625
+ " # translated_name vẫn là original_name\n",
626
+ " if translated_name_raw and translated_name_raw.strip() and translated_name_raw == original_name:\n",
627
+ " print(f\"Bản dịch cho '{original_name}' giống hệt bản gốc, không thay đổi.\")\n",
628
+ " elif not (translated_name_raw and translated_name_raw.strip()):\n",
629
+ " print(f\"Bản dịch cho '{original_name}' trống hoặc không hợp lệ, giữ nguyên.\")\n",
630
+ "\n",
631
+ " except Exception as e_translate:\n",
632
+ " print(f\"Lỗi khi gọi hàm dịch cho '{original_name}': {e_translate}\")\n",
633
+ " original_to_translated_map[original_name] = original_name\n",
634
+ "\n",
635
+ " translated_name_xml_encoded = translated_name # Tạm thời bỏ qua escape\n",
636
+ "\n",
637
+ " return f\"{attr_prefix}{opening_quote}{translated_name_xml_encoded}{opening_quote}{attr_suffix}\"\n",
638
+ "\n",
639
+ " sheet_name_pattern = re.compile(\n",
640
+ " r'(<sheet[^>]*?\\sname=)([\"\\'])((?:(?!\\2).)*?)(\\2)([^>]*?>)'\n",
641
+ " )\n",
642
+ " modified_content = sheet_name_pattern.sub(replace_name_callback, current_content)\n",
643
+ "\n",
644
+ " if file_changed_flag:\n",
645
+ " with open(workbook_xml_path, 'w', encoding='utf-8') as f:\n",
646
+ " f.write(modified_content)\n",
647
+ " print(f\"Regex: Đã cập nhật thành công file: {workbook_xml_path}\")\n",
648
+ " return original_to_translated_map, True\n",
649
+ " else:\n",
650
+ " print(f\"Regex: Không có tên sheet nào được thay đổi trong file: {workbook_xml_path}\")\n",
651
+ "\n",
652
+ " except FileNotFoundError:\n",
653
+ " print(f\"Lỗi: Không tìm thấy file tại '{workbook_xml_path}'\")\n",
654
+ " except Exception as e:\n",
655
+ " print(f\"Đã xảy ra lỗi không mong muốn khi xử lý file '{workbook_xml_path}' bằng regex: {e}\")\n",
656
+ " import traceback\n",
657
+ " traceback.print_exc()\n"
658
+ ]
659
+ },
660
+ {
661
+ "cell_type": "code",
662
+ "execution_count": 38,
663
+ "metadata": {},
664
+ "outputs": [
665
+ {
666
+ "name": "stdout",
667
+ "output_type": "stream",
668
+ "text": [
669
+ "Regex: Đã dịch sheet: '流程图' -> 'Lưu đồ'\n",
670
+ "Regex: Đã dịch sheet: '分割光源板' -> 'Tấm dẫn sáng phân đoạn'\n",
671
+ "Regex: Đã dịch sheet: '支架外观检验' -> 'Kiểm tra ngoại quan giá đỡ'\n",
672
+ "Regex: Đã dịch sheet: '固定驱动' -> 'Ổ đĩa cố định'\n",
673
+ "Regex: Đã dịch sheet: '固定接地线' -> 'Dây tiếp đất cố định'\n",
674
+ "Regex: Đã dịch sheet: '整理电源线' -> 'Sắp xếp dây nguồn'\n",
675
+ "Regex: Đã dịch sheet: '固定光源板' -> 'Bảng nguồn sáng cố định'\n",
676
+ "Regex: Đã dịch sheet: '连接光源板' -> 'Kết nối bảng đèn nền'\n",
677
+ "Regex: Đã dịch sheet: '焊接光源板' -> 'Bảng nguồn sáng hàn'\n",
678
+ "Regex: Đã dịch sheet: '连接驱动' -> 'Kết nối trình điều khiển'\n",
679
+ "Regex: Đã dịch sheet: '安装端头 ' -> 'Lắp đặt đầu cuối'\n",
680
+ "Regex: Đã dịch sheet: '试 亮' -> 'Thử Sáng'\n",
681
+ "Regex: Đã dịch sheet: '绝缘、接地 ' -> 'Cách điện, tiếp đất'\n",
682
+ "Regex: Đã dịch sheet: '安装透光罩 (2)' -> 'Lắp chụp đèn (2)'\n",
683
+ "Regex: Đã dịch sheet: '老练' -> 'Lão luyện'\n",
684
+ "Regex: Đã dịch sheet: '二次试亮' -> 'Thử sáng lần hai'\n",
685
+ "Regex: Đã cập nhật thành công file: D:\\Show_me_everything\\MT deploy\\MT_deploy\\unzipped_office\\xl\\workbook.xml\n"
686
+ ]
687
+ }
688
+ ],
689
+ "source": [
690
+ "translation_map_regex, success_regex = translate_sheet_names_via_regex(r'D:\\Show_me_everything\\MT deploy\\MT_deploy\\unzipped_office\\xl\\workbook.xml')"
691
+ ]
692
+ },
693
+ {
694
+ "cell_type": "code",
695
+ "execution_count": null,
696
+ "metadata": {},
697
+ "outputs": [],
698
+ "source": [
699
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n",
700
+ "<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"x15 xr xr6 xr10 xr2\" xmlns:x15=\"http://schemas.microsoft.com/office/spreadsheetml/2010/11/main\" xmlns:xr=\"http://schemas.microsoft.com/office/spreadsheetml/2014/revision\" xmlns:xr6=\"http://schemas.microsoft.com/office/spreadsheetml/2016/revision6\" xmlns:xr10=\"http://schemas.microsoft.com/office/spreadsheetml/2016/revision10\" xmlns:xr2=\"http://schemas.microsoft.com/office/spreadsheetml/2015/revision2\"><fileVersion appName=\"xl\" lastEdited=\"7\" lowestEdited=\"5\" rupBuild=\"28324\"/><workbookPr codeName=\"ThisWorkbook\"/><mc:AlternateContent xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"><mc:Choice Requires=\"x15\"><x15ac:absPath url=\"G:\\Machine_Learning\\machine_translation\\temp\\\" xmlns:x15ac=\"http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac\"/></mc:Choice></mc:AlternateContent><xr:revisionPtr revIDLastSave=\"0\" documentId=\"13_ncr:1_{0BB03666-2754-4098-B7E4-88837ADAC82E}\" xr6:coauthVersionLast=\"47\" xr6:coauthVersionMax=\"47\" xr10:uidLastSave=\"{00000000-0000-0000-0000-000000000000}\"/><bookViews><workbookView xWindow=\"-110\" yWindow=\"-110\" windowWidth=\"25820\" windowHeight=\"15500\" firstSheet=\"15\" activeTab=\"15\" xr2:uid=\"{00000000-000D-0000-FFFF-FFFF00000000}\"/></bookViews><sheets><sheet name=\"流程图\" sheetId=\"12\" r:id=\"rId1\"/><sheet name=\"分割光源板\" sheetId=\"2\" r:id=\"rId2\"/><sheet name=\"支架外观检验\" sheetId=\"24\" r:id=\"rId3\"/><sheet name=\"固定驱动\" sheetId=\"21\" r:id=\"rId4\"/><sheet name=\"固定接地线\" sheetId=\"4\" r:id=\"rId5\"/><sheet name=\"整理电源线\" sheetId=\"22\" r:id=\"rId6\"/><sheet name=\"固定光源板\" sheetId=\"3\" r:id=\"rId7\"/><sheet name=\"连接光源板\" sheetId=\"5\" r:id=\"rId8\"/><sheet name=\"焊接光源板\" sheetId=\"29\" r:id=\"rId9\"/><sheet name=\"连接驱动\" sheetId=\"30\" r:id=\"rId10\"/><sheet name=\"安装端头 \" sheetId=\"31\" r:id=\"rId11\"/><sheet name=\"试 亮\" sheetId=\"20\" r:id=\"rId12\"/><sheet name=\"绝缘、接地 \" sheetId=\"9\" r:id=\"rId13\"/><sheet name=\"安装透光罩 (2)\" sheetId=\"32\" state=\"hidden\" r:id=\"rId14\"/><sheet name=\"老练\" sheetId=\"10\" r:id=\"rId15\"/><sheet name=\"二次试亮\" sheetId=\"6\" r:id=\"rId16\"/></sheets><definedNames><definedName name=\"_xlnm.Print_Area\" localSheetId=\"15\">二次试亮!$A$1:$L$39</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"1\">分割光源板!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"6\">固定光源板!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"4\">固定接地线!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"3\">固定驱动!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"10\">'安装端头 '!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"5\">整理电源线!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"0\">流程图!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"8\">焊接光源板!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"12\">'绝缘、接地 '!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"14\">老练!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"11\">'试 亮'!$A$1:$L$39</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"7\">连接光源板!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"9\">连接驱动!$A$1:$L$40</definedName></definedNames><calcPr calcId=\"191029\"/><extLst><ext uri=\"{B58B0392-4F1F-4190-BB64-5DF3571DCE5F}\" xmlns:xcalcf=\"http://schemas.microsoft.com/office/spreadsheetml/2018/calcfeatures\"><xcalcf:calcFeatures><xcalcf:feature name=\"microsoft.com:RD\"/><xcalcf:feature name=\"microsoft.com:Single\"/><xcalcf:feature name=\"microsoft.com:FV\"/><xcalcf:feature name=\"microsoft.com:CNMTM\"/><xcalcf:feature name=\"microsoft.com:LET_WF\"/><xcalcf:feature name=\"microsoft.com:LAMBDA_WF\"/><xcalcf:feature name=\"microsoft.com:ARRAYTEXT_WF\"/></xcalcf:calcFeatures></ext></extLst></workbook>\n",
701
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n",
702
+ "<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"x15 xr xr6 xr10 xr2\" xmlns:x15=\"http://schemas.microsoft.com/office/spreadsheetml/2010/11/main\" xmlns:xr=\"http://schemas.microsoft.com/office/spreadsheetml/2014/revision\" xmlns:xr6=\"http://schemas.microsoft.com/office/spreadsheetml/2016/revision6\" xmlns:xr10=\"http://schemas.microsoft.com/office/spreadsheetml/2016/revision10\" xmlns:xr2=\"http://schemas.microsoft.com/office/spreadsheetml/2015/revision2\"><fileVersion appName=\"xl\" lastEdited=\"7\" lowestEdited=\"5\" rupBuild=\"28324\"/><workbookPr codeName=\"ThisWorkbook\"/><mc:AlternateContent xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"><mc:Choice Requires=\"x15\"><x15ac:absPath url=\"G:\\Machine_Learning\\machine_translation\\temp\\\" xmlns:x15ac=\"http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac\"/></mc:Choice></mc:AlternateContent><xr:revisionPtr revIDLastSave=\"0\" documentId=\"13_ncr:1_{0BB03666-2754-4098-B7E4-88837ADAC82E}\" xr6:coauthVersionLast=\"47\" xr6:coauthVersionMax=\"47\" xr10:uidLastSave=\"{00000000-0000-0000-0000-000000000000}\"/><bookViews><workbookView xWindow=\"-110\" yWindow=\"-110\" windowWidth=\"25820\" windowHeight=\"15500\" firstSheet=\"15\" activeTab=\"15\" xr2:uid=\"{00000000-000D-0000-FFFF-FFFF00000000}\"/></bookViews><sheets><sheet name=\"Lưu đồ\" sheetId=\"12\" r:id=\"rId1\"/><sheet name=\"Tấm dẫn sáng phân đoạn\" sheetId=\"2\" r:id=\"rId2\"/><sheet name=\"Kiểm tra ngoại quan giá đỡ\" sheetId=\"24\" r:id=\"rId3\"/><sheet name=\"Ổ đĩa cố định\" sheetId=\"21\" r:id=\"rId4\"/><sheet name=\"Dây tiếp đất cố định\" sheetId=\"4\" r:id=\"rId5\"/><sheet name=\"S���p xếp dây nguồn\" sheetId=\"22\" r:id=\"rId6\"/><sheet name=\"Tấm nền nguồn sáng cố định\" sheetId=\"3\" r:id=\"rId7\"/><sheet name=\"Kết nối bảng đèn.\" sheetId=\"5\" r:id=\"rId8\"/><sheet name=\"Hàn bảng nguồn sáng\" sheetId=\"29\" r:id=\"rId9\"/><sheet name=\"Kết nối trình điều khiển\" sheetId=\"30\" r:id=\"rId10\"/><sheet name=\"Lắp đặt đầu cuối\" sheetId=\"31\" r:id=\"rId11\"/><sheet name=\"Thử Sáng\" sheetId=\"20\" r:id=\"rId12\"/><sheet name=\"Cách điện, tiếp đất\" sheetId=\"9\" r:id=\"rId13\"/><sheet name=\"Lắp chụp đèn (2)\" sheetId=\"32\" state=\"hidden\" r:id=\"rId14\"/><sheet name=\"Lão luyện\" sheetId=\"10\" r:id=\"rId15\"/><sheet name=\"Thử sáng lần hai\" sheetId=\"6\" r:id=\"rId16\"/></sheets><definedNames><definedName name=\"_xlnm.Print_Area\" localSheetId=\"15\">二次试亮!$A$1:$L$39</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"1\">分割光源板!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"6\">固定光源板!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"4\">固定接地线!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"3\">固定驱动!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"10\">'安装端头 '!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"5\">整理电源线!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"0\">流程图!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"8\">焊接光源板!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"12\">'绝缘、接地 '!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"14\">老练!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"11\">'试 亮'!$A$1:$L$39</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"7\">连接光源板!$A$1:$L$40</definedName><definedName name=\"_xlnm.Print_Area\" localSheetId=\"9\">连接驱动!$A$1:$L$40</definedName></definedNames><calcPr calcId=\"191029\"/><extLst><ext uri=\"{B58B0392-4F1F-4190-BB64-5DF3571DCE5F}\" xmlns:xcalcf=\"http://schemas.microsoft.com/office/spreadsheetml/2018/calcfeatures\"><xcalcf:calcFeatures><xcalcf:feature name=\"microsoft.com:RD\"/><xcalcf:feature name=\"microsoft.com:Single\"/><xcalcf:feature name=\"microsoft.com:FV\"/><xcalcf:feature name=\"microsoft.com:CNMTM\"/><xcalcf:feature name=\"microsoft.com:LET_WF\"/><xcalcf:feature name=\"microsoft.com:LAMBDA_WF\"/><xcalcf:feature name=\"microsoft.com:ARRAYTEXT_WF\"/></xcalcf:calcFeatures></ext></extLst></workbook>\n"
703
+ ]
704
+ },
705
+ {
706
+ "cell_type": "code",
707
+ "execution_count": 39,
708
+ "metadata": {},
709
+ "outputs": [
710
+ {
711
+ "data": {
712
+ "text/plain": [
713
+ "26"
714
+ ]
715
+ },
716
+ "execution_count": 39,
717
+ "metadata": {},
718
+ "output_type": "execute_result"
719
+ }
720
+ ],
721
+ "source": [
722
+ "str = 'Kiểm tra ngoại quan giá đỡ'\n",
723
+ "len(str)"
724
+ ]
725
  }
726
  ],
727
  "metadata": {
utils/__pycache__/utils.cpython-310.pyc CHANGED
Binary files a/utils/__pycache__/utils.cpython-310.pyc and b/utils/__pycache__/utils.cpython-310.pyc differ
 
utils/utils.py CHANGED
@@ -4,11 +4,12 @@ import google.generativeai as genai
4
  import tempfile
5
  import io
6
  import json
 
 
7
 
8
  genai.configure(api_key="AIzaSyBH8O5IfqYrJ5wtWnmUC21IfMjzJCrTm3I")
9
 
10
 
11
-
12
  def unzip_office_file(pptx_file: io.BytesIO):
13
  """
14
  Giải nén nội dung từ file PPTX (dạng BytesIO) vào thư mục tạm thời.
@@ -24,36 +25,57 @@ def unzip_office_file(pptx_file: io.BytesIO):
24
  return output_dir
25
 
26
 
27
- def translate_single_text(text, source_lang='English', target_lang="Vietnamese"):
28
- if not text:
29
- return "" # Bỏ qua nếu chuỗi rỗng
30
-
31
- try:
32
- model = genai.GenerativeModel('gemini-2.0-flash') # Sử dụng model từ code gốc nếu hoạt động tốt
33
-
34
- # --- Prompt đơn giản chỉ yêu cầu dịch thuật ---
35
- system_prompt_simple = f"""You are a translation engine.
36
- Translate the following text accurately from {source_lang} to {target_lang}.
37
- Provide *only* the translated text as a single string.
38
- Do NOT add any extra formatting, delimiters like '#', introductory phrases, or explanations."""
39
 
40
- user_prompt = f"Source language: {source_lang}. Target language: {target_lang}. Text to translate: {text}"
41
- full_prompt = system_prompt_simple.strip() + "\n\n" + user_prompt.strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- response = model.generate_content(
44
- contents=full_prompt,
45
- generation_config={
46
- 'temperature': 0.7, # Nhiệt độ phù hợp cho dịch thuật (có thể điều chỉnh)
47
- 'top_p': 1,
48
- 'top_k': 1,
49
- }
50
- )
51
- translated_text = response.text.strip()
52
- return translated_text
53
 
54
- except Exception as e:
55
- print(f"Lỗi trong quá trình dịch (translate_single_text): {e}")
56
- return "" # Trả về chuỗi rỗng nếu có lỗi
57
 
58
 
59
  def preprocess_text(text_list):
 
4
  import tempfile
5
  import io
6
  import json
7
+ import time
8
+ from google.api_core.exceptions import ResourceExhausted
9
 
10
  genai.configure(api_key="AIzaSyBH8O5IfqYrJ5wtWnmUC21IfMjzJCrTm3I")
11
 
12
 
 
13
  def unzip_office_file(pptx_file: io.BytesIO):
14
  """
15
  Giải nén nội dung từ file PPTX (dạng BytesIO) vào thư mục tạm thời.
 
25
  return output_dir
26
 
27
 
28
+ def translate_single_text(text: str, source_lang: str = 'English', target_lang: str = "Vietnamese",
29
+ max_retries: int = 5, retry_delay_seconds: int = 3) -> str:
30
+ if not text or not text.strip():
31
+ return "" # Bỏ qua nếu chuỗi rỗng hoặc chỉ chứa khoảng trắng
 
 
 
 
 
 
 
 
32
 
33
+ retries = 0
34
+ while retries <= max_retries:
35
+ try:
36
+ model = genai.GenerativeModel('gemini-2.0-flash') # Hoặc 'gemini-1.0-pro', 'gemini-1.5-flash' tùy bạn chọn
37
+
38
+ system_prompt_simple = f"""You are a translation engine.
39
+ Translate the following text accurately from {source_lang} to {target_lang}.
40
+ Provide *only* the translated text as a single string.
41
+ Do NOT add any extra formatting, delimiters like '#', introductory phrases, or explanations."""
42
+
43
+ user_prompt = f"Source language: {source_lang}. Target language: {target_lang}. Text to translate: {text}"
44
+ full_prompt = system_prompt_simple.strip() + "\n\n" + user_prompt.strip()
45
+
46
+ response = model.generate_content(
47
+ contents=full_prompt,
48
+ generation_config={
49
+ 'temperature': 0.2,
50
+ 'top_p': 1.0,
51
+ 'top_k': 1,
52
+ # 'max_output_tokens': 2048,
53
+ }
54
+ )
55
+ # Kiểm tra xem response có text không và có ứng viên không
56
+ if response.candidates and response.candidates[0].content.parts:
57
+ translated_text = "".join(part.text for part in response.candidates[0].content.parts if hasattr(part, 'text')).strip()
58
+ return translated_text
59
+ else:
60
+ print(f"Không nhận được nội dung hợp lệ từ API cho văn bản: '{text[:50]}...'")
61
+ # Không thử lại với lỗi này, trả về rỗng
62
+ return ""
63
+
64
+
65
+ except ResourceExhausted as e: # Bắt lỗi 429 (Too Many Requests / Quota Exceeded)
66
+ print(f"Lỗi quota (429) khi dịch '{text[:50]}...': {e}. Đang thử lại sau {retry_delay_seconds} giây. Lần thử {retries + 1}/{max_retries +1 }.")
67
+ if retries < max_retries:
68
+ time.sleep(retry_delay_seconds)
69
+ retries += 1
70
+ else:
71
+ print(f"Đã vượt quá số lần thử lại tối đa ({max_retries + 1}) cho '{text[:50]}...'. Bỏ qua.")
72
+ return "" # Trả về rỗng sau khi đã thử lại tối đa số lần
73
 
74
+ except Exception as e:
75
+ print(f"Lỗi không mong muốn trong quá trình dịch (translate_single_text) cho '{text[:50]}...': {e}")
76
+ return ""
 
 
 
 
 
 
 
77
 
78
+ return "" # Trường hợp không bao giờ nên xảy ra nếu logic vòng lặp đúng
 
 
79
 
80
 
81
  def preprocess_text(text_list):