Spaces:
Running
Running
add translate sheet_name
Browse files- excel/__pycache__/excel_translate.cpython-310.pyc +0 -0
- excel/__pycache__/xlsx.cpython-310.pyc +0 -0
- excel/xlsx.py +89 -37
- test.ipynb +416 -18
- utils/__pycache__/utils.cpython-310.pyc +0 -0
- utils/utils.py +50 -28
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:
|
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":
|
34 |
"metadata": {},
|
35 |
"outputs": [],
|
36 |
"source": [
|
@@ -125,11 +125,11 @@
|
|
125 |
},
|
126 |
{
|
127 |
"cell_type": "code",
|
128 |
-
"execution_count":
|
129 |
"metadata": {},
|
130 |
"outputs": [],
|
131 |
"source": [
|
132 |
-
"def download_input_from_mongodb(file_id, save_name, db_name=\"
|
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=\"
|
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":
|
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\\
|
198 |
]
|
199 |
}
|
200 |
],
|
201 |
"source": [
|
202 |
-
"download_input_from_mongodb(file_id=\"
|
203 |
]
|
204 |
},
|
205 |
{
|
206 |
"cell_type": "code",
|
207 |
-
"execution_count":
|
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\\
|
215 |
]
|
216 |
}
|
217 |
],
|
218 |
"source": [
|
219 |
-
"download_output_from_mongodb(file_id=\"
|
220 |
]
|
221 |
},
|
222 |
{
|
@@ -228,17 +228,17 @@
|
|
228 |
},
|
229 |
{
|
230 |
"cell_type": "code",
|
231 |
-
"execution_count":
|
232 |
"metadata": {},
|
233 |
"outputs": [
|
234 |
{
|
235 |
"name": "stdout",
|
236 |
"output_type": "stream",
|
237 |
"text": [
|
238 |
-
"✅ Đã xóa
|
239 |
"✅ Đã xóa 0 file trong collection 'final_pptx'\n",
|
240 |
-
"✅ Đã xóa
|
241 |
-
"✅ Đã xóa
|
242 |
]
|
243 |
}
|
244 |
],
|
@@ -250,21 +250,21 @@
|
|
250 |
},
|
251 |
{
|
252 |
"cell_type": "code",
|
253 |
-
"execution_count":
|
254 |
"metadata": {},
|
255 |
"outputs": [
|
256 |
{
|
257 |
"name": "stdout",
|
258 |
"output_type": "stream",
|
259 |
"text": [
|
260 |
-
"✅ Đã xóa
|
261 |
-
"✅ Đã xóa
|
262 |
]
|
263 |
}
|
264 |
],
|
265 |
"source": [
|
266 |
"for i in ['root_file', 'final_file']:\n",
|
267 |
-
" delete_all_files_in_collection(i, db_name=\"
|
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 |
-
|
29 |
-
|
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 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
|
43 |
-
|
44 |
-
|
45 |
-
|
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 |
-
|
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):
|