import pandas as pd import os import PyLibrary.funciones_comunes as fc from translation_config import TranslationConfig import langid from openpyxl import load_workbook from openpyxl.styles import PatternFill, Alignment, Font from collections import defaultdict from openai import OpenAI from openai_api_key import openai_api_key # Definir el logger a nivel de módulo logger = None openai_client = OpenAI(api_key=openai_api_key()) def configurar_detector_idiomas(): codigos_idioma = [code.split("-")[0] for _, code in fc.IDIOMAS.values()] langid.set_languages(codigos_idioma) def detectar_idioma(texto, tipo_PLC): texto_limpio = fc.limpiar_texto(tipo_PLC, texto) if len(texto_limpio.strip()) < 3: # No detectar idioma en textos muy cortos return "unknown" try: idioma, _ = langid.classify(texto_limpio) return idioma except: return "unknown" def obtener_nombre_idioma(codigo_corto): for nombre, codigo in fc.IDIOMAS.values(): if codigo.startswith(codigo_corto): return nombre return "Desconocido" def exportar_para_traduccion(config: TranslationConfig): master_path = config.get_master_path() if not os.path.exists(master_path): print("El archivo maestro no existe.") return configurar_detector_idiomas() df_maestro = fc.read_dataframe_with_cleanup_retries(master_path) df_export = pd.DataFrame() primera_columna = df_maestro.columns[0] df_export[primera_columna] = df_maestro[primera_columna] columna_propuesta = f"{config.codigo_idioma_seleccionado}_Propuesto" df_export[columna_propuesta] = df_maestro[config.codigo_idioma_seleccionado] # Add validation columns if source and target languages are different if config.codigo_columna_maestra != config.codigo_idioma_seleccionado: df_export["Validation_Error"] = "" df_export["Affinity_Score"] = None df_export["Idioma_Detectado"] = "" # Agregar columna del idioma secundario if config.codigo_idioma_secundario in df_maestro.columns: df_export[config.codigo_idioma_secundario] = df_maestro[ config.codigo_idioma_secundario ] ruta_export = config.get_translate_path() with pd.ExcelWriter(ruta_export, engine="openpyxl") as writer: df_export.to_excel(writer, index=False, sheet_name="Sheet1") workbook = writer.book worksheet = writer.sheets["Sheet1"] # Inmovilizar paneles en A2 worksheet.freeze_panes = 'A2' wrap_alignment = Alignment(wrap_text=True, vertical="top") for col in worksheet.columns: max_length = 0 column = col[0].column_letter for cell in col: try: if cell.value: text_length = len(str(cell.value)) if text_length > 50: cell.alignment = wrap_alignment text_length = min( 50, max(len(word) for word in str(cell.value).split()) ) max_length = max(max_length, text_length) except: pass adjusted_width = min(50, max_length + 2) worksheet.column_dimensions[column].width = ( adjusted_width if adjusted_width > 8 else 8 ) red_fill = PatternFill( start_color="FF0000", end_color="FF0000", fill_type="solid" ) yellow_fill = PatternFill( start_color="FFFF00", end_color="FFFF00", fill_type="solid" ) blue_fill = PatternFill( start_color="ADD8E6", end_color="ADD8E6", fill_type="solid" ) total_rows = worksheet.max_row - 1 progress_bar = fc.ProgressBar( total_rows, prefix="Procesando filas:", suffix="Completado" ) texto_a_filas = defaultdict(list) inconsistencias = 0 afinidad_baja = 0 for row in range(2, worksheet.max_row + 1): texto = worksheet.cell(row=row, column=2).value if texto: # Language detection texto_limpio = fc.limpiar_texto(config.codigo_tipo_PLC, texto) if texto == texto_limpio: texto_a_filas[texto].append(row) idioma_detectado = detectar_idioma(texto, config.codigo_tipo_PLC) idioma_esperado = fc.idiomas_shortcodefromcode( config.codigo_idioma_seleccionado ) if ( idioma_detectado != "unknown" and idioma_detectado != idioma_esperado ): worksheet.cell(row=row, column=2).fill = blue_fill nombre_idioma = obtener_nombre_idioma(idioma_detectado) worksheet.cell( row=row, column=df_export.columns.get_loc("Idioma_Detectado") + 1, ).value = nombre_idioma # Validation checks for different languages if config.codigo_columna_maestra != config.codigo_idioma_seleccionado: texts_to_check = {} batch_size = 20 for row in range(2, worksheet.max_row + 1): clave = worksheet.cell(row=row, column=1).value texto = worksheet.cell(row=row, column=2).value if pd.notnull(texto) and texto.strip() != "": texts_to_check[clave] = texto if len(texts_to_check) >= batch_size: try: affinities = fc.affinity_batch_openai( config.codigo_tipo_PLC, texts_to_check, openai_client, logger, ) for check_row, (key, score) in enumerate( affinities.items(), start=2 ): col_idx = ( df_export.columns.get_loc("Affinity_Score") + 1 ) worksheet.cell( row=check_row, column=col_idx ).value = score if score < 1: worksheet.cell( row=check_row, column=2 ).fill = yellow_fill afinidad_baja += 1 except Exception as e: logger.error(f"Error en lote de afinidad: {str(e)}") texts_to_check.clear() progress_bar.increment() # Mark duplicate cells in bold bold_font = Font(bold=True) celdas_duplicadas = 0 for filas in texto_a_filas.values(): if len(filas) > 1: for row in filas: cell = worksheet.cell(row=row, column=2) cell.font = bold_font celdas_duplicadas += len(filas) progress_bar.finish() print(f"\nArchivo exportado para traducción: {ruta_export}") print("Las celdas con idioma incorrecto han sido marcadas en azul.") print( "Se ha añadido el nombre del idioma detectado cuando es diferente del esperado." ) print( f"Se ha agregado la columna del idioma secundario ({config.codigo_idioma_secundario}) al final de la planilla." ) if config.codigo_columna_maestra != config.codigo_idioma_seleccionado: print( f"Se encontraron {inconsistencias} celdas con errores de validación (marcadas en rojo)" ) print( f"Se encontraron {afinidad_baja} celdas con afinidad menor a 1 (marcadas en amarillo)" ) print( f"Se han marcado {celdas_duplicadas} celdas en negrita por tener texto duplicado." ) def run(config: TranslationConfig): global logger logger = fc.configurar_logger(config.work_dir) script_name = os.path.basename(__file__) print(f"\rIniciando: {script_name}\r") exportar_para_traduccion(config) if __name__ == "__main__": import menu_pasos_traduccion menu_pasos_traduccion.main()