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