102 lines
4.2 KiB
Python
102 lines
4.2 KiB
Python
from openpyxl import load_workbook, Workbook
|
|
import asyncio
|
|
from googletrans import Translator
|
|
import os
|
|
from tqdm import tqdm
|
|
import copy
|
|
import re
|
|
|
|
async def translate_text(translator, text, target_language):
|
|
try:
|
|
translation = await translator.translate(text, dest=target_language)
|
|
return translation.text
|
|
except Exception as e:
|
|
print(f"Error translating '{text}': {e}")
|
|
return text # Return the original text if translation fails
|
|
|
|
def is_formula(text):
|
|
"""Check if a cell value is a formula"""
|
|
if isinstance(text, str):
|
|
return text.startswith('=')
|
|
return False
|
|
|
|
def copy_cell_format(source_cell, target_cell):
|
|
"""Copy formatting from source cell to target cell without copying the problematic style index"""
|
|
if source_cell.has_style:
|
|
try:
|
|
# Copy individual style attributes instead of the entire style object
|
|
target_cell.font = copy.copy(source_cell.font)
|
|
target_cell.border = copy.copy(source_cell.border)
|
|
target_cell.fill = copy.copy(source_cell.fill)
|
|
target_cell.number_format = source_cell.number_format
|
|
target_cell.protection = copy.copy(source_cell.protection)
|
|
target_cell.alignment = copy.copy(source_cell.alignment)
|
|
# Copy any hyperlink
|
|
if source_cell.hyperlink:
|
|
target_cell.hyperlink = source_cell.hyperlink
|
|
except Exception as e:
|
|
print(f"Error copying format: {e}")
|
|
|
|
async def translate_excel(file_path: str, target_language: str):
|
|
translator = Translator()
|
|
workbook = load_workbook(file_path)
|
|
translated_workbook = Workbook()
|
|
|
|
# Count total cells for progress bar
|
|
total_cells = sum(
|
|
sum(1 for _ in sheet.iter_rows())
|
|
for sheet in workbook.worksheets
|
|
)
|
|
|
|
progress_bar = tqdm(total=total_cells, desc="Translating cells")
|
|
|
|
for sheet_name in workbook.sheetnames:
|
|
original_sheet = workbook[sheet_name]
|
|
translated_sheet = translated_workbook.create_sheet(title=sheet_name)
|
|
|
|
# Copy sheet properties (column dimensions, etc.)
|
|
for key, dimension in original_sheet.column_dimensions.items():
|
|
if hasattr(dimension, 'width') and dimension.width:
|
|
translated_sheet.column_dimensions[key].width = dimension.width
|
|
|
|
for key, dimension in original_sheet.row_dimensions.items():
|
|
if hasattr(dimension, 'height') and dimension.height:
|
|
translated_sheet.row_dimensions[key].height = dimension.height
|
|
|
|
# Copy merged cells
|
|
for merged_cell_range in original_sheet.merged_cells:
|
|
translated_sheet.merge_cells(str(merged_cell_range))
|
|
|
|
for row in original_sheet.iter_rows():
|
|
for cell in row:
|
|
progress_bar.update(1)
|
|
# Create the cell at the same position in the new sheet
|
|
if cell.value:
|
|
if is_formula(cell.value):
|
|
# Don't translate formulas
|
|
translated_cell = translated_sheet.cell(row=cell.row, column=cell.column, value=cell.value)
|
|
else:
|
|
translated_text = await translate_text(translator, str(cell.value), target_language)
|
|
translated_cell = translated_sheet.cell(row=cell.row, column=cell.column, value=translated_text)
|
|
else:
|
|
translated_cell = translated_sheet.cell(row=cell.row, column=cell.column)
|
|
|
|
# Copy formatting
|
|
copy_cell_format(cell, translated_cell)
|
|
|
|
# Remove the default sheet created by Workbook
|
|
if "Sheet" in translated_workbook.sheetnames:
|
|
del translated_workbook["Sheet"]
|
|
|
|
translated_file_path = os.path.splitext(file_path)[0] + f"_translated_{target_language}.xlsx"
|
|
translated_workbook.save(translated_file_path)
|
|
progress_bar.close()
|
|
print(f"Translated file saved as: {translated_file_path}")
|
|
|
|
async def main():
|
|
input_file = r"F:\Dev\excel-translator\data\sample\test_sample.xlsx"
|
|
language = "fr" # French
|
|
await translate_excel(input_file, language)
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main()) |