chore: baseline plantilla-proyectos como base del CRM
This commit is contained in:
358
frontend/scripts/merge_csv_upload_i18n.py
Normal file
358
frontend/scripts/merge_csv_upload_i18n.py
Normal file
@@ -0,0 +1,358 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Fusiona bloques csv_upload en messages/en.json y messages/es.json y vuelca a src/lib/i18n/csv-upload-messages.*.json.
|
||||
|
||||
La fuente de verdad del copy CSV es `messages/{en,es}.json` (alineado con sidebar, dashboard, facturas).
|
||||
Si editas solo esos JSON, sincroniza con:
|
||||
node -e "const fs=require('fs'),p=require('path'),r='.../frontend';for(const l of['en','es']){const j=JSON.parse(fs.readFileSync(p.join(r,'messages',l+'.json'),'utf8'));fs.writeFileSync(p.join(r,'src/lib/i18n','csv-upload-messages.'+l+'.json'),JSON.stringify(j.csv_upload,null,'\\t')+'\\n')}"
|
||||
|
||||
Ejecutar desde frontend/: python scripts/merge_csv_upload_i18n.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
MESSAGES = ROOT / "messages"
|
||||
|
||||
EN_CSV = {
|
||||
"page_title": "CSV import",
|
||||
"intro_help": "Left-click: upload CSV file. Right-click: download template.",
|
||||
"tab_catalogos": "Catalogs",
|
||||
"tab_transportes": "Transportation",
|
||||
"tab_importacion": "Import",
|
||||
"tab_exportacion": "Export",
|
||||
"section_catalogs": "General Catalogs",
|
||||
"section_transport": "Transportation",
|
||||
"section_import": "Import operations",
|
||||
"section_export": "Export operations",
|
||||
"params_header": "Global parameters",
|
||||
"config_prefix": "Settings",
|
||||
"soon": "Coming soon",
|
||||
"drop_here": "Drop the file!",
|
||||
"groups": {
|
||||
"permisos": "Permissions",
|
||||
"impo_temp": "Temporary import",
|
||||
"impo_def": "Definitive import",
|
||||
"cmex": "Mexican purchases",
|
||||
"expo_def": "Definitive export / regime change",
|
||||
"expo_rep": "Export replenishment",
|
||||
"manifest": "Manifest",
|
||||
},
|
||||
"items": {
|
||||
"customs_brokers": "Customs Brokers",
|
||||
"clients_providers": "Clients and Providers",
|
||||
"exchange_rates": "Exchange Rates",
|
||||
"material_classes": "Classes",
|
||||
"part_numbers": "Parts",
|
||||
"boms": "BOMs",
|
||||
"items": "Lines (permissions)",
|
||||
"headers": "Headers (permissions)",
|
||||
"historical_fractions": "Historical tariff fractions",
|
||||
"pedimentos": "Pedimentos",
|
||||
"transporters": "Carriers",
|
||||
"transports": "Vehicles",
|
||||
"drivers": "Drivers",
|
||||
"trailers": "Trailers",
|
||||
"imp_temp_header": "Header",
|
||||
"imp_temp_details": "Lines",
|
||||
"imp_temp_series": "Serial numbers",
|
||||
"imp_def_header": "Header",
|
||||
"imp_def_details": "Lines",
|
||||
"imp_def_series": "Serial numbers",
|
||||
"comp_mex_header": "Header",
|
||||
"comp_mex_details": "Lines",
|
||||
"comp_mex_series": "Serial numbers",
|
||||
"exp_def_header": "Header",
|
||||
"exp_def_details": "Lines",
|
||||
"exp_def_series": "Serial numbers",
|
||||
"exp_def_nodes": "NODES",
|
||||
"exp_rep_header": "Header",
|
||||
"exp_rep_details": "Lines",
|
||||
"exp_rep_series": "Serial numbers",
|
||||
"manifest_header": "Header",
|
||||
},
|
||||
"params": {
|
||||
"load_mode": "Load mode",
|
||||
"date_format": "Date format",
|
||||
"weight_unit": "Weight unit",
|
||||
"autonumber_series": "Autonumber lines/series",
|
||||
"load_subpartidas": "Load sub-lines",
|
||||
"recalculate_pedimento_date": "Recalculate pedimento date",
|
||||
"autonumber_remesas": "Autonumber consignments",
|
||||
"recalculate_dates": "Recalculate dates",
|
||||
"invoice_type": "Invoice type",
|
||||
"is_regime_change": "Regime change",
|
||||
},
|
||||
"options": {
|
||||
"update": "Update",
|
||||
"replace": "Replace",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"kgs": "Kilograms (kg)",
|
||||
"lbs": "Pounds (lb)",
|
||||
"date_dd_mm": "DD/MM/YYYY",
|
||||
"date_mm_dd": "MM/DD/YYYY",
|
||||
"date_iso": "YYYY-MM-DD",
|
||||
"afi": "AFIJO",
|
||||
"normal": "NORMAL",
|
||||
},
|
||||
"progress": {
|
||||
"upload": "Uploading CSV file",
|
||||
"scan": "Validating records on the server",
|
||||
"commit": "Saving records to the database",
|
||||
"upload_known": "Uploading file…",
|
||||
"upload_unknown": "Uploading file (unknown size in browser)…",
|
||||
"in_progress": "In progress…",
|
||||
"resume_hint": "Resuming import saved in this tab…",
|
||||
"rows_file": "File: ~{n} data row(s) — uploading (not yet validated on server)…",
|
||||
"rows_scan": "Records processed: {current} / {total}",
|
||||
"rows_commit": "Records saved: {current} / {total}",
|
||||
"rows_commit_fallback": "Saving to database… ({current} / {total} using last known total)",
|
||||
},
|
||||
"toast": {
|
||||
"invalid_csv": "Invalid format. Only .csv files are allowed.",
|
||||
"download_loading": "Downloading template…",
|
||||
"download_ok": "Template downloaded.",
|
||||
"download_err": "Could not download the template.",
|
||||
"upload_err": "Could not upload the file.",
|
||||
"upload_err_generic": "Unexpected error uploading the file.",
|
||||
"scan_done": "Scan complete. Review the results.",
|
||||
"import_done": "Import completed. Review the record list.",
|
||||
"import_maybe_done": "Import may have completed. Review the record list.",
|
||||
"stale_job": "This import is no longer available (session expired or job removed). You can start a new upload.",
|
||||
"poll_err": "Could not fetch status",
|
||||
"commit_err": "Could not start import",
|
||||
"scan_alt": "Scan finished. If you do not see the modal, check the record list.",
|
||||
"finished_none": "No records inserted. Review the errors below.",
|
||||
"commit_warning_ok": "{inserted} inserted, {updated} updated. {skipped} rejected.",
|
||||
"commit_warning_none": "No records inserted or updated. {skipped} rejected.",
|
||||
"success_counts": "Import completed: {msg}",
|
||||
"warn_skipped": "{n} records rejected or skipped",
|
||||
"error_processing": "Processing error: {msg}",
|
||||
},
|
||||
"pending": {
|
||||
"badge": "Pending",
|
||||
"title": "Imports pending confirmation",
|
||||
"description": "Scans ready to save to the database. Expired jobs disappear when you refresh.",
|
||||
"refresh": "Refresh",
|
||||
"empty": "No pending imports for this company.",
|
||||
"checking": "Checking with the server…",
|
||||
"total_rows": "Total rows",
|
||||
"valid_rows": "Valid",
|
||||
"resume": "Resume",
|
||||
"remove": "Remove",
|
||||
"profiles": {
|
||||
"customs_brokers": "Customs Brokers",
|
||||
"clients_providers": "Clients and Providers",
|
||||
"exchange_rates": "Exchange Rates",
|
||||
"pedimentos": "Pedimentos",
|
||||
"material_classes": "Classes",
|
||||
"vehicles": "Vehicles",
|
||||
"drivers": "Drivers",
|
||||
"trailers": "Trailers",
|
||||
"transporters": "Carriers",
|
||||
"part_numbers": "Parts",
|
||||
"boms": "BOMs",
|
||||
"exportacion": "Export operations",
|
||||
"imports": "Import operations",
|
||||
},
|
||||
},
|
||||
"modal": {
|
||||
"title_pending": "Import validation",
|
||||
"title_success": "Import successful",
|
||||
"title_warning": "Import with remarks",
|
||||
"desc_pending": "Review the preliminary analysis before confirming.",
|
||||
"desc_done": "The import process has finished.",
|
||||
"total_rows": "Total rows",
|
||||
"valid_rows": "Valid",
|
||||
"invalid_rows": "Invalid",
|
||||
},
|
||||
}
|
||||
|
||||
ES_CSV = {
|
||||
"page_title": "Importación CSV",
|
||||
"intro_help": "Clic izquierdo: cargar archivo CSV. Clic derecho: descargar plantilla.",
|
||||
"tab_catalogos": "Catálogos",
|
||||
"tab_transportes": "Transportes",
|
||||
"tab_importacion": "Importación",
|
||||
"tab_exportacion": "Exportación",
|
||||
"section_catalogs": "Catalogos Generales",
|
||||
"section_transport": "Transportes",
|
||||
"section_import": "Operaciones de importación",
|
||||
"section_export": "Operaciones de exportación",
|
||||
"params_header": "Parámetros globales",
|
||||
"config_prefix": "Configuración",
|
||||
"soon": "Próximamente",
|
||||
"drop_here": "¡Suelta el archivo!",
|
||||
"groups": {
|
||||
"permisos": "Permisos",
|
||||
"impo_temp": "Impo. temp.",
|
||||
"impo_def": "Impo. def.",
|
||||
"cmex": "Compras mex.",
|
||||
"expo_def": "Expo. def./Cam. reg.",
|
||||
"expo_rep": "Expo. rep.",
|
||||
"manifest": "Manifiesto",
|
||||
},
|
||||
"items": {
|
||||
"customs_brokers": "Agentes Aduanales",
|
||||
"clients_providers": "Clientes y Proveedores",
|
||||
"exchange_rates": "Tipos de cambio",
|
||||
"material_classes": "Clases",
|
||||
"part_numbers": "Partes",
|
||||
"boms": "BOMs",
|
||||
"items": "Partidas (permisos)",
|
||||
"headers": "Encabezados (permisos)",
|
||||
"historical_fractions": "Fracciones históricas",
|
||||
"pedimentos": "Pedimentos",
|
||||
"transporters": "Transportistas",
|
||||
"transports": "Vehículos",
|
||||
"drivers": "Conductores",
|
||||
"trailers": "Trailers",
|
||||
"imp_temp_header": "Encabezado",
|
||||
"imp_temp_details": "Partidas",
|
||||
"imp_temp_series": "Series",
|
||||
"imp_def_header": "Encabezado",
|
||||
"imp_def_details": "Partidas",
|
||||
"imp_def_series": "Series",
|
||||
"comp_mex_header": "Encabezado",
|
||||
"comp_mex_details": "Partidas",
|
||||
"comp_mex_series": "Series",
|
||||
"exp_def_header": "Encabezado",
|
||||
"exp_def_details": "Partidas",
|
||||
"exp_def_series": "Series",
|
||||
"exp_def_nodes": "NODES",
|
||||
"exp_rep_header": "Encabezado",
|
||||
"exp_rep_details": "Partidas",
|
||||
"exp_rep_series": "Series",
|
||||
"manifest_header": "Encabezado",
|
||||
},
|
||||
"params": {
|
||||
"load_mode": "Modo de carga",
|
||||
"date_format": "Formato de fecha",
|
||||
"weight_unit": "Unidad de peso",
|
||||
"autonumber_series": "Autonumerar partidas/series",
|
||||
"load_subpartidas": "Levantar subpartidas",
|
||||
"recalculate_pedimento_date": "Recalcular fecha pedimento",
|
||||
"autonumber_remesas": "Autonumerar remesas",
|
||||
"recalculate_dates": "Recalcular fechas",
|
||||
"invoice_type": "Tipo de factura",
|
||||
"is_regime_change": "Es cambio de régimen",
|
||||
},
|
||||
"options": {
|
||||
"update": "Actualizar",
|
||||
"replace": "Reemplazar",
|
||||
"yes": "Sí",
|
||||
"no": "No",
|
||||
"kgs": "Kilos (kg)",
|
||||
"lbs": "Libras (lb)",
|
||||
"date_dd_mm": "DD/MM/YYYY",
|
||||
"date_mm_dd": "MM/DD/YYYY",
|
||||
"date_iso": "YYYY-MM-DD",
|
||||
"afi": "AFIJO",
|
||||
"normal": "NORMAL",
|
||||
},
|
||||
"progress": {
|
||||
"upload": "Subiendo archivo CSV",
|
||||
"scan": "Validando registros en el servidor",
|
||||
"commit": "Grabando registros en base de datos",
|
||||
"upload_known": "Subiendo archivo…",
|
||||
"upload_unknown": "Subiendo archivo (tamaño desconocido en el navegador)…",
|
||||
"in_progress": "En proceso…",
|
||||
"resume_hint": "Reanudando la importación guardada en esta pestaña…",
|
||||
"rows_file": "Archivo: ~{n} fila(s) de datos — subiendo (aún no se validan registros en servidor)…",
|
||||
"rows_scan": "Registros procesados: {current} / {total}",
|
||||
"rows_commit": "Registros grabados: {current} / {total}",
|
||||
"rows_commit_fallback": "Grabando en base de datos… ({current} / {total} según último total conocido)",
|
||||
},
|
||||
"toast": {
|
||||
"invalid_csv": "Formato inválido. Solo se permiten archivos .csv",
|
||||
"download_loading": "Descargando plantilla…",
|
||||
"download_ok": "Plantilla descargada.",
|
||||
"download_err": "Error al descargar la plantilla",
|
||||
"upload_err": "Error al subir el archivo",
|
||||
"upload_err_generic": "Error inesperado al subir el archivo",
|
||||
"scan_done": "Escaneo completado. Revisa los resultados.",
|
||||
"import_done": "Importación completada. Revisa el listado de registros.",
|
||||
"import_maybe_done": "La importación pudo completarse. Revisa el listado de registros.",
|
||||
"stale_job": "Esta importación ya no está disponible (sesión expirada o trabajo eliminado). Puedes iniciar una nueva carga.",
|
||||
"poll_err": "Error al consultar el estado",
|
||||
"commit_err": "Error al iniciar la importación",
|
||||
"scan_alt": "El escaneo terminó. Si no ves el modal, revisa el listado de registros.",
|
||||
"finished_none": "No se insertaron registros. Revisa los errores a continuación.",
|
||||
"commit_warning_ok": "{inserted} insertados, {updated} actualizados. {skipped} rechazados.",
|
||||
"commit_warning_none": "No se insertaron ni actualizaron registros. {skipped} rechazados.",
|
||||
"success_counts": "Importación completada: {msg}",
|
||||
"warn_skipped": "{n} registros fueron rechazados u omitidos",
|
||||
"error_processing": "Error en el procesamiento: {msg}",
|
||||
},
|
||||
"pending": {
|
||||
"badge": "Pendientes",
|
||||
"title": "Importaciones pendientes de confirmar",
|
||||
"description": "Escaneos listos para insertar en base de datos. Si el trabajo ya expiró en el servidor, desaparecerán al actualizar.",
|
||||
"refresh": "Actualizar",
|
||||
"empty": "No hay importaciones pendientes para esta empresa.",
|
||||
"checking": "Comprobando con el servidor…",
|
||||
"total_rows": "Total filas",
|
||||
"valid_rows": "Válidas",
|
||||
"resume": "Reanudar",
|
||||
"remove": "Quitar",
|
||||
"profiles": {
|
||||
"customs_brokers": "Agentes Aduanales",
|
||||
"clients_providers": "Clientes y Proveedores",
|
||||
"exchange_rates": "Tipos de cambio",
|
||||
"pedimentos": "Pedimentos",
|
||||
"material_classes": "Clases",
|
||||
"vehicles": "Vehículos",
|
||||
"drivers": "Conductores",
|
||||
"trailers": "Trailers",
|
||||
"transporters": "Transportistas",
|
||||
"part_numbers": "Partes",
|
||||
"boms": "BOMs",
|
||||
"exportacion": "Exportación (operaciones)",
|
||||
"imports": "Importación (operaciones)",
|
||||
},
|
||||
},
|
||||
"modal": {
|
||||
"title_pending": "Validación de importación",
|
||||
"title_success": "Importación exitosa",
|
||||
"title_warning": "Importación con observaciones",
|
||||
"desc_pending": "Revise el análisis preliminar antes de confirmar la carga de datos.",
|
||||
"desc_done": "El proceso de importación ha finalizado.",
|
||||
"total_rows": "Total filas",
|
||||
"valid_rows": "Válidos",
|
||||
"invalid_rows": "Inválidos",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def merge_locale(filename: str, csv_obj: dict) -> None:
|
||||
path = MESSAGES / filename
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
data["csv_upload"] = csv_obj
|
||||
path.write_text(json.dumps(data, ensure_ascii=False, indent="\t") + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def extract_csv_upload_to_lib() -> None:
|
||||
"""Copia `csv_upload` a src/lib/i18n/csv-upload-messages.*.json (lo que importa csv-msg.ts)."""
|
||||
dest_dir = ROOT / "src/lib/i18n"
|
||||
for filename, suffix in (("en.json", "en"), ("es.json", "es")):
|
||||
path = MESSAGES / filename
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
cu = data.get("csv_upload")
|
||||
if cu is None:
|
||||
raise SystemExit(f"merge_csv_upload_i18n: falta csv_upload en {filename}")
|
||||
out = dest_dir / f"csv-upload-messages.{suffix}.json"
|
||||
out.write_text(json.dumps(cu, ensure_ascii=False, indent="\t") + "\n", encoding="utf-8")
|
||||
print(f"Wrote {out.relative_to(ROOT)}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
merge_locale("en.json", EN_CSV)
|
||||
merge_locale("es.json", ES_CSV)
|
||||
print("Merged csv_upload into en.json and es.json")
|
||||
extract_csv_upload_to_lib()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user