From 392ab1b3ad1f78a21e5f6e7154bfc65632acc0c0 Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 1 Aug 2024 13:53:38 +0200 Subject: [PATCH] Mejorada la logica general con Funciones Base --- __pycache__/manejoArchivos.cpython-310.pyc | Bin 1359 -> 1371 bytes data/1_hmi_master_translates.xlsx | Bin 49771 -> 0 bytes data/2_master_export2translate.xlsx | Bin 49768 -> 0 bytes .../funciones_base.cpython-310.pyc | Bin 1864 -> 5450 bytes funciones_comunes/funciones_base.py | 171 ++++++- logs/translate_log.log | 416 ++++++++++++++++++ manejoArchivos.py | 4 +- x1_importar_to_master.py | 41 +- x2_master_export2translate.py | 20 +- x3_llm_translate_text.py | 74 ++-- x4_import_translate2master.py | 69 --- ...ranslates.py => x4_integrate_translates.py | 32 +- ...er.py => x5_complete_empty_cells_master.py | 43 +- x5_update_from_master.py | 102 ----- x6_update_from_master.py | 80 ++++ 15 files changed, 739 insertions(+), 313 deletions(-) delete mode 100644 data/1_hmi_master_translates.xlsx delete mode 100644 data/2_master_export2translate.xlsx create mode 100644 logs/translate_log.log delete mode 100644 x4_import_translate2master.py rename x3.5_integrate_translates.py => x4_integrate_translates.py (72%) rename x4.5_complete_empty_cells_master.py => x5_complete_empty_cells_master.py (60%) delete mode 100644 x5_update_from_master.py create mode 100644 x6_update_from_master.py diff --git a/__pycache__/manejoArchivos.cpython-310.pyc b/__pycache__/manejoArchivos.cpython-310.pyc index cbe1d3ece182c49670f25d054644f37179320d7e..04b55a9b8badb1131d72f50224e233b3a8e1d040 100644 GIT binary patch delta 114 zcmX@lb(@PXpO=@50SGvHSEVtsPvo1=Xg6`4q)rXPY=#u3xy)dic`j253y3wBDUB(G z6^Pk-nQED8n1UHJ*{i}PzhYLM%*ALV!WEpFlbT$jkf@+n#j22&nUh+@HaUp#A~P4G K*k&~*O=bX+;2lc< delta 95 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
lx?s59@-}(Dn&2`*`V!NAA!$ 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∾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 diff --git a/data/2_master_export2translate.xlsx b/data/2_master_export2translate.xlsx deleted file mode 100644 index 588cb2d90abddbfa6f0beb8bea2d648ac24c064b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49768 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 delta 713 zcmYjP&ubGw6rMLbvpd-&+oX+3O~itSvPF9FAWBFP!Gl6A+X*%I6>$7K=WkbK3pb{q7zF zHGZERT(92Z=%7G}E_$di_rZ$<`k3Emk;DQPNxE3ZIV|l%#Hkkjj>a|)(FLn@8Znu#e-45KjXSHbK=pHkVi7< zyhw)8!}&~ZC%Qd|yFg_E2f+cKs<%58L2V8(&ut{#3lUJti zNJW?kBMg7e^x8Nu>=`pO3Oa8&umn)N0bq|9$|e&u=*!!{CKA~AGWlF1-!t@#L#Pg= zjWhytH`zoa&XF+AahCg-vM2JD9LO`d2YVDp9jh#Msf=$p704etwt#IE7DmJLlZ?a? zos*io2+q9_(hbi5PrrH(K&6Xn8KU%#x{*J(gLJBvrdRFAH3E@Sz##wyF5yLz^u6Z4 z)vt=Ls}vA&?UKkKRJv^SO9V4_w>`jitmmvHXCbhVEzTyM+k4hMTfVCA3~|(7?lgcx WG6stNA>tr7@%VS$Q{^ie_ - texto_transformado = re.sub(r'\[\[digits\]\]', '<>', texto) - # Sustituir cualquier <...> por <#> - texto_transformado = re.sub(r'<.*?>', '<#>', texto_transformado) - return texto_transformado +def configurar_logger(): + logger = logging.getLogger("translate_logger") + logger.setLevel(logging.DEBUG) + os.makedirs(".\\logs", exist_ok=True) + fh = logging.FileHandler(".\\logs\\translate_log.log", encoding="utf-8") + fh.setLevel(logging.DEBUG) + formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s : ") + fh.setFormatter(formatter) + logger.addHandler(fh) + return logger +# +# Salvar archivo Excel controlando que no este abierto. Sino espera. +# def save_dataframe_with_retries(df, output_path, max_retries=5, retry_delay=5): """ Guarda un DataFrame en un archivo Excel, reintentando si el archivo está en uso. - + :param df: El DataFrame a guardar. :param output_path: La ruta del archivo donde se guardará el DataFrame. :param max_retries: El número máximo de reintentos en caso de error. @@ -40,12 +49,150 @@ def save_dataframe_with_retries(df, output_path, max_retries=5, retry_delay=5): retries = 0 while retries < max_retries: try: - df.to_excel(output_path, index=False) + df.to_excel(output_path, sheet_name="User Texts", index=False) print("Archivo guardado exitosamente.") return except PermissionError as e: - print(f"Error de permiso: {e}. Por favor cierre el archivo. Reintentando en {retry_delay} segundos...") + print( + f"Error de permiso: {e}. Por favor cierre el archivo. Reintentando en {retry_delay} segundos..." + ) retries += 1 time.sleep(retry_delay) + + print(f"No se pudo guardar el archivo después de {max_retries} intentos.") + + +def cambiar_nombre_hoja(archivo_excel, nombre_hoja_actual, nombre_hoja_nuevo): + # Cargar el archivo Excel existente + libro = load_workbook(archivo_excel) + + # Verificar si la hoja existe en el archivo + if nombre_hoja_actual in libro.sheetnames: + # Obtener la hoja actual + hoja = libro[nombre_hoja_actual] + # Cambiar el nombre de la hoja + hoja.title = nombre_hoja_nuevo + # Guardar los cambios en el archivo Excel + libro.save(archivo_excel) + print( + f"El nombre de la hoja ha sido cambiado de '{nombre_hoja_actual}' a '{nombre_hoja_nuevo}'." + ) + else: + print(f"La hoja '{nombre_hoja_actual}' no existe en el archivo.") + +# Verificar si la columna es del tipo "xx-YY" usando una expresión regular +def es_columna_tipo_xxYY(columna): + # Verificar si la columna es del tipo "xx-YY" usando una expresión regular + return bool(re.match(r"^[a-z]{2}-[A-Z]{2}$", columna)) + + +# +# Transforma: "A271/47/6 Air - M - Necessaria Manutenzione Filtro" -> +# "A[[digits]]/[[digits]]/[[digits]] Air - M - Necessaria Manutenzione Filtro" +# +# Este procesamiento se aplica a las celdas clave +def compactar_celda_clave(celda_original): + if pd.isnull(celda_original): + return celda_original - print(f"No se pudo guardar el archivo después de {max_retries} intentos.") \ No newline at end of file + def reemplazar(match): + if match.group(1): # Si hay contenido dentro de <> + return f"<{match.group(1)}>" + return "[[digits]]" + + # Reemplaza dígitos fuera de <> con [[digits]], y preserva el contenido dentro de <> + return re.sub(r"<(.*?)>|\d+", reemplazar, str(celda_original)) + + +# +# Transforma: "A[[digits]]/[[digits]]/[[digits]] Air - M - Necessaria Manutenzione Filtro" -> +# "A<>/<>/<> Air - M<#>" /> - Necessaria Manutenzione Filtro" +# +# Este procesamiento se aplica a las celdas traducidas +def compactar_celda_traducida(celda_traducida): + if pd.isnull(celda_traducida): + return celda_traducida + celda_traducida = compactar_celda_clave(celda_traducida) + + def reemplazar(match): + if match.group(1): # Si hay contenido dentro de <> + return "<#>" + return "<>" + + # Reemplaza <...> con <#> y [[digits]] con <> + return re.sub(r"<(.*?)>|\[\[digits\]\]", reemplazar, str(celda_traducida)) + + +# de "A271/47/6 Air - M - Necessaria Manutenzione Filtro" -> [271,47,6] +# Obtener la secuencias de dígitos por [[digits]] +def obtener_digitos_celda_original(celda_original): + if pd.isnull(celda_original): + return [] + + # Primero, reemplazamos temporalmente el contenido de los tags con un marcador + texto_sin_tags = re.sub(r'<[^>]*>', '<>', str(celda_original)) + + # Ahora buscamos los dígitos + digitos = re.findall(r'\d+', texto_sin_tags) + + return digitos + + +# Original Traducida +# Transforma: "A271/47/6 Air - M - Necessaria Manutenzione Filtro" , "A<>/<>/<> Air - M<#> - Filter Maintenance Required" -> +# "A271/47/6 Air - M - Necessaria Manutenzione Filtro" +# +# Este procesamiento se aplica a las celdas traducidas para regresar al valor original +def decompactar_celda_traducida(celda_original, celda_traducida): + digitos = obtener_digitos_celda_original(celda_original) + celda_destino = celda_traducida + + # Replace <> with digits + for d in digitos: + celda_destino = celda_destino.replace("<>", d, 1) + + # Replace <#> with original content within <> + original_tags = re.findall(r"<.*?>", celda_original) + translated_tags = re.findall(r"<#>", celda_destino) + + for orig, trans in zip(original_tags, translated_tags): + celda_destino = celda_destino.replace(trans, orig, 1) + + return celda_destino + + +def verificar_celda_traducida(celda_clave, celda_traducida): + # Contar los placeholders de dígitos + digitos_clave = celda_clave.count("[[digits]]") + digitos_traducida = celda_traducida.count("<>") + + # Contar los placeholders de tags + tags_clave = sum(1 for tag in re.findall(r"<.*?>", celda_clave) if tag != "[[digits]]") + tags_traducida = celda_traducida.count("<#>") + + # Verificar si las cantidades coinciden + if digitos_clave == digitos_traducida and tags_clave == tags_traducida: + return True , "" + else: + text_error = f"Error de verificación:" + f" - Celda clave: {celda_clave}" + f" - Celda traducida: {celda_traducida}" + text_error += f" - Dígitos en clave: {digitos_clave}, Dígitos en traducida: {digitos_traducida}" + text_error += f" - Tags en clave: {tags_clave}, Tags en traducida: {tags_traducida}" + return False, text_error + +if __name__ == "__main__": + celda_original = 'A271/47/6 Air - M - Necessaria Manutenzione Filtro' + celda_original = 'DB/DB/DB' + celda_original = 'Text' + + celda_clave = compactar_celda_clave(celda_original) + celda_tradc = compactar_celda_traducida(celda_original) + " TEXTO " + + print() + print("Celda Original : " +celda_original) + print("Celda Clave : " + celda_clave) + print("Celda Traducida: " + celda_tradc) + print("Digitos : " + ','.join(obtener_digitos_celda_original(celda_original))) + print("Celda : " + decompactar_celda_traducida(celda_original, celda_tradc)) + print("Celda Original : " + celda_original) + + print(verificar_celda_traducida(celda_clave=celda_clave, celda_traducida= celda_tradc)) \ No newline at end of file diff --git a/logs/translate_log.log b/logs/translate_log.log new file mode 100644 index 0000000..ab15f59 --- /dev/null +++ b/logs/translate_log.log @@ -0,0 +1,416 @@ +2024-08-01 13:30:13,249 - INFO - .... : +2024-08-01 13:30:13,249 - INFO - Iniciando actualizacion en C:/Trabajo/VM/22 - 93841 - Sidel - Tilting/Reporte/Translate/TIAProjectTexts.xlsx desde el archivo maestro. Para ru-RU : +2024-08-01 13:30:13,801 - INFO - Fila 304, Columna ru-RU: "### ОШИБКА ###" actualizado a "### ОШИБКА ###" : +2024-08-01 13:30:13,801 - INFO - Fila 305, Columna ru-RU: "### ОШИБКА ###" actualizado a "### ОШИБКА ###" : +2024-08-01 13:30:13,801 - INFO - Fila 306, Columna ru-RU: "### ОШИБКА ###" actualizado a "### ОШИБКА ###" : +2024-08-01 13:30:13,802 - INFO - Fila 307, Columna ru-RU: "### ОШИБКА ###" actualizado a "### ОШИБКА ###" : +2024-08-01 13:30:13,802 - INFO - Fila 308, Columna ru-RU: "### ОШИБКА ###" actualizado a "### ОШИБКА ###" : +2024-08-01 13:30:13,803 - ERROR - Fila 327, Columna ru-RU: "текст 1" valor:"текст <>" no actualizado porque Error de verificación: - Celda clave: ### Output Scorta IN - ERRORE TESTO ### - Celda traducida: текст <> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:30:13,803 - ERROR - Fila 328, Columna ru-RU: "текст 1" valor:"текст <>" no actualizado porque Error de verificación: - Celda clave: ### Output Scorta OUT - ERRORE TESTO ### - Celda traducida: текст <> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:30:13,805 - INFO - Fila 351, Columna ru-RU: "#### ОШИБКА ####" actualizado a "#### ОШИБКА ####" : +2024-08-01 13:30:13,805 - INFO - Fila 352, Columna ru-RU: "#### ОШИБКА ####" actualizado a "#### ОШИБКА ####" : +2024-08-01 13:30:13,806 - INFO - Fila 353, Columna ru-RU: "#### ОШИБКА ####" actualizado a "#### ОШИБКА ####" : +2024-08-01 13:30:13,866 - ERROR - Fila 1899, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,866 - ERROR - Fila 1900, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,867 - ERROR - Fila 1901, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,868 - ERROR - Fila 1902, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,868 - ERROR - Fila 1904, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,868 - ERROR - Fila 1905, Columna ru-RU: "этикетировочные" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,869 - ERROR - Fila 1906, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,869 - ERROR - Fila 1907, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,869 - ERROR - Fila 1908, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,870 - ERROR - Fila 1909, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,870 - ERROR - Fila 1910, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,870 - ERROR - Fila 1911, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,870 - ERROR - Fila 1912, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:13,871 - ERROR - Fila 1914, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:30:14,067 - ERROR - Fila 5263, Columna ru-RU: "реле давления S1M03 - OK" valor:"реле давления S<>M<> - OK" no actualizado porque Error de verificación: - Celda clave: Abilitazione - Celda traducida: реле давления S<>M<> - OK - Dígitos en clave: 0, Dígitos en traducida: 2 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:30:14,076 - INFO - Fila 5306, Columna ru-RU: "Накопление Вход DOS" actualizado a "Накопление Вход DOS" : +2024-08-01 13:30:14,081 - INFO - Fila 5335, Columna ru-RU: "Текст" actualizado a "Текст" : +2024-08-01 13:30:14,083 - INFO - Fila 5342, Columna ru-RU: "Сигнализация Watchdog Modbus" actualizado a "Сигнализация Watchdog Modbus" : +2024-08-01 13:30:14,083 - INFO - Fila 5343, Columna ru-RU: "Сигнализация тайм-аута процедуры автотюнинга электрических параметров" actualizado a "Сигнализация тайм-аута процедуры автотюнинга электрических параметров" : +2024-08-01 13:30:14,083 - INFO - Fila 5344, Columna ru-RU: "Сигнализация Encoder SPI многооборотной части, многооборотная позиция больше не надежна" actualizado a "Сигнализация Encoder SPI многооборотной части, многооборотная позиция больше не надежна" : +2024-08-01 13:30:14,083 - INFO - Fila 5345, Columna ru-RU: "Сигнализация Encoder SPI однородной части, однородная позиция больше не надежна" actualizado a "Сигнализация Encoder SPI однородной части, однородная позиция больше не надежна" : +2024-08-01 13:30:14,084 - INFO - Fila 5346, Columna ru-RU: "Сигнализация неисправности флеш-памяти" actualizado a "Сигнализация неисправности флеш-памяти" : +2024-08-01 13:30:14,084 - INFO - Fila 5347, Columna ru-RU: "Сигнализация чтения энкодера SPI" actualizado a "Сигнализация чтения энкодера SPI" : +2024-08-01 13:30:14,084 - INFO - Fila 5348, Columna ru-RU: "Сигнализация недоступной или поврежденной памяти параметров" actualizado a "Сигнализация недоступной или поврежденной памяти параметров" : +2024-08-01 13:30:14,085 - INFO - Fila 5349, Columna ru-RU: "Сигнализация Не Присутствует" actualizado a "Сигнализация Не Присутствует" : +2024-08-01 13:30:14,085 - INFO - Fila 5350, Columna ru-RU: "Сигнализация аппаратного перенапряжения" actualizado a "Сигнализация аппаратного перенапряжения" : +2024-08-01 13:30:14,085 - INFO - Fila 5351, Columna ru-RU: "Сигнализация программного перенапряжения" actualizado a "Сигнализация программного перенапряжения" : +2024-08-01 13:30:14,085 - INFO - Fila 5352, Columna ru-RU: "Сигнализация перегрева двигателя" actualizado a "Сигнализация перегрева двигателя" : +2024-08-01 13:30:14,086 - INFO - Fila 5353, Columna ru-RU: "Сигнал тревоги о перегреве платы" actualizado a "Сигнал тревоги о перегреве платы" : +2024-08-01 13:30:14,086 - INFO - Fila 5354, Columna ru-RU: "Сигнал тревоги о перенапряжении" actualizado a "Сигнал тревоги о перенапряжении" : +2024-08-01 13:30:14,086 - INFO - Fila 5355, Columna ru-RU: "Сигнал тревоги о неправильном значении параметра" actualizado a "Сигнал тревоги о неправильном значении параметра" : +2024-08-01 13:30:14,086 - INFO - Fila 5356, Columna ru-RU: "Сигнал тревоги о неудачном восстановлении параметров по умолчанию" actualizado a "Сигнал тревоги о неудачном восстановлении параметров по умолчанию" : +2024-08-01 13:30:14,087 - INFO - Fila 5357, Columna ru-RU: "Сигнал тревоги о неудачном восстановлении параметров двигателя по умолчанию" actualizado a "Сигнал тревоги о неудачном восстановлении параметров двигателя по умолчанию" : +2024-08-01 13:30:14,087 - INFO - Fila 5358, Columna ru-RU: "Сигнал тревоги о пониженном напряжении" actualizado a "Сигнал тревоги о пониженном напряжении" : +2024-08-01 13:30:14,087 - INFO - Fila 5359, Columna ru-RU: "Сигнал тревоги пользователя" actualizado a "Сигнал тревоги пользователя" : +2024-08-01 13:30:14,087 - INFO - Fila 5360, Columna ru-RU: "Сигнал тревоги пользователя от цифрового входа" actualizado a "Сигнал тревоги пользователя от цифрового входа" : +2024-08-01 13:30:14,092 - INFO - Fila 5375, Columna ru-RU: "ALLARM: DX Channel Valve Sensors Gate A" actualizado a "ALLARM: DX Channel Valve Sensors Gate A" : +2024-08-01 13:30:14,092 - ERROR - Fila 5380, Columna ru-RU: "аварийные сигналы - делителя [DB1071]" valor:"аварийные сигналы - делителя [DB<>]" no actualizado porque Error de verificación: - Celda clave: Allarmi - SKID - Celda traducida: аварийные сигналы - делителя [DB<>] - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:30:14,092 - ERROR - Fila 5381, Columna ru-RU: "аварийные сигналы - Geosync [DB10171]" valor:"аварийные сигналы - Geosync [DB<>]" no actualizado porque Error de verificación: - Celda clave: Allarmi - Tilter - Celda traducida: аварийные сигналы - Geosync [DB<>] - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:30:14,108 - INFO - Fila 5535, Columna ru-RU: "Подъемный механизм" actualizado a "Подъемный механизм" : +2024-08-01 13:30:14,108 - INFO - Fila 5539, Columna ru-RU: "Низкий [Подъемный механизм]" actualizado a "Низкий [Подъемный механизм]" : +2024-08-01 13:30:14,108 - INFO - Fila 5540, Columna ru-RU: "Низкий [Платформа]" actualizado a "Низкий [Платформа]" : +2024-08-01 13:30:14,111 - INFO - Fila 5553, Columna ru-RU: "Обход" actualizado a "Обход" : +2024-08-01 13:30:14,112 - INFO - Fila 5558, Columna ru-RU: "Канал A" actualizado a "Канал A" : +2024-08-01 13:30:14,112 - INFO - Fila 5559, Columna ru-RU: "Канал B" actualizado a "Канал B" : +2024-08-01 13:30:14,117 - INFO - Fila 5589, Columna ru-RU: "Вызов пакетов" actualizado a "Вызов пакетов" : +2024-08-01 13:30:14,117 - INFO - Fila 5590, Columna ru-RU: "Вызов пакетов" actualizado a "Вызов пакетов" : +2024-08-01 13:30:14,118 - INFO - Fila 5591, Columna ru-RU: "Вызванные пакеты канала справа (B)" actualizado a "Вызванные пакеты канала справа (B)" : +2024-08-01 13:30:14,118 - INFO - Fila 5592, Columna ru-RU: "Packs Request on Left Channel (A)" actualizado a "Packs Request on Left Channel (A)" : +2024-08-01 13:30:14,130 - INFO - Fila 5672, Columna ru-RU: "Manual Divider Infeed Wrappers" actualizado a "Manual Divider Infeed Wrappers" : +2024-08-01 13:30:14,132 - INFO - Fila 5682, Columna ru-RU: "Pack Divider" actualizado a "Pack Divider" : +2024-08-01 13:30:14,138 - INFO - Fila 5759, Columna ru-RU: "Encoder not aligned yet" actualizado a "Encoder not aligned yet" : +2024-08-01 13:30:14,138 - INFO - Fila 5760, Columna ru-RU: "Encoder does not detect movement" actualizado a "Encoder does not detect movement" : +2024-08-01 13:30:14,138 - INFO - Fila 5761, Columna ru-RU: "Encoder detects wrong side movement" actualizado a "Encoder detects wrong side movement" : +2024-08-01 13:30:14,139 - INFO - Fila 5767, Columna ru-RU: "Hmi Error" actualizado a "Hmi Error" : +2024-08-01 13:30:14,140 - INFO - Fila 5768, Columna ru-RU: "Hmi Error" actualizado a "Hmi Error" : +2024-08-01 13:30:14,140 - INFO - Fila 5769, Columna ru-RU: "Hmi Error" actualizado a "Hmi Error" : +2024-08-01 13:30:14,140 - INFO - Fila 5770, Columna ru-RU: "Hmi Error" actualizado a "Hmi Error" : +2024-08-01 13:30:14,141 - INFO - Fila 5771, Columna ru-RU: "Hmi Error" actualizado a "Hmi Error" : +2024-08-01 13:30:14,141 - INFO - Fila 5772, Columna ru-RU: "CSP mode position reference error" actualizado a "CSP mode position reference error" : +2024-08-01 13:30:14,141 - INFO - Fila 5773, Columna ru-RU: "Error in CSP synchronization" actualizado a "Error in CSP synchronization" : +2024-08-01 13:30:14,142 - INFO - Fila 5781, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,144 - INFO - Fila 5782, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,144 - INFO - Fila 5783, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,144 - INFO - Fila 5784, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,152 - INFO - Fila 5869, Columna ru-RU: "Out Of Position" actualizado a "Out Of Position" : +2024-08-01 13:30:14,153 - INFO - Fila 5870, Columna ru-RU: "Out Of Position" actualizado a "Out Of Position" : +2024-08-01 13:30:14,153 - INFO - Fila 5871, Columna ru-RU: "Out Of Position" actualizado a "Out Of Position" : +2024-08-01 13:30:14,155 - INFO - Fila 5879, Columna ru-RU: "Geosync DOS" actualizado a "Geosync DOS" : +2024-08-01 13:30:14,157 - INFO - Fila 5899, Columna ru-RU: "Hardware DRS" actualizado a "Hardware DRS" : +2024-08-01 13:30:14,159 - INFO - Fila 5919, Columna ru-RU: "Normal Work" actualizado a "Normal Work" : +2024-08-01 13:30:14,159 - INFO - Fila 5920, Columna ru-RU: "Normal Work" actualizado a "Normal Work" : +2024-08-01 13:30:14,160 - INFO - Fila 5921, Columna ru-RU: "Normal Work" actualizado a "Normal Work" : +2024-08-01 13:30:14,166 - INFO - Fila 5951, Columna ru-RU: "Higher Infeed Platform Belt" actualizado a "Higher Infeed Platform Belt" : +2024-08-01 13:30:14,166 - INFO - Fila 5952, Columna ru-RU: "Hinge Conveyor Infeed" actualizado a "Hinge Conveyor Infeed" : +2024-08-01 13:30:14,166 - INFO - Fila 5953, Columna ru-RU: "Lower Infeed Platform Accumulation" actualizado a "Lower Infeed Platform Accumulation" : +2024-08-01 13:30:14,167 - INFO - Fila 5954, Columna ru-RU: "Lower Infeed Platform Belt" actualizado a "Lower Infeed Platform Belt" : +2024-08-01 13:30:14,167 - INFO - Fila 5956, Columna ru-RU: "Pack Divider Infeed" actualizado a "Pack Divider Infeed" : +2024-08-01 13:30:14,169 - INFO - Fila 5970, Columna ru-RU: "Pal Infeed Channel A (Left)" actualizado a "Pal Infeed Channel A (Left)" : +2024-08-01 13:30:14,169 - INFO - Fila 5971, Columna ru-RU: "Pal Infeed Channel B (Right)" actualizado a "Pal Infeed Channel B (Right)" : +2024-08-01 13:30:14,170 - INFO - Fila 5972, Columna ru-RU: "Initialization" actualizado a "Initialization" : +2024-08-01 13:30:14,171 - INFO - Fila 5988, Columna ru-RU: "Positioning interruption" actualizado a "Positioning interruption" : +2024-08-01 13:30:14,172 - INFO - Fila 5989, Columna ru-RU: "Oil aging overtemperature" actualizado a "Oil aging overtemperature" : +2024-08-01 13:30:14,172 - INFO - Fila 5992, Columna ru-RU: "Ion_Alm" actualizado a "Ion_Alm" : +2024-08-01 13:30:14,173 - INFO - Fila 5993, Columna ru-RU: "Ion_Level" actualizado a "Ion_Level" : +2024-08-01 13:30:14,173 - INFO - Fila 5994, Columna ru-RU: "Ion_Sts_Alm" actualizado a "Ion_Sts_Alm" : +2024-08-01 13:30:14,173 - INFO - Fila 5995, Columna ru-RU: "IPOS-ILLOP" actualizado a "IPOS-ILLOP" : +2024-08-01 13:30:14,175 - INFO - Fila 6007, Columna ru-RU: "KRONES" actualizado a "KRONES" : +2024-08-01 13:30:14,176 - INFO - Fila 6010, Columna ru-RU: "Labeller Selected" actualizado a "Labeller Selected" : +2024-08-01 13:30:14,178 - INFO - Fila 6027, Columna ru-RU: "EcoLab Lubrification" actualizado a "EcoLab Lubrification" : +2024-08-01 13:30:14,196 - INFO - Fila 6386, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,196 - INFO - Fila 6387, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,197 - INFO - Fila 6388, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,197 - INFO - Fila 6389, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,217 - INFO - Fila 6516, Columna ru-RU: "Fieldbus mode incompatible with hardware present" actualizado a "Fieldbus mode incompatible with hardware present" : +2024-08-01 13:30:14,221 - INFO - Fila 6539, Columna ru-RU: "No Request" actualizado a "No Request" : +2024-08-01 13:30:14,221 - INFO - Fila 6540, Columna ru-RU: "No Request" actualizado a "No Request" : +2024-08-01 13:30:14,222 - INFO - Fila 6541, Columna ru-RU: "No Request" actualizado a "No Request" : +2024-08-01 13:30:14,222 - INFO - Fila 6542, Columna ru-RU: "No Request" actualizado a "No Request" : +2024-08-01 13:30:14,222 - INFO - Fila 6543, Columna ru-RU: "No Request" actualizado a "No Request" : +2024-08-01 13:30:14,223 - INFO - Fila 6544, Columna ru-RU: "No Allarm: In Production" actualizado a "No Allarm: In Production" : +2024-08-01 13:30:14,223 - INFO - Fila 6545, Columna ru-RU: "No Allarm: In Production" actualizado a "No Allarm: In Production" : +2024-08-01 13:30:14,223 - INFO - Fila 6546, Columna ru-RU: "No Allarm: In Production" actualizado a "No Allarm: In Production" : +2024-08-01 13:30:14,223 - INFO - Fila 6547, Columna ru-RU: "No Allarm: In Production" actualizado a "No Allarm: In Production" : +2024-08-01 13:30:14,224 - INFO - Fila 6548, Columna ru-RU: "No Allarm: In Production" actualizado a "No Allarm: In Production" : +2024-08-01 13:30:14,224 - INFO - Fila 6549, Columna ru-RU: "No Allarm: In Production" actualizado a "No Allarm: In Production" : +2024-08-01 13:30:14,224 - INFO - Fila 6550, Columna ru-RU: "Nessuna Selezione" actualizado a "Nessuna Selezione" : +2024-08-01 13:30:14,224 - INFO - Fila 6551, Columna ru-RU: "Nessuna Selezione" actualizado a "Nessuna Selezione" : +2024-08-01 13:30:14,237 - INFO - Fila 6690, Columna ru-RU: "Palletizer" actualizado a "Palletizer" : +2024-08-01 13:30:14,268 - ERROR - Fila 6931, Columna ru-RU: "Recipe_element_14" valor:"Recipe_element_<>" no actualizado porque Error de verificación: - Celda clave: RCP\CONSENSI\DISCHARGE\SYNCHROBLOC - Celda traducida: Recipe_element_<> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:30:14,268 - ERROR - Fila 6932, Columna ru-RU: "Recipe_element_13" valor:"Recipe_element_<>" no actualizado porque Error de verificación: - Celda clave: RCP\CONSENSI\INFEED\SYNCHROBLOC - Celda traducida: Recipe_element_<> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:30:14,274 - INFO - Fila 6966, Columna ru-RU: "Filler" actualizado a "Filler" : +2024-08-01 13:30:14,274 - INFO - Fila 6967, Columna ru-RU: "Filler" actualizado a "Filler" : +2024-08-01 13:30:14,274 - INFO - Fila 6968, Columna ru-RU: "Filler" actualizado a "Filler" : +2024-08-01 13:30:14,275 - INFO - Fila 6969, Columna ru-RU: "Filler" actualizado a "Filler" : +2024-08-01 13:30:14,275 - INFO - Fila 6970, Columna ru-RU: "Filler" actualizado a "Filler" : +2024-08-01 13:30:14,275 - INFO - Fila 6971, Columna ru-RU: "Filler" actualizado a "Filler" : +2024-08-01 13:30:14,275 - INFO - Fila 6972, Columna ru-RU: "Filler" actualizado a "Filler" : +2024-08-01 13:30:14,276 - INFO - Fila 6973, Columna ru-RU: "Labeller Reference" actualizado a "Labeller Reference" : +2024-08-01 13:30:14,276 - INFO - Fila 6974, Columna ru-RU: "Labeller Reference" actualizado a "Labeller Reference" : +2024-08-01 13:30:14,276 - INFO - Fila 6983, Columna ru-RU: "Pal Reference" actualizado a "Pal Reference" : +2024-08-01 13:30:14,277 - INFO - Fila 6984, Columna ru-RU: "Pal Reference" actualizado a "Pal Reference" : +2024-08-01 13:30:14,277 - INFO - Fila 6985, Columna ru-RU: "Filler Reference" actualizado a "Filler Reference" : +2024-08-01 13:30:14,278 - INFO - Fila 6986, Columna ru-RU: "Filler Reference" actualizado a "Filler Reference" : +2024-08-01 13:30:14,278 - INFO - Fila 6987, Columna ru-RU: "Filler Reference" actualizado a "Filler Reference" : +2024-08-01 13:30:14,278 - INFO - Fila 6988, Columna ru-RU: "VDOS Reference" actualizado a "VDOS Reference" : +2024-08-01 13:30:14,279 - INFO - Fila 6989, Columna ru-RU: "VREC Reference" actualizado a "VREC Reference" : +2024-08-01 13:30:14,279 - INFO - Fila 6990, Columna ru-RU: "VREC Reference" actualizado a "VREC Reference" : +2024-08-01 13:30:14,279 - INFO - Fila 6991, Columna ru-RU: "VREC Reference" actualizado a "VREC Reference" : +2024-08-01 13:30:14,279 - INFO - Fila 6992, Columna ru-RU: "VREC Reference" actualizado a "VREC Reference" : +2024-08-01 13:30:14,280 - INFO - Fila 6993, Columna ru-RU: "VSFI Reference" actualizado a "VSFI Reference" : +2024-08-01 13:30:14,280 - INFO - Fila 6994, Columna ru-RU: "VSFI Reference" actualizado a "VSFI Reference" : +2024-08-01 13:30:14,280 - INFO - Fila 6995, Columna ru-RU: "Labeller Early Restart" actualizado a "Labeller Early Restart" : +2024-08-01 13:30:14,280 - INFO - Fila 6996, Columna ru-RU: "Sinchrobloc Early Restart" actualizado a "Sinchrobloc Early Restart" : +2024-08-01 13:30:14,281 - INFO - Fila 6997, Columna ru-RU: "Filler Early Restart" actualizado a "Filler Early Restart" : +2024-08-01 13:30:14,295 - INFO - Fila 7190, Columna ru-RU: "Fieldbus card not consistent with the selected one" actualizado a "Fieldbus card not consistent with the selected one" : +2024-08-01 13:30:14,295 - INFO - Fila 7191, Columna ru-RU: "Fieldbus card not initialised correctly" actualizado a "Fieldbus card not initialised correctly" : +2024-08-01 13:30:14,295 - INFO - Fila 7192, Columna ru-RU: "Wireless card not working" actualizado a "Wireless card not working" : +2024-08-01 13:30:14,296 - INFO - Fila 7193, Columna ru-RU: "Wireless card not working" actualizado a "Wireless card not working" : +2024-08-01 13:30:14,323 - INFO - Fila 7339, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,324 - INFO - Fila 7340, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,324 - INFO - Fila 7341, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,325 - INFO - Fila 7342, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,325 - INFO - Fila 7343, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,325 - INFO - Fila 7344, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,325 - INFO - Fila 7345, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,326 - INFO - Fila 7346, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,326 - INFO - Fila 7347, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,326 - INFO - Fila 7348, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,326 - INFO - Fila 7349, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,327 - INFO - Fila 7350, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,327 - INFO - Fila 7351, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,327 - INFO - Fila 7352, Columna ru-RU: "стоп Carico Preforme" actualizado a "стоп Carico Preforme" : +2024-08-01 13:30:14,338 - INFO - Fila 7418, Columna ru-RU: "Security memory fieldbus card not working" actualizado a "Security memory fieldbus card not working" : +2024-08-01 13:30:14,345 - ERROR - Fila 7467, Columna ru-RU: "Настройка смазки — зона 1 [Mxx-Myy]" valor:"Настройка смазки — зона <> [Mxx-Myy]" no actualizado porque Error de verificación: - Celda clave: Setup Lubrificazione a Secco - Celda traducida: Настройка смазки — зона <> [Mxx-Myy] - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:30:14,351 - INFO - Fila 7507, Columna ru-RU: "Sleever" actualizado a "Sleever" : +2024-08-01 13:30:14,351 - INFO - Fila 7509, Columna ru-RU: "Blower" actualizado a "Blower" : +2024-08-01 13:30:14,353 - INFO - Fila 7531, Columna ru-RU: "фактическая скор. Hz" actualizado a "фактическая скор. Hz" : +2024-08-01 13:30:14,354 - INFO - Fila 7532, Columna ru-RU: "фактическая скор. Hz" actualizado a "фактическая скор. Hz" : +2024-08-01 13:30:14,354 - INFO - Fila 7535, Columna ru-RU: "требуемая ско. Hz" actualizado a "требуемая ско. Hz" : +2024-08-01 13:30:14,355 - INFO - Fila 7536, Columna ru-RU: "требуемая ско. Hz" actualizado a "требуемая ско. Hz" : +2024-08-01 13:30:14,359 - INFO - Fila 7570, Columna ru-RU: "история тревоги" actualizado a "история тревоги" : +2024-08-01 13:30:14,361 - INFO - Fila 7592, Columna ru-RU: "Homing switches not configured correctly" actualizado a "Homing switches not configured correctly" : +2024-08-01 13:30:14,384 - ERROR - Fila 8015, Columna ru-RU: "Recipe_element_2" valor:"Recipe_element_<>" no actualizado porque Error de verificación: - Celda clave: TILTER/PID_RCP - Celda traducida: Recipe_element_<> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:30:14,384 - ERROR - Fila 8016, Columna ru-RU: "Recipe_element_1" valor:"Recipe_element_<>" no actualizado porque Error de verificación: - Celda clave: TILTER/RCP - Celda traducida: Recipe_element_<> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:30:14,386 - INFO - Fila 8028, Columna ru-RU: "Timeout during Homing procedure" actualizado a "Timeout during Homing procedure" : +2024-08-01 13:30:14,389 - INFO - Fila 8056, Columna ru-RU: "Engine Type Not Selected" actualizado a "Engine Type Not Selected" : +2024-08-01 13:30:14,394 - INFO - Fila 8090, Columna ru-RU: "Infeed Pack Conveyors Running" actualizado a "Infeed Pack Conveyors Running" : +2024-08-01 13:30:14,395 - INFO - Fila 8095, Columna ru-RU: "Left (A) Infeed Conveyors Running" actualizado a "Left (A) Infeed Conveyors Running" : +2024-08-01 13:30:14,395 - INFO - Fila 8096, Columna ru-RU: "Left (A) Infeed Conveyors Running" actualizado a "Left (A) Infeed Conveyors Running" : +2024-08-01 13:30:14,397 - INFO - Fila 8105, Columna ru-RU: "Higher Conveyor Platform" actualizado a "Higher Conveyor Platform" : +2024-08-01 13:30:14,397 - INFO - Fila 8106, Columna ru-RU: "Lower Conveyor Platform" actualizado a "Lower Conveyor Platform" : +2024-08-01 13:30:14,400 - INFO - Fila 8151, Columna ru-RU: "Higher Discharge Hinge Conveyor" actualizado a "Higher Discharge Hinge Conveyor" : +2024-08-01 13:30:14,401 - INFO - Fila 8154, Columna ru-RU: "Lower Discharge Hinge Conveyor" actualizado a "Lower Discharge Hinge Conveyor" : +2024-08-01 13:30:14,401 - INFO - Fila 8155, Columna ru-RU: "Pack Divider Discharge" actualizado a "Pack Divider Discharge" : +2024-08-01 13:30:14,401 - INFO - Fila 8156, Columna ru-RU: "Pack Divider Discharge Right" actualizado a "Pack Divider Discharge Right" : +2024-08-01 13:30:14,401 - INFO - Fila 8157, Columna ru-RU: "Pack Divider Discharge Left" actualizado a "Pack Divider Discharge Left" : +2024-08-01 13:30:14,402 - INFO - Fila 8158, Columna ru-RU: "Labeller Discharge" actualizado a "Labeller Discharge" : +2024-08-01 13:30:14,403 - INFO - Fila 8162, Columna ru-RU: "Labeller Discharge (Slowing Conveyor)" actualizado a "Labeller Discharge (Slowing Conveyor)" : +2024-08-01 13:30:14,403 - INFO - Fila 8172, Columna ru-RU: "Handler Discharge (Accumulation, Right)" actualizado a "Handler Discharge (Accumulation, Right)" : +2024-08-01 13:30:14,404 - INFO - Fila 8173, Columna ru-RU: "Handler Discharge (Accumulation, Left)" actualizado a "Handler Discharge (Accumulation, Left)" : +2024-08-01 13:30:14,404 - INFO - Fila 8174, Columna ru-RU: "Platform Discharge" actualizado a "Platform Discharge" : +2024-08-01 13:30:14,404 - INFO - Fila 8175, Columna ru-RU: "Platform Discharge Accumulation" actualizado a "Platform Discharge Accumulation" : +2024-08-01 13:30:14,404 - INFO - Fila 8176, Columna ru-RU: "Sinchrobloc Discharge" actualizado a "Sinchrobloc Discharge" : +2024-08-01 13:30:14,405 - INFO - Fila 8177, Columna ru-RU: "Sinchrobloc Discharge (Reject Table)" actualizado a "Sinchrobloc Discharge (Reject Table)" : +2024-08-01 13:30:14,405 - INFO - Fila 8179, Columna ru-RU: "Sinchrobloc Discharge (Slowing Conveyor)" actualizado a "Sinchrobloc Discharge (Slowing Conveyor)" : +2024-08-01 13:30:14,410 - INFO - Fila 8245, Columna ru-RU: "максимальная скорость" actualizado a "максимальная скорость" : +2024-08-01 13:30:14,417 - INFO - Fila 8282, Columna ru-RU: "Check With Format" actualizado a "Check With Format" : +2024-08-01 13:30:14,419 - INFO - Fila 8283, Columna ru-RU: "Check With Format" actualizado a "Check With Format" : +2024-08-01 13:30:14,419 - INFO - Fila 8284, Columna ru-RU: "Check With Format" actualizado a "Check With Format" : +2024-08-01 13:30:14,419 - INFO - Fila 8285, Columna ru-RU: "Check With Format" actualizado a "Check With Format" : +2024-08-01 13:30:14,420 - INFO - Fila 8286, Columna ru-RU: "Check With Format" actualizado a "Check With Format" : +2024-08-01 13:30:20,906 - INFO - Se han actualizado las filas en C:/Trabajo/VM/22 - 93841 - Sidel - Tilting/Reporte/Translate/TIAProjectTexts.xlsx desde el archivo maestro. : +2024-08-01 13:30:20,906 - INFO - .... : +2024-08-01 13:38:37,368 - INFO - .... : +2024-08-01 13:38:37,369 - INFO - Iniciando actualizacion en C:/Trabajo/VM/22 - 93841 - Sidel - Tilting/Reporte/Translate/TIAProjectTexts.xlsx desde el archivo maestro. Para ru-RU : +2024-08-01 13:39:20,406 - INFO - .... : +2024-08-01 13:39:20,407 - INFO - Iniciando actualizacion en C:/Trabajo/VM/22 - 93841 - Sidel - Tilting/Reporte/Translate/TIAProjectTexts.xlsx desde el archivo maestro. Para ru-RU : +2024-08-01 13:49:34,956 - INFO - .... : +2024-08-01 13:49:34,956 - INFO - Iniciando actualizacion en C:/Trabajo/VM/22 - 93841 - Sidel - Tilting/Reporte/Translate/TIAProjectTexts.xlsx desde el archivo maestro. Para ru-RU : +2024-08-01 13:49:35,517 - INFO - Fila 304 : Clave: ### ERRORE ###, Columna ru-RU: "nan" actualizado a "### ОШИБКА ###" : +2024-08-01 13:49:35,518 - INFO - Fila 305 : Clave: ### ERRORE ###, Columna ru-RU: "текст 1" actualizado a "### ОШИБКА ###" : +2024-08-01 13:49:35,518 - INFO - Fila 306 : Clave: ### ERRORE ###, Columna ru-RU: "текст 1" actualizado a "### ОШИБКА ###" : +2024-08-01 13:49:35,518 - INFO - Fila 307 : Clave: ### ERRORE ###, Columna ru-RU: "nan" actualizado a "### ОШИБКА ###" : +2024-08-01 13:49:35,519 - INFO - Fila 308 : Clave: ### ERRORE ###, Columna ru-RU: "nan" actualizado a "### ОШИБКА ###" : +2024-08-01 13:49:35,520 - ERROR - Fila 327, Columna ru-RU: "текст 1" valor:"текст <>" no actualizado porque Error de verificación: - Celda clave: ### Output Scorta IN - ERRORE TESTO ### - Celda traducida: текст <> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:49:35,520 - ERROR - Fila 328, Columna ru-RU: "текст 1" valor:"текст <>" no actualizado porque Error de verificación: - Celda clave: ### Output Scorta OUT - ERRORE TESTO ### - Celda traducida: текст <> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:49:35,522 - INFO - Fila 351 : Clave: #### ERRORE ####, Columna ru-RU: "nan" actualizado a "#### ОШИБКА ####" : +2024-08-01 13:49:35,522 - INFO - Fila 352 : Clave: #### ERRORE ####, Columna ru-RU: "nan" actualizado a "#### ОШИБКА ####" : +2024-08-01 13:49:35,523 - INFO - Fila 353 : Clave: #### ERRORE ####, Columna ru-RU: "текст 1" actualizado a "#### ОШИБКА ####" : +2024-08-01 13:49:35,583 - ERROR - Fila 1899, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,584 - ERROR - Fila 1900, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,584 - ERROR - Fila 1901, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,584 - ERROR - Fila 1902, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,585 - ERROR - Fila 1904, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,585 - ERROR - Fila 1905, Columna ru-RU: "этикетировочные" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,585 - ERROR - Fila 1906, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,586 - ERROR - Fila 1907, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,586 - ERROR - Fila 1908, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,586 - ERROR - Fila 1909, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,586 - ERROR - Fila 1910, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,587 - ERROR - Fila 1911, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,587 - ERROR - Fila 1912, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,587 - ERROR - Fila 1914, Columna ru-RU: "" valor:"Text" no actualizado porque Error de verificación: - Celda clave: - Celda traducida: Text - Dígitos en clave: 0, Dígitos en traducida: 0 - Tags en clave: 1, Tags en traducida: 0 : +2024-08-01 13:49:35,783 - ERROR - Fila 5263, Columna ru-RU: "реле давления S1M03 - OK" valor:"реле давления S<>M<> - OK" no actualizado porque Error de verificación: - Celda clave: Abilitazione - Celda traducida: реле давления S<>M<> - OK - Dígitos en clave: 0, Dígitos en traducida: 2 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:49:35,792 - INFO - Fila 5306 : Clave: Accumulo Ingresso DOS, Columna ru-RU: "nan" actualizado a "Накопление Вход DOS" : +2024-08-01 13:49:35,797 - INFO - Fila 5335 : Clave: Allarme, Columna ru-RU: "реле давления S1M03 - OK" actualizado a "Текст" : +2024-08-01 13:49:35,799 - INFO - Fila 5342 : Clave: Allarme del Watchdog Modbus, Columna ru-RU: "nan" actualizado a "Сигнализация Watchdog Modbus" : +2024-08-01 13:49:35,799 - INFO - Fila 5343 : Clave: Allarme di time-out procedura di autotuning parametri elettrici, Columna ru-RU: "nan" actualizado a "Сигнализация тайм-аута процедуры автотюнинга электрических параметров" : +2024-08-01 13:49:35,799 - INFO - Fila 5344 : Clave: Allarme Encoder SPI della parte Multi Turn, la posizione multigiro non è più affidabile, Columna ru-RU: "nan" actualizado a "Сигнализация Encoder SPI многооборотной части, многооборотная позиция больше не надежна" : +2024-08-01 13:49:35,800 - INFO - Fila 5345 : Clave: Allarme Encoder SPI della parte Single Turn, la posizione singolo giro non è più affidabile, Columna ru-RU: "nan" actualizado a "Сигнализация Encoder SPI однородной части, однородная позиция больше не надежна" : +2024-08-01 13:49:35,800 - INFO - Fila 5346 : Clave: Allarme flash dati non funzionante, Columna ru-RU: "nan" actualizado a "Сигнализация неисправности флеш-памяти" : +2024-08-01 13:49:35,800 - INFO - Fila 5347 : Clave: Allarme lettura encoder SPI , Columna ru-RU: "nan" actualizado a "Сигнализация чтения энкодера SPI" : +2024-08-01 13:49:35,801 - INFO - Fila 5348 : Clave: Allarme memoria parametri non accessibile o corrotta, Columna ru-RU: "nan" actualizado a "Сигнализация недоступной или поврежденной памяти параметров" : +2024-08-01 13:49:35,801 - INFO - Fila 5349 : Clave: Allarme Non Presente, Columna ru-RU: "nan" actualizado a "Сигнализация Не Присутствует" : +2024-08-01 13:49:35,801 - INFO - Fila 5350 : Clave: Allarme overcurrent hardware, Columna ru-RU: "nan" actualizado a "Сигнализация аппаратного перенапряжения" : +2024-08-01 13:49:35,802 - INFO - Fila 5351 : Clave: Allarme overcurrent software, Columna ru-RU: "nan" actualizado a "Сигнализация программного перенапряжения" : +2024-08-01 13:49:35,802 - INFO - Fila 5352 : Clave: Allarme overtemperature motore, Columna ru-RU: "nan" actualizado a "Сигнализация перегрева двигателя" : +2024-08-01 13:49:35,803 - INFO - Fila 5353 : Clave: Allarme overtemperature scheda, Columna ru-RU: "nan" actualizado a "Сигнал тревоги о перегреве платы" : +2024-08-01 13:49:35,804 - INFO - Fila 5354 : Clave: Allarme overvoltage , Columna ru-RU: "nan" actualizado a "Сигнал тревоги о перенапряжении" : +2024-08-01 13:49:35,804 - INFO - Fila 5355 : Clave: Allarme parametro con valore sbagliato, Columna ru-RU: "nan" actualizado a "Сигнал тревоги о неправильном значении параметра" : +2024-08-01 13:49:35,804 - INFO - Fila 5356 : Clave: Allarme restore parametri default fallita, Columna ru-RU: "nan" actualizado a "Сигнал тревоги о неудачном восстановлении параметров по умолчанию" : +2024-08-01 13:49:35,805 - INFO - Fila 5357 : Clave: Allarme restore parametri motore default fallita, Columna ru-RU: "nan" actualizado a "Сигнал тревоги о неудачном восстановлении параметров двигателя по умолчанию" : +2024-08-01 13:49:35,805 - INFO - Fila 5358 : Clave: Allarme undervoltage, Columna ru-RU: "nan" actualizado a "Сигнал тревоги о пониженном напряжении" : +2024-08-01 13:49:35,806 - INFO - Fila 5359 : Clave: Allarme Utente, Columna ru-RU: "nan" actualizado a "Сигнал тревоги пользователя" : +2024-08-01 13:49:35,806 - INFO - Fila 5360 : Clave: Allarme utente da ingresso digitale, Columna ru-RU: "nan" actualizado a "Сигнал тревоги пользователя от цифрового входа" : +2024-08-01 13:49:35,809 - INFO - Fila 5375 : Clave: ALLARME: Sicurezza non attivata, Columna ru-RU: "JAM OUTFEED CONE" actualizado a "ALLARM: DX Channel Valve Sensors Gate A" : +2024-08-01 13:49:35,810 - ERROR - Fila 5380, Columna ru-RU: "аварийные сигналы - делителя [DB1071]" valor:"аварийные сигналы - делителя [DB<>]" no actualizado porque Error de verificación: - Celda clave: Allarmi - SKID - Celda traducida: аварийные сигналы - делителя [DB<>] - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:49:35,810 - ERROR - Fila 5381, Columna ru-RU: "аварийные сигналы - Geosync [DB10171]" valor:"аварийные сигналы - Geosync [DB<>]" no actualizado porque Error de verificación: - Celda clave: Allarmi - Tilter - Celda traducida: аварийные сигналы - Geosync [DB<>] - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:49:35,825 - INFO - Fila 5535 : Clave: Basculante, Columna ru-RU: "nan" actualizado a "Подъемный механизм" : +2024-08-01 13:49:35,825 - INFO - Fila 5539 : Clave: Basso [Basculante], Columna ru-RU: "nan" actualizado a "Низкий [Подъемный механизм]" : +2024-08-01 13:49:35,826 - INFO - Fila 5540 : Clave: Basso [Piattaforma], Columna ru-RU: "nan" actualizado a "Низкий [Платформа]" : +2024-08-01 13:49:35,828 - INFO - Fila 5553 : Clave: Bypass, Columna ru-RU: "nan" actualizado a "Обход" : +2024-08-01 13:49:35,829 - INFO - Fila 5558 : Clave: Canale A, Columna ru-RU: "nan" actualizado a "Канал A" : +2024-08-01 13:49:35,829 - INFO - Fila 5559 : Clave: Canale B, Columna ru-RU: "nan" actualizado a "Канал B" : +2024-08-01 13:49:35,836 - INFO - Fila 5589 : Clave: Chiamata Fardelli, Columna ru-RU: "nan" actualizado a "Вызов пакетов" : +2024-08-01 13:49:35,836 - INFO - Fila 5590 : Clave: Chiamata Fardelli, Columna ru-RU: "стоп Carico Preforme" actualizado a "Вызов пакетов" : +2024-08-01 13:49:35,836 - INFO - Fila 5591 : Clave: Chiamati Pacchi Canale Destro (B), Columna ru-RU: "nan" actualizado a "Вызванные пакеты канала справа (B)" : +2024-08-01 13:49:35,837 - INFO - Fila 5592 : Clave: Chiamati Pacchi Canale Sinistro (A), Columna ru-RU: "nan" actualizado a "Packs Request on Left Channel (A)" : +2024-08-01 13:49:35,849 - INFO - Fila 5672 : Clave: Devio Ingresso Fardellatrici, Columna ru-RU: "nan" actualizado a "Manual Divider Infeed Wrappers" : +2024-08-01 13:49:35,851 - INFO - Fila 5682 : Clave: Divisore Pacchi, Columna ru-RU: "nan" actualizado a "Pack Divider" : +2024-08-01 13:49:35,858 - INFO - Fila 5759 : Clave: Encoder non ancora allineato, Columna ru-RU: "nan" actualizado a "Encoder not aligned yet" : +2024-08-01 13:49:35,858 - INFO - Fila 5760 : Clave: Encoder non rileva movimento, Columna ru-RU: "nan" actualizado a "Encoder does not detect movement" : +2024-08-01 13:49:35,858 - INFO - Fila 5761 : Clave: Encoder rileva movimento lato sbagliato, Columna ru-RU: "nan" actualizado a "Encoder detects wrong side movement" : +2024-08-01 13:49:35,859 - INFO - Fila 5767 : Clave: Errore Hmi, Columna ru-RU: "nan" actualizado a "Hmi Error" : +2024-08-01 13:49:35,860 - INFO - Fila 5768 : Clave: Errore Hmi, Columna ru-RU: "nan" actualizado a "Hmi Error" : +2024-08-01 13:49:35,860 - INFO - Fila 5769 : Clave: Errore Hmi, Columna ru-RU: "nan" actualizado a "Hmi Error" : +2024-08-01 13:49:35,861 - INFO - Fila 5770 : Clave: Errore Hmi, Columna ru-RU: "nan" actualizado a "Hmi Error" : +2024-08-01 13:49:35,861 - INFO - Fila 5771 : Clave: Errore Hmi, Columna ru-RU: "nan" actualizado a "Hmi Error" : +2024-08-01 13:49:35,862 - INFO - Fila 5772 : Clave: Errore nel riferimento di posizione del modo CSP, Columna ru-RU: "nan" actualizado a "CSP mode position reference error" : +2024-08-01 13:49:35,862 - INFO - Fila 5773 : Clave: Errore nella sincronizzazione CSP, Columna ru-RU: "nan" actualizado a "Error in CSP synchronization" : +2024-08-01 13:49:35,864 - INFO - Fila 5781 : Clave: Etichettatrice, Columna ru-RU: "nan" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:35,864 - INFO - Fila 5782 : Clave: Etichettatrice, Columna ru-RU: "nan" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:35,864 - INFO - Fila 5783 : Clave: Etichettatrice, Columna ru-RU: "этикетировочные" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:35,865 - INFO - Fila 5784 : Clave: Etichettatrice, Columna ru-RU: "этикетировочные" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:35,873 - INFO - Fila 5869 : Clave: Fuori Posizione, Columna ru-RU: "nan" actualizado a "Out Of Position" : +2024-08-01 13:49:35,873 - INFO - Fila 5870 : Clave: Fuori Posizione, Columna ru-RU: "nan" actualizado a "Out Of Position" : +2024-08-01 13:49:35,873 - INFO - Fila 5871 : Clave: Fuori Posizione, Columna ru-RU: "nan" actualizado a "Out Of Position" : +2024-08-01 13:49:35,875 - INFO - Fila 5879 : Clave: Geosync DOS, Columna ru-RU: "nan" actualizado a "Geosync DOS" : +2024-08-01 13:49:35,877 - INFO - Fila 5899 : Clave: Hardware DRS, Columna ru-RU: "nan" actualizado a "Hardware DRS" : +2024-08-01 13:49:35,879 - INFO - Fila 5919 : Clave: In Funzione, Columna ru-RU: "nan" actualizado a "Normal Work" : +2024-08-01 13:49:35,879 - INFO - Fila 5920 : Clave: In Funzione, Columna ru-RU: "Готовый" actualizado a "Normal Work" : +2024-08-01 13:49:35,880 - INFO - Fila 5921 : Clave: In Funzione, Columna ru-RU: "nan" actualizado a "Normal Work" : +2024-08-01 13:49:35,886 - INFO - Fila 5951 : Clave: Ingresso Alto Piattaforma Tappeto, Columna ru-RU: "nan" actualizado a "Higher Infeed Platform Belt" : +2024-08-01 13:49:35,886 - INFO - Fila 5952 : Clave: Ingresso Basculante, Columna ru-RU: "nan" actualizado a "Hinge Conveyor Infeed" : +2024-08-01 13:49:35,887 - INFO - Fila 5953 : Clave: Ingresso Basso Piattaforma Accumulo, Columna ru-RU: "nan" actualizado a "Lower Infeed Platform Accumulation" : +2024-08-01 13:49:35,887 - INFO - Fila 5954 : Clave: Ingresso Basso Piattaforma Tappeto, Columna ru-RU: "nan" actualizado a "Lower Infeed Platform Belt" : +2024-08-01 13:49:35,888 - INFO - Fila 5956 : Clave: Ingresso Divisore Pacchi, Columna ru-RU: "nan" actualizado a "Pack Divider Infeed" : +2024-08-01 13:49:35,889 - INFO - Fila 5970 : Clave: Ingresso Pal Canale A (Sinistra), Columna ru-RU: "nan" actualizado a "Pal Infeed Channel A (Left)" : +2024-08-01 13:49:35,889 - INFO - Fila 5971 : Clave: Ingresso Pal Canale B (Destra), Columna ru-RU: "nan" actualizado a "Pal Infeed Channel B (Right)" : +2024-08-01 13:49:35,889 - INFO - Fila 5972 : Clave: Inizializzazione, Columna ru-RU: "nan" actualizado a "Initialization" : +2024-08-01 13:49:35,891 - INFO - Fila 5988 : Clave: Interruzione posizionamento, Columna ru-RU: "nan" actualizado a "Positioning interruption" : +2024-08-01 13:49:35,891 - INFO - Fila 5989 : Clave: Invecchiamento/sovratemperatura olio, Columna ru-RU: "nan" actualizado a "Oil aging overtemperature" : +2024-08-01 13:49:35,892 - INFO - Fila 5992 : Clave: Ion_Alm, Columna ru-RU: "nan" actualizado a "Ion_Alm" : +2024-08-01 13:49:35,892 - INFO - Fila 5993 : Clave: Ion_Level, Columna ru-RU: "nan" actualizado a "Ion_Level" : +2024-08-01 13:49:35,893 - INFO - Fila 5994 : Clave: Ion_Sts_Alm, Columna ru-RU: "nan" actualizado a "Ion_Sts_Alm" : +2024-08-01 13:49:35,893 - INFO - Fila 5995 : Clave: IPOS-ILLOP, Columna ru-RU: "nan" actualizado a "IPOS-ILLOP" : +2024-08-01 13:49:35,895 - INFO - Fila 6007 : Clave: KRONES, Columna ru-RU: "nan" actualizado a "KRONES" : +2024-08-01 13:49:35,895 - INFO - Fila 6010 : Clave: Labeller Selected, Columna ru-RU: "nan" actualizado a "Labeller Selected" : +2024-08-01 13:49:35,899 - INFO - Fila 6027 : Clave: Lubrificazione EcoLab, Columna ru-RU: "nan" actualizado a "EcoLab Lubrification" : +2024-08-01 13:49:35,916 - INFO - Fila 6386 : Clave: Macchina Vuota, Columna ru-RU: "пустая машина" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:35,916 - INFO - Fila 6387 : Clave: Macchina Vuota, Columna ru-RU: "пустая машина" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:35,917 - INFO - Fila 6388 : Clave: Macchina Vuota, Columna ru-RU: "пустая машина" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:35,917 - INFO - Fila 6389 : Clave: Macchina Vuota, Columna ru-RU: "пустая машина" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:35,937 - INFO - Fila 6516 : Clave: Modalità fieldbus incompatibile con hardware presente, Columna ru-RU: "nan" actualizado a "Fieldbus mode incompatible with hardware present" : +2024-08-01 13:49:35,941 - INFO - Fila 6539 : Clave: Nessuna Richiesta, Columna ru-RU: "nan" actualizado a "No Request" : +2024-08-01 13:49:35,941 - INFO - Fila 6540 : Clave: Nessuna Richiesta, Columna ru-RU: "nan" actualizado a "No Request" : +2024-08-01 13:49:35,942 - INFO - Fila 6541 : Clave: Nessuna Richiesta, Columna ru-RU: "nan" actualizado a "No Request" : +2024-08-01 13:49:35,942 - INFO - Fila 6542 : Clave: Nessuna Richiesta, Columna ru-RU: "nan" actualizado a "No Request" : +2024-08-01 13:49:35,942 - INFO - Fila 6543 : Clave: Nessuna Richiesta, Columna ru-RU: "nan" actualizado a "No Request" : +2024-08-01 13:49:35,943 - INFO - Fila 6544 : Clave: Nessuna Segnalazione, Columna ru-RU: "nan" actualizado a "No Allarm: In Production" : +2024-08-01 13:49:35,943 - INFO - Fila 6545 : Clave: Nessuna Segnalazione: In Produzione, Columna ru-RU: "nan" actualizado a "No Allarm: In Production" : +2024-08-01 13:49:35,943 - INFO - Fila 6546 : Clave: Nessuna Segnalazione: In Produzione, Columna ru-RU: "nan" actualizado a "No Allarm: In Production" : +2024-08-01 13:49:35,943 - INFO - Fila 6547 : Clave: Nessuna Segnalazione: In Produzione, Columna ru-RU: "nan" actualizado a "No Allarm: In Production" : +2024-08-01 13:49:35,944 - INFO - Fila 6548 : Clave: Nessuna Segnalazione: In Produzione, Columna ru-RU: "nan" actualizado a "No Allarm: In Production" : +2024-08-01 13:49:35,944 - INFO - Fila 6549 : Clave: Nessuna Segnalazione: In Produzione, Columna ru-RU: "nan" actualizado a "No Allarm: In Production" : +2024-08-01 13:49:35,944 - INFO - Fila 6550 : Clave: Nessuna Selezione, Columna ru-RU: "nan" actualizado a "Nessuna Selezione" : +2024-08-01 13:49:35,945 - INFO - Fila 6551 : Clave: Nessuna Selezione, Columna ru-RU: "nan" actualizado a "Nessuna Selezione" : +2024-08-01 13:49:35,959 - INFO - Fila 6690 : Clave: Paletizzatore, Columna ru-RU: "nan" actualizado a "Palletizer" : +2024-08-01 13:49:35,992 - ERROR - Fila 6931, Columna ru-RU: "Recipe_element_14" valor:"Recipe_element_<>" no actualizado porque Error de verificación: - Celda clave: RCP\CONSENSI\DISCHARGE\SYNCHROBLOC - Celda traducida: Recipe_element_<> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:49:35,992 - ERROR - Fila 6932, Columna ru-RU: "Recipe_element_13" valor:"Recipe_element_<>" no actualizado porque Error de verificación: - Celda clave: RCP\CONSENSI\INFEED\SYNCHROBLOC - Celda traducida: Recipe_element_<> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:49:35,998 - INFO - Fila 6966 : Clave: Riempitrice, Columna ru-RU: "nan" actualizado a "Filler" : +2024-08-01 13:49:35,998 - INFO - Fila 6967 : Clave: Riempitrice, Columna ru-RU: "наполнитель" actualizado a "Filler" : +2024-08-01 13:49:35,998 - INFO - Fila 6968 : Clave: Riempitrice, Columna ru-RU: "наполнитель" actualizado a "Filler" : +2024-08-01 13:49:35,999 - INFO - Fila 6969 : Clave: Riempitrice, Columna ru-RU: "наполнитель" actualizado a "Filler" : +2024-08-01 13:49:35,999 - INFO - Fila 6970 : Clave: Riempitrice, Columna ru-RU: "наполнитель" actualizado a "Filler" : +2024-08-01 13:49:35,999 - INFO - Fila 6971 : Clave: Riempitrice, Columna ru-RU: "наполнитель" actualizado a "Filler" : +2024-08-01 13:49:36,000 - INFO - Fila 6972 : Clave: Riempitrice, Columna ru-RU: "наполнитель" actualizado a "Filler" : +2024-08-01 13:49:36,000 - INFO - Fila 6973 : Clave: Riferimento Etichettatrice, Columna ru-RU: "nan" actualizado a "Labeller Reference" : +2024-08-01 13:49:36,000 - INFO - Fila 6974 : Clave: Riferimento Etichettatrice, Columna ru-RU: "nan" actualizado a "Labeller Reference" : +2024-08-01 13:49:36,001 - INFO - Fila 6983 : Clave: Riferimento Pal, Columna ru-RU: "nan" actualizado a "Pal Reference" : +2024-08-01 13:49:36,001 - INFO - Fila 6984 : Clave: Riferimento Pal, Columna ru-RU: "nan" actualizado a "Pal Reference" : +2024-08-01 13:49:36,001 - INFO - Fila 6985 : Clave: Riferimento Riempitrice, Columna ru-RU: "nan" actualizado a "Filler Reference" : +2024-08-01 13:49:36,002 - INFO - Fila 6986 : Clave: Riferimento Riempitrice, Columna ru-RU: "nan" actualizado a "Filler Reference" : +2024-08-01 13:49:36,002 - INFO - Fila 6987 : Clave: Riferimento Riempitrice, Columna ru-RU: "nan" actualizado a "Filler Reference" : +2024-08-01 13:49:36,002 - INFO - Fila 6988 : Clave: Riferimento VDOS, Columna ru-RU: "nan" actualizado a "VDOS Reference" : +2024-08-01 13:49:36,003 - INFO - Fila 6989 : Clave: Riferimento VREC, Columna ru-RU: "nan" actualizado a "VREC Reference" : +2024-08-01 13:49:36,003 - INFO - Fila 6990 : Clave: Riferimento VREC, Columna ru-RU: "nan" actualizado a "VREC Reference" : +2024-08-01 13:49:36,003 - INFO - Fila 6991 : Clave: Riferimento VREC, Columna ru-RU: "nan" actualizado a "VREC Reference" : +2024-08-01 13:49:36,003 - INFO - Fila 6992 : Clave: Riferimento VREC, Columna ru-RU: "nan" actualizado a "VREC Reference" : +2024-08-01 13:49:36,004 - INFO - Fila 6993 : Clave: Riferimento VSFI, Columna ru-RU: "nan" actualizado a "VSFI Reference" : +2024-08-01 13:49:36,004 - INFO - Fila 6994 : Clave: Riferimento VSFI, Columna ru-RU: "nan" actualizado a "VSFI Reference" : +2024-08-01 13:49:36,004 - INFO - Fila 6995 : Clave: Ripartenza Anticipata Etichettatrice, Columna ru-RU: "nan" actualizado a "Labeller Early Restart" : +2024-08-01 13:49:36,005 - INFO - Fila 6996 : Clave: Ripartenza Anticipata Monoblocco, Columna ru-RU: "nan" actualizado a "Sinchrobloc Early Restart" : +2024-08-01 13:49:36,005 - INFO - Fila 6997 : Clave: Ripartenza Anticipata Riempitrice, Columna ru-RU: "nan" actualizado a "Filler Early Restart" : +2024-08-01 13:49:36,019 - INFO - Fila 7190 : Clave: Scheda fieldbus non coerente con quella selezionata, Columna ru-RU: "nan" actualizado a "Fieldbus card not consistent with the selected one" : +2024-08-01 13:49:36,019 - INFO - Fila 7191 : Clave: Scheda fieldbus non inizializzata correttamente, Columna ru-RU: "nan" actualizado a "Fieldbus card not initialised correctly" : +2024-08-01 13:49:36,019 - INFO - Fila 7192 : Clave: Scheda wireless non funzionante, Columna ru-RU: "nan" actualizado a "Wireless card not working" : +2024-08-01 13:49:36,020 - INFO - Fila 7193 : Clave: Scheda wireless non funzionante, Columna ru-RU: "nan" actualizado a "Wireless card not working" : +2024-08-01 13:49:36,048 - INFO - Fila 7339 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,048 - INFO - Fila 7340 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,049 - INFO - Fila 7341 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,049 - INFO - Fila 7342 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,049 - INFO - Fila 7343 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,050 - INFO - Fila 7344 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,050 - INFO - Fila 7345 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,050 - INFO - Fila 7346 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,051 - INFO - Fila 7347 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,051 - INFO - Fila 7348 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,051 - INFO - Fila 7349 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,052 - INFO - Fila 7350 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,052 - INFO - Fila 7351 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,052 - INFO - Fila 7352 : Clave: Scorta, Columna ru-RU: "запасной" actualizado a "стоп Carico Preforme" : +2024-08-01 13:49:36,064 - INFO - Fila 7418 : Clave: Secury memory scheda fieldbus non funzionante, Columna ru-RU: "nan" actualizado a "Security memory fieldbus card not working" : +2024-08-01 13:49:36,070 - ERROR - Fila 7467, Columna ru-RU: "Настройка смазки — зона 1 [Mxx-Myy]" valor:"Настройка смазки — зона <> [Mxx-Myy]" no actualizado porque Error de verificación: - Celda clave: Setup Lubrificazione a Secco - Celda traducida: Настройка смазки — зона <> [Mxx-Myy] - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:49:36,076 - INFO - Fila 7507 : Clave: Sleever, Columna ru-RU: "nan" actualizado a "Sleever" : +2024-08-01 13:49:36,076 - INFO - Fila 7509 : Clave: Soffiatrice, Columna ru-RU: "nan" actualizado a "Blower" : +2024-08-01 13:49:36,079 - INFO - Fila 7531 : Clave: SPEED - Actual Hz, Columna ru-RU: "скорость - актual Hz" actualizado a "фактическая скор. Hz" : +2024-08-01 13:49:36,079 - INFO - Fila 7532 : Clave: SPEED - Actual Hz, Columna ru-RU: "фактическая скор Hz" actualizado a "фактическая скор. Hz" : +2024-08-01 13:49:36,080 - INFO - Fila 7535 : Clave: SPEED - Req Hz, Columna ru-RU: "скорость - обязательный Hz" actualizado a "требуемая ско. Hz" : +2024-08-01 13:49:36,080 - INFO - Fila 7536 : Clave: SPEED - Req Hz, Columna ru-RU: "требуемая ско Hz" actualizado a "требуемая ско. Hz" : +2024-08-01 13:49:36,084 - INFO - Fila 7570 : Clave: Storico Allarmi, Columna ru-RU: "история аварий" actualizado a "история тревоги" : +2024-08-01 13:49:36,086 - INFO - Fila 7592 : Clave: Switch di homing non configurati correttamente, Columna ru-RU: "nan" actualizado a "Homing switches not configured correctly" : +2024-08-01 13:49:36,111 - ERROR - Fila 8015, Columna ru-RU: "Recipe_element_2" valor:"Recipe_element_<>" no actualizado porque Error de verificación: - Celda clave: TILTER/PID_RCP - Celda traducida: Recipe_element_<> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:49:36,111 - ERROR - Fila 8016, Columna ru-RU: "Recipe_element_1" valor:"Recipe_element_<>" no actualizado porque Error de verificación: - Celda clave: TILTER/RCP - Celda traducida: Recipe_element_<> - Dígitos en clave: 0, Dígitos en traducida: 1 - Tags en clave: 0, Tags en traducida: 0 : +2024-08-01 13:49:36,114 - INFO - Fila 8028 : Clave: Timeout durante procedura Homing, Columna ru-RU: "nan" actualizado a "Timeout during Homing procedure" : +2024-08-01 13:49:36,115 - INFO - Fila 8056 : Clave: Tipo di Motore non Selezionato, Columna ru-RU: "nan" actualizado a "Engine Type Not Selected" : +2024-08-01 13:49:36,121 - INFO - Fila 8090 : Clave: Trasportatori Pacchi In Ingresso In Marcia, Columna ru-RU: "nan" actualizado a "Infeed Pack Conveyors Running" : +2024-08-01 13:49:36,122 - INFO - Fila 8095 : Clave: Trasporti In Igresso Canale Sinistro (A) In Marcia, Columna ru-RU: "nan" actualizado a "Left (A) Infeed Conveyors Running" : +2024-08-01 13:49:36,123 - INFO - Fila 8096 : Clave: Trasporti In Igresso Canale Sinistro (A) In Marcia, Columna ru-RU: "nan" actualizado a "Left (A) Infeed Conveyors Running" : +2024-08-01 13:49:36,125 - INFO - Fila 8105 : Clave: Trasporto Alto Piattaforma, Columna ru-RU: "nan" actualizado a "Higher Conveyor Platform" : +2024-08-01 13:49:36,126 - INFO - Fila 8106 : Clave: Trasporto Basso Piattaforma, Columna ru-RU: "nan" actualizado a "Lower Conveyor Platform" : +2024-08-01 13:49:36,129 - INFO - Fila 8151 : Clave: Uscita Alta Basculante, Columna ru-RU: "nan" actualizado a "Higher Discharge Hinge Conveyor" : +2024-08-01 13:49:36,129 - INFO - Fila 8154 : Clave: Uscita Bassa Basculante, Columna ru-RU: "nan" actualizado a "Lower Discharge Hinge Conveyor" : +2024-08-01 13:49:36,130 - INFO - Fila 8155 : Clave: Uscita Divisore Pacchi, Columna ru-RU: "nan" actualizado a "Pack Divider Discharge" : +2024-08-01 13:49:36,130 - INFO - Fila 8156 : Clave: Uscita Divisore Pacchi Destra, Columna ru-RU: "nan" actualizado a "Pack Divider Discharge Right" : +2024-08-01 13:49:36,130 - INFO - Fila 8157 : Clave: Uscita Divisore Pacchi Sinistra, Columna ru-RU: "nan" actualizado a "Pack Divider Discharge Left" : +2024-08-01 13:49:36,130 - INFO - Fila 8158 : Clave: Uscita Etichettatrice, Columna ru-RU: "nan" actualizado a "Labeller Discharge" : +2024-08-01 13:49:36,131 - INFO - Fila 8162 : Clave: Uscita Etichettatrice (Rallentatore), Columna ru-RU: "nan" actualizado a "Labeller Discharge (Slowing Conveyor)" : +2024-08-01 13:49:36,132 - INFO - Fila 8172 : Clave: Uscita Manigliatrice (Accumulo, Destro), Columna ru-RU: "nan" actualizado a "Handler Discharge (Accumulation, Right)" : +2024-08-01 13:49:36,132 - INFO - Fila 8173 : Clave: Uscita Manigliatrice (Accumulo, Sinistro), Columna ru-RU: "nan" actualizado a "Handler Discharge (Accumulation, Left)" : +2024-08-01 13:49:36,132 - INFO - Fila 8174 : Clave: Uscita Piattaforma, Columna ru-RU: "nan" actualizado a "Platform Discharge" : +2024-08-01 13:49:36,132 - INFO - Fila 8175 : Clave: Uscita Piattaforma Accumulo, Columna ru-RU: "nan" actualizado a "Platform Discharge Accumulation" : +2024-08-01 13:49:36,133 - INFO - Fila 8176 : Clave: Uscita Sinchrobloc, Columna ru-RU: "nan" actualizado a "Sinchrobloc Discharge" : +2024-08-01 13:49:36,133 - INFO - Fila 8177 : Clave: Uscita Sinchrobloc (Bancale di Scarto), Columna ru-RU: "nan" actualizado a "Sinchrobloc Discharge (Reject Table)" : +2024-08-01 13:49:36,133 - INFO - Fila 8179 : Clave: Uscita Sinchrobloc (Rallentatore), Columna ru-RU: "nan" actualizado a "Sinchrobloc Discharge (Slowing Conveyor)" : +2024-08-01 13:49:36,140 - INFO - Fila 8245 : Clave: Velocità Attuale, Columna ru-RU: "диаметр бутылок " actualizado a "максимальная скорость" : +2024-08-01 13:49:36,147 - INFO - Fila 8282 : Clave: Verificare Con Formato, Columna ru-RU: "nan" actualizado a "Check With Format" : +2024-08-01 13:49:36,147 - INFO - Fila 8283 : Clave: Verificare Con Formato, Columna ru-RU: "nan" actualizado a "Check With Format" : +2024-08-01 13:49:36,147 - INFO - Fila 8284 : Clave: Verificare Con Formato, Columna ru-RU: "nan" actualizado a "Check With Format" : +2024-08-01 13:49:36,147 - INFO - Fila 8285 : Clave: Verificare Con Formato, Columna ru-RU: "nan" actualizado a "Check With Format" : +2024-08-01 13:49:36,148 - INFO - Fila 8286 : Clave: Verificare Con Formato, Columna ru-RU: "nan" actualizado a "Check With Format" : +2024-08-01 13:49:42,755 - INFO - Se han actualizado las filas en C:/Trabajo/VM/22 - 93841 - Sidel - Tilting/Reporte/Translate/TIAProjectTexts.xlsx desde el archivo maestro. : +2024-08-01 13:49:42,755 - INFO - .... : diff --git a/manejoArchivos.py b/manejoArchivos.py index f99cc52..bc9fcca 100644 --- a/manejoArchivos.py +++ b/manejoArchivos.py @@ -13,8 +13,8 @@ def select_file(extension = "txt"): # Open file dialog and return the selected file path file_path = filedialog.askopenfilename( - title="Select a .db file", - filetypes=(("DB files", f"*.{extension}"), ("All files", "*.*")) + title=f"Select a .{extension} file", + filetypes=((f"{extension} files", f"*.{extension}"), ("All files", "*.*")) ) return file_path diff --git a/x1_importar_to_master.py b/x1_importar_to_master.py index 00c30e1..c14da20 100644 --- a/x1_importar_to_master.py +++ b/x1_importar_to_master.py @@ -2,34 +2,27 @@ import pandas as pd import os import re from manejoArchivos import select_file -import funciones_comunes - -def es_columna_tipo_xxYY(columna): - # Verificar si la columna es del tipo "xx-YY" usando una expresión regular - return bool(re.match(r'^[a-z]{2}-[A-Z]{2}$', columna)) - -def sustituir_digitos(celda): - # Convertir a cadena y sustituir secuencias de dígitos por [[digits]] - if pd.isnull(celda): - return celda - return re.sub(r'\d+', '[[digits]]', str(celda)) +import funciones_comunes as fc def preprocesar_importacion(df_importacion): # Iterar sobre las filas del DataFrame de importación for index, fila in df_importacion.iterrows(): - clave_original = str(fila['it-IT']) - clave_sustituida = sustituir_digitos(clave_original) - + clave_original = str(fila["it-IT"]) + clave_sustituida = fc.compactar_celda_clave(clave_original) + # Sustituir en las demás columnas del tipo "xx-YY" for columna in df_importacion.columns: - if columna != 'it-IT' and es_columna_tipo_xxYY(columna): - df_importacion.at[index, columna] = funciones_comunes.transformar_texto(sustituir_digitos(fila[columna])) - + if columna != "it-IT" and fc.es_columna_tipo_xxYY(columna): + df_importacion.at[index, columna] = ( + fc.compactar_celda_traducida(fila[columna]) + ) + # Guardar la clave sustituida - df_importacion.at[index, 'it-IT'] = clave_sustituida + df_importacion.at[index, "it-IT"] = clave_sustituida return df_importacion + def importar(archivo_maestro, archivo_importacion): if not os.path.exists(archivo_maestro): # Crear un DataFrame maestro vacío con la columna "it-IT" @@ -59,7 +52,10 @@ def importar(archivo_maestro, archivo_importacion): # Agregar columnas del tipo "xx-YY" que no existen en el archivo maestro for columna in nuevas_filas.columns: - if es_columna_tipo_xxYY(columna) and columna not in df_maestro.columns: + if ( + fc.es_columna_tipo_xxYY(columna) + and columna not in df_maestro.columns + ): df_maestro[columna] = None # Crear una lista de diccionarios para las filas que se van a agregar @@ -71,7 +67,11 @@ def importar(archivo_maestro, archivo_importacion): if clave not in claves_maestro: claves_maestro.add(clave) # Solo agregar las columnas del tipo "xx-YY" y "it-IT" - fila_filtrada = {col: fila[col] for col in fila.index if col == "it-IT" or es_columna_tipo_xxYY(col)} + fila_filtrada = { + col: fila[col] + for col in fila.index + if col == "it-IT" or fc.es_columna_tipo_xxYY(col) + } filas_a_agregar.append(fila_filtrada) # Concatenar las nuevas filas al DataFrame maestro @@ -83,6 +83,7 @@ def importar(archivo_maestro, archivo_importacion): df_maestro.to_excel(archivo_maestro, index=False) print(f"Se han agregado {len(filas_a_agregar)} nuevas filas al archivo maestro.") + if __name__ == "__main__": # Cargar el archivo maestro y el archivo de importación archivo_maestro = ".\\data\\1_hmi_master_translates.xlsx" diff --git a/x2_master_export2translate.py b/x2_master_export2translate.py index 8d11e8b..97f2f7d 100644 --- a/x2_master_export2translate.py +++ b/x2_master_export2translate.py @@ -1,9 +1,9 @@ import pandas as pd import os from manejoArchivos import select_file -import funciones_comunes +import funciones_comunes as fc -def exportar_para_traduccion(archivo_maestro): +def exportar_para_traduccion(archivo_maestro, target_lang_code): if not os.path.exists(archivo_maestro): print("El archivo maestro no existe.") return @@ -15,16 +15,20 @@ def exportar_para_traduccion(archivo_maestro): # Copiar la primera columna tal cual df_export[df_maestro.columns[0]] = df_maestro[df_maestro.columns[0]] - - # Transformar las demás columnas - for columna in df_maestro.columns[1:]: - df_export[columna] = df_maestro[columna].apply(lambda x: funciones_comunes.transformar_texto(str(x)) if pd.notnull(x) else x) + df_export[target_lang_code] = df_maestro[target_lang_code] # Guardar el archivo exportado ruta_export = os.path.join(os.path.dirname(archivo_maestro), '2_master_export2translate.xlsx') - df_export.to_excel(ruta_export, index=False) + fc.save_dataframe_with_retries(df_export,output_path=ruta_export) + print(f"Archivo exportado para traducción: {ruta_export}") if __name__ == "__main__": archivo_maestro = ".\\data\\1_hmi_master_translates.xlsx" - exportar_para_traduccion(archivo_maestro) + fc.mostrar_idiomas() + seleccion_idioma = int(input("Introduce el número del idioma de destino: ")) + if seleccion_idioma not in fc.IDIOMAS: + print("Selección inválida.") + else: + _, target_lang_code = fc.IDIOMAS[seleccion_idioma] + exportar_para_traduccion(archivo_maestro, target_lang_code) diff --git a/x3_llm_translate_text.py b/x3_llm_translate_text.py index 76f6f27..ef3fcb8 100644 --- a/x3_llm_translate_text.py +++ b/x3_llm_translate_text.py @@ -2,7 +2,6 @@ import pandas as pd from openai import OpenAI import os import re -import logging from openai_api_key import openai_api_key from google_api_key import google_api_key import ollama @@ -11,22 +10,11 @@ from google.cloud import translate_v2 as translate from google.oauth2 import service_account import html from tqdm import tqdm -import funciones_comunes +import funciones_comunes as fc openai_client = OpenAI(api_key=openai_api_key()) GOOGLE_APPLICATION_CREDENTIALS = "translate-431108-020c17463fbb.json" - - -def configurar_logger(): - logger = logging.getLogger("translate_logger") - logger.setLevel(logging.DEBUG) - os.makedirs(".\\data", exist_ok=True) - fh = logging.FileHandler(".\\data\\translate_log.log", encoding="utf-8") - fh.setLevel(logging.DEBUG) - formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") - fh.setFormatter(formatter) - logger.addHandler(fh) - return logger +logger = fc.configurar_logger() def init_google_translate_client(): @@ -41,19 +29,14 @@ def init_google_translate_client(): "No se han proporcionado credenciales válidas para Google Translate" ) - google_translate_client = init_google_translate_client() - def google_translate(text, target_language): result = google_translate_client.translate(text, target_language=target_language) translated_text = result["translatedText"] return html.unescape(translated_text) -logger = configurar_logger() - - def read_system_prompt(): try: with open(".\\data\\system_prompt.txt", "r", encoding="utf-8") as file: @@ -130,7 +113,9 @@ def affinity_batch_openai(texts_dict): "Evaluate the semantic similarity between the following table of pairs of texts in json format on a scale from 0 to 1. " "Return the similarity scores for every row in JSON format as a list of numbers, without any additional text or formatting." ) - original_list = [funciones_comunes.transformar_texto(key) for key in texts_dict.keys()] + original_list = [ + fc.compactar_celda_traducida(key) for key in texts_dict.keys() + ] re_translated_list = list(texts_dict.values()) request_payload = json.dumps( @@ -162,8 +147,8 @@ def affinity_batch_openai(texts_dict): raise ValueError("La respuesta no se pudo decodificar como JSON.") # Manejar diferentes formatos de respuesta - if isinstance(response_payload, dict) and 'similarity_scores' in response_payload: - scores = response_payload['similarity_scores'] + if isinstance(response_payload, dict) and "similarity_scores" in response_payload: + scores = response_payload["similarity_scores"] elif isinstance(response_payload, list): scores = response_payload else: @@ -198,26 +183,28 @@ def main(file_path, target_lang_code, target_lang, traducir_todo, batch_size=10) texts_to_translate = {} for _, row in df.iterrows(): - source_text = str(row[source_col]) + celda_clave = str(row[source_col]) source_translated_text = ( str(row[source_translated_col]) if source_translated_col in df.columns else "" ) - processed_text = funciones_comunes.transformar_texto(source_text) + celda_clave_compactada = fc.compactar_celda_traducida(celda_clave) if traducir_todo: - if texto_requiere_traduccion(processed_text): - texts_to_translate[source_text] = processed_text + if texto_requiere_traduccion(celda_clave_compactada): + texts_to_translate[celda_clave] = celda_clave_compactada else: if ( pd.isna(row[source_translated_col]) or source_translated_text.strip() == "" ): - if texto_requiere_traduccion(processed_text): - texts_to_translate[source_text] = processed_text + if texto_requiere_traduccion(celda_clave_compactada): + texts_to_translate[celda_clave] = celda_clave_compactada num_texts = len(texts_to_translate) + num_texts = 40 + logger.info(f"Número total de textos a traducir: {num_texts}") print(f"Número total de textos a traducir: {num_texts}") @@ -258,17 +245,19 @@ def main(file_path, target_lang_code, target_lang, traducir_todo, batch_size=10) # Traduccion inversa # Actualizar el DataFrame con las traducciones y hacemos la Traduccion inversa - for index, row in tqdm(df.iterrows(), total=df.shape[0], desc="Procesando traducciones"): - source_text = str(row[source_col]) - if source_text in translations: - df.at[index, target_col] = translations[source_text] + for index, row in tqdm( + df.iterrows(), total=df.shape[0], desc="Procesando traducciones" + ): + celda_clave = str(row[source_col]) + if celda_clave in translations: + df.at[index, target_col] = translations[celda_clave] # Realizar la traducción de verificación con Google Translate try: - google_translation = google_translate(translations[source_text], "it") + google_translation = google_translate(translations[celda_clave], "it") df.at[index, check_translate_col] = google_translation except Exception as e: logger.error( - f"Error en la traducción de Google para el texto '{source_text}': {e}" + f"Error en la traducción de Google para el texto '{celda_clave}': {e}" ) df.at[index, check_translate_col] = "Error en la traducción" df.at[index, affinity_col] = 0.0 @@ -276,8 +265,7 @@ def main(file_path, target_lang_code, target_lang, traducir_todo, batch_size=10) # Afinidades # Se calculan las Afinidades affinities = {} - batch_size = 10 - for start_idx in range(0, num_texts, batch_size): + for start_idx in range(0, num_texts, batch_size): # num_text end_idx = min(start_idx + batch_size, num_texts) batch_texts = dict(list(texts_to_translate.items())[start_idx:end_idx]) logger.info(f"Afinidad: celdas desde {start_idx} a {end_idx}.") @@ -307,14 +295,14 @@ def main(file_path, target_lang_code, target_lang, traducir_todo, batch_size=10) # Actualizar el DataFrame con las Afinidades for index, row in df.iterrows(): - source_text = str(row[source_col]) - if source_text in affinities: - df.at[index, affinity_col] = affinities[source_text] + celda_clave = str(row[source_col]) + if celda_clave in affinities: + df.at[index, affinity_col] = affinities[celda_clave] output_path = os.path.join( os.path.dirname(file_path), "3_master_export2translate_translated.xlsx" ) - funciones_comunes.save_dataframe_with_retries(df,output_path=output_path) + fc.save_dataframe_with_retries(df, output_path=output_path) logger.info(f"Archivo traducido guardado en: {output_path}") print(f"Archivo traducido guardado en: {output_path}") @@ -323,12 +311,12 @@ if __name__ == "__main__": batch_size = 20 translate_file = ".\\data\\2_master_export2translate.xlsx" - funciones_comunes.mostrar_idiomas() + fc.mostrar_idiomas() seleccion_idioma = int(input("Introduce el número del idioma de destino: ")) - if seleccion_idioma not in funciones_comunes.IDIOMAS: + if seleccion_idioma not in fc.IDIOMAS: print("Selección inválida.") else: - target_lang, target_lang_code = funciones_comunes.IDIOMAS[seleccion_idioma] + target_lang, target_lang_code = fc.IDIOMAS[seleccion_idioma] traducir_todo = ( input("¿Desea traducir todas las celdas (s/n)? ").strip().lower() == "s" ) diff --git a/x4_import_translate2master.py b/x4_import_translate2master.py deleted file mode 100644 index 4c402c0..0000000 --- a/x4_import_translate2master.py +++ /dev/null @@ -1,69 +0,0 @@ -import pandas as pd -import os -import re -import logging -from manejoArchivos import select_file - -def configurar_logger(ruta_log): - os.makedirs(".\\data", exist_ok=True) - logger = logging.getLogger('.\\data\\importacion_logger') - logger.setLevel(logging.INFO) - fh = logging.FileHandler(ruta_log, encoding='utf-8') - fh.setLevel(logging.INFO) - formatter = logging.Formatter('%(asctime)s - %(message)s') - fh.setFormatter(formatter) - logger.addHandler(fh) - return logger - -def revertir_transformaciones(texto, digitos, secciones): - # Revertir <> a [[digits]] - for digito in digitos: - texto = texto.replace('<>', digito, 1) - # Revertir <#> a <...> usando las secciones originales - for seccion in secciones: - texto = texto.replace('<#>', f'<{seccion}>', 1) - return texto - -def importar_traduccion(archivo_maestro, archivo_traduccion): - if not os.path.exists(archivo_maestro): - print("El archivo maestro no existe.") - return - - df_maestro = pd.read_excel(archivo_maestro) - df_traduccion = pd.read_excel(archivo_traduccion) - - # Configurar el logger - directorio = os.path.dirname(archivo_maestro) - nombre_log = os.path.join(directorio, 'importacion_traduccion.log') - logger = configurar_logger(nombre_log) - - # Iterar sobre las filas del archivo de traducción para revertir transformaciones y actualizar el maestro - for index, fila in df_traduccion.iterrows(): - clave = fila[df_maestro.columns[0]] - if clave in df_maestro[df_maestro.columns[0]].values: - # Obtener los dígitos y secciones originales de la clave - digitos = re.findall(r'\d+', str(clave)) - secciones = re.findall(r'<(.*?)>', str(clave)) - - # Actualizar solo las columnas que existen en df_maestro y df_traduccion - for columna in df_traduccion.columns[1:]: - if columna in df_maestro.columns: - valor_traducido = fila[columna] - if pd.isnull(valor_traducido): - continue # Omitir celdas vacías - valor_original = df_maestro.loc[df_maestro[df_maestro.columns[0]] == clave, columna].values[0] - valor_revertido = revertir_transformaciones(valor_traducido, digitos, secciones) - - if pd.notnull(valor_original) and str(valor_original) != valor_revertido: - df_maestro.loc[df_maestro[df_maestro.columns[0]] == clave, columna] = valor_revertido - logger.info(f'Fila {index}, Columna {columna}: "{valor_original}" actualizado a "{valor_revertido}"') - - # Guardar el archivo maestro actualizado - df_maestro.to_excel(archivo_maestro, index=False) - print(f"Traducciones importadas y archivo maestro actualizado: {archivo_maestro}. Detalles de los cambios en {nombre_log}") - - -if __name__ == "__main__": - archivo_maestro = ".\\data\\1_hmi_master_translates.xlsx" - archivo_traduccion = ".\\data\\2_master_export2translate.xlsx" - importar_traduccion(archivo_maestro, archivo_traduccion) diff --git a/x3.5_integrate_translates.py b/x4_integrate_translates.py similarity index 72% rename from x3.5_integrate_translates.py rename to x4_integrate_translates.py index d3fd8c5..4625b6f 100644 --- a/x3.5_integrate_translates.py +++ b/x4_integrate_translates.py @@ -1,22 +1,10 @@ -import funciones_comunes - +import funciones_comunes as fc import pandas as pd import os import re import logging from manejoArchivos import select_file -def configurar_logger(ruta_log): - os.makedirs(".\\data", exist_ok=True) - logger = logging.getLogger('.\\data\\importacion_logger') - logger.setLevel(logging.INFO) - fh = logging.FileHandler(ruta_log, encoding='utf-8') - fh.setLevel(logging.INFO) - formatter = logging.Formatter('%(asctime)s - %(message)s') - fh.setFormatter(formatter) - logger.addHandler(fh) - return logger - def revertir_transformaciones(texto, digitos, secciones): # Revertir <> a [[digits]] for digito in digitos: @@ -38,10 +26,8 @@ def importar_traduccion(archivo_maestro, archivo_traduccion, target_lang_code, n df_maestro = pd.read_excel(archivo_maestro) df_traduccion = pd.read_excel(archivo_traduccion) - # Configurar el logger - directorio = os.path.dirname(archivo_maestro) - nombre_log = os.path.join(directorio, 'importacion_traduccion.log') - logger = configurar_logger(nombre_log) + # Configurar el logger + logger = fc.configurar_logger() # Iterar sobre las filas del archivo de traducción para actualizar el maestro for index, fila in df_traduccion.iterrows(): @@ -57,8 +43,8 @@ def importar_traduccion(archivo_maestro, archivo_traduccion, target_lang_code, n logger.info(f'Fila {index}, Columna {translated_col}: "{valor_original}" actualizado a "{valor_traducido}"') # Guardar el archivo maestro actualizado - funciones_comunes.save_dataframe_with_retries(df_maestro,output_path=archivo_maestro) - print(f"Traducciones importadas y archivo maestro actualizado: {archivo_maestro}. Detalles de los cambios en {nombre_log}") + fc.save_dataframe_with_retries(df_maestro,output_path=archivo_maestro) + print(f"Traducciones importadas y archivo maestro actualizado: {archivo_maestro}.") if __name__ == "__main__": @@ -67,11 +53,11 @@ if __name__ == "__main__": nivel_afinidad_minimo = input("Introduce el nivel minimo de afinidad para importar (presiona Enter para usar el valor por defecto 0.5): ") nivel_afinidad_minimo = float(nivel_afinidad_minimo) if nivel_afinidad_minimo else 0.5 - - funciones_comunes.mostrar_idiomas() + + fc.mostrar_idiomas() seleccion_idioma = int(input("Introduce el número del idioma de destino: ")) - if seleccion_idioma not in funciones_comunes.IDIOMAS: + if seleccion_idioma not in fc.IDIOMAS: print("Selección inválida.") else: - target_lang, target_lang_code = funciones_comunes.IDIOMAS[seleccion_idioma] + target_lang, target_lang_code = fc.IDIOMAS[seleccion_idioma] importar_traduccion(archivo_maestro, archivo_traduccion, target_lang_code, nivel_afinidad_minimo ) diff --git a/x4.5_complete_empty_cells_master.py b/x5_complete_empty_cells_master.py similarity index 60% rename from x4.5_complete_empty_cells_master.py rename to x5_complete_empty_cells_master.py index 043714f..1e0a733 100644 --- a/x4.5_complete_empty_cells_master.py +++ b/x5_complete_empty_cells_master.py @@ -1,5 +1,4 @@ -import funciones_comunes - +import funciones_comunes as fc import pandas as pd import os import re @@ -7,28 +6,6 @@ import logging from manejoArchivos import select_file -def configurar_logger(ruta_log): - os.makedirs(".\\data", exist_ok=True) - logger = logging.getLogger(".\\data\\importacion_logger") - logger.setLevel(logging.INFO) - fh = logging.FileHandler(ruta_log, encoding="utf-8") - fh.setLevel(logging.INFO) - formatter = logging.Formatter("%(asctime)s - %(message)s") - fh.setFormatter(formatter) - logger.addHandler(fh) - return logger - - -def revertir_transformaciones(texto, digitos, secciones): - # Revertir <> a [[digits]] - for digito in digitos: - texto = texto.replace("<>", digito, 1) - # Revertir <#> a <...> usando las secciones originales - for seccion in secciones: - texto = texto.replace("<#>", f"<{seccion}>", 1) - return texto - - def complete_emptys(archivo_maestro, target_lang_code, second_lang_code): if not os.path.exists(archivo_maestro): print("El archivo maestro no existe.") @@ -40,9 +17,7 @@ def complete_emptys(archivo_maestro, target_lang_code, second_lang_code): df_maestro = pd.read_excel(archivo_maestro) # Configurar el logger - directorio = os.path.dirname(archivo_maestro) - nombre_log = os.path.join(directorio, "importacion_traduccion.log") - logger = configurar_logger(nombre_log) + logger = fc.configurar_logger() # Iterar sobre las filas del archivo de traducción para actualizar el maestro for index, fila in df_maestro.iterrows(): @@ -64,20 +39,20 @@ def complete_emptys(archivo_maestro, target_lang_code, second_lang_code): ) # Guardar el archivo maestro actualizado - funciones_comunes.save_dataframe_with_retries( + fc.save_dataframe_with_retries( df_maestro, output_path=archivo_maestro ) print( - f"Traducciones importadas y archivo maestro actualizado: {archivo_maestro}. Detalles de los cambios en {nombre_log}" + f"Traducciones importadas y archivo maestro actualizado: {archivo_maestro}." ) if __name__ == "__main__": archivo_maestro = ".\\data\\1_hmi_master_translates.xlsx" - funciones_comunes.mostrar_idiomas() + fc.mostrar_idiomas() seleccion_idioma = int(input("Introduce el número del idioma de destino: ")) - if seleccion_idioma not in funciones_comunes.IDIOMAS: + if seleccion_idioma not in fc.IDIOMAS: print("Selección inválida.") exit seleccion_idioma_secundario = int( @@ -85,10 +60,10 @@ if __name__ == "__main__": "Introduce el número del idioma de secundario para copiar desde en caso de vacios: " ) ) - if seleccion_idioma_secundario not in funciones_comunes.IDIOMAS: + if seleccion_idioma_secundario not in fc.IDIOMAS: print("Selección inválida.") exit - _, target_lang_code = funciones_comunes.IDIOMAS[seleccion_idioma] - _, second_lang_code = funciones_comunes.IDIOMAS[seleccion_idioma_secundario] + _, target_lang_code = fc.IDIOMAS[seleccion_idioma] + _, second_lang_code = fc.IDIOMAS[seleccion_idioma_secundario] complete_emptys(archivo_maestro, target_lang_code, second_lang_code) diff --git a/x5_update_from_master.py b/x5_update_from_master.py deleted file mode 100644 index 316797c..0000000 --- a/x5_update_from_master.py +++ /dev/null @@ -1,102 +0,0 @@ -import pandas as pd -import os -import re -import logging -from manejoArchivos import select_file - -def es_columna_tipo_xxYY(columna): - # Verificar si la columna es del tipo "xx-YY" usando una expresión regular - return bool(re.match(r'^[a-z]{2}-[A-Z]{2}$', columna)) - -def sustituir_digitos(celda): - # Convertir a cadena y sustituir secuencias de dígitos por [[digits]] - if pd.isnull(celda): - return celda, [] - digitos = re.findall(r'\d+', str(celda)) - celda_sustituida = re.sub(r'\d+', '[[digits]]', str(celda)) - return celda_sustituida, digitos - -def preprocesar_update(df_update): - # Diccionario para almacenar los dígitos reemplazados por fila - digitos_reemplazados = {} - - # Iterar sobre las filas del DataFrame de actualización - for index, fila in df_update.iterrows(): - clave_original = str(fila['it-IT']) - clave_sustituida, digitos = sustituir_digitos(clave_original) - digitos_reemplazados[index] = digitos - df_update.at[index, 'it-IT_preprocessed'] = clave_sustituida # Agregar una columna preprocesada - - return df_update, digitos_reemplazados - -def configurar_logger(ruta_log): - logger = logging.getLogger('actualizacion_logger') - logger.setLevel(logging.INFO) - fh = logging.FileHandler(ruta_log, encoding='utf-8') - fh.setLevel(logging.INFO) - formatter = logging.Formatter('%(asctime)s - %(message)s') - fh.setFormatter(formatter) - logger.addHandler(fh) - return logger - -def update_from_master(archivo_maestro, archivo_to_update): - if not os.path.exists(archivo_maestro): - print("El archivo maestro no existe.") - return - - df_maestro = pd.read_excel(archivo_maestro) - df_to_update = pd.read_excel(archivo_to_update) - - # Configurar el logger - directorio = os.path.dirname(archivo_to_update) - nombre_log = os.path.join(directorio, 'actualizacion.log') - logger = configurar_logger(nombre_log) - - # Preprocesar el archivo de actualización - df_to_update, digitos_reemplazados = preprocesar_update(df_to_update) - - # Obtener las claves del archivo maestro - claves_maestro = set(df_maestro["it-IT"].dropna().astype(str)) - - # Iterar sobre las filas del archivo de actualización para actualizarlas - for index, fila in df_to_update.iterrows(): - clave_preprocesada = str(fila['it-IT_preprocessed']) - if clave_preprocesada in claves_maestro: - # Obtener los dígitos originales para esta fila - digitos = digitos_reemplazados.get(index, []) - df_maestro_fila = df_maestro[df_maestro['it-IT'] == clave_preprocesada].iloc[0] - - # Verificar que la cantidad de dígitos coincida con la cantidad de [[digits]] en la clave - cantidad_digits = clave_preprocesada.count('[[digits]]') - if len(digitos) != cantidad_digits: - logger.info(f'Fila {index}: no se actualiza porque la cantidad de dígitos no coincide.') - continue - - # Actualizar solo las columnas que existen en df_to_update y que no sean 'it-IT' - for columna in df_to_update.columns: - if columna != 'it-IT' and columna != 'it-IT_preprocessed' and columna in df_maestro.columns: - valor = df_maestro_fila[columna] - # Convertir a cadena si no lo es y reemplazar [[digits]] con los dígitos originales - if not pd.isnull(valor): - valor_original = str(valor) - valor_actualizado = valor_original - for d in digitos: - valor_actualizado = valor_actualizado.replace('[[digits]]', d, 1) - # Solo actualizar si el valor ha cambiado - if str(fila[columna]) != valor_actualizado: - df_to_update.at[index, columna] = valor_actualizado - # Registrar el cambio - logger.info(f'Fila {index}, Columna {columna}: "{fila[columna]}" actualizado a "{valor_actualizado}"') - - # Eliminar la columna preprocesada - df_to_update.drop(columns=['it-IT_preprocessed'], inplace=True) - - # Guardar el archivo actualizado - df_to_update.to_excel(archivo_to_update, index=False) - print(f"Se han actualizado las filas en {archivo_to_update} desde el archivo maestro. Detalles de los cambios en {nombre_log}") - -if __name__ == "__main__": - archivo_maestro = ".\\data\\1_hmi_master_translates.xlsx" - archivo_to_update = select_file("xlsx") - if archivo_to_update: - update_from_master(archivo_maestro, archivo_to_update) diff --git a/x6_update_from_master.py b/x6_update_from_master.py new file mode 100644 index 0000000..9ac6435 --- /dev/null +++ b/x6_update_from_master.py @@ -0,0 +1,80 @@ +import pandas as pd +import os +import re +import logging +import funciones_comunes as fc +from manejoArchivos import select_file + + +def update_from_master(archivo_maestro, archivo_to_update, target_lang_code): + if not os.path.exists(archivo_maestro): + print("El archivo maestro no existe.") + return + + # Configurar el logger + logger = fc.configurar_logger() + + logger.info(" .... ") + logger.info( + f"Iniciando actualizacion en {archivo_to_update} desde el archivo maestro. Para {target_lang_code} " + ) + + df_maestro = pd.read_excel(archivo_maestro) + df_to_update = pd.read_excel(archivo_to_update) + + col_clave = df_maestro.columns[0] + + # Iterar sobre las filas del archivo de actualización para actualizarlas + for index, fila in df_to_update.iterrows(): + clave = fila[col_clave] + if not pd.isnull(clave) and clave in df_maestro[col_clave].values: + # Obtenemos los valores + valor_original = fila[col_clave] + valor_traducido_compacto = df_maestro.loc[ + df_maestro[col_clave] == clave, target_lang_code + ].values[0] + # Descompactamos + valor_traducido = fc.decompactar_celda_traducida( + celda_original=valor_original, celda_traducida=valor_traducido_compacto + ) + + if ( + not pd.isnull(valor_traducido) + and fila[target_lang_code] != valor_traducido + ): + # Salvamos en el file to Update + okToSave, Error = fc.verificar_celda_traducida( + valor_original, valor_traducido + ) + if okToSave: + logger.info( + f'Fila {index} : Clave: {clave}, Columna {target_lang_code}: "{df_to_update.at[index, target_lang_code]}" actualizado a "{valor_traducido}"' + ) + df_to_update.at[index, target_lang_code] = valor_traducido + else: + logger.error( + f'Fila {index}, Columna {target_lang_code}: "{df_to_update.at[index, target_lang_code]}" valor:"{valor_traducido}" no actualizado porque {Error}' + ) + + # Guardar el archivo actualizado + fc.save_dataframe_with_retries(df_to_update, output_path=archivo_to_update) + print( + f"Se han actualizado las filas en {archivo_to_update} desde el archivo maestro. " + ) + logger.info( + f"Se han actualizado las filas en {archivo_to_update} desde el archivo maestro. " + ) + logger.info(" .... ") + + +if __name__ == "__main__": + archivo_maestro = ".\\data\\1_hmi_master_translates.xlsx" + archivo_to_update = select_file("xlsx") + if archivo_to_update: + fc.mostrar_idiomas() + seleccion_idioma = int(input("Introduce el número del idioma de destino: ")) + if seleccion_idioma not in fc.IDIOMAS: + print("Selección inválida.") + else: + target_lang, target_lang_code = fc.IDIOMAS[seleccion_idioma] + update_from_master(archivo_maestro, archivo_to_update, target_lang_code)