From 6295804b19517700dd3640e5c025f4f7112a3828 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 15 Oct 2024 15:00:51 +0200 Subject: [PATCH] Mejorado logica de 6x exportacion --- ...x2_master_export2translate.cpython-310.pyc | Bin 4063 -> 3946 bytes .../x6_update_from_master.cpython-310.pyc | Bin 3225 -> 3789 bytes translation_config.json | 10 +- x2_master_export2translate.py | 88 +++++---------- x6_update_from_master.py | 104 +++++++++++------- 5 files changed, 94 insertions(+), 108 deletions(-) diff --git a/__pycache__/x2_master_export2translate.cpython-310.pyc b/__pycache__/x2_master_export2translate.cpython-310.pyc index ae0cef5bdafd91cb5ef76fb00ce48e6acdc96c79..3617308f79dad4b60a763d451646eb18fe59998f 100644 GIT binary patch delta 1873 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 KstPty{_PJUNxz-| diff --git a/__pycache__/x6_update_from_master.cpython-310.pyc b/__pycache__/x6_update_from_master.cpython-310.pyc index b79170ecc974d58d4f238442e258f6a166912396..755bedb8939af1edaa94024b12fde2668168fff2 100644 GIT binary patch delta 2109 zcmZuy-EZ7P5cjUvA7}e~zK`d`8 zAV7Ao9@qthJw|LuOI+jS^HQRWRBG_jml8Ga$zz11@G^urz3-OW)Pevjg^=lIQ)pV;9?KBClUBLIzAI461**-hFQt1#AP;zjlg=St+K=eG6gIf|xC9Jm zX@yt81Pc>h<*Epi>!Z1`grpm<19w<(3F_d{5stypS6gquypWNPHSKajtH%V7>iGuEza!_++F^?Yy#V?^U2li&cq98-xj>pzOw0aKR_F8bKC%ay zw*5G_HYa%An$Os=>;v^STFib|{lTXYhK?+xBZ3S}kb}scK@6l~0xN=n+jEGHY;*`W zWDL7R23^q6Q3Lh~!tkmObQSN}V51`)G^P>8&K_3mJqNT6tYZh;fPt~l1{6g8!J2`{ zU=PbSz%_s}(Yh@HRr-Q=OJ}5KIU( zDisssC{(|hTHK_@jOci92OX~ocd5;FZhK;y*q)d<7Bz=Btw0yrUKu(GPcY^R3`bzR z`4o_n00DF7G4nMTS}>eMlR_32m;RT9)GTLT>6hNi)up9Z;K`LZ>b7Z9&doUSS>m;# zZp89Z5Yht{+NSFzH#Y-eBdqp+mzJ6+R|@q%F`Rt%P(S>3e+jtdz}@ge=n~d~9&@4T z4yv~mK_4*|LA|;+C$$_uy}8_GC0i|>x>yH5CT^CA>&}&S67=Gnh@gPNcxS4RYptkP z6gi2Zjha>VvM_m7kki>ur89%vC>(o*p%L^plbaL%;|;*{3aGOJsth=>-wC|JfW09w zmIe7x>}r!;wkSjexgfZgfLwzwehr9@RMfyw^zh<`HX&%)hN?D@166OsrV70NXeD?9 z*H8h{5{G&4$iRrai?SBTi8MkmDq+z1a(2f!k^N}QpqcDf_GaP<7%Q6yBMg{qcJL96LYGkGhp8;QoXPRgk6?B5D+s9=HUG6antmvuW(u>twvC zN;Hd+oNFY)Af&2lWuG{3%dz6fwNek9_RIxw;Eq(xn@s`&G1ff4dGozD@8{bW3y-UA z*KsTb*7uXngP%)B?mYVT=+ep^q)>%wZM)-aIH04@rFvv+Vro$HfNXfQK&=C1!#}ka zsSVarG(nwh%x;4(YL_?4QF&N7dVa$|8CmPbi724JE5l<3>|3yVzaX)M?)Nzv7Dvje z^4XW4;?zh@ZgQ=vq=m#B+FWTlyfDJ4m1skqYTS6DP@P*(l&55bkdnAVk6RVG9N=d{^bEBYiBvXPQgcGGyFPL7Xic6b*LHyB|SG6s`*Vln3Urza79x7 z?5Ub1KDJh;e#KBprmwACg;hhD*66moO#EiemG`~%DA)?)pcAqNj4RlGTU^nm3G24H z;(cvO4Qj4fFD@>5GKAJlqE3$ysgq6kSea~AW;D8;P825@=>Zei>tL(d>`nM%m&H%T zcQLyv&fDeno6@o>#ce5;{ubAzb^*jEuzS*94ygiDCh)_5x`d#U+1tp1fm#@&31p7h z1u?W2D(`_qq6`u696pv%<%lha7xu;ZoUiJK`?m8z+-x+%n0A+gKaf+iSXp?^`MwXH zOb(qnATslQ*o)$@6J=(-zS(R?^*WP<=R~QgOqco_5?SmuSaT<-OYnaR$yBx%?*gbN z1KXG&8~MOQ@`~M+t`NEtHsgA|HtA*h4kQ)!SQT!VEuK5qP+9!$tkkkncPEN>zIfDL wJne2TZ#K(Qmc-2)#_o#G-An#It<1IS;;|c4Y+KXU&3%AeC2t0jly;pa1{> diff --git a/translation_config.json b/translation_config.json index c2f8afc..e443b63 100644 --- a/translation_config.json +++ b/translation_config.json @@ -1,12 +1,12 @@ { "codigo_tipo_PLC": "allenbradley", - "codigo_columna_maestra": "en-US", - "codigo_idioma_seleccionado": "es-ES", - "codigo_idioma_secundario": "en-US", + "codigo_columna_maestra": "es-ES", + "codigo_idioma_seleccionado": "en-US", + "codigo_idioma_secundario": "es-ES", "work_dir": "C:/Trabajo/VM/31 - 9.3953 - Omega - Mexico - (ABradley)/Reporte/Languages", "master_name": "1_hmi_master_translates_allenbradley.xlsx", - "translate_name": "2_master_export2translate_allenbradley_es-ES.xlsx", - "auto_translate_name": "3_master_export2translate_translated_allenbradley_es-ES.xlsx", + "translate_name": "2_master_export2translate_allenbradley_en-US.xlsx", + "auto_translate_name": "3_master_export2translate_translated_allenbradley_en-US.xlsx", "nivel_afinidad_minimo": 0.5, "traducir_todo": false } \ No newline at end of file diff --git a/x2_master_export2translate.py b/x2_master_export2translate.py index 6f1cab4..19b7fe2 100644 --- a/x2_master_export2translate.py +++ b/x2_master_export2translate.py @@ -1,12 +1,11 @@ import pandas as pd import os -import sys -import time import PyLibrary.funciones_comunes as fc from translation_config import TranslationConfig import langid from openpyxl import load_workbook -from openpyxl.styles import PatternFill, Alignment +from openpyxl.styles import PatternFill, Alignment, Font +from collections import defaultdict # Definir el logger a nivel de módulo logger = None @@ -71,15 +70,26 @@ def exportar_para_traduccion(config: TranslationConfig): config.codigo_idioma_seleccionado ) fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid") + bold_font = Font(bold=True) total_rows = worksheet.max_row - 1 # Excluimos la fila de encabezado progress_bar = fc.ProgressBar( total_rows, prefix="Procesando filas:", suffix="Completado" ) + print("Iniciando procesamiento de filas...") + + texto_a_filas = defaultdict(list) for row in range(2, worksheet.max_row + 1): texto = worksheet.cell(row=row, column=2).value if texto: + texto_limpio = fc.limpiar_texto(config.codigo_tipo_PLC, texto) + + # Solo considerar para duplicados si el texto limpio es igual al original + if texto == texto_limpio: + texto_a_filas[texto].append(row) + + # Detectar idioma y marcar si es incorrecto idioma_detectado = detectar_idioma(texto, config.codigo_tipo_PLC) if ( idioma_detectado != "unknown" @@ -88,7 +98,17 @@ def exportar_para_traduccion(config: TranslationConfig): worksheet.cell(row=row, column=2).fill = fill nombre_idioma = obtener_nombre_idioma(idioma_detectado) worksheet.cell(row=row, column=3).value = nombre_idioma - progress_bar.update(row - 1) + + progress_bar.increment() + + # Marcar celdas duplicadas en negrita + 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() @@ -97,66 +117,8 @@ def exportar_para_traduccion(config: TranslationConfig): print( "Se ha añadido el nombre del idioma detectado cuando es diferente del esperado." ) - 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] - df_export[config.codigo_idioma_seleccionado] = df_maestro[ - config.codigo_idioma_seleccionado - ] - df_export["Idioma_Detectado"] = "" - - 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"] - - wrap_alignment = Alignment(wrap_text=True, vertical="top") - for col in ["A", "B"]: - for cell in worksheet[col]: - cell.alignment = wrap_alignment - worksheet.column_dimensions[col].width = 50 - - idioma_esperado = fc.idiomas_shortcodefromcode( - config.codigo_idioma_seleccionado - ) - fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid") - - total_rows = worksheet.max_row - 1 # Excluimos la fila de encabezado - progress_bar = fc.ProgressBar( - total_rows, prefix="Progreso:", suffix="Completado" - ) - - for row in range(2, worksheet.max_row + 1): - texto = worksheet.cell(row=row, column=2).value - if texto: - idioma_detectado = detectar_idioma(texto, config.codigo_tipo_PLC) - if ( - idioma_detectado != "unknown" - and idioma_detectado != idioma_esperado - ): - worksheet.cell(row=row, column=2).fill = fill - nombre_idioma = obtener_nombre_idioma(idioma_detectado) - worksheet.cell(row=row, column=3).value = nombre_idioma - progress_bar.increment() - - 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." + f"Se han marcado {celdas_duplicadas} celdas en negrita por tener texto duplicado en la columna del idioma seleccionado." ) diff --git a/x6_update_from_master.py b/x6_update_from_master.py index 7a6e296..ec5cc02 100644 --- a/x6_update_from_master.py +++ b/x6_update_from_master.py @@ -3,7 +3,7 @@ import os import PyLibrary.funciones_comunes as fc from translation_config import TranslationConfig from openpyxl import load_workbook -from openpyxl.styles import Font +from openpyxl.styles import Font, PatternFill from openpyxl.comments import Comment # Definir el logger a nivel de módulo @@ -27,13 +27,19 @@ def update_from_master(config: TranslationConfig, archivo_to_update): col_clave = config.codigo_columna_maestra celdas_con_errores = {} + celdas_vacias = {} + + progress_bar = fc.ProgressBar( + len(df_to_update), prefix="Actualizando filas:", suffix="Completado" + ) for index, fila in df_to_update.iterrows(): valor_original = fila[col_clave] clave = fc.compactar_celda_clave(config.codigo_tipo_PLC, valor_original) - logger.info(f"Fila {index} : Clave: {clave}") - if not pd.isnull(clave) and clave in df_maestro[col_clave].values: + if not pd.isna(clave) and clave in df_maestro[col_clave].values: + # logger.info(f"Fila {index} : Clave: {clave}") + indice_maestro = df_maestro.index[df_maestro[col_clave] == clave].tolist()[ 0 ] @@ -41,50 +47,60 @@ def update_from_master(config: TranslationConfig, archivo_to_update): indice_maestro, config.codigo_idioma_seleccionado ] - valor_traducido = fc.decompactar_celda_traducida( - config.codigo_tipo_PLC, - celda_original=valor_original, - celda_traducida=valor_traducido_compacto, - ) - if ( - not pd.isnull(valor_traducido) - and fila[config.codigo_idioma_seleccionado] != valor_traducido - ): - okToSave, Error = fc.verificar_celda_traducida( - config.codigo_tipo_PLC, clave, valor_traducido_compacto + if pd.isna(valor_traducido_compacto): + celdas_vacias[indice_maestro] = "Celda vacía en el archivo maestro" + logger.info(f"Fila {index}: Celda vacía en el archivo maestro") + else: + valor_traducido = fc.decompactar_celda_traducida( + config.codigo_tipo_PLC, + celda_original=valor_original, + celda_traducida=valor_traducido_compacto, ) - if okToSave: - logger.info("Actualizado.") - df_to_update.at[index, config.codigo_idioma_seleccionado] = ( - valor_traducido + if ( + not pd.isna(valor_traducido) + and fila[config.codigo_idioma_seleccionado] != valor_traducido + ): + okToSave, Error = fc.verificar_celda_traducida( + config.codigo_tipo_PLC, clave, valor_traducido_compacto ) - else: - df_to_update.at[index, config.codigo_idioma_seleccionado] = ( - valor_original - ) - logger.error(f"No actualizado porque: {Error}") - celdas_con_errores[indice_maestro] = Error + if okToSave: + logger.info(f"Actualizado: Fila {index} : Clave: {clave}") + df_to_update.at[index, config.codigo_idioma_seleccionado] = ( + valor_traducido + ) + else: + df_to_update.at[index, config.codigo_idioma_seleccionado] = ( + valor_original + ) + logger.error(f"No actualizado porque: {Error}") + celdas_con_errores[indice_maestro] = Error + + progress_bar.increment() + + progress_bar.finish() nombre, extension = os.path.splitext(archivo_to_update) nuevo_nombre = f"{nombre}_import{extension}" fc.save_dataframe_with_retries(df_to_update, output_path=nuevo_nombre) marcar_celdas_con_errores( - archivo_maestro, celdas_con_errores, config.codigo_idioma_seleccionado + archivo_maestro, + celdas_con_errores, + celdas_vacias, + config.codigo_idioma_seleccionado, ) print( - f"Se han actualizado las filas en {archivo_to_update} desde el archivo maestro. " - f"Se han marcado {len(celdas_con_errores)} celdas con errores en el archivo maestro." - ) - logger.info( - f"Se han actualizado las filas en {archivo_to_update} desde el archivo maestro. " + f"Se han actualizado las filas en {archivo_to_update} desde el archivo maestro." + ) + print( f"Se han marcado {len(celdas_con_errores)} celdas con errores en el archivo maestro." ) + print(f"Se han marcado {len(celdas_vacias)} celdas vacías en el archivo maestro.") logger.info(" .... ") -def marcar_celdas_con_errores(archivo_maestro, celdas_con_errores, target_lang_code): +def marcar_celdas_con_errores(archivo_maestro, celdas_con_errores, celdas_vacias, target_lang_code): workbook = load_workbook(archivo_maestro) sheet = workbook.active @@ -96,27 +112,35 @@ def marcar_celdas_con_errores(archivo_maestro, celdas_con_errores, target_lang_c print(f"No se encontró la columna para el idioma {target_lang_code}") return + error_fill = PatternFill(start_color="FF0000", end_color="FF0000", fill_type="solid") + empty_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") + white_font = Font(color="FFFFFF") # Fuente blanca para celdas con fondo rojo + for indice_maestro, mensaje_error in celdas_con_errores.items(): row = indice_maestro + 2 cell = sheet.cell(row=row, column=target_col) - cell.font = Font(color="FF0000") - + cell.fill = error_fill + cell.font = white_font # Aplicar fuente blanca comment = Comment(mensaje_error, "Sistema de Traducción") cell.comment = comment + for indice_maestro, mensaje in celdas_vacias.items(): + row = indice_maestro + 2 + cell = sheet.cell(row=row, column=target_col) + cell.fill = empty_fill + comment = Comment(mensaje, "Sistema de Traducción") + cell.comment = comment + workbook.save(archivo_maestro) - print( - f"Se han marcado {len(celdas_con_errores)} celdas con errores en rojo en el archivo maestro {archivo_maestro}" - ) + print(f"Se han marcado las celdas con errores y vacías en el archivo maestro {archivo_maestro}") def run(config: TranslationConfig, archivo_to_update): global logger logger = fc.configurar_logger(config.work_dir) - if archivo_to_update: - script_name = os.path.basename(__file__) - print(f"\rIniciando: {script_name}\r") - update_from_master(config, archivo_to_update) + script_name = os.path.basename(__file__) + print(f"\rIniciando: {script_name}\r") + update_from_master(config, archivo_to_update) if __name__ == "__main__":