Compare commits
No commits in common. "f2a410485b19c566c35082ecdd4f81f6d7012094" and "39116ca425e36f42325a10ae76b7e30a29d328e9" have entirely different histories.
f2a410485b
...
39116ca425
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"codigo_tipo_PLC": "siemens",
|
||||
"codigo_columna_maestra": "it-IT",
|
||||
"codigo_idioma_seleccionado": "es-ES",
|
||||
"codigo_idioma_secundario": "en-GB",
|
||||
"work_dir": "C:/Trabajo/VM/38 - 93998 - Sipa - PortoRico/Reporte/Language",
|
||||
"master_name": "1_hmi_master_translates_siemens.xlsx",
|
||||
"translate_name": "2_master_export2translate_siemens_es-ES.xlsx",
|
||||
"auto_translate_name": "3_master_export2translate_translated_siemens_es-ES.xlsx",
|
||||
"codigo_tipo_PLC": "allenbradley",
|
||||
"codigo_columna_maestra": "es-ES",
|
||||
"codigo_idioma_seleccionado": "en-US",
|
||||
"codigo_idioma_secundario": "es-ES",
|
||||
"work_dir": "C:/Trabajo/VM/33 - 9.4022 - Shibuya - Usa/Reporte/Language",
|
||||
"master_name": "1_hmi_master_translates_allenbradley.xlsx",
|
||||
"translate_name": "2_master_export2translate_allenbradley_en-US.xlsx",
|
||||
"auto_translate_name": "3_master_export2translate_translated_allenbradley_en-US.xlsx",
|
||||
"nivel_afinidad_minimo": 0.5,
|
||||
"traducir_todo": false
|
||||
}
|
|
@ -6,7 +6,6 @@ import langid
|
|||
from openpyxl import load_workbook
|
||||
from openpyxl.styles import PatternFill, Alignment, Font
|
||||
from collections import defaultdict
|
||||
from openai_api_key import openai_api_key
|
||||
|
||||
# Definir el logger a nivel de módulo
|
||||
logger = None
|
||||
|
@ -36,172 +35,73 @@ def obtener_nombre_idioma(codigo_corto):
|
|||
|
||||
|
||||
def exportar_para_traduccion(config: TranslationConfig):
|
||||
"""
|
||||
Exporta los textos del archivo maestro para su traducción, realizando validaciones
|
||||
y cálculos de afinidad en lotes. Los textos idénticos reciben afinidad 1 automáticamente.
|
||||
"""
|
||||
master_path = config.get_master_path()
|
||||
if not os.path.exists(master_path):
|
||||
print("El archivo maestro no existe.")
|
||||
return
|
||||
|
||||
configurar_detector_idiomas()
|
||||
|
||||
df_maestro = fc.read_dataframe_with_cleanup_retries(master_path)
|
||||
|
||||
# Preparar DataFrame de exportación
|
||||
df_export = pd.DataFrame()
|
||||
primera_columna = df_maestro.columns[0]
|
||||
df_export[primera_columna] = df_maestro[primera_columna]
|
||||
|
||||
columna_propuesta = f"{config.codigo_idioma_seleccionado}_Propuesto"
|
||||
df_export[columna_propuesta] = df_maestro[config.codigo_idioma_seleccionado]
|
||||
|
||||
# Agregar columnas de validación si los idiomas son diferentes
|
||||
if config.codigo_columna_maestra != config.codigo_idioma_seleccionado:
|
||||
df_export["Validation_Error"] = ""
|
||||
df_export["Affinity_Score"] = None
|
||||
|
||||
df_export[config.codigo_idioma_seleccionado] = df_maestro[
|
||||
config.codigo_idioma_seleccionado
|
||||
]
|
||||
df_export["Idioma_Detectado"] = ""
|
||||
|
||||
# Agregar columna del idioma secundario
|
||||
if config.codigo_idioma_secundario in df_maestro.columns:
|
||||
df_export[config.codigo_idioma_secundario] = df_maestro[config.codigo_idioma_secundario]
|
||||
|
||||
ruta_export = config.get_translate_path()
|
||||
|
||||
with pd.ExcelWriter(ruta_export, engine="openpyxl") as writer:
|
||||
df_export.to_excel(writer, index=False, sheet_name="Sheet1")
|
||||
|
||||
workbook = writer.book
|
||||
worksheet = writer.sheets["Sheet1"]
|
||||
|
||||
# Inmovilizar paneles en A2
|
||||
worksheet.freeze_panes = "A2"
|
||||
|
||||
# Configurar estilos
|
||||
wrap_alignment = Alignment(wrap_text=True, vertical="top")
|
||||
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")
|
||||
for col in ["A", "B"]:
|
||||
for cell in worksheet[col]:
|
||||
cell.alignment = wrap_alignment
|
||||
worksheet.column_dimensions[col].width = 50
|
||||
|
||||
# Ajustar anchos de columna
|
||||
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
|
||||
|
||||
# Primera fase: Procesar detección de idioma y recopilar textos para afinidad
|
||||
texts_to_check = {} # Para textos que necesitan cálculo de afinidad
|
||||
identical_texts = {} # Para textos idénticos (afinidad 1)
|
||||
texto_a_filas = defaultdict(list)
|
||||
inconsistencias = 0
|
||||
afinidad_baja = 0
|
||||
idioma_esperado = fc.idiomas_shortcodefromcode(
|
||||
config.codigo_idioma_seleccionado
|
||||
)
|
||||
fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
|
||||
bold_font = Font(bold=True)
|
||||
|
||||
total_rows = worksheet.max_row - 1 # Excluimos la fila de encabezado
|
||||
progress_bar = fc.ProgressBar(
|
||||
worksheet.max_row - 1, prefix="Procesando textos:", suffix="Completado"
|
||||
total_rows, prefix="Procesando filas:", suffix="Completado"
|
||||
)
|
||||
|
||||
print("Iniciando procesamiento de filas...")
|
||||
|
||||
texto_a_filas = defaultdict(list)
|
||||
for row in range(2, worksheet.max_row + 1):
|
||||
texto_original = worksheet.cell(row=row, column=1).value
|
||||
texto_propuesto = worksheet.cell(row=row, column=2).value
|
||||
texto = worksheet.cell(row=row, column=2).value
|
||||
if texto:
|
||||
texto_limpio = fc.limpiar_texto(config.codigo_tipo_PLC, texto)
|
||||
|
||||
if texto_original and texto_propuesto:
|
||||
# Detección de idioma
|
||||
texto_limpio = fc.limpiar_texto(config.codigo_tipo_PLC, texto_propuesto)
|
||||
if texto_propuesto == texto_limpio:
|
||||
texto_a_filas[texto_propuesto].append(row)
|
||||
# Solo considerar para duplicados si el texto limpio es igual al original
|
||||
if texto == texto_limpio:
|
||||
texto_a_filas[texto].append(row)
|
||||
|
||||
idioma_detectado = detectar_idioma(texto_propuesto, config.codigo_tipo_PLC)
|
||||
idioma_esperado = fc.idiomas_shortcodefromcode(config.codigo_idioma_seleccionado)
|
||||
|
||||
if idioma_detectado != "unknown" and idioma_detectado != idioma_esperado:
|
||||
worksheet.cell(row=row, column=2).fill = blue_fill
|
||||
# Detectar idioma y marcar si es incorrecto
|
||||
idioma_detectado = detectar_idioma(texto, config.codigo_tipo_PLC)
|
||||
if (
|
||||
idioma_detectado != "unknown"
|
||||
and idioma_detectado != idioma_esperado
|
||||
):
|
||||
worksheet.cell(row=row, column=2).fill = fill
|
||||
nombre_idioma = obtener_nombre_idioma(idioma_detectado)
|
||||
worksheet.cell(
|
||||
row=row,
|
||||
column=df_export.columns.get_loc("Idioma_Detectado") + 1
|
||||
).value = nombre_idioma
|
||||
|
||||
# Recopilar textos para afinidad si los idiomas son diferentes
|
||||
if config.codigo_columna_maestra != config.codigo_idioma_seleccionado:
|
||||
if pd.notnull(texto_propuesto) and texto_propuesto.strip() != "":
|
||||
# Compactar los textos para comparación
|
||||
texto_original_comp = fc.compactar_celda_traducida(config.codigo_tipo_PLC, str(texto_original))
|
||||
texto_propuesto_comp = fc.compactar_celda_traducida(config.codigo_tipo_PLC, str(texto_propuesto))
|
||||
|
||||
# Si los textos son idénticos después de compactar, afinidad automática de 1
|
||||
if texto_original_comp == texto_propuesto_comp:
|
||||
identical_texts[texto_original] = row
|
||||
else:
|
||||
texts_to_check[texto_original] = texto_propuesto
|
||||
worksheet.cell(row=row, column=3).value = nombre_idioma
|
||||
|
||||
progress_bar.increment()
|
||||
|
||||
progress_bar.finish()
|
||||
|
||||
# Configurar el modelo a usar
|
||||
modelo_llm = fc.LLM_MODELS["OpenAI"] # o el que se prefiera
|
||||
api_key = openai_api_key() # solo necesario para OpenAI y Grok
|
||||
|
||||
# Segunda fase: Procesar textos idénticos y calcular afinidades en lote
|
||||
if config.codigo_columna_maestra != config.codigo_idioma_seleccionado:
|
||||
# Asignar afinidad 1 a textos idénticos
|
||||
logger.info(f"Asignando afinidad 1 a {len(identical_texts)} textos idénticos")
|
||||
for _, row in identical_texts.items():
|
||||
col_idx = df_export.columns.get_loc("Affinity_Score") + 1
|
||||
worksheet.cell(row=row, column=col_idx).value = 1.0
|
||||
|
||||
# Calcular afinidades para textos diferentes
|
||||
if texts_to_check:
|
||||
logger.info(f"Calculando afinidad para {len(texts_to_check)} textos diferentes")
|
||||
try:
|
||||
# Calcular afinidades
|
||||
affinities = fc.calcular_afinidad_batch(
|
||||
texts_to_check,
|
||||
config.codigo_tipo_PLC,
|
||||
modelo_llm,
|
||||
logger,
|
||||
api_key
|
||||
)
|
||||
|
||||
# Aplicar resultados de afinidad
|
||||
progress_bar = fc.ProgressBar(
|
||||
len(affinities), prefix="Aplicando afinidades:", suffix="Completado"
|
||||
)
|
||||
|
||||
for texto_original, afinidad in affinities.items():
|
||||
row = next(row for row in range(2, worksheet.max_row + 1)
|
||||
if worksheet.cell(row=row, column=1).value == texto_original)
|
||||
|
||||
col_idx = df_export.columns.get_loc("Affinity_Score") + 1
|
||||
worksheet.cell(row=row, column=col_idx).value = afinidad
|
||||
|
||||
if afinidad < 1:
|
||||
worksheet.cell(row=row, column=2).fill = yellow_fill
|
||||
afinidad_baja += 1
|
||||
|
||||
progress_bar.increment()
|
||||
|
||||
progress_bar.finish()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error en el cálculo de afinidad por lotes: {str(e)}")
|
||||
print(f"Error en el cálculo de afinidad por lotes: {str(e)}")
|
||||
|
||||
# Marcar celdas duplicadas
|
||||
bold_font = Font(bold=True)
|
||||
# Marcar celdas duplicadas en negrita
|
||||
celdas_duplicadas = 0
|
||||
for filas in texto_a_filas.values():
|
||||
if len(filas) > 1:
|
||||
|
@ -210,18 +110,17 @@ def exportar_para_traduccion(config: TranslationConfig):
|
|||
cell.font = bold_font
|
||||
celdas_duplicadas += len(filas)
|
||||
|
||||
# Imprimir resumen
|
||||
progress_bar.finish()
|
||||
|
||||
print(f"\nArchivo exportado para traducción: {ruta_export}")
|
||||
print("Las celdas con idioma incorrecto han sido marcadas en azul.")
|
||||
print("Se ha añadido el nombre del idioma detectado cuando es diferente del esperado.")
|
||||
print(f"Se ha agregado la columna del idioma secundario ({config.codigo_idioma_secundario}) al final de la planilla.")
|
||||
print(
|
||||
"Se ha añadido el nombre del idioma detectado cuando es diferente del esperado."
|
||||
)
|
||||
print(
|
||||
f"Se han marcado {celdas_duplicadas} celdas en negrita por tener texto duplicado en la columna del idioma seleccionado."
|
||||
)
|
||||
|
||||
if config.codigo_columna_maestra != config.codigo_idioma_seleccionado:
|
||||
print(f"Se encontraron {len(identical_texts)} textos idénticos (afinidad 1)")
|
||||
print(f"Se encontraron {inconsistencias} celdas con errores de validación (marcadas en rojo)")
|
||||
print(f"Se encontraron {afinidad_baja} celdas con afinidad menor a 1 (marcadas en amarillo)")
|
||||
|
||||
print(f"Se han marcado {celdas_duplicadas} celdas en negrita por tener texto duplicado.")
|
||||
|
||||
def run(config: TranslationConfig):
|
||||
global logger
|
||||
|
|
|
@ -11,19 +11,18 @@ import html
|
|||
from tqdm import tqdm
|
||||
import PyLibrary.funciones_comunes as fc
|
||||
import time
|
||||
import PyLibrary.funciones_comunes as fc
|
||||
from translation_config import TranslationConfig
|
||||
from openpyxl.styles import PatternFill, Alignment
|
||||
import sys
|
||||
from openai import OpenAI
|
||||
from tqdm import tqdm
|
||||
|
||||
openai_client = OpenAI(api_key=openai_api_key())
|
||||
GOOGLE_APPLICATION_CREDENTIALS = "translate-431108-020c17463fbb.json"
|
||||
batch_size = 20
|
||||
|
||||
# Definir el logger a nivel de módulo
|
||||
logger = None
|
||||
|
||||
# Crear el cliente OpenAI
|
||||
openai_client = OpenAI(api_key=openai_api_key())
|
||||
|
||||
|
||||
def init_google_translate_client():
|
||||
if os.path.exists(GOOGLE_APPLICATION_CREDENTIALS):
|
||||
|
@ -106,11 +105,109 @@ def translate_batch_openai(texts_dict, source_lang, target_lang):
|
|||
return dict(zip(texts_dict.keys(), translations))
|
||||
|
||||
|
||||
def affinity_batch_openai(codigo_tipo_PLC, texts_dict):
|
||||
system_prompt = (
|
||||
"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 = [
|
||||
fc.compactar_celda_traducida(codigo_tipo_PLC, key) for key in texts_dict.keys()
|
||||
]
|
||||
re_translated_list = list(texts_dict.values())
|
||||
|
||||
request_payload = json.dumps(
|
||||
{"original": original_list, "compared": re_translated_list}
|
||||
)
|
||||
logger.info(f"Solicitando Afinidad para el lote de textos:\n{request_payload}")
|
||||
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{
|
||||
"role": "system",
|
||||
"content": system_prompt,
|
||||
},
|
||||
{"role": "user", "content": request_payload},
|
||||
],
|
||||
max_tokens=1500,
|
||||
temperature=0.3,
|
||||
)
|
||||
response_content = response.choices[0].message.content
|
||||
|
||||
# Limpiar y convertir el contenido de la respuesta
|
||||
cleaned_response_content = response_content.strip().strip("'```json").strip("```")
|
||||
|
||||
# Intentar convertir el contenido a JSON
|
||||
try:
|
||||
response_payload = json.loads(cleaned_response_content)
|
||||
except json.JSONDecodeError:
|
||||
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"]
|
||||
elif isinstance(response_payload, list):
|
||||
scores = response_payload
|
||||
else:
|
||||
raise ValueError("Formato de respuesta inesperado.")
|
||||
|
||||
logger.info(f"Respuestas recibidas:\n{scores}")
|
||||
|
||||
if len(scores) != len(original_list):
|
||||
raise ValueError(
|
||||
"La cantidad de afinidades recibidas no coincide con la cantidad de textos enviados."
|
||||
)
|
||||
|
||||
return dict(zip(texts_dict.keys(), scores))
|
||||
|
||||
|
||||
# Función que calcula la afinidad entre dos textos
|
||||
def calcular_afinidad(tipo_PLC, texto1, texto2):
|
||||
system_prompt = (
|
||||
"Evaluate the semantic similarity between the following pair of texts on a scale from 0 to 1. "
|
||||
"Return the similarity score as a single number."
|
||||
)
|
||||
|
||||
original_text = fc.compactar_celda_traducida(tipo_PLC, texto1)
|
||||
compared_text = texto2
|
||||
|
||||
request_payload = json.dumps({"original": original_text, "compared": compared_text})
|
||||
logger.info(f"Solicitando afinidad para el par de textos:\n{request_payload}")
|
||||
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{
|
||||
"role": "system",
|
||||
"content": system_prompt,
|
||||
},
|
||||
{"role": "user", "content": request_payload},
|
||||
],
|
||||
max_tokens=1500,
|
||||
temperature=0.3,
|
||||
)
|
||||
response_content = response.choices[0].message.content
|
||||
|
||||
# Limpiar y convertir el contenido de la respuesta
|
||||
cleaned_response_content = response_content.strip().strip("'```json").strip("```")
|
||||
|
||||
# Intentar convertir el contenido a JSON
|
||||
try:
|
||||
score = float(cleaned_response_content)
|
||||
except ValueError:
|
||||
raise ValueError(
|
||||
f"La respuesta no se pudo decodificar como un número: {cleaned_response_content}"
|
||||
)
|
||||
|
||||
return score
|
||||
|
||||
|
||||
def main(config: TranslationConfig):
|
||||
global logger
|
||||
df = fc.read_dataframe_with_cleanup_retries(config.get_translate_path())
|
||||
|
||||
source_col = config.codigo_columna_maestra
|
||||
source_translated_col = f"{config.codigo_idioma_seleccionado}_Propuesto"
|
||||
source_translated_col = config.codigo_idioma_seleccionado
|
||||
target_col = f"{config.codigo_idioma_seleccionado} Translated"
|
||||
check_translate_col = f"{config.codigo_idioma_seleccionado} CheckTranslate"
|
||||
affinity_col = f"{config.codigo_idioma_seleccionado} Affinity"
|
||||
|
@ -123,37 +220,20 @@ def main(config: TranslationConfig):
|
|||
texts_to_translate = {}
|
||||
|
||||
# Inicializar ProgressBar para la fase de preparación
|
||||
prep_progress = fc.ProgressBar(
|
||||
len(df), prefix="Preparando textos:", suffix="Completado"
|
||||
)
|
||||
prep_progress = fc.ProgressBar(len(df), prefix='Preparando textos:', suffix='Completado')
|
||||
|
||||
for index, row in df.iterrows():
|
||||
celda_clave = str(row[source_col])
|
||||
source_translated_text = (
|
||||
str(row[source_translated_col])
|
||||
if source_translated_col in df.columns
|
||||
else ""
|
||||
)
|
||||
celda_clave_compactada = fc.compactar_celda_traducida(
|
||||
config.codigo_tipo_PLC, celda_clave
|
||||
)
|
||||
source_translated_text = str(row[source_translated_col]) if source_translated_col in df.columns else ""
|
||||
celda_clave_compactada = fc.compactar_celda_traducida(config.codigo_tipo_PLC, celda_clave)
|
||||
|
||||
if config.traducir_todo:
|
||||
if fc.texto_requiere_traduccion(
|
||||
config.codigo_tipo_PLC, celda_clave_compactada, logger
|
||||
):
|
||||
if fc.texto_requiere_traduccion(config.codigo_tipo_PLC, celda_clave_compactada, logger):
|
||||
df.at[index, source_translated_col] = ""
|
||||
texts_to_translate[celda_clave] = celda_clave_compactada
|
||||
else:
|
||||
if (
|
||||
pd.isna(row[source_translated_col])
|
||||
or source_translated_text.strip() == ""
|
||||
):
|
||||
if fc.texto_requiere_traduccion(
|
||||
config.codigo_tipo_PLC, celda_clave_compactada, logger
|
||||
) or fc.texto_con_campos_especiales(
|
||||
config.codigo_tipo_PLC, celda_clave_compactada
|
||||
):
|
||||
if pd.isna(row[source_translated_col]) or source_translated_text.strip() == "":
|
||||
if fc.texto_requiere_traduccion(config.codigo_tipo_PLC, celda_clave_compactada, logger) or fc.texto_con_campos_especiales(config.codigo_tipo_PLC, celda_clave_compactada):
|
||||
texts_to_translate[celda_clave] = celda_clave_compactada
|
||||
|
||||
prep_progress.update(index + 1)
|
||||
|
@ -165,9 +245,7 @@ def main(config: TranslationConfig):
|
|||
print(f"\nNúmero total de textos a traducir: {num_texts}")
|
||||
|
||||
# Inicializar ProgressBar para la fase de traducción
|
||||
trans_progress = fc.ProgressBar(
|
||||
num_texts, prefix="Traduciendo:", suffix="Completado"
|
||||
)
|
||||
trans_progress = fc.ProgressBar(num_texts, prefix='Traduciendo:', suffix='Completado')
|
||||
|
||||
# Traducciones
|
||||
translations = {}
|
||||
|
@ -182,26 +260,18 @@ def main(config: TranslationConfig):
|
|||
batch_translations = translate_batch_openai(
|
||||
batch_texts,
|
||||
fc.idiomas_idiomafromcode(config.codigo_columna_maestra),
|
||||
fc.idiomas_idiomafromcode(config.codigo_idioma_seleccionado),
|
||||
fc.idiomas_idiomafromcode(config.codigo_idioma_seleccionado)
|
||||
)
|
||||
translations.update(batch_translations)
|
||||
break
|
||||
except Exception as e:
|
||||
if attempt < retries - 1:
|
||||
logger.warning(
|
||||
f"Error en el intento {attempt + 1} de traducción de celdas desde {start_idx} a {end_idx}: {e}. Reintentando..."
|
||||
)
|
||||
print(
|
||||
f"Error en el intento {attempt + 1} de traducción de celdas desde {start_idx} a {end_idx}: {e}. Reintentando..."
|
||||
)
|
||||
logger.warning(f"Error en el intento {attempt + 1} de traducción de celdas desde {start_idx} a {end_idx}: {e}. Reintentando...")
|
||||
print(f"Error en el intento {attempt + 1} de traducción de celdas desde {start_idx} a {end_idx}: {e}. Reintentando...")
|
||||
time.sleep(3)
|
||||
else:
|
||||
logger.error(
|
||||
f"Error en todos los intentos de traducción de celdas desde {start_idx} a {end_idx}: {e}"
|
||||
)
|
||||
print(
|
||||
f"Error en todos los intentos de traducción de celdas desde {start_idx} a {end_idx}: {e}"
|
||||
)
|
||||
logger.error(f"Error en todos los intentos de traducción de celdas desde {start_idx} a {end_idx}: {e}")
|
||||
print(f"Error en todos los intentos de traducción de celdas desde {start_idx} a {end_idx}: {e}")
|
||||
|
||||
trans_progress.update(end_idx)
|
||||
|
||||
|
@ -209,9 +279,7 @@ def main(config: TranslationConfig):
|
|||
logger.info(f"Número total de traducciones recibidas: {len(translations)}")
|
||||
|
||||
# Inicializar ProgressBar para la fase de actualización del DataFrame
|
||||
update_progress = fc.ProgressBar(
|
||||
len(df), prefix="Actualizando DataFrame:", suffix="Completado"
|
||||
)
|
||||
update_progress = fc.ProgressBar(len(df), prefix='Actualizando DataFrame:', suffix='Completado')
|
||||
|
||||
# Actualizar el DataFrame con las traducciones y hacemos la Traduccion inversa
|
||||
for index, row in df.iterrows():
|
||||
|
@ -221,106 +289,63 @@ def main(config: TranslationConfig):
|
|||
try:
|
||||
google_translation = google_translate(
|
||||
translations[celda_clave],
|
||||
fc.idiomas_shortcodefromcode(config.codigo_columna_maestra),
|
||||
fc.idiomas_shortcodefromcode(config.codigo_columna_maestra)
|
||||
)
|
||||
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 '{celda_clave}': {e}"
|
||||
)
|
||||
logger.error(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
|
||||
update_progress.increment()
|
||||
|
||||
update_progress.finish()
|
||||
|
||||
# Configurar el modelo a usar
|
||||
modelo_llm = fc.LLM_MODELS["OpenAI"] # o el que se prefiera
|
||||
api_key = openai_api_key() # solo necesario para OpenAI y Grok
|
||||
# Inicializar ProgressBar para la fase de cálculo de afinidad
|
||||
affinity_progress = fc.ProgressBar(num_texts, prefix='Calculando afinidad:', suffix='Completado')
|
||||
|
||||
# Afinidades
|
||||
# Los textos ya vienen del proceso de traducción
|
||||
texts_to_check = {}
|
||||
for key, translated_text in translations.items():
|
||||
if pd.notna(translated_text) and str(translated_text).strip() != "":
|
||||
texts_to_check[key] = translated_text
|
||||
affinities = {}
|
||||
for start_idx in range(0, num_texts, batch_size):
|
||||
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}.")
|
||||
|
||||
# Calcular afinidades usando LLM
|
||||
affinities_dict = fc.calcular_afinidad_batch(
|
||||
texts_to_check, config.codigo_tipo_PLC, modelo_llm, logger, api_key
|
||||
)
|
||||
retries = 2
|
||||
for attempt in range(retries):
|
||||
try:
|
||||
batch_affinities = affinity_batch_openai(config.codigo_tipo_PLC, batch_texts)
|
||||
affinities.update(batch_affinities)
|
||||
break
|
||||
except Exception as e:
|
||||
if attempt < retries - 1:
|
||||
logger.warning(f"Error en el intento {attempt + 1} de Afinidad de celdas desde {start_idx} a {end_idx}: {e}. Reintentando...")
|
||||
print(f"Error en el intento {attempt + 1} de Afinidad de celdas desde {start_idx} a {end_idx}: {e}. Reintentando...")
|
||||
time.sleep(3)
|
||||
else:
|
||||
logger.error(f"Error en todos los intentos de Afinidad de celdas desde {start_idx} a {end_idx}: {e}")
|
||||
print(f"Error en todos los intentos de Afinidad de celdas desde {start_idx} a {end_idx}: {e}")
|
||||
for key, value in batch_texts.items():
|
||||
try:
|
||||
score = calcular_afinidad(config.codigo_tipo_PLC, key, value)
|
||||
affinities[key] = score
|
||||
except Exception as ind_e:
|
||||
affinities[key] = "0"
|
||||
logger.error(f"Error en el cálculo individual de Afinidad para el texto '{key}': {ind_e}")
|
||||
print(f"Error en el cálculo individual de Afinidad para el texto '{key}': {ind_e}")
|
||||
|
||||
# Asignar resultados al DataFrame
|
||||
affinity_progress.increment()
|
||||
|
||||
affinity_progress.finish()
|
||||
# Actualizar el DataFrame con las Afinidades
|
||||
for index, row in df.iterrows():
|
||||
key = str(row[source_col])
|
||||
if key in affinities_dict:
|
||||
df.at[index, affinity_col] = affinities_dict[key]
|
||||
celda_clave = str(row[source_col])
|
||||
if celda_clave in affinities:
|
||||
df.at[index, affinity_col] = affinities[celda_clave]
|
||||
|
||||
output_path = config.get_auto_translate_path()
|
||||
|
||||
with pd.ExcelWriter(output_path, engine="openpyxl") as writer:
|
||||
df.to_excel(writer, index=False, sheet_name="Sheet1")
|
||||
|
||||
workbook = writer.book
|
||||
worksheet = writer.sheets["Sheet1"]
|
||||
# Inmovilizar paneles en A2
|
||||
worksheet.freeze_panes = "A2"
|
||||
|
||||
# Configurar ancho de columnas basado en contenido
|
||||
from openpyxl.utils import get_column_letter
|
||||
|
||||
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))
|
||||
# Si el texto es más largo que 50, aplicamos wrap_text
|
||||
if text_length > 50:
|
||||
cell.alignment = Alignment(wrap_text=True, vertical="top")
|
||||
text_length = min(
|
||||
50, max(len(word) for word in str(cell.value).split())
|
||||
)
|
||||
max_length = max(max_length, text_length)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Ajustar el ancho con un pequeño padding
|
||||
adjusted_width = min(50, max_length + 2)
|
||||
worksheet.column_dimensions[column].width = (
|
||||
adjusted_width if adjusted_width > 8 else 8
|
||||
)
|
||||
|
||||
# Colores para el formato condicional
|
||||
light_blue = PatternFill(
|
||||
start_color="ADD8E6", end_color="ADD8E6", fill_type="solid"
|
||||
)
|
||||
yellow = PatternFill(
|
||||
start_color="FFFF00", end_color="FFFF00", fill_type="solid"
|
||||
)
|
||||
|
||||
# Aplicar formatos
|
||||
for row in worksheet.iter_rows(min_row=2):
|
||||
translated_cell = row[df.columns.get_loc(target_col)]
|
||||
if translated_cell.value:
|
||||
affinity_cell = row[df.columns.get_loc(affinity_col)]
|
||||
try:
|
||||
affinity_value = float(
|
||||
affinity_cell.value if affinity_cell.value else 0
|
||||
)
|
||||
if affinity_value == 1:
|
||||
translated_cell.fill = light_blue
|
||||
elif affinity_value < 1:
|
||||
translated_cell.fill = yellow
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
fc.save_dataframe_with_retries(df, output_path=output_path)
|
||||
logger.info(f"Archivo traducido guardado en: {output_path}")
|
||||
print(f"\nArchivo traducido guardado en: {output_path}")
|
||||
|
||||
|
||||
def run(config: TranslationConfig):
|
||||
global logger
|
||||
logger = fc.configurar_logger(config.work_dir)
|
||||
|
@ -328,8 +353,6 @@ def run(config: TranslationConfig):
|
|||
print(f"\rIniciando: {script_name}\r")
|
||||
main(config)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import menu_pasos_traduccion
|
||||
|
||||
menu_pasos_traduccion.main()
|
|
@ -18,7 +18,6 @@ def importar_traduccion_manual(config: TranslationConfig):
|
|||
|
||||
archivo_traduccion = config.get_translate_path()
|
||||
master_col = config.codigo_idioma_seleccionado
|
||||
propuesto_col = f"{config.codigo_idioma_seleccionado}_Propuesto"
|
||||
|
||||
df_maestro = fc.read_dataframe_with_cleanup_retries(archivo_maestro)
|
||||
df_traduccion = fc.read_dataframe_with_cleanup_retries(archivo_traduccion)
|
||||
|
@ -29,7 +28,7 @@ def importar_traduccion_manual(config: TranslationConfig):
|
|||
for index, fila in df_traduccion.iterrows():
|
||||
clave = fila[df_maestro.columns[0]]
|
||||
if clave in df_maestro[df_maestro.columns[0]].values:
|
||||
valor_traducido = fila[propuesto_col] # Use propuesto column
|
||||
valor_traducido = fila[master_col]
|
||||
valor_original = df_maestro.loc[
|
||||
df_maestro[df_maestro.columns[0]] == clave, master_col
|
||||
].values[0]
|
||||
|
@ -39,7 +38,6 @@ def importar_traduccion_manual(config: TranslationConfig):
|
|||
and valor_traducido != ""
|
||||
and str(valor_original) != str(valor_traducido)
|
||||
):
|
||||
|
||||
okToSave, Error = fc.verificar_celda_traducida(
|
||||
config.codigo_tipo_PLC, clave, valor_traducido
|
||||
)
|
||||
|
@ -64,7 +62,7 @@ def importar_traduccion_manual(config: TranslationConfig):
|
|||
f"Fila {index}, Columna {master_col}: No actualizado porque: {Error}"
|
||||
)
|
||||
fila_excel = index + 2
|
||||
columna_excel = df_traduccion.columns.get_loc(propuesto_col) + 1
|
||||
columna_excel = df_traduccion.columns.get_loc(master_col) + 1
|
||||
celdas_con_errores[(fila_excel, columna_excel)] = Error
|
||||
|
||||
fc.save_dataframe_with_retries(df_maestro, output_path=archivo_maestro)
|
||||
|
|
|
@ -4,7 +4,6 @@ import os
|
|||
from translation_config import TranslationConfig
|
||||
from openpyxl import load_workbook
|
||||
from openpyxl.styles import Font
|
||||
from openpyxl.styles import PatternFill, Alignment, Font
|
||||
|
||||
# Definir el logger a nivel de módulo
|
||||
logger = None
|
||||
|
@ -17,7 +16,6 @@ def importar_traduccion(config: TranslationConfig):
|
|||
return
|
||||
|
||||
master_col = config.codigo_idioma_seleccionado
|
||||
master_propuesto_col = f"{master_col}_Propuesto"
|
||||
translated_col = f"{config.codigo_idioma_seleccionado} Translated"
|
||||
affinity_col = f"{config.codigo_idioma_seleccionado} Affinity"
|
||||
|
||||
|
@ -26,106 +24,47 @@ def importar_traduccion(config: TranslationConfig):
|
|||
config.get_auto_translate_path()
|
||||
)
|
||||
|
||||
# Caso especial: columna maestra es igual al idioma seleccionado
|
||||
is_same_column = config.codigo_columna_maestra == config.codigo_idioma_seleccionado
|
||||
|
||||
# Si es el mismo, asegurarse que existe la columna propuesta
|
||||
if is_same_column and master_propuesto_col not in df_maestro.columns:
|
||||
df_maestro[master_propuesto_col] = df_maestro[master_col]
|
||||
|
||||
celdas_modificadas = {}
|
||||
|
||||
if config.codigo_columna_maestra not in df_maestro.columns:
|
||||
print(f"Error: Columnas requeridas no encontradas en el archivo maestro")
|
||||
return
|
||||
|
||||
if (
|
||||
config.codigo_columna_maestra not in df_traduccion.columns
|
||||
or translated_col not in df_traduccion.columns
|
||||
or affinity_col not in df_traduccion.columns
|
||||
):
|
||||
print(f"Error: Columnas requeridas no encontradas en el archivo de traducción")
|
||||
return
|
||||
|
||||
for index, fila in df_traduccion.iterrows():
|
||||
clave = fila[config.codigo_columna_maestra]
|
||||
mascara = df_maestro[config.codigo_columna_maestra] == clave
|
||||
|
||||
if mascara.any():
|
||||
clave = fila[df_maestro.columns[0]]
|
||||
if clave in df_maestro[df_maestro.columns[0]].values:
|
||||
if (
|
||||
pd.notna(fila[affinity_col])
|
||||
and fila[affinity_col] >= config.nivel_afinidad_minimo
|
||||
and pd.notna(fila[translated_col])
|
||||
fila[affinity_col] >= config.nivel_afinidad_minimo
|
||||
and pd.notnull(fila[translated_col])
|
||||
and fila[translated_col] != ""
|
||||
):
|
||||
valor_traducido = fila[translated_col]
|
||||
indice_maestro = df_maestro.index[mascara].tolist()[0]
|
||||
|
||||
# Determinar la columna a actualizar según el caso
|
||||
columna_destino = master_propuesto_col if is_same_column else master_col
|
||||
valor_original = df_maestro.loc[indice_maestro, columna_destino]
|
||||
valor_original = df_maestro.loc[
|
||||
df_maestro[df_maestro.columns[0]] == clave, master_col
|
||||
].values[0]
|
||||
|
||||
if str(valor_original) != str(valor_traducido):
|
||||
df_maestro.loc[indice_maestro, columna_destino] = valor_traducido
|
||||
df_maestro.loc[
|
||||
df_maestro[df_maestro.columns[0]] == clave, master_col
|
||||
] = valor_traducido
|
||||
logger.info(
|
||||
f'Fila {index}, Columna {columna_destino}: "{valor_original}" actualizado a "{valor_traducido}"'
|
||||
f'Fila {index}, Columna {translated_col}: "{valor_original}" actualizado a "{valor_traducido}"'
|
||||
)
|
||||
|
||||
fila_excel = indice_maestro + 2
|
||||
columna_excel = df_maestro.columns.get_loc(columna_destino) + 1
|
||||
fila_excel = (
|
||||
df_maestro.index[
|
||||
df_maestro[df_maestro.columns[0]] == clave
|
||||
].tolist()[0]
|
||||
+ 2
|
||||
)
|
||||
columna_excel = df_maestro.columns.get_loc(master_col) + 1
|
||||
celdas_modificadas[(fila_excel, columna_excel)] = valor_traducido
|
||||
|
||||
# Guardar con formato Excel
|
||||
with pd.ExcelWriter(archivo_maestro, engine="openpyxl") as writer:
|
||||
df_maestro.to_excel(writer, index=False, sheet_name="Sheet1")
|
||||
|
||||
workbook = writer.book
|
||||
worksheet = writer.sheets["Sheet1"]
|
||||
|
||||
# Inmovilizar paneles en A2
|
||||
worksheet.freeze_panes = "A2"
|
||||
|
||||
# Configurar ancho de columnas basado en contenido
|
||||
from openpyxl.utils import get_column_letter
|
||||
from openpyxl.styles import Alignment, Font, PatternFill
|
||||
|
||||
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 = Alignment(wrap_text=True, vertical="top")
|
||||
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
|
||||
else :
|
||||
logger.error(
|
||||
f'Clave {clave} no encontrada en master.'
|
||||
)
|
||||
|
||||
# Aplicar negrita y color a las celdas modificadas
|
||||
light_blue = PatternFill(
|
||||
start_color="ADD8E6", end_color="ADD8E6", fill_type="solid"
|
||||
)
|
||||
for (fila, columna), valor in celdas_modificadas.items():
|
||||
celda = worksheet.cell(row=fila, column=columna)
|
||||
celda.font = Font(bold=True)
|
||||
celda.value = valor
|
||||
celda.fill = light_blue
|
||||
fc.save_dataframe_with_retries(df_maestro, output_path=archivo_maestro)
|
||||
|
||||
if celdas_modificadas:
|
||||
print(
|
||||
f"Se han actualizado y marcado {len(celdas_modificadas)} celdas en el archivo maestro."
|
||||
)
|
||||
else:
|
||||
print("No se realizaron modificaciones en el archivo maestro.")
|
||||
aplicar_negrita_celdas_modificadas(archivo_maestro, celdas_modificadas)
|
||||
|
||||
print(f"Traducciones importadas y archivo maestro actualizado: {archivo_maestro}.")
|
||||
|
||||
|
||||
def aplicar_negrita_celdas_modificadas(archivo, celdas_modificadas):
|
||||
|
|
|
@ -16,139 +16,91 @@ def update_from_master(config: TranslationConfig, archivo_to_update):
|
|||
print("El archivo maestro no existe.")
|
||||
return
|
||||
|
||||
logger.info(f"Iniciando actualización en {archivo_to_update} desde el archivo maestro. Para {config.codigo_idioma_seleccionado}")
|
||||
logger.info(" .... ")
|
||||
logger.info(
|
||||
f"Iniciando actualización en {archivo_to_update} desde el archivo maestro. Para {config.codigo_idioma_seleccionado}"
|
||||
)
|
||||
|
||||
df_maestro = fc.read_dataframe_with_cleanup_retries(archivo_maestro)
|
||||
df_to_update = fc.read_dataframe_with_cleanup_retries(archivo_to_update)
|
||||
|
||||
# Create copy for changes tracking
|
||||
df_changes = df_to_update.copy()
|
||||
df_changes["Original_Value"] = ""
|
||||
|
||||
col_clave = config.codigo_columna_maestra
|
||||
# Si la columna maestra es igual al idioma seleccionado, usamos la columna propuesta
|
||||
is_same_column = config.codigo_columna_maestra == config.codigo_idioma_seleccionado
|
||||
master_col = f"{config.codigo_idioma_seleccionado}_Propuesto" if is_same_column else config.codigo_idioma_seleccionado
|
||||
|
||||
if master_col not in df_maestro.columns:
|
||||
print(f"Error: Columna {master_col} no encontrada en el archivo maestro")
|
||||
return
|
||||
celdas_con_errores = {}
|
||||
celdas_vacias = {}
|
||||
|
||||
celdas_modificadas = []
|
||||
|
||||
progress_bar = fc.ProgressBar(len(df_to_update), prefix="Actualizando filas:", suffix="Completado")
|
||||
progress_bar = fc.ProgressBar(
|
||||
len(df_to_update), prefix="Actualizando filas:", suffix="Completado"
|
||||
)
|
||||
|
||||
for index, fila in df_to_update.iterrows():
|
||||
valor_original = fila[col_clave]
|
||||
clave = fc.compactar_celda_clave(config.codigo_tipo_PLC, valor_original)
|
||||
|
||||
if not pd.isna(clave) and clave in df_maestro[col_clave].values:
|
||||
indice_maestro = df_maestro.index[df_maestro[col_clave] == clave].tolist()[0]
|
||||
valor_traducido_compacto = df_maestro.loc[indice_maestro, master_col]
|
||||
# logger.info(f"Fila {index} : Clave: {clave}")
|
||||
|
||||
indice_maestro = df_maestro.index[df_maestro[col_clave] == clave].tolist()[
|
||||
0
|
||||
]
|
||||
valor_traducido_compacto = df_maestro.loc[
|
||||
indice_maestro, config.codigo_idioma_seleccionado
|
||||
]
|
||||
|
||||
if pd.isna(valor_traducido_compacto):
|
||||
continue
|
||||
|
||||
valor_traducido = fc.decompactar_celda_traducida(
|
||||
config.codigo_tipo_PLC,
|
||||
celda_original=valor_original,
|
||||
celda_traducida=valor_traducido_compacto
|
||||
)
|
||||
|
||||
if not pd.isna(valor_traducido) and fila[config.codigo_idioma_seleccionado] != valor_traducido:
|
||||
okToSave, Error = fc.verificar_celda_traducida(
|
||||
config.codigo_tipo_PLC, clave, valor_traducido_compacto
|
||||
celdas_vacias[indice_maestro] = "Celda vacía en el archivo maestro"
|
||||
logger.info(f"Fila {index}: Celda vacía en el archivo maestro")
|
||||
else:
|
||||
valor_traducido = fc.decompactar_celda_traducida(
|
||||
config.codigo_tipo_PLC,
|
||||
celda_original=valor_original,
|
||||
celda_traducida=valor_traducido_compacto,
|
||||
)
|
||||
if okToSave:
|
||||
# Store original value in changes DataFrame
|
||||
df_changes.at[index, "Original_Value"] = fila[config.codigo_idioma_seleccionado]
|
||||
|
||||
# Update both DataFrames
|
||||
df_to_update.at[index, config.codigo_idioma_seleccionado] = valor_traducido
|
||||
df_changes.at[index, config.codigo_idioma_seleccionado] = valor_traducido
|
||||
|
||||
celdas_modificadas.append(index)
|
||||
logger.info(f"Actualizado: Fila {index} : Clave: {clave}")
|
||||
if (
|
||||
not pd.isna(valor_traducido)
|
||||
and fila[config.codigo_idioma_seleccionado] != valor_traducido
|
||||
):
|
||||
okToSave, Error = fc.verificar_celda_traducida(
|
||||
config.codigo_tipo_PLC, clave, valor_traducido_compacto
|
||||
)
|
||||
if okToSave:
|
||||
logger.info(f"Actualizado: Fila {index} : Clave: {clave}")
|
||||
df_to_update.at[index, config.codigo_idioma_seleccionado] = (
|
||||
valor_traducido
|
||||
)
|
||||
else:
|
||||
df_to_update.at[index, config.codigo_idioma_seleccionado] = (
|
||||
valor_original
|
||||
)
|
||||
logger.error(f"No actualizado porque: {Error}")
|
||||
celdas_con_errores[indice_maestro] = Error
|
||||
|
||||
progress_bar.increment()
|
||||
|
||||
progress_bar.finish()
|
||||
|
||||
# Save updated file with formatting
|
||||
nombre, extension = os.path.splitext(archivo_to_update)
|
||||
nuevo_nombre = f"{nombre}_import{extension}"
|
||||
fc.save_dataframe_with_retries(df_to_update, output_path=nuevo_nombre)
|
||||
|
||||
with pd.ExcelWriter(nuevo_nombre, engine='openpyxl') as writer:
|
||||
df_to_update.to_excel(writer, sheet_name="User Texts", index=False)
|
||||
marcar_celdas_con_errores(
|
||||
archivo_maestro,
|
||||
celdas_con_errores,
|
||||
celdas_vacias,
|
||||
config.codigo_idioma_seleccionado,
|
||||
)
|
||||
|
||||
workbook = writer.book
|
||||
worksheet = writer.sheets["User Texts"]
|
||||
|
||||
# Format columns
|
||||
from openpyxl.utils import get_column_letter
|
||||
from openpyxl.styles import Alignment, PatternFill
|
||||
|
||||
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 = Alignment(wrap_text=True, vertical='top')
|
||||
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
|
||||
|
||||
# Save changes file with highlighting
|
||||
changes_nombre = f"{nombre}_changes{extension}"
|
||||
if len(celdas_modificadas) > 0:
|
||||
with pd.ExcelWriter(changes_nombre, engine="openpyxl") as writer:
|
||||
df_changes.to_excel(writer, index=False)
|
||||
|
||||
workbook = writer.book
|
||||
worksheet = writer.sheets["User Texts"]
|
||||
|
||||
light_blue = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
|
||||
|
||||
for row_idx in celdas_modificadas:
|
||||
for col in range(1, len(df_changes.columns) + 1):
|
||||
cell = worksheet.cell(row=row_idx + 2, column=col)
|
||||
cell.fill = light_blue
|
||||
|
||||
# Format columns in changes file too
|
||||
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 = Alignment(wrap_text=True, vertical='top')
|
||||
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
|
||||
|
||||
print(f"Se han actualizado las filas en {archivo_to_update} desde el archivo maestro.")
|
||||
print(f"Archivo de cambios guardado en: {changes_nombre}")
|
||||
print(f"Se han marcado {len(celdas_modificadas)} filas modificadas.")
|
||||
print(
|
||||
f"Se han actualizado las filas en {archivo_to_update} desde el archivo maestro."
|
||||
)
|
||||
print(
|
||||
f"Se han marcado {len(celdas_con_errores)} celdas con errores en el archivo maestro."
|
||||
)
|
||||
print(f"Se han marcado {len(celdas_vacias)} celdas vacías en el archivo maestro.")
|
||||
logger.info(" .... ")
|
||||
|
||||
def marcar_celdas_con_errores(
|
||||
archivo_maestro, celdas_con_errores, celdas_vacias, target_lang_code
|
||||
):
|
||||
|
||||
def marcar_celdas_con_errores(archivo_maestro, celdas_con_errores, celdas_vacias, target_lang_code):
|
||||
workbook = load_workbook(archivo_maestro)
|
||||
sheet = workbook.active
|
||||
|
||||
|
@ -160,12 +112,8 @@ def marcar_celdas_con_errores(
|
|||
print(f"No se encontró la columna para el idioma {target_lang_code}")
|
||||
return
|
||||
|
||||
error_fill = PatternFill(
|
||||
start_color="FF0000", end_color="FF0000", fill_type="solid"
|
||||
)
|
||||
empty_fill = PatternFill(
|
||||
start_color="FFFF00", end_color="FFFF00", fill_type="solid"
|
||||
)
|
||||
error_fill = PatternFill(start_color="FF0000", end_color="FF0000", fill_type="solid")
|
||||
empty_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
|
||||
white_font = Font(color="FFFFFF") # Fuente blanca para celdas con fondo rojo
|
||||
|
||||
for indice_maestro, mensaje_error in celdas_con_errores.items():
|
||||
|
@ -184,9 +132,7 @@ def marcar_celdas_con_errores(
|
|||
cell.comment = comment
|
||||
|
||||
workbook.save(archivo_maestro)
|
||||
print(
|
||||
f"Se han marcado las celdas con errores y vacías en el archivo maestro {archivo_maestro}"
|
||||
)
|
||||
print(f"Se han marcado las celdas con errores y vacías en el archivo maestro {archivo_maestro}")
|
||||
|
||||
|
||||
def run(config: TranslationConfig, archivo_to_update):
|
||||
|
|
Loading…
Reference in New Issue