Spaces:
Running
Running
add no mongodb
Browse files- db/__pycache__/mongodb.cpython-310.pyc +0 -0
- excel/__pycache__/excel_translate.cpython-310.pyc +0 -0
- excel/__pycache__/xlsx.cpython-310.pyc +0 -0
- excel/excel_translate.py +16 -139
- excel/xlsx.py +14 -25
- pages/upload.py +17 -21
- powerpoint/__pycache__/pptx.cpython-310.pyc +0 -0
- powerpoint/pptx.py +34 -68
- test.ipynb +80 -20
- word/__pycache__/word_helper.cpython-310.pyc +0 -0
- word/word_helper.py +6 -18
db/__pycache__/mongodb.cpython-310.pyc
CHANGED
Binary files a/db/__pycache__/mongodb.cpython-310.pyc and b/db/__pycache__/mongodb.cpython-310.pyc differ
|
|
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/excel_translate.py
CHANGED
@@ -1,171 +1,48 @@
|
|
1 |
-
import
|
2 |
-
|
3 |
from translate.translator import translate_text_dict
|
4 |
import math
|
5 |
import chardet
|
6 |
-
import io
|
7 |
-
import pandas as pd
|
8 |
-
import pymongo
|
9 |
-
import gridfs
|
10 |
-
import tempfile
|
11 |
-
import os
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
def translate_xlsx(file_id: str, target_lang: str = ""):
|
16 |
-
# Kết nối MongoDB
|
17 |
-
client = pymongo.MongoClient("mongodb+srv://admin:[email protected]/?retryWrites=true&w=majority&appName=Cluster0")
|
18 |
-
db = client["excel"]
|
19 |
-
fs_input = gridfs.GridFS(db, collection="root_file")
|
20 |
-
fs_output = gridfs.GridFS(db, collection="final_file")
|
21 |
-
|
22 |
-
# Tải file từ MongoDB
|
23 |
-
file_data = fs_input.get(file_id)
|
24 |
-
|
25 |
-
|
26 |
-
# Lưu file tạm thời
|
27 |
-
with tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") as temp_file:
|
28 |
-
temp_file.write(file_data.read())
|
29 |
-
temp_file_path = temp_file.name
|
30 |
-
|
31 |
-
# Đọc file Excel bằng openpyxl
|
32 |
-
wb = openpyxl.load_workbook(temp_file_path)
|
33 |
-
|
34 |
-
|
35 |
-
sheets = wb.worksheets # Chọn tất cả sheets nếu sheet_name không hợp lệ
|
36 |
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
# Tạo dictionary lưu trữ nội dung cần dịch và mapping từ key đến cell
|
42 |
-
text_dict: Dict[str, List[str]] = {}
|
43 |
-
cell_map: Dict[str, any] = {} # lưu mapping key -> cell object
|
44 |
-
|
45 |
-
for row in range(1, max_row + 1):
|
46 |
-
for col in range(1, max_col + 1):
|
47 |
-
cell = ws.cell(row=row, column=col)
|
48 |
-
if isinstance(cell.value, str):
|
49 |
-
key = f"R{row}C{col}" # key theo dạng R{row}C{col}
|
50 |
-
text_dict[key] = [cell.value] # Lưu giá trị dưới dạng danh sách với 1 phần tử
|
51 |
-
cell_map[key] = cell
|
52 |
-
|
53 |
-
# Gọi hàm dịch theo dạng bulk
|
54 |
-
translated_dict = translate_text_dict(text_dict, target_lang=target_lang)
|
55 |
-
|
56 |
-
# Cập nhật lại các cell với nội dung đã dịch
|
57 |
-
for key, cell in cell_map.items():
|
58 |
-
if key in translated_dict:
|
59 |
-
translated_text_list = translated_dict[key]
|
60 |
-
if translated_text_list and len(translated_text_list) > 0:
|
61 |
-
cell.value = translated_text_list[0]
|
62 |
-
|
63 |
-
# Lưu workbook vào file tạm thời
|
64 |
-
with tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") as output_file:
|
65 |
-
wb.save(output_file.name)
|
66 |
-
output_file.seek(0)
|
67 |
-
translated_file_id = fs_output.put(output_file.read(), filename=file_data.filename)
|
68 |
-
|
69 |
-
# Đóng workbook và xóa file tạm
|
70 |
-
wb.close()
|
71 |
-
os.remove(temp_file_path)
|
72 |
-
|
73 |
-
print(f"✅ Dịch thành công! File đã lưu vào MongoDB với file_id: {translated_file_id}")
|
74 |
-
return translated_file_id
|
75 |
-
|
76 |
-
|
77 |
-
def read_csv_with_auto_encoding(csv_path):
|
78 |
-
# Đọc file dưới dạng nhị phân
|
79 |
-
with open(csv_path, "rb") as f:
|
80 |
-
raw_data = f.read()
|
81 |
-
# Dò tìm encoding
|
82 |
-
detect_result = chardet.detect(raw_data)
|
83 |
-
encoding = detect_result["encoding"]
|
84 |
-
confidence = detect_result["confidence"]
|
85 |
-
|
86 |
-
print(f"Chardet dự đoán file '{csv_path}' có encoding = {encoding} (độ tin cậy = {confidence})")
|
87 |
-
|
88 |
-
# Nếu chardet không phát hiện được, ta đặt fallback = 'utf-8'
|
89 |
-
if encoding is None:
|
90 |
-
encoding = "utf-8"
|
91 |
-
|
92 |
decoded_data = raw_data.decode(encoding, errors='replace')
|
93 |
-
|
94 |
-
# Sử dụng io.StringIO để chuyển đổi chuỗi thành đối tượng file-like
|
95 |
csv_data = io.StringIO(decoded_data)
|
96 |
-
|
97 |
-
return df
|
98 |
|
99 |
-
|
100 |
-
|
101 |
-
# Kết nối MongoDB
|
102 |
-
client = pymongo.MongoClient("mongodb+srv://admin:[email protected]/?retryWrites=true&w=majority&appName=Cluster0")
|
103 |
-
db = client["csv"]
|
104 |
-
fs_input = gridfs.GridFS(db, collection="root_file")
|
105 |
-
fs_output = gridfs.GridFS(db, collection="final_file")
|
106 |
-
|
107 |
-
# Tải file từ MongoDB
|
108 |
-
file_data = fs_input.get(file_id).read()
|
109 |
-
|
110 |
-
# Lưu file tạm thời
|
111 |
-
with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as temp_file:
|
112 |
-
temp_file.write(file_data)
|
113 |
-
temp_file_path = temp_file.name
|
114 |
-
|
115 |
-
df = read_csv_with_auto_encoding(temp_file_path)
|
116 |
-
|
117 |
-
# If text_columns is not specified, we assume we want to translate everything that looks like text.
|
118 |
-
# Otherwise, only translate the given columns.
|
119 |
-
|
120 |
text_columns = df.select_dtypes(include=["object"]).columns.tolist()
|
121 |
|
122 |
num_rows = len(df)
|
123 |
num_chunks = math.ceil(num_rows / chunk_size)
|
124 |
-
|
125 |
-
translated_df = df.copy() # copy to store the final translations
|
126 |
|
127 |
for chunk_index in range(num_chunks):
|
128 |
start_idx = chunk_index * chunk_size
|
129 |
end_idx = min((chunk_index + 1) * chunk_size, num_rows)
|
130 |
chunk_df = df.iloc[start_idx:end_idx]
|
131 |
|
132 |
-
# Build a dictionary structure. For example, row-based:
|
133 |
-
# {
|
134 |
-
# "0": {"colA": "some text", "colB": "some text"},
|
135 |
-
# "1": {"colA": "some text", "colB": "some text"},
|
136 |
-
# ...
|
137 |
-
# }
|
138 |
chunk_dict = {}
|
139 |
for i, row in chunk_df.iterrows():
|
140 |
-
row_dict = {}
|
141 |
-
for col in text_columns:
|
142 |
-
row_dict[col] = str(row[col]) if pd.notnull(row[col]) else ""
|
143 |
chunk_dict[str(i)] = row_dict
|
144 |
|
145 |
-
# Now call your LLM translator on this dictionary
|
146 |
translated_chunk = translate_text_dict(
|
147 |
text_dict=chunk_dict,
|
148 |
source_lang=source_lang,
|
149 |
target_lang=target_lang
|
150 |
)
|
151 |
|
152 |
-
|
153 |
for i_str, row_data in translated_chunk.items():
|
154 |
i = int(i_str)
|
155 |
for col, translated_val in row_data.items():
|
156 |
translated_df.at[i, col] = translated_val
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
# Đọc lại file tạm để lưu vào MongoDB
|
163 |
-
with open(translated_file_path, "rb") as f:
|
164 |
-
translated_file_id = fs_output.put(f, filename=f"translated_{file_id}.csv")
|
165 |
-
|
166 |
-
# Xóa file tạm
|
167 |
-
os.remove(temp_file_path)
|
168 |
-
os.remove(translated_file_path)
|
169 |
-
|
170 |
-
print(f"Translation complete! Saved to MongoDB with file_id: {translated_file_id}")
|
171 |
-
return translated_file_id
|
|
|
1 |
+
import io
|
2 |
+
import pandas as pd
|
3 |
from translate.translator import translate_text_dict
|
4 |
import math
|
5 |
import chardet
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
+
def read_csv_with_auto_encoding_from_bytes(csv_bytes) -> pd.DataFrame:
|
8 |
+
raw_data = csv_bytes.read()
|
9 |
+
detect_result = chardet.detect(raw_data)
|
10 |
+
encoding = detect_result["encoding"] or "utf-8"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
decoded_data = raw_data.decode(encoding, errors='replace')
|
|
|
|
|
12 |
csv_data = io.StringIO(decoded_data)
|
13 |
+
return pd.read_csv(csv_data)
|
|
|
14 |
|
15 |
+
def translate_csv(file_bytes, file_name, source_lang: str, target_lang: str = "vi", chunk_size: int = 50) -> bytes:
|
16 |
+
df = read_csv_with_auto_encoding_from_bytes(file_bytes)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
text_columns = df.select_dtypes(include=["object"]).columns.tolist()
|
18 |
|
19 |
num_rows = len(df)
|
20 |
num_chunks = math.ceil(num_rows / chunk_size)
|
21 |
+
translated_df = df.copy()
|
|
|
22 |
|
23 |
for chunk_index in range(num_chunks):
|
24 |
start_idx = chunk_index * chunk_size
|
25 |
end_idx = min((chunk_index + 1) * chunk_size, num_rows)
|
26 |
chunk_df = df.iloc[start_idx:end_idx]
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
chunk_dict = {}
|
29 |
for i, row in chunk_df.iterrows():
|
30 |
+
row_dict = {col: str(row[col]) if pd.notnull(row[col]) else "" for col in text_columns}
|
|
|
|
|
31 |
chunk_dict[str(i)] = row_dict
|
32 |
|
|
|
33 |
translated_chunk = translate_text_dict(
|
34 |
text_dict=chunk_dict,
|
35 |
source_lang=source_lang,
|
36 |
target_lang=target_lang
|
37 |
)
|
38 |
|
39 |
+
|
40 |
for i_str, row_data in translated_chunk.items():
|
41 |
i = int(i_str)
|
42 |
for col, translated_val in row_data.items():
|
43 |
translated_df.at[i, col] = translated_val
|
44 |
|
45 |
+
output_buffer = io.BytesIO()
|
46 |
+
translated_df.to_csv(output_buffer, index=False, encoding='utf-8-sig')
|
47 |
+
output_buffer.seek(0)
|
48 |
+
return output_buffer, file_name
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
excel/xlsx.py
CHANGED
@@ -406,9 +406,12 @@ def translate_sheet_names_via_regex(
|
|
406 |
traceback.print_exc()
|
407 |
|
408 |
|
409 |
-
def
|
|
|
|
|
|
|
|
|
410 |
try:
|
411 |
-
# Nén thư mục thành file .xlsx trong RAM
|
412 |
xlsx_buffer = io.BytesIO()
|
413 |
with zipfile.ZipFile(xlsx_buffer, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
414 |
for root, _, files in os.walk(folder_path):
|
@@ -418,19 +421,11 @@ def zip_folder_to_excel_file(folder_path, file_name):
|
|
418 |
zipf.write(file_path, archive_path)
|
419 |
|
420 |
xlsx_buffer.seek(0)
|
421 |
-
|
422 |
-
client = MongoClient("mongodb+srv://admin:[email protected]/?retryWrites=true&w=majority&appName=Cluster0")
|
423 |
-
db = client['excel']
|
424 |
-
fs = gridfs.GridFS(db, collection='final_file')
|
425 |
-
|
426 |
-
file_id = fs.put(xlsx_buffer.read(), filename=file_name)
|
427 |
-
print(f"✅ Đã lưu file Excel vào MongoDB với ID: {file_id}")
|
428 |
-
return file_id
|
429 |
|
430 |
except Exception as e:
|
431 |
-
print(f"❌ Lỗi khi nén
|
432 |
-
return None
|
433 |
-
|
434 |
|
435 |
def get_text_list_from_nodes(modifiable_nodes: Optional[List[Dict[str, Any]]]) -> List[str]:
|
436 |
if modifiable_nodes is None:
|
@@ -482,16 +477,10 @@ def _translate_batch_helper(segments_to_translate, original_indices_1based, sour
|
|
482 |
return batch_results
|
483 |
|
484 |
|
485 |
-
def translate_xlsx(
|
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')
|
490 |
|
491 |
-
|
492 |
-
|
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 |
|
@@ -600,9 +589,9 @@ def translate_xlsx(file_id, file_name, source_lang='en', target_lang='vi', batch
|
|
600 |
print("LỖI NGHIÊM TRỌNG: Không thể lưu thay đổi vào file XML.")
|
601 |
else:
|
602 |
# Only zip if saving XML was successful
|
603 |
-
|
604 |
-
if
|
605 |
shutil.rmtree(xml_folder) # Mark folder as 'handled' by zipping
|
606 |
else:
|
607 |
print("LỖI NGHIÊM TRỌNG: Không thể tạo file XLSX đã dịch cuối cùng.")
|
608 |
-
return
|
|
|
406 |
traceback.print_exc()
|
407 |
|
408 |
|
409 |
+
def zip_folder_to_excel_bytes(folder_path):
|
410 |
+
"""
|
411 |
+
Nén toàn bộ thư mục thành file Excel (.xlsx) dưới dạng BytesIO (trong RAM).
|
412 |
+
Trả lại buffer BytesIO chứa nội dung file.
|
413 |
+
"""
|
414 |
try:
|
|
|
415 |
xlsx_buffer = io.BytesIO()
|
416 |
with zipfile.ZipFile(xlsx_buffer, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
417 |
for root, _, files in os.walk(folder_path):
|
|
|
421 |
zipf.write(file_path, archive_path)
|
422 |
|
423 |
xlsx_buffer.seek(0)
|
424 |
+
return xlsx_buffer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
|
426 |
except Exception as e:
|
427 |
+
print(f"❌ Lỗi khi nén thư mục thành file Excel: {e}")
|
428 |
+
return None
|
|
|
429 |
|
430 |
def get_text_list_from_nodes(modifiable_nodes: Optional[List[Dict[str, Any]]]) -> List[str]:
|
431 |
if modifiable_nodes is None:
|
|
|
477 |
return batch_results
|
478 |
|
479 |
|
480 |
+
def translate_xlsx(file_io, file_name, source_lang='en', target_lang='vi', batch_size_segments=50, max_words_per_segment=100, delay_between_requests=1):
|
|
|
|
|
|
|
|
|
481 |
|
482 |
+
file_io.seek(0)
|
483 |
+
xml_folder = unzip_office_file(file_io)
|
|
|
|
|
484 |
path_to_workbook_xml = os.path.join(xml_folder, "xl", "workbook.xml")
|
485 |
translate_sheet_names_via_regex(path_to_workbook_xml, source_lang, target_lang)
|
486 |
|
|
|
589 |
print("LỖI NGHIÊM TRỌNG: Không thể lưu thay đổi vào file XML.")
|
590 |
else:
|
591 |
# Only zip if saving XML was successful
|
592 |
+
translated_buffer = zip_folder_to_excel_bytes(xml_folder)
|
593 |
+
if translated_buffer:
|
594 |
shutil.rmtree(xml_folder) # Mark folder as 'handled' by zipping
|
595 |
else:
|
596 |
print("LỖI NGHIÊM TRỌNG: Không thể tạo file XLSX đã dịch cuối cùng.")
|
597 |
+
return translated_buffer, file_name
|
pages/upload.py
CHANGED
@@ -9,10 +9,9 @@ import dotenv
|
|
9 |
import os
|
10 |
|
11 |
dotenv.load_dotenv(".env")
|
12 |
-
|
13 |
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
|
14 |
|
15 |
-
# Cấu hình
|
16 |
st.set_page_config(page_title="Translate Your File", page_icon="🌍", layout="centered")
|
17 |
|
18 |
# CSS custom
|
@@ -55,7 +54,6 @@ st.markdown("""
|
|
55 |
color: black !important;
|
56 |
border-radius: 8px;
|
57 |
}
|
58 |
-
/* Thu hẹp khoảng cách giữa label và selectbox */
|
59 |
.stSelectbox label {
|
60 |
margin-bottom: 0.2rem;
|
61 |
font-weight: bold;
|
@@ -65,11 +63,12 @@ st.markdown("""
|
|
65 |
</style>
|
66 |
""", unsafe_allow_html=True)
|
67 |
|
68 |
-
# Upload file
|
69 |
with st.container():
|
70 |
st.markdown("### 📂 Chọn file để dịch")
|
71 |
uploaded_file = st.file_uploader("Kéo thả hoặc chọn file", type=['pptx', 'xlsx', 'csv', 'docx'])
|
72 |
|
|
|
73 |
with st.container():
|
74 |
col1, col2 = st.columns(2)
|
75 |
|
@@ -81,39 +80,36 @@ with st.container():
|
|
81 |
st.markdown('<p style="font-size:16px; font-weight:bold; margin-bottom:4px;">🌐 Ngôn ngữ muốn dịch sang</p>', unsafe_allow_html=True)
|
82 |
target_lang = st.selectbox(" ", ["chinese", "english", "vietnamese"], key="target_lang")
|
83 |
|
|
|
84 |
def process_file(file, file_type):
|
85 |
progress_bar = st.progress(0)
|
86 |
-
|
87 |
-
|
88 |
-
progress_bar.progress(20)
|
89 |
-
st.write(f"📂 **File ID:** `{file_id}`")
|
90 |
|
91 |
with st.spinner("🔍 Đang xử lý và dịch tài liệu..."):
|
92 |
if file_type == "PPTX":
|
93 |
-
|
94 |
-
progress_bar.progress(60)
|
95 |
elif file_type == "Excel":
|
96 |
-
|
97 |
elif file_type == "CSV":
|
98 |
-
|
99 |
elif file_type == "Word":
|
100 |
-
|
101 |
else:
|
102 |
st.error("❌ Loại file không hỗ trợ!")
|
103 |
return
|
104 |
|
105 |
-
progress_bar.progress(
|
106 |
-
|
107 |
-
with st.spinner("📦 Đang tải file đã dịch..."):
|
108 |
-
file_io, file_name = fetch_file_from_mongodb(file_type.lower(), "final_file", final_id)
|
109 |
-
progress_bar.progress(100)
|
110 |
|
111 |
-
if
|
112 |
st.success("🎉 File đã được dịch thành công!")
|
113 |
-
|
|
|
114 |
else:
|
115 |
-
st.error("❌
|
|
|
116 |
|
|
|
117 |
if uploaded_file and st.button("🚀 Upload và dịch ngay!"):
|
118 |
with st.spinner("🔎 Đang phát hiện loại file..."):
|
119 |
file_type = detect_file_type(uploaded_file)
|
|
|
9 |
import os
|
10 |
|
11 |
dotenv.load_dotenv(".env")
|
|
|
12 |
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
|
13 |
|
14 |
+
# Cấu hình giao diện
|
15 |
st.set_page_config(page_title="Translate Your File", page_icon="🌍", layout="centered")
|
16 |
|
17 |
# CSS custom
|
|
|
54 |
color: black !important;
|
55 |
border-radius: 8px;
|
56 |
}
|
|
|
57 |
.stSelectbox label {
|
58 |
margin-bottom: 0.2rem;
|
59 |
font-weight: bold;
|
|
|
63 |
</style>
|
64 |
""", unsafe_allow_html=True)
|
65 |
|
66 |
+
# Upload file
|
67 |
with st.container():
|
68 |
st.markdown("### 📂 Chọn file để dịch")
|
69 |
uploaded_file = st.file_uploader("Kéo thả hoặc chọn file", type=['pptx', 'xlsx', 'csv', 'docx'])
|
70 |
|
71 |
+
# Lựa chọn ngôn ngữ
|
72 |
with st.container():
|
73 |
col1, col2 = st.columns(2)
|
74 |
|
|
|
80 |
st.markdown('<p style="font-size:16px; font-weight:bold; margin-bottom:4px;">🌐 Ngôn ngữ muốn dịch sang</p>', unsafe_allow_html=True)
|
81 |
target_lang = st.selectbox(" ", ["chinese", "english", "vietnamese"], key="target_lang")
|
82 |
|
83 |
+
# Xử lý file trực tiếp
|
84 |
def process_file(file, file_type):
|
85 |
progress_bar = st.progress(0)
|
86 |
+
file_name = file.name
|
87 |
+
progress_bar.progress(10)
|
|
|
|
|
88 |
|
89 |
with st.spinner("🔍 Đang xử lý và dịch tài liệu..."):
|
90 |
if file_type == "PPTX":
|
91 |
+
output_io, output_name = translate_pptx(file, file_name, source_lang=source_lang, target_lang=target_lang)
|
|
|
92 |
elif file_type == "Excel":
|
93 |
+
output_io, output_name = translate_xlsx(file, file_name, source_lang=source_lang, target_lang=target_lang)
|
94 |
elif file_type == "CSV":
|
95 |
+
output_io, output_name = translate_csv(file, file_name, source_lang=source_lang, target_lang=target_lang)
|
96 |
elif file_type == "Word":
|
97 |
+
output_io, output_name = translate_docx(file, file_name, source_lang=source_lang, target_lang=target_lang)
|
98 |
else:
|
99 |
st.error("❌ Loại file không hỗ trợ!")
|
100 |
return
|
101 |
|
102 |
+
progress_bar.progress(100)
|
|
|
|
|
|
|
|
|
103 |
|
104 |
+
if output_io:
|
105 |
st.success("🎉 File đã được dịch thành công!")
|
106 |
+
print(f"✅ File đã dịch: {output_name}")
|
107 |
+
st.download_button("⬇️ Tải file về", data=output_io.getvalue(), file_name=output_name)
|
108 |
else:
|
109 |
+
st.error("❌ Xảy ra lỗi khi xử lý file.")
|
110 |
+
|
111 |
|
112 |
+
# Nút xử lý
|
113 |
if uploaded_file and st.button("🚀 Upload và dịch ngay!"):
|
114 |
with st.spinner("🔎 Đang phát hiện loại file..."):
|
115 |
file_type = detect_file_type(uploaded_file)
|
powerpoint/__pycache__/pptx.cpython-310.pyc
CHANGED
Binary files a/powerpoint/__pycache__/pptx.cpython-310.pyc and b/powerpoint/__pycache__/pptx.cpython-310.pyc differ
|
|
powerpoint/pptx.py
CHANGED
@@ -3,15 +3,13 @@ import zipfile
|
|
3 |
import shutil
|
4 |
from utils.utils import unzip_office_file, translate_text, preprocess_text, postprocess_text
|
5 |
from powerpoint.xml_handling import *
|
6 |
-
from pymongo import MongoClient
|
7 |
-
import gridfs
|
8 |
from io import BytesIO
|
9 |
|
10 |
-
def
|
11 |
"""
|
12 |
-
Tạo file PPTX từ thư mục chứa nội dung đã giải nén và
|
13 |
"""
|
14 |
-
pptx_buffer = BytesIO()
|
15 |
|
16 |
with zipfile.ZipFile(pptx_buffer, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
17 |
for root_dir, _, files in os.walk(temp_dir):
|
@@ -20,45 +18,32 @@ def create_pptx_and_store_in_mongodb(temp_dir, pptx_filename):
|
|
20 |
arcname = os.path.relpath(file_path, temp_dir)
|
21 |
zipf.write(file_path, arcname)
|
22 |
|
23 |
-
pptx_buffer.seek(0)
|
|
|
24 |
|
25 |
-
|
26 |
-
db = client['pptx']
|
27 |
-
fs = gridfs.GridFS(db, collection='final_file')
|
28 |
-
|
29 |
-
file_id = fs.put(pptx_buffer, filename=pptx_filename)
|
30 |
-
|
31 |
-
print(f"PPTX đã được lưu vào MongoDB với ID: {file_id}")
|
32 |
-
client.close()
|
33 |
-
|
34 |
-
return file_id
|
35 |
-
|
36 |
-
def translate_and_replace_pptx(xml_folder, file_name, source_lang='vn', target_lang='en', slides_per_batch=5):
|
37 |
slides_dir = os.path.join(xml_folder, "ppt/slides")
|
38 |
all_slides = sorted([f for f in os.listdir(slides_dir)
|
39 |
if f.startswith("slide") and f.endswith(".xml")],
|
40 |
key=lambda x: int(x[5:-4]))
|
41 |
|
42 |
-
# Xử lý theo từng batch slide
|
43 |
for i in range(0, len(all_slides), slides_per_batch):
|
44 |
batch_slides = all_slides[i:i + slides_per_batch]
|
45 |
-
slide_text_mapping = {}
|
46 |
-
smartart_text_mapping = {}
|
47 |
|
48 |
for slide_file in batch_slides:
|
49 |
slide_index = int(slide_file[5:-4])
|
50 |
slide_path = os.path.join(slides_dir, slide_file)
|
51 |
-
slide_text_mapping[slide_index] = extract_text_from_slide(slide_path)
|
52 |
|
53 |
-
# Xử lý SmartArt qua file .rels của slide
|
54 |
rels_file = os.path.join(xml_folder, "ppt/slides/_rels", slide_file + ".rels")
|
55 |
base_path = os.path.join(xml_folder, "ppt")
|
56 |
smartart_data_path = get_smartart_data_file(rels_file, base_path)
|
57 |
if smartart_data_path:
|
58 |
-
smartart_text_mapping[slide_index] = extract_text_from_smartart(smartart_data_path)
|
59 |
|
60 |
-
|
61 |
-
# Gộp text để dịch theo batch, giữ lại rPr
|
62 |
combined_slide_text_list = []
|
63 |
for slide_index in sorted(slide_text_mapping.keys()):
|
64 |
combined_slide_text_list.extend(slide_text_mapping[slide_index])
|
@@ -66,48 +51,33 @@ def translate_and_replace_pptx(xml_folder, file_name, source_lang='vn', target_l
|
|
66 |
combined_smartart_text_list = []
|
67 |
for slide_index in sorted(smartart_text_mapping.keys()):
|
68 |
combined_smartart_text_list.extend(smartart_text_mapping[slide_index])
|
69 |
-
|
70 |
-
#
|
71 |
slide_texts_to_translate = [text for text, _ in combined_slide_text_list]
|
72 |
smartart_texts_to_translate = [text for text, _ in combined_smartart_text_list]
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
combined_smartart_text_string = preprocess_text(smartart_texts_to_translate)
|
77 |
-
|
78 |
-
translated_slide_string = translate_text(combined_slide_text_string, source_lang, target_lang)
|
79 |
-
translated_smartart_string = translate_text(combined_smartart_text_string, source_lang, target_lang)
|
80 |
|
81 |
-
# Postprocess để có list các văn bản đã dịch
|
82 |
translated_slide_texts = postprocess_text(translated_slide_string)
|
83 |
translated_smartart_texts = postprocess_text(translated_smartart_string)
|
84 |
|
85 |
-
# **Quan trọng:** Tạo danh sách tuple (translated_text, rPr)
|
86 |
translated_slide_data = []
|
87 |
for i, (original_text, rPr) in enumerate(combined_slide_text_list):
|
88 |
-
if i < len(translated_slide_texts)
|
89 |
-
|
90 |
-
else:
|
91 |
-
translated_slide_data.append(("", rPr)) # Trường hợp không đủ translated text
|
92 |
-
|
93 |
translated_smartart_data = []
|
94 |
for i, (original_text, rPr) in enumerate(combined_smartart_text_list):
|
95 |
-
if i < len(translated_smartart_texts)
|
96 |
-
translated_smartart_data.append((translated_smartart_texts[i], rPr))
|
97 |
-
else:
|
98 |
-
translated_smartart_data.append(("", rPr)) # Trường hợp không đủ translated text
|
99 |
|
100 |
-
# Thay thế văn bản trong slide
|
101 |
-
slide_index = 0
|
102 |
for slide_index in sorted(slide_text_mapping.keys()):
|
103 |
slide_file = f"slide{slide_index}.xml"
|
104 |
slide_path = os.path.join(slides_dir, slide_file)
|
105 |
num_texts = len(slide_text_mapping[slide_index])
|
106 |
replace_data = translated_slide_data[:num_texts]
|
107 |
-
replace_text_in_slide(slide_path, replace_data)
|
108 |
-
translated_slide_data = translated_slide_data[num_texts:]
|
109 |
|
110 |
-
# Thay thế văn bản trong SmartArt
|
111 |
for slide_index in sorted(smartart_text_mapping.keys()):
|
112 |
rels_file = os.path.join(xml_folder, "ppt/slides/_rels", f"slide{slide_index}.xml.rels")
|
113 |
base_path = os.path.join(xml_folder, "ppt")
|
@@ -115,23 +85,19 @@ def translate_and_replace_pptx(xml_folder, file_name, source_lang='vn', target_l
|
|
115 |
if smartart_data_path:
|
116 |
num_texts = len(smartart_text_mapping[slide_index])
|
117 |
replace_data = translated_smartart_data[:num_texts]
|
118 |
-
replace_text_in_smartart(smartart_data_path, replace_data, None)
|
119 |
-
translated_smartart_data = translated_smartart_data[num_texts:]
|
120 |
-
|
121 |
-
file_id = create_pptx_and_store_in_mongodb(xml_folder, file_name)
|
122 |
-
return file_id
|
123 |
-
|
124 |
-
def translate_pptx(pptx_id, file_name, source_lang='vn', target_lang='en', slides_per_batch=5):
|
125 |
-
client = MongoClient("mongodb+srv://admin:[email protected]/?retryWrites=true&w=majority&appName=Cluster0")
|
126 |
-
db = client['pptx']
|
127 |
-
fs = gridfs.GridFS(db, collection='root_file')
|
128 |
-
|
129 |
-
ppt_file = fs.get(pptx_id)
|
130 |
-
prs = BytesIO(ppt_file.read())
|
131 |
-
|
132 |
-
xml_folder = unzip_office_file(prs)
|
133 |
-
file_id = translate_and_replace_pptx(xml_folder, file_name, source_lang, target_lang, slides_per_batch=slides_per_batch)
|
134 |
-
shutil.rmtree(xml_folder)
|
135 |
|
136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
|
|
|
|
3 |
import shutil
|
4 |
from utils.utils import unzip_office_file, translate_text, preprocess_text, postprocess_text
|
5 |
from powerpoint.xml_handling import *
|
|
|
|
|
6 |
from io import BytesIO
|
7 |
|
8 |
+
def create_pptx_from_dir(temp_dir, pptx_filename):
|
9 |
"""
|
10 |
+
Tạo file PPTX từ thư mục chứa nội dung đã giải nén và trả về BytesIO object.
|
11 |
"""
|
12 |
+
pptx_buffer = BytesIO()
|
13 |
|
14 |
with zipfile.ZipFile(pptx_buffer, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
15 |
for root_dir, _, files in os.walk(temp_dir):
|
|
|
18 |
arcname = os.path.relpath(file_path, temp_dir)
|
19 |
zipf.write(file_path, arcname)
|
20 |
|
21 |
+
pptx_buffer.seek(0)
|
22 |
+
return pptx_buffer, pptx_filename
|
23 |
|
24 |
+
def translate_and_replace_pptx(xml_folder, source_lang='vn', target_lang='en', slides_per_batch=5):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
slides_dir = os.path.join(xml_folder, "ppt/slides")
|
26 |
all_slides = sorted([f for f in os.listdir(slides_dir)
|
27 |
if f.startswith("slide") and f.endswith(".xml")],
|
28 |
key=lambda x: int(x[5:-4]))
|
29 |
|
|
|
30 |
for i in range(0, len(all_slides), slides_per_batch):
|
31 |
batch_slides = all_slides[i:i + slides_per_batch]
|
32 |
+
slide_text_mapping = {}
|
33 |
+
smartart_text_mapping = {}
|
34 |
|
35 |
for slide_file in batch_slides:
|
36 |
slide_index = int(slide_file[5:-4])
|
37 |
slide_path = os.path.join(slides_dir, slide_file)
|
38 |
+
slide_text_mapping[slide_index] = extract_text_from_slide(slide_path)
|
39 |
|
|
|
40 |
rels_file = os.path.join(xml_folder, "ppt/slides/_rels", slide_file + ".rels")
|
41 |
base_path = os.path.join(xml_folder, "ppt")
|
42 |
smartart_data_path = get_smartart_data_file(rels_file, base_path)
|
43 |
if smartart_data_path:
|
44 |
+
smartart_text_mapping[slide_index] = extract_text_from_smartart(smartart_data_path)
|
45 |
|
46 |
+
# Gộp text
|
|
|
47 |
combined_slide_text_list = []
|
48 |
for slide_index in sorted(slide_text_mapping.keys()):
|
49 |
combined_slide_text_list.extend(slide_text_mapping[slide_index])
|
|
|
51 |
combined_smartart_text_list = []
|
52 |
for slide_index in sorted(smartart_text_mapping.keys()):
|
53 |
combined_smartart_text_list.extend(smartart_text_mapping[slide_index])
|
54 |
+
|
55 |
+
# Dịch
|
56 |
slide_texts_to_translate = [text for text, _ in combined_slide_text_list]
|
57 |
smartart_texts_to_translate = [text for text, _ in combined_smartart_text_list]
|
58 |
|
59 |
+
translated_slide_string = translate_text(preprocess_text(slide_texts_to_translate), source_lang, target_lang)
|
60 |
+
translated_smartart_string = translate_text(preprocess_text(smartart_texts_to_translate), source_lang, target_lang)
|
|
|
|
|
|
|
|
|
61 |
|
|
|
62 |
translated_slide_texts = postprocess_text(translated_slide_string)
|
63 |
translated_smartart_texts = postprocess_text(translated_smartart_string)
|
64 |
|
|
|
65 |
translated_slide_data = []
|
66 |
for i, (original_text, rPr) in enumerate(combined_slide_text_list):
|
67 |
+
translated_slide_data.append((translated_slide_texts[i] if i < len(translated_slide_texts) else "", rPr))
|
68 |
+
|
|
|
|
|
|
|
69 |
translated_smartart_data = []
|
70 |
for i, (original_text, rPr) in enumerate(combined_smartart_text_list):
|
71 |
+
translated_smartart_data.append((translated_smartart_texts[i] if i < len(translated_smartart_texts) else "", rPr))
|
|
|
|
|
|
|
72 |
|
|
|
|
|
73 |
for slide_index in sorted(slide_text_mapping.keys()):
|
74 |
slide_file = f"slide{slide_index}.xml"
|
75 |
slide_path = os.path.join(slides_dir, slide_file)
|
76 |
num_texts = len(slide_text_mapping[slide_index])
|
77 |
replace_data = translated_slide_data[:num_texts]
|
78 |
+
replace_text_in_slide(slide_path, replace_data)
|
79 |
+
translated_slide_data = translated_slide_data[num_texts:]
|
80 |
|
|
|
81 |
for slide_index in sorted(smartart_text_mapping.keys()):
|
82 |
rels_file = os.path.join(xml_folder, "ppt/slides/_rels", f"slide{slide_index}.xml.rels")
|
83 |
base_path = os.path.join(xml_folder, "ppt")
|
|
|
85 |
if smartart_data_path:
|
86 |
num_texts = len(smartart_text_mapping[slide_index])
|
87 |
replace_data = translated_smartart_data[:num_texts]
|
88 |
+
replace_text_in_smartart(smartart_data_path, replace_data, None)
|
89 |
+
translated_smartart_data = translated_smartart_data[num_texts:]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
+
def translate_pptx(file_obj: BytesIO, file_name: str, source_lang='vn', target_lang='en', slides_per_batch=5):
|
92 |
+
"""
|
93 |
+
Hàm chính: nhận file PPTX (BytesIO), dịch, và trả về BytesIO của file đã dịch.
|
94 |
+
"""
|
95 |
+
file_obj.seek(0)
|
96 |
+
xml_folder = unzip_office_file(file_obj)
|
97 |
+
|
98 |
+
translate_and_replace_pptx(xml_folder, source_lang, target_lang, slides_per_batch)
|
99 |
+
|
100 |
+
translated_io, translated_filename = create_pptx_from_dir(xml_folder, file_name)
|
101 |
+
shutil.rmtree(xml_folder)
|
102 |
|
103 |
+
return translated_io, translated_filename
|
test.ipynb
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
"cells": [
|
3 |
{
|
4 |
"cell_type": "code",
|
5 |
-
"execution_count":
|
6 |
"metadata": {},
|
7 |
"outputs": [],
|
8 |
"source": [
|
@@ -30,7 +30,7 @@
|
|
30 |
},
|
31 |
{
|
32 |
"cell_type": "code",
|
33 |
-
"execution_count":
|
34 |
"metadata": {},
|
35 |
"outputs": [],
|
36 |
"source": [
|
@@ -78,7 +78,7 @@
|
|
78 |
},
|
79 |
{
|
80 |
"cell_type": "code",
|
81 |
-
"execution_count":
|
82 |
"metadata": {},
|
83 |
"outputs": [],
|
84 |
"source": [
|
@@ -119,7 +119,7 @@
|
|
119 |
},
|
120 |
{
|
121 |
"cell_type": "code",
|
122 |
-
"execution_count":
|
123 |
"metadata": {},
|
124 |
"outputs": [],
|
125 |
"source": [
|
@@ -150,7 +150,7 @@
|
|
150 |
},
|
151 |
{
|
152 |
"cell_type": "code",
|
153 |
-
"execution_count":
|
154 |
"metadata": {},
|
155 |
"outputs": [],
|
156 |
"source": [
|
@@ -181,36 +181,36 @@
|
|
181 |
},
|
182 |
{
|
183 |
"cell_type": "code",
|
184 |
-
"execution_count":
|
185 |
"metadata": {},
|
186 |
"outputs": [
|
187 |
{
|
188 |
"name": "stdout",
|
189 |
"output_type": "stream",
|
190 |
"text": [
|
191 |
-
"✅ File đã được tải về: D:\\Show_me_everything\\Machine Translation\\input\\
|
192 |
]
|
193 |
}
|
194 |
],
|
195 |
"source": [
|
196 |
-
"download_input_from_mongodb(file_id=\"
|
197 |
]
|
198 |
},
|
199 |
{
|
200 |
"cell_type": "code",
|
201 |
-
"execution_count":
|
202 |
"metadata": {},
|
203 |
"outputs": [
|
204 |
{
|
205 |
"name": "stdout",
|
206 |
"output_type": "stream",
|
207 |
"text": [
|
208 |
-
"✅ File đã được tải về: D:\\Show_me_everything\\Machine Translation\\output\\
|
209 |
]
|
210 |
}
|
211 |
],
|
212 |
"source": [
|
213 |
-
"download_output_from_mongodb(file_id=\"
|
214 |
]
|
215 |
},
|
216 |
{
|
@@ -244,7 +244,7 @@
|
|
244 |
},
|
245 |
{
|
246 |
"cell_type": "code",
|
247 |
-
"execution_count":
|
248 |
"metadata": {},
|
249 |
"outputs": [
|
250 |
{
|
@@ -252,12 +252,12 @@
|
|
252 |
"output_type": "stream",
|
253 |
"text": [
|
254 |
"✅ Đã xóa 0 file trong collection 'root_file' của db 'word'\n",
|
255 |
-
"✅ Đã xóa
|
256 |
-
"✅ Đã xóa
|
257 |
"✅ Đã xóa 0 file trong collection 'root_file' của db 'csv'\n",
|
258 |
"✅ Đã xóa 0 file trong collection 'final_file' của db 'word'\n",
|
259 |
-
"✅ Đã xóa
|
260 |
-
"✅ Đã xóa
|
261 |
"✅ Đã xóa 0 file trong collection 'final_file' của db 'csv'\n"
|
262 |
]
|
263 |
}
|
@@ -270,16 +270,16 @@
|
|
270 |
},
|
271 |
{
|
272 |
"cell_type": "code",
|
273 |
-
"execution_count":
|
274 |
"metadata": {},
|
275 |
"outputs": [
|
276 |
{
|
277 |
"data": {
|
278 |
"text/plain": [
|
279 |
-
"
|
280 |
]
|
281 |
},
|
282 |
-
"execution_count":
|
283 |
"metadata": {},
|
284 |
"output_type": "execute_result"
|
285 |
}
|
@@ -291,11 +291,71 @@
|
|
291 |
"for db_name in ['word', 'exce', 'pptx', 'csv']:\n",
|
292 |
" db = client[db_name]\n",
|
293 |
" stats = db.command(\"dbstats\")\n",
|
294 |
-
" db_size = stats.get(\"
|
295 |
" total_size += db_size\n",
|
296 |
"total_size / (1024** 2)"
|
297 |
]
|
298 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
{
|
300 |
"cell_type": "code",
|
301 |
"execution_count": 9,
|
|
|
2 |
"cells": [
|
3 |
{
|
4 |
"cell_type": "code",
|
5 |
+
"execution_count": 1,
|
6 |
"metadata": {},
|
7 |
"outputs": [],
|
8 |
"source": [
|
|
|
30 |
},
|
31 |
{
|
32 |
"cell_type": "code",
|
33 |
+
"execution_count": 2,
|
34 |
"metadata": {},
|
35 |
"outputs": [],
|
36 |
"source": [
|
|
|
78 |
},
|
79 |
{
|
80 |
"cell_type": "code",
|
81 |
+
"execution_count": 3,
|
82 |
"metadata": {},
|
83 |
"outputs": [],
|
84 |
"source": [
|
|
|
119 |
},
|
120 |
{
|
121 |
"cell_type": "code",
|
122 |
+
"execution_count": 13,
|
123 |
"metadata": {},
|
124 |
"outputs": [],
|
125 |
"source": [
|
|
|
150 |
},
|
151 |
{
|
152 |
"cell_type": "code",
|
153 |
+
"execution_count": 16,
|
154 |
"metadata": {},
|
155 |
"outputs": [],
|
156 |
"source": [
|
|
|
181 |
},
|
182 |
{
|
183 |
"cell_type": "code",
|
184 |
+
"execution_count": 20,
|
185 |
"metadata": {},
|
186 |
"outputs": [
|
187 |
{
|
188 |
"name": "stdout",
|
189 |
"output_type": "stream",
|
190 |
"text": [
|
191 |
+
"✅ File đã được tải về: D:\\Show_me_everything\\Machine Translation\\input\\szero-point-ieks-essays-1350537845-9781350537842_compress.docx\n"
|
192 |
]
|
193 |
}
|
194 |
],
|
195 |
"source": [
|
196 |
+
"download_input_from_mongodb(file_id=\"6843696876015abc15cc759f\", save_name=\"szero-point-ieks-essays-1350537845-9781350537842_compress.docx\", db_name=\"word\", collection_name=\"root_file\")"
|
197 |
]
|
198 |
},
|
199 |
{
|
200 |
"cell_type": "code",
|
201 |
+
"execution_count": 17,
|
202 |
"metadata": {},
|
203 |
"outputs": [
|
204 |
{
|
205 |
"name": "stdout",
|
206 |
"output_type": "stream",
|
207 |
"text": [
|
208 |
+
"✅ File đã được tải về: D:\\Show_me_everything\\Machine Translation\\output\\samsung_presentation_vietnamese.pptx\n"
|
209 |
]
|
210 |
}
|
211 |
],
|
212 |
"source": [
|
213 |
+
"download_output_from_mongodb(file_id=\"684194c376015abc15cc7428\", save_name=\"samsung_presentation_vietnamese.pptx\", db_name=\"pptx\", collection_name=\"final_file\")"
|
214 |
]
|
215 |
},
|
216 |
{
|
|
|
244 |
},
|
245 |
{
|
246 |
"cell_type": "code",
|
247 |
+
"execution_count": 4,
|
248 |
"metadata": {},
|
249 |
"outputs": [
|
250 |
{
|
|
|
252 |
"output_type": "stream",
|
253 |
"text": [
|
254 |
"✅ Đã xóa 0 file trong collection 'root_file' của db 'word'\n",
|
255 |
+
"✅ Đã xóa 0 file trong collection 'root_file' của db 'excel'\n",
|
256 |
+
"✅ Đã xóa 3 file trong collection 'root_file' của db 'pptx'\n",
|
257 |
"✅ Đã xóa 0 file trong collection 'root_file' của db 'csv'\n",
|
258 |
"✅ Đã xóa 0 file trong collection 'final_file' của db 'word'\n",
|
259 |
+
"✅ Đã xóa 0 file trong collection 'final_file' của db 'excel'\n",
|
260 |
+
"✅ Đã xóa 3 file trong collection 'final_file' của db 'pptx'\n",
|
261 |
"✅ Đã xóa 0 file trong collection 'final_file' của db 'csv'\n"
|
262 |
]
|
263 |
}
|
|
|
270 |
},
|
271 |
{
|
272 |
"cell_type": "code",
|
273 |
+
"execution_count": 9,
|
274 |
"metadata": {},
|
275 |
"outputs": [
|
276 |
{
|
277 |
"data": {
|
278 |
"text/plain": [
|
279 |
+
"0.0"
|
280 |
]
|
281 |
},
|
282 |
+
"execution_count": 9,
|
283 |
"metadata": {},
|
284 |
"output_type": "execute_result"
|
285 |
}
|
|
|
291 |
"for db_name in ['word', 'exce', 'pptx', 'csv']:\n",
|
292 |
" db = client[db_name]\n",
|
293 |
" stats = db.command(\"dbstats\")\n",
|
294 |
+
" db_size = stats.get(\"StorageSize\", 0)\n",
|
295 |
" total_size += db_size\n",
|
296 |
"total_size / (1024** 2)"
|
297 |
]
|
298 |
},
|
299 |
+
{
|
300 |
+
"cell_type": "code",
|
301 |
+
"execution_count": 16,
|
302 |
+
"metadata": {},
|
303 |
+
"outputs": [
|
304 |
+
{
|
305 |
+
"name": "stdout",
|
306 |
+
"output_type": "stream",
|
307 |
+
"text": [
|
308 |
+
"✅ Đã lấy 0 dữ liệu đo lường.\n",
|
309 |
+
"⚠️ Không có dữ liệu đo lường.\n"
|
310 |
+
]
|
311 |
+
}
|
312 |
+
],
|
313 |
+
"source": [
|
314 |
+
"import requests\n",
|
315 |
+
"from requests.auth import HTTPDigestAuth\n",
|
316 |
+
"import datetime\n",
|
317 |
+
"\n",
|
318 |
+
"# ==== Cấu hình ====\n",
|
319 |
+
"PUBLIC_KEY = 'uetgyqkj'\n",
|
320 |
+
"PRIVATE_KEY = '892caec5-8474-4043-862b-f4d4c617daa2'\n",
|
321 |
+
"GROUP_ID = '67db8bf4ed971c2114aad7f1#' # còn gọi là Project ID\n",
|
322 |
+
"CLUSTER_NAME = 'Cluster0'\n",
|
323 |
+
"\n",
|
324 |
+
"# ==== Lấy metric dung lượng dữ liệu ====\n",
|
325 |
+
"url = f\"https://cloud.mongodb.com/api/atlas/v1.0/groups/{GROUP_ID}/clusters/{CLUSTER_NAME}/measurements\"\n",
|
326 |
+
"\n",
|
327 |
+
"params = {\n",
|
328 |
+
" \"granularity\": \"PT1M\", # lấy theo từng phút\n",
|
329 |
+
" \"period\": \"PT1H\", # 5 phút gần nhất\n",
|
330 |
+
" \"m\": \"DATA_SIZE_TOTAL\", # metric cần lấy\n",
|
331 |
+
"}\n",
|
332 |
+
"\n",
|
333 |
+
"response = requests.get(\n",
|
334 |
+
" url,\n",
|
335 |
+
" auth=HTTPDigestAuth(PUBLIC_KEY, PRIVATE_KEY),\n",
|
336 |
+
" params=params\n",
|
337 |
+
")\n",
|
338 |
+
"\n",
|
339 |
+
"# ==== Xử lý kết quả ====\n",
|
340 |
+
"if response.status_code == 200:\n",
|
341 |
+
" data = response.json()\n",
|
342 |
+
" measurements = data.get(\"measurements\", [])\n",
|
343 |
+
" print(f\"✅ Đã lấy {len(measurements)} dữ liệu đo lường.\")\n",
|
344 |
+
" if measurements:\n",
|
345 |
+
" datapoints = measurements[0].get(\"dataPoints\", [])\n",
|
346 |
+
" if datapoints:\n",
|
347 |
+
" latest_point = [d for d in datapoints if d['value'] is not None][-1]\n",
|
348 |
+
" value_bytes = latest_point['value']\n",
|
349 |
+
" ts = latest_point['timestamp']\n",
|
350 |
+
" print(f\"✅ Dung lượng hiện tại: {value_bytes / (1024**2):.2f} MB (timestamp: {ts})\")\n",
|
351 |
+
" else:\n",
|
352 |
+
" print(\"⚠️ Không có datapoint nào.\")\n",
|
353 |
+
" else:\n",
|
354 |
+
" print(\"⚠️ Không có dữ liệu đo lường.\")\n",
|
355 |
+
"else:\n",
|
356 |
+
" print(f\"❌ Lỗi {response.status_code}: {response.text}\")\n"
|
357 |
+
]
|
358 |
+
},
|
359 |
{
|
360 |
"cell_type": "code",
|
361 |
"execution_count": 9,
|
word/__pycache__/word_helper.cpython-310.pyc
CHANGED
Binary files a/word/__pycache__/word_helper.cpython-310.pyc and b/word/__pycache__/word_helper.cpython-310.pyc differ
|
|
word/word_helper.py
CHANGED
@@ -8,8 +8,6 @@ import re
|
|
8 |
import time
|
9 |
import dotenv
|
10 |
import os
|
11 |
-
from pymongo import MongoClient
|
12 |
-
import gridfs
|
13 |
from io import BytesIO
|
14 |
|
15 |
dotenv.load_dotenv(".env")
|
@@ -253,18 +251,13 @@ def merge_elements(doc):
|
|
253 |
current_run = [element]
|
254 |
return doc
|
255 |
|
256 |
-
def translate_docx(
|
257 |
-
"""
|
258 |
-
|
259 |
-
|
260 |
-
fs_input = gridfs.GridFS(db, collection="root_file")
|
261 |
-
fs_output = gridfs.GridFS(db, collection="final_file")
|
262 |
|
263 |
-
|
264 |
-
input_file = fs_input.get(file_id)
|
265 |
-
doc = Document(BytesIO(input_file.read()))
|
266 |
|
267 |
-
# Dịch nội dung
|
268 |
doc = merge_elements(doc)
|
269 |
|
270 |
print('Translating paragraphs.')
|
@@ -286,13 +279,8 @@ def translate_docx(file_id, source_lang="English", target_lang="Vietnamese", fil
|
|
286 |
translate_header_footer(doc, source_lang, target_lang)
|
287 |
print('Done translating headers & footers.')
|
288 |
|
289 |
-
# Lưu tài liệu đã dịch vào MongoDB
|
290 |
output_stream = BytesIO()
|
291 |
doc.save(output_stream)
|
292 |
output_stream.seek(0)
|
293 |
|
294 |
-
|
295 |
-
client.close()
|
296 |
-
|
297 |
-
print(f"Translation complete! Saved to MongoDB with id: {translated_file_id}")
|
298 |
-
return translated_file_id
|
|
|
8 |
import time
|
9 |
import dotenv
|
10 |
import os
|
|
|
|
|
11 |
from io import BytesIO
|
12 |
|
13 |
dotenv.load_dotenv(".env")
|
|
|
251 |
current_run = [element]
|
252 |
return doc
|
253 |
|
254 |
+
def translate_docx(uploaded_file, file_name, source_lang="English", target_lang="Vietnamese"):
|
255 |
+
"""
|
256 |
+
Translates a Word document passed as a Streamlit UploadedFile and returns a BytesIO object.
|
257 |
+
"""
|
|
|
|
|
258 |
|
259 |
+
doc = Document(uploaded_file)
|
|
|
|
|
260 |
|
|
|
261 |
doc = merge_elements(doc)
|
262 |
|
263 |
print('Translating paragraphs.')
|
|
|
279 |
translate_header_footer(doc, source_lang, target_lang)
|
280 |
print('Done translating headers & footers.')
|
281 |
|
|
|
282 |
output_stream = BytesIO()
|
283 |
doc.save(output_stream)
|
284 |
output_stream.seek(0)
|
285 |
|
286 |
+
return output_stream, file_name
|
|
|
|
|
|
|
|