signalk-pypilot-newui 2.7.2 → 2.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.7.3 — 2026-09-14 — Spanish accents restored
4
+
5
+ The Spanish translation now carries the accents it always should have
6
+ had. About 140 previously plain-ASCII words in the ES dictionary and
7
+ a handful of hard-coded strings in the Info modal placeholders now
8
+ render as `Configuración`, `Conexión`, `Timón`, `Ángulo`, `Sesión`,
9
+ `Grabador de sesiones de navegación`, `Versión pypilot` and so on.
10
+ No functional change.
11
+
3
12
  ## 2.7.2 — 2026-09-14 — Registry score bump
4
13
 
5
14
  No code change vs 2.7.1. Adds a smoke test suite (Node built-in test
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ const session_recorder_1 = require("./session-recorder");
15
15
  const trip_recorder_1 = require("./trip-recorder");
16
16
  // Rev counter bumped on every build so the user can distinguish deploys
17
17
  // from the webapp header (feedback_revision_bump_each_build).
18
- const PLUGIN_REVISION = "Rev277";
18
+ const PLUGIN_REVISION = "Rev278";
19
19
  // Rev59: read package.json once at load time so /status can report the
20
20
  // npm package version alongside the internal Rev counter.
21
21
  // eslint-disable-next-line @typescript-eslint/no-require-imports
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalk-pypilot-newui",
3
- "version": "2.7.2",
3
+ "version": "2.7.3",
4
4
  "description": "Signal K friendly UI for the pypilot autopilot, with the capability to spread its functions and buttons to other programs like KIP, WilhelmSK and freeboard. Touch-first mobile visor + full pypilot data (servo, gains, calibration, tack, warnings) as first-class Signal K paths and Simple Switches. Coexists with pypilot-autopilot-provider.",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
package/public/app.js CHANGED
@@ -687,15 +687,15 @@
687
687
  "tack": "VIRAR",
688
688
  "cal": "CAL",
689
689
  "cal.level": "Nivelar (barco adrizado)",
690
- "cal.rudCentered": "Timon centrado",
690
+ "cal.rudCentered": "Timón centrado",
691
691
  "cal.rudPort": "Rango babor",
692
692
  "cal.rudStar": "Rango estribor",
693
- "cal.rudReset": "Reset timon",
693
+ "cal.rudReset": "Reset timón",
694
694
  "cal.headingOffset": "Offset rumbo IMU (grados)",
695
- "cal.rudRange": "Rango timon (grados)",
695
+ "cal.rudRange": "Rango timón (grados)",
696
696
  "cal.advanced.title": "Sliders avanzados",
697
697
  "cal.advanced.hint": "Todos los RangeSettings de pypilot, agrupados. Pulsa largo o pon el raton sobre el nombre para ver la clave pypilot cruda.",
698
- "cal.grp.rudder": "Timon",
698
+ "cal.grp.rudder": "Timón",
699
699
  "cal.grp.servo": "Servo",
700
700
  "cal.grp.imu": "IMU",
701
701
  "cal.grp.ap": "Piloto",
@@ -717,12 +717,12 @@
717
717
  "setup.status.sshSummary": "SSH: {user}",
718
718
  "setup.status.sshMissing": "SSH sin configurar",
719
719
  "setup.status.sentences": "Sentencias activas:",
720
- "setup.status.calLast": "Ultimo ajuste:",
720
+ "setup.status.calLast": "Último ajuste:",
721
721
  "setup.status.calNever": "Todavia no se ha ajustado nada.",
722
722
  "setup.status.calNeverShort": "sin ajustar",
723
723
  "cal.unlock": "Desbloquear sliders",
724
- "configuration": "Configuracion",
725
- "calibration.title": "Calibracion",
724
+ "configuration": "Configuración",
725
+ "calibration.title": "Calibración",
726
726
  "save": "Guardar",
727
727
  "cancel": "Cancelar",
728
728
  "close": "Cerrar",
@@ -733,7 +733,7 @@
733
733
  "paths.put": "PUT?",
734
734
  "paths.copy": "Copiar",
735
735
  "paths.hint": "Se aplica al instante, sin reinicio. Los paths esenciales (state / mode / target / tack / selectores) siempre publican. Con \"solo esenciales\" ON marca el check para activar un path; con OFF marca para mantener y desmarca para parar.",
736
- "paths.header": "Catalogo en vivo de paths Signal K que este plugin publica y responde a PUT. Copia con los botones para pegar en configuraciones de widgets KIP.",
736
+ "paths.header": "Catálogo en vivo de paths Signal K que este plugin publica y responde a PUT. Copia con los botones para pegar en configuraciones de widgets KIP.",
737
737
  "paths.refresh": "Refrescar",
738
738
  "paths.kip.title": "Sentencias de accion para KIP",
739
739
  "paths.kip.hint": "Enlaza estas sentencias con widgets KIP \"Simple Switch\" (filas azules) o \"Put\" (filas verdes).",
@@ -743,7 +743,7 @@
743
743
  "paths.kip.col.values": "Valor(es)",
744
744
  "paths.kip.col.copy": "Copiar",
745
745
  "paths.kip.widget.apEngage": "Activar AP",
746
- "paths.kip.widget.nudge": "Correccion rumbo <code>-10 / -1 / +1 / +10</code>",
746
+ "paths.kip.widget.nudge": "Corrección rumbo <code>-10 / -1 / +1 / +10</code>",
747
747
  "paths.kip.widget.tack": "Virar <code>babor / estribor / cancelar</code>",
748
748
  "paths.kip.widget.mode": "Modo <code>compass / gps / wind / true / nav</code>",
749
749
  "paths.kip.widget.profile": "Perfil <code>&lt;nombre&gt;</code>",
@@ -754,7 +754,7 @@
754
754
  "paths.kip.type.radio": "Simple Switch (radio)",
755
755
  "paths.kip.type.radioDyn": "Simple Switch (radio, dinamico)",
756
756
  "paths.kip.type.string": "texto",
757
- "paths.kip.type.numberRad": "numero (rad)",
757
+ "paths.kip.type.numberRad": "número (rad)",
758
758
  "paths.kip.val.engage": "1 = activar, 0 = desactivar",
759
759
  "paths.kip.val.fireReset": "1 = disparar, auto-reset",
760
760
  "paths.kip.val.fire": "1 = disparar",
@@ -769,30 +769,30 @@
769
769
  "paths.all.title": "Todos los paths publicados",
770
770
  "paths.search.ph": "filtrar paths...",
771
771
  "paths.essentials.label": "Publicar solo esenciales + los activados explicitamente (recomendado)",
772
- "nudge.title": "Botones correccion rumbo",
773
- "nudge.small": "Pequeno (-1/+1)",
772
+ "nudge.title": "Botones corrección rumbo",
773
+ "nudge.small": "Pequeño (-1/+1)",
774
774
  "nudge.big": "Grande (-10/+10)",
775
- "nudge.hint": "Grados anadidos al rumbo objetivo cada vez que pulsas un boton de nudge. Tambien se configura en SK Admin -> Plugin Config -> PyPilot New-UI.",
775
+ "nudge.hint": "Grados añadidos al rumbo objetivo cada vez que pulsas un botón de nudge. También se configura en SK Admin -> Plugin Config -> PyPilot New-UI.",
776
776
  "language.title": "Idioma",
777
777
  "language.hint": "Solo en este navegador. No pasa por el servidor.",
778
778
  // Tabs
779
779
  "tab.control": "Control",
780
780
  "tab.tune": "Ajustes",
781
- "tab.chart": "Grafica",
781
+ "tab.chart": "Gráfica",
782
782
  "tab.regata": "Regata",
783
783
  "tab.paths": "Paths & API",
784
784
  "tab.setup": "Setup",
785
785
  "tab.info": "Info",
786
786
  // Chart tab (Rev96)
787
787
  "chart.stats.title": "ESTADISTICAS SESION",
788
- "chart.session.empty": "Sesion no iniciada",
789
- "chart.session.started": "Sesion iniciada a las",
788
+ "chart.session.empty": "Sesión no iniciada",
789
+ "chart.session.started": "Sesión iniciada a las",
790
790
  "chart.session.ago": "hace",
791
791
  "chart.session.reset": "Reiniciar",
792
- "chart.session.confirm": "Poner las estadisticas a cero? El historico grafico se conserva.",
792
+ "chart.session.confirm": "Poner las estadísticas a cero? El histórico grafico se conserva.",
793
793
  "chart.stat.engaged": "AP activo",
794
794
  "chart.stat.distance": "Distancia",
795
- "chart.stat.energy": "Energia",
795
+ "chart.stat.energy": "Energía",
796
796
  "chart.stat.meanErr": "Error medio",
797
797
  "chart.stat.rmsErr": "RMS error",
798
798
  "chart.stat.p95Err": "p95 error",
@@ -801,7 +801,7 @@
801
801
  "chart.stat.maxServoA": "Max servo A",
802
802
  "chart.history.title": "HISTORICO",
803
803
  "chart.history.refresh": "Actualizar",
804
- "chart.empty": "Aun sin datos - esperando primera muestra...",
804
+ "chart.empty": "Aún sin datos - esperando primera muestra...",
805
805
  "chart.servoHealth.title": "SALUD DEL SERVO",
806
806
  "chart.servoHealth.learning":"Aprendiendo baseline...",
807
807
  "chart.servoHealth.baseline":"Baseline",
@@ -811,12 +811,12 @@
811
811
  "chart.servoHealth.temp": "Temp",
812
812
  "chart.servoHealth.voltage": "Voltaje",
813
813
  "setup.paths.title": "Sentencias de Signal K",
814
- "setup.conn.title": "Conexion pypilot",
814
+ "setup.conn.title": "Conexión pypilot",
815
815
  "setup.conn.status": "Estado",
816
816
  "setup.remoteConsole": "Consola control remoto",
817
817
  // Alarms (Rev101)
818
818
  "setup.alarms.title": "Alarmas",
819
- "setup.alarms.hint": "Activa o desactiva cada regla y silencia temporalmente. Las alarmas activas salen en el banner de arriba y publican notificaciones SK canonicas para KIP / WilhelmSK.",
819
+ "setup.alarms.hint": "Activa o desactiva cada regla y silencia temporalmente. Las alarmás activas salen en el banner de arriba y publican notificaciones SK canonicas para KIP / WilhelmSK.",
820
820
  "alarm.ack": "ACK",
821
821
  "alarm.acked": "Ack'd",
822
822
  "alarm.mute15": "Silenciar 15m",
@@ -827,7 +827,7 @@
827
827
  "alarm.off": "OFF",
828
828
  // Pre-departure check (Rev102)
829
829
  "setup.precheck.title": "Comprobacion del piloto",
830
- "setup.precheck.hint": "Chequeo antes de zarpar. Agrega sensores, servo, voltaje y conectividad en un veredicto unico. Se recalcula cada 3 s mientras esta pestana esta abierta.",
830
+ "setup.precheck.hint": "Chequeo antes de zarpar. Agrega sensores, servo, voltaje y conectividad en un veredicto único. Se recalcula cada 3 s mientras esta pestaña está abierta.",
831
831
  "setup.precheck.refresh": "Actualizar",
832
832
  "setup.precheck.unknown": "Comprobando...",
833
833
  "setup.precheck.verdict.ready": "Listo para activar",
@@ -835,7 +835,7 @@
835
835
  "setup.precheck.verdict.fail": "NO activar",
836
836
  // Doctor (Rev104)
837
837
  "setup.doctor.title": "Asesoramiento y diagnostico",
838
- "setup.doctor.hint": "Activa el AP primero y pulsa DIAGNOSTICAR. El plugin graba el error de rumbo y respuesta del servo, y propone ajustes P/I/D. Nada se aplica automaticamente - revisa cada sugerencia y pulsa APLICAR.",
838
+ "setup.doctor.hint": "Activa el AP primero y pulsa DIAGNOSTICAR. El plugin graba el error de rumbo y respuesta del servo, y propone ajustes P/I/D. Nada se aplica automáticamente - revisa cada sugerencia y pulsa APLICAR.",
839
839
  "setup.doctor.start": "DIAGNOSTICAR",
840
840
  "setup.doctor.cancel": "Cancelar",
841
841
  "setup.doctor.recording": "Grabando",
@@ -846,9 +846,9 @@
846
846
  "setup.doctor.applied": "APLICADO",
847
847
  "setup.doctor.applyAll": "Aplicar todo",
848
848
  "setup.doctor.applyAllConfirm": "Aplicar todos los ajustes sugeridos a pypilot?",
849
- "setup.doctor.applyTop": "Aplicar el mas prioritario",
850
- "setup.doctor.applyTopConfirm": "Aplicar el ajuste mas prioritario y correr otra sesion del Doctor antes del siguiente?",
851
- "setup.doctor.freshRequired": "Aplicado 1 ajuste. Corre otra sesion del Doctor antes de aplicar los siguientes {n}.",
849
+ "setup.doctor.applyTop": "Aplicar el más prioritario",
850
+ "setup.doctor.applyTopConfirm": "Aplicar el ajuste más prioritario y correr otra sesión del Doctor antes del siguiente?",
851
+ "setup.doctor.freshRequired": "Aplicado 1 ajuste. Corre otra sesión del Doctor antes de aplicar los siguientes {n}.",
852
852
  "setup.doctor.confidence": "Confianza",
853
853
  "setup.doctor.samplesSummary": "{engaged} muestras activas de {total}, piloto '{pilot}'.",
854
854
  "setup.doctor.forkedProfile": "Cambios aplicados en un perfil NUEVO {new}. Tu perfil original {orig} queda intacto y a un toque en Ajustes → Perfil.",
@@ -862,12 +862,12 @@
862
862
  "doctor.conf.low": "baja",
863
863
  "doctor.conf.medium": "media",
864
864
  "doctor.conf.high": "alta",
865
- "doctor.reason.bias": "El barco se ha desviado del rumbo objetivo {deg}° de media. Esa deriva es lo que corrige la ganancia integral (I) con el tiempo — una I baja hace que el AP tarde mucho (o nunca) en cerrar un desvio persistente.",
865
+ "doctor.reason.bias": "El barco se ha desviado del rumbo objetivo {deg}° de media. Esa deriva es lo que corrige la ganancia integral (I) con el tiempo — una I baja hace que el AP tarde mucho (o nunca) en cerrar un desvío persistente.",
866
866
  "doctor.effect.bias": "Subir I deberia borrar la deriva en segundos. Vigila la rueda: una I demasiado alta genera overshoot y empieza a bailar — si lo ves, reduce de nuevo.",
867
867
  "doctor.reason.oscillation": "El rumbo oscila con un periodo de unos {period} segundos. Sin suficiente ganancia derivativa (D) el AP no puede amortiguar sus propias correcciones y el barco culea de un lado a otro.",
868
- "doctor.effect.oscillation": "Mas D calma el vaiven y hace que el AP se sienta menos nervioso. La respuesta al timon se vuelve algo mas lenta — es un cambio razonable para conseguir un rumbo mas recto.",
869
- "doctor.reason.authority": "El servo esta trabajando mucho pero el barco sigue sin alcanzar el rumbo. Esto es P debil clasico: el AP pide, el timon se mueve, pero la correccion es demasiado pequena.",
870
- "doctor.effect.authority": "Una P mayor mete mas timon para el mismo error. Deberia apretar el seguimiento del rumbo. Si empieza a bailar con cada ola, reduce y prueba a subir D en su lugar.",
868
+ "doctor.effect.oscillation": "Más D calma el vaivén y hace que el AP se sienta menos nervioso. La respuesta al timón se vuelve algo más lenta — es un cambio razonable para conseguir un rumbo más recto.",
869
+ "doctor.reason.authority": "El servo está trabajando mucho pero el barco sigue sin alcanzar el rumbo. Esto es P débil clásico: el AP pide, el timón se mueve, pero la corrección es demasiado pequeña.",
870
+ "doctor.effect.authority": "Una P mayor mete más timón para el mismo error. Deberia apretar el seguimiento del rumbo. Si empieza a bailar con cada ola, reduce y prueba a subir D en su lugar.",
871
871
  "setup.doctor.idle": "inactivo",
872
872
  "setup.doctor.analyzing.short": "analizando...",
873
873
  "setup.doctor.healthy": "sano",
@@ -876,12 +876,12 @@
876
876
  "doctor.summary.clean": "Sin incidencias significativas. Las ganancias parecen sanas.",
877
877
  "doctor.summary.notedOnly": "{issues} incidencia(s) anotada(s) (sin cambio de ganancia sugerido).",
878
878
  "doctor.summary.detected": "{issues} incidencia(s) detectada(s). {suggestions} cambio(s) de ganancia sugerido(s).",
879
- "doctor.finding.insufficientData": "Solo {n} muestras activas. Analisis omitido - deja el piloto enganchado toda la sesion.",
880
- "doctor.finding.bias": "Desvio de rumbo persistente de {deg}° (error medio).",
879
+ "doctor.finding.insufficientData": "Solo {n} muestras activas. Análisis omitido - deja el piloto enganchado toda la sesión.",
880
+ "doctor.finding.bias": "Desvío de rumbo persistente de {deg}° (error medio).",
881
881
  "doctor.finding.oscillation": "Rumbo oscilando con periodo ~{period}s, RMS {rms}°.",
882
882
  "doctor.finding.authority": "Servo al {duty}% de trabajo pero el error de rumbo sigue en {rms}°. El piloto pierde autoridad.",
883
883
  "doctor.finding.noise": "Rumbo muy ajustado ({rms}°) pero servo al {duty}% de trabajo - posible ruido en la señal de rumbo.",
884
- "doctor.finding.hardwareCeiling": "Servo al {duty}% de trabajo con {rms}° de error RMS - el actuador esta saturado. Ningun ajuste de P/I/D cierra un limite hardware; considera un servo mas potente o reducir la friccion del sistema de direccion.",
884
+ "doctor.finding.hardwareCeiling": "Servo al {duty}% de trabajo con {rms}° de error RMS - el actuador esta saturado. Ningun ajuste de P/I/D cierra un limite hardware; considera un servo más potente o reducir la friccion del sistema de dirección.",
885
885
  "alarm.summary.active": "{n} activas",
886
886
  "alarm.summary.muted": "{n} silenciadas",
887
887
  "alarm.summary.off": "{n} off",
@@ -904,9 +904,9 @@
904
904
  "sq.col.status": "Estado",
905
905
  "sq.action.ignore": "Ignorar",
906
906
  "sq.action.restore": "Restaurar",
907
- "alarm.rule.heading-deviation.label": "Desvio de rumbo",
907
+ "alarm.rule.heading-deviation.label": "Desvío de rumbo",
908
908
  "alarm.rule.heading-deviation.msg": "Error de rumbo del piloto: {deg}° sostenido",
909
- "alarm.rule.cruise-drift.label": "Desvio sostenido del rumbo",
909
+ "alarm.rule.cruise-drift.label": "Desvío sostenido del rumbo",
910
910
  "alarm.rule.cruise-drift.msg": "El barco corre {deg}° a {side} del rumbo objetivo",
911
911
  "alarm.rule.unable-to-steer.label": "Piloto sin autoridad",
912
912
  "alarm.rule.unable-to-steer.msg": "El piloto pierde autoridad: {deg}° de error, servo al {duty}%",
@@ -926,7 +926,7 @@
926
926
  // Rev265 (Carlos): mensaje viene ya formateado por el backend
927
927
  // con h/min/s dinámicos; no se traduce con template.
928
928
  // Setup tab
929
- "setup.connection": "Conexion",
929
+ "setup.connection": "Conexión",
930
930
  "setup.scan.title": "Escanear LAN buscando pypilot_web",
931
931
  "setup.scan.subnet.ph": "auto-detectar (p.ej. 192.168.1.0/24)",
932
932
  "setup.scan.btn": "Escanear",
@@ -940,7 +940,7 @@
940
940
  "setup.absorb.title": "Provider de Autopiloto (modo un-solo-socket)",
941
941
  "setup.absorb.label": "Absorber el provider oficial",
942
942
  "setup.absorb.btn": "Guardar y reiniciar",
943
- "setup.absorb.hint": "Cuando esta ON, este plugin se registra como Signal K Autopilot Provider (WilhelmSK / freeboard / KIP se conectan por /signalk/v2/api/vessels/self/autopilots). Debes desactivar tambien el plugin 'pypilot-autopilot-provider' en SK Admin - dos providers pelearian por el pilot ID. Ventaja: un socket menos hacia la TinyPilot Pi Zero.",
943
+ "setup.absorb.hint": "Cuando esta ON, este plugin se registra como Signal K Autopilot Provider (WilhelmSK / freeboard / KIP se conectan por /signalk/v2/api/vessels/self/autopilots). Debes desactivar también el plugin 'pypilot-autopilot-provider' en SK Admin - dos providers pelearian por el pilot ID. Ventaja: un socket menos hacia la TinyPilot Pi Zero.",
944
944
  "setup.emergency": "Emergencia",
945
945
  "setup.ssh.user": "Usuario SSH",
946
946
  "setup.ssh.password": "Password SSH",
@@ -961,7 +961,7 @@
961
961
  "smart.autoProfile.heavy": "Perfil para TWS > 16 kn",
962
962
  "smart.autoProfile.skip": "(saltar)",
963
963
  "smart.gust.title": "Estrategia frente a rachas",
964
- "smart.gust.hint": "Detecta cuando el AWS sube 5 kn o mas en 5 s y aplica la accion elegida.",
964
+ "smart.gust.hint": "Detecta cuando el AWS sube 5 kn o más en 5 s y aplica la accion elegida.",
965
965
  "smart.gust.strategy": "Accion en racha",
966
966
  "smart.gust.opt.off": "OFF — no hacer nada",
967
967
  "smart.gust.opt.warn": "Solo avisar",
@@ -987,17 +987,17 @@
987
987
  "watch.detailsToggle": "Ver detalle del focus",
988
988
  "watch.noFocus": "(sin focus activo)",
989
989
  "sess.title": "Grabador de sesiones de navegacion",
990
- "sess.hint": "Cada sesion con el AP enganchado se guarda en el Pi 5 como JSONL. Comparte con el autor del plugin para recibir consejos de ajuste personalizados.",
991
- "sess.tag": "Etiquetar sesion actual",
990
+ "sess.hint": "Cada sesión con el AP enganchado se guarda en el Pi 5 como JSONL. Comparte con el autor del plugin para recibir consejos de ajuste personalizados.",
991
+ "sess.tag": "Etiquetar sesión actual",
992
992
  "sess.list": "Ver sesiones grabadas",
993
993
  "sess.advice": "Consejos recibidos",
994
994
  "sess.close": "Cerrar",
995
995
  "sess.cancel": "Cancelar",
996
996
  "sess.st.disabled": "grabador desactivado en config del plugin",
997
- "sess.st.idle": "en reposo — AP no enganchado, no hay sesion abierta",
997
+ "sess.st.idle": "en reposo — AP no enganchado, no hay sesión abierta",
998
998
  "sess.st.recording": "grabando",
999
999
  "sess.st.samples": "muestras",
1000
- "sess.tag.title": "Etiquetar sesion actual",
1000
+ "sess.tag.title": "Etiquetar sesión actual",
1001
1001
  "sess.tag.save": "Guardar",
1002
1002
  "sess.tag.err": "Fallo al guardar",
1003
1003
  "sess.tag.wind": "Viento (kn)",
@@ -1014,7 +1014,7 @@
1014
1014
  "sess.motor.sail": "solo vela",
1015
1015
  "sess.motor.motor-sailing": "motorvela",
1016
1016
  "sess.motor.motor": "solo motor",
1017
- "sess.pos.close-hauled": "cenida",
1017
+ "sess.pos.close-hauled": "ceñida",
1018
1018
  "sess.pos.reaching": "traves",
1019
1019
  "sess.pos.broad-reach": "largo",
1020
1020
  "sess.pos.running": "empopada",
@@ -1026,10 +1026,10 @@
1026
1026
  "sess.list.download": "Descargar JSON",
1027
1027
  "sess.list.share": "Compartir por WhatsApp",
1028
1028
  "sess.list.delete": "Borrar",
1029
- "sess.list.delConfirm": "Borrar sesion {id}?",
1029
+ "sess.list.delConfirm": "Borrar sesión {id}?",
1030
1030
  "sess.list.hasAdvice": "consejos recibidos",
1031
1031
  "sess.advice.title": "Consejos recibidos",
1032
- "sess.advice.empty": "No hay consejos aun. Comparte una sesion y sube despues el JSON de consejos que recibas.",
1032
+ "sess.advice.empty": "No hay consejos aún. Comparte una sesión y sube después el JSON de consejos que recibas.",
1033
1033
  "sess.advice.findings": "Hallazgos",
1034
1034
  "sess.advice.recs": "Recomendaciones",
1035
1035
  "sess.advice.upload": "Subir JSON de consejos",
@@ -1044,31 +1044,31 @@
1044
1044
  // "VIENTO APARENTE" / "VIENTO REAL" fully.
1045
1045
  "mode.label.wind.long": "VIENTO APARENTE",
1046
1046
  "mode.label.true-wind.long": "VIENTO REAL",
1047
- "tune.gain.helpBtn": "Mas info",
1048
- "tune.gain.P.short": "Corrige el error de rumbo al instante con mas rueda. Es el reflejo 'hay que corregir ya'.",
1049
- "tune.gain.P.long": "Subir si el AP tarda en cerrar un desvio. Bajar si el timon 'baila' a cada ola.",
1047
+ "tune.gain.helpBtn": "Más info",
1048
+ "tune.gain.P.short": "Corrige el error de rumbo al instante con más rueda. Es el reflejo 'hay que corregir ya'.",
1049
+ "tune.gain.P.long": "Subir si el AP tarda en cerrar un desvío. Bajar si el timón 'baila' a cada ola.",
1050
1050
  "tune.gain.I.short": "Cierra una deriva mantenida en el tiempo: si el barco se queda 5° a un lado, la I lo empuja de vuelta.",
1051
- "tune.gain.I.long": "Subir si hay desvio persistente que no se cierra. Bajar si el AP se pasa de largo (overshoot).",
1052
- "tune.gain.D.short": "Frena la correccion cuando el barco ya vuelve al rumbo, para no pasarse.",
1051
+ "tune.gain.I.long": "Subir si hay desvío persistente que no se cierra. Bajar si el AP se pasa de largo (overshoot).",
1052
+ "tune.gain.D.short": "Frena la corrección cuando el barco ya vuelve al rumbo, para no pasarse.",
1053
1053
  "tune.gain.D.long": "Subir si el AP oscila y no se estabiliza. Bajar si la respuesta se siente pastosa o lenta.",
1054
- "tune.gain.DD.short": "Anticipa la velocidad a la que crece el error. Ayuda con olas cortas y guinadas rapidas.",
1055
- "tune.gain.DD.long": "Subir en mar rizada o con olas cortas de popa. Bajar si mete nervios al timon.",
1054
+ "tune.gain.DD.short": "Anticipa la velocidad a la que crece el error. Ayuda con olas cortas y guiñadas rápidas.",
1055
+ "tune.gain.DD.long": "Subir en mar rizada o con olas cortas de popa. Bajar si mete nervios al timón.",
1056
1056
  "tune.gain.PR.short": "Como la P pero reacciona a la velocidad de giro del barco, no al error en si.",
1057
1057
  "tune.gain.PR.long": "Subir si el barco entra en el giro con demasiadas ganas. Bajar si va apatico.",
1058
1058
  "tune.gain.FF.short": "Reacciona al cambio de rumbo objetivo antes de que aparezca el error.",
1059
- "tune.gain.FF.long": "Subir para cambios de rumbo mas nitidos. Bajar si hay overshoot al fijar rumbo nuevo.",
1060
- "tune.gain.servo.max_current.short": "Corriente maxima que aceptas del motor del timon. Protege el servo de tirones.",
1061
- "tune.gain.servo.max_current.long": "Subir si el barco necesita mas par en mal tiempo. Bajar para saltar antes la proteccion en un actuador fragil.",
1062
- "tune.gain.servo.max_slew_speed.short": "Velocidad maxima con la que el timon se mueve. Si es muy alta, el timon 'corta' el agua.",
1063
- "tune.gain.servo.max_slew_speed.long": "Subir para respuesta mas viva en barco ligero. Bajar en desplazamiento pesado para suavizar el movimiento.",
1064
- "tune.gain.imu.heading_offset.short": "Angulo entre la linea de cruja y el sensor IMU. Se ajusta con el boton 'Level (boat is flat)'.",
1065
- "tune.gain.imu.heading_offset.long": "No lo toques a mano salvo que sepas la desalineacion exacta. Usa el boton de calibracion.",
1066
- "tune.gain.rudder.range.short": "Grados maximos que puede mover el timon a cada banda.",
1067
- "tune.gain.rudder.range.long": "Ajusta al tope fisico real del timon. Muy pequeno y el AP pierde autoridad; muy grande y quemas el motor.",
1068
- "tune.gain.ap.tack.angle.short": "Grados que gira una virada automatica.",
1069
- "tune.gain.ap.tack.angle.long": "Subir para viradas amplias (mas seguras en marejada). Bajar para viradas cerradas estilo regata.",
1070
- "tune.gain.ap.tack.rate.short": "Velocidad de una virada automatica en grados por segundo.",
1071
- "tune.gain.ap.tack.rate.long": "Subir para virada mas rapida. Bajar si el barco escora demasiado o la tripulacion no sigue.",
1059
+ "tune.gain.FF.long": "Subir para cambios de rumbo más nitidos. Bajar si hay overshoot al fijar rumbo nuevo.",
1060
+ "tune.gain.servo.max_current.short": "Corriente máxima que aceptas del motor del timón. Protege el servo de tirones.",
1061
+ "tune.gain.servo.max_current.long": "Subir si el barco necesita más par en mal tiempo. Bajar para saltar antes la proteccion en un actuador fragil.",
1062
+ "tune.gain.servo.max_slew_speed.short": "Velocidad máxima con la que el timón se mueve. Si es muy alta, el timón 'corta' el agua.",
1063
+ "tune.gain.servo.max_slew_speed.long": "Subir para respuesta más viva en barco ligero. Bajar en desplazamiento pesado para suavizar el movimiento.",
1064
+ "tune.gain.imu.heading_offset.short": "Ángulo entre la linea de crujía y el sensor IMU. Se ajusta con el botón 'Level (boat is flat)'.",
1065
+ "tune.gain.imu.heading_offset.long": "No lo toques a mano salvo que sepas la desalineación exacta. Usa el botón de calibración.",
1066
+ "tune.gain.rudder.range.short": "Grados máximos que puede mover el timón a cada banda.",
1067
+ "tune.gain.rudder.range.long": "Ajusta al tope físico real del timón. Muy pequeño y el AP pierde autoridad; muy grande y quemás el motor.",
1068
+ "tune.gain.ap.tack.angle.short": "Grados que gira una virada automática.",
1069
+ "tune.gain.ap.tack.angle.long": "Subir para viradas amplias (más seguras en marejada). Bajar para viradas cerradas estilo regata.",
1070
+ "tune.gain.ap.tack.rate.short": "Velocidad de una virada automática en grados por segundo.",
1071
+ "tune.gain.ap.tack.rate.long": "Subir para virada más rápida. Bajar si el barco escora demasiado o la tripulacion no sigue.",
1072
1072
  "lc.title": "Captura de logs (Pi Zero)",
1073
1073
  "lc.hint": "piCore guarda /var/log solo en RAM, un hard reset los pierde. Activalo para que el plugin guarde pypilot / pypilot_web / pypilot_hat en un archivo persistente del Pi 5.",
1074
1074
  "lc.toggle": "Activar captura",
@@ -1079,7 +1079,7 @@
1079
1079
  "lc.st.off": "PARADA",
1080
1080
  "lc.st.every": "cada",
1081
1081
  "lc.st.file": "archivo",
1082
- "lc.st.last": "ultima",
1082
+ "lc.st.last": "última",
1083
1083
  "setup.ssh.password.ph.set": "(configurado - reescribe para cambiarlo)",
1084
1084
  "setup.ssh.save.btn": "Guardar",
1085
1085
  "setup.restart.btn": "REINICIAR pypilot",
@@ -1120,45 +1120,45 @@
1120
1120
  "dash.polar.title": "DATOS DE POLARES",
1121
1121
  "dash.polar.hint": "Activa las que quieras que aparezcan en los selectores de esquinas. Requiere el plugin signalk-polar-performance-plugin.",
1122
1122
  "dash.custom.title": "SK PATH PERSONALIZADO",
1123
- "dash.custom.hint": "Anade cualquier path publicado por Signal K. Se muestra como aparezca en el bus (sin conversion).",
1123
+ "dash.custom.hint": "Añade cualquier path publicado por Signal K. Se muestra como aparezca en el bus (sin conversion).",
1124
1124
  "dash.custom.path.ph": "p.ej. environment.water.temperature",
1125
1125
  "dash.custom.label.ph": "Etiqueta",
1126
1126
  "dash.custom.unit.ph": "Unidad (opt)",
1127
- "dash.custom.add": "Anadir",
1127
+ "dash.custom.add": "Añadir",
1128
1128
  "dash.helmBar.title": "BARRA INFERIOR (indicador)",
1129
- "dash.helmBar.hint": "Elige que se muestra en la barra de abajo: el angulo del timon o la escora del barco.",
1129
+ "dash.helmBar.hint": "Elige que se muestra en la barra de abajo: el ángulo del timón o la escora del barco.",
1130
1130
  "dash.helmBar.heel": "Escora (por defecto)",
1131
- "dash.helmBar.rudder": "Angulo del timon",
1132
- "dash.overlay.gust.title": "Marca de rafagas",
1131
+ "dash.helmBar.rudder": "Ángulo del timón",
1132
+ "dash.overlay.gust.title": "Marca de ráfagas",
1133
1133
  "dash.overlay.gust.needs": "Deja una flecha A fantasma con la velocidad de la racha; se desvanece en 10 s. Necesita sensor de viento.",
1134
1134
  "dash.overlay.gust.test": "Probar ahora",
1135
1135
  "tack.port.title": "Virar a babor",
1136
1136
  "tack.star.title": "Virar a estribor",
1137
- "nav.toggle.aria": "Mostrar / ocultar barra de pestanas",
1138
- "helmChip.heelTitle": "Escora - toca para ver angulo de timon",
1139
- "helmChip.rudderTitle": "Timon - toca para ver escora",
1137
+ "nav.toggle.aria": "Mostrar / ocultar barra de pestañas",
1138
+ "helmChip.heelTitle": "Escora - toca para ver ángulo de timón",
1139
+ "helmChip.rudderTitle": "Timón - toca para ver escora",
1140
1140
  // Modal historial de bordos
1141
1141
  "tackLog.empty": "Sin bordos registrados en el rango.",
1142
1142
  "tackLog.total": "Total",
1143
1143
  "tackLog.totalUnit": "bordos",
1144
- "tackLog.bestRet": "Mejor retencion",
1145
- "tackLog.bestRec": "Recuperacion mas rapida",
1144
+ "tackLog.bestRet": "Mejor retención",
1145
+ "tackLog.bestRec": "Recuperación más rápida",
1146
1146
  "tackLog.badgeRet": "MEJOR RET",
1147
1147
  "tackLog.badgeRec": "MAS RAPIDA",
1148
- "tackLog.recoverLabel": "Recuperacion 95% SOG:",
1148
+ "tackLog.recoverLabel": "Recuperación 95% SOG:",
1149
1149
  "tackLog.clearConfirm": "¿Vaciar todo el historial de bordos?",
1150
1150
  // Veredicto HUD de maniobra
1151
1151
  "maneuver.tack.title": "VIRADA",
1152
1152
  "maneuver.jibe.title": "TRASLUCHADA",
1153
1153
  "maneuver.verdict.good": "buena virada",
1154
1154
  "maneuver.verdict.normal": "virada normal",
1155
- "maneuver.verdict.lost": "virada perdida",
1155
+ "maneuver.verdict.lost": "virada pérdida",
1156
1156
  // Viajes (Setup card + lista + detalle + share card)
1157
1157
  "setup.trips.title": "Viajes",
1158
1158
  "setup.trips.hint": "Cada vez que sales de puerto (navigation.state pasa de moored a otro estado) se abre un viaje. Al volver a puerto se cierra y se calcula el resumen. Toca uno para ver el detalle.",
1159
1159
  "trips.delConfirm": "¿Eliminar este viaje?",
1160
1160
  "trips.summaryFail": "No se pudo cargar el resumen.",
1161
- "trips.captureLibFail": "No hay conexion para cargar la libreria de captura.",
1161
+ "trips.captureLibFail": "No hay conexión para cargar la libreria de captura.",
1162
1162
  "trips.captureFail": "Fallo la captura:",
1163
1163
  "trips.imageFail": "No se pudo generar la imagen.",
1164
1164
  "trips.shareTitle": "Viaje",
@@ -1177,17 +1177,17 @@
1177
1177
  "trips.status.navState": "Estado nav",
1178
1178
  "trips.status.noneOpen": "sin viaje en curso.",
1179
1179
  "trips.loadFail": "No se pudieron cargar los viajes.",
1180
- "trips.empty": "Aun no hay viajes registrados. Sal a navegar y al volver aparecera el resumen.",
1181
- "trips.noSummary": "Viaje sin resumen aun.",
1182
- "trips.map.noConn": "Sin conexion a los tiles del mapa.",
1180
+ "trips.empty": "Aún no hay viajes registrados. Sal a navegar y al volver aparecera el resumen.",
1181
+ "trips.noSummary": "Viaje sin resumen aún.",
1182
+ "trips.map.noConn": "Sin conexión a los tiles del mapa.",
1183
1183
  "trips.map.trackFail": "No se pudo cargar el trazado.",
1184
1184
  "trips.map.noPositions": "Este viaje no tiene posiciones validas para dibujar.",
1185
- "trips.map.legend": "⛵ rafaga · 🌀 vel max · 🔋 volt bajo · ↻ bordo",
1185
+ "trips.map.legend": "⛵ ráfaga · 🌀 vel max · 🔋 volt bajo · ↻ bordo",
1186
1186
  "trips.card.track": "TRAYECTO",
1187
1187
  "trips.detail.loading": "Cargando...",
1188
1188
  "trips.detail.noSummary": "Sin resumen",
1189
1189
  "trips.kpi.distance": "Distancia",
1190
- "trips.kpi.duration": "Duracion",
1190
+ "trips.kpi.duration": "Duración",
1191
1191
  "trips.kpi.sogAvg": "SOG med",
1192
1192
  "trips.kpi.sogMax": "SOG max",
1193
1193
  "trips.kpi.twsAvg": "TWS med",
@@ -1204,21 +1204,21 @@
1204
1204
  "trips.kpi.upwind": "ceñida",
1205
1205
  "trips.kpi.reach": "traves",
1206
1206
  "trips.kpi.downwind": "popa",
1207
- "trips.hl.peakWind": "Maxima rafaga",
1208
- "trips.hl.peakSog": "Maxima velocidad",
1209
- "trips.hl.minVolt": "Voltaje minimo",
1207
+ "trips.hl.peakWind": "Máxima ráfaga",
1208
+ "trips.hl.peakSog": "Máxima velocidad",
1209
+ "trips.hl.minVolt": "Voltaje mínimo",
1210
1210
  "trips.hl.checkServo": "revisar cableado servo",
1211
1211
  "trips.hl.tack": "Bordo",
1212
1212
  "trips.hl.at": "a las",
1213
- // Banner de restauracion tras reconexion
1213
+ // Banner de restauración tras reconexion
1214
1214
  "restore.msg": "Pypilot volvio tras {sec}s. ¿Restaurar target anterior {tgt}?",
1215
1215
  "restore.yes": "Si, restaurar",
1216
1216
  "restore.no": "No",
1217
1217
  "restore.speak": "Pypilot operativo. ¿Restaurar target anterior?",
1218
1218
  "restore.currentHdg": "rumbo actual",
1219
1219
  "restore.doneSpeak": "Target restaurado",
1220
- "restore.failSpeak": "Restauracion fallida",
1221
- "restore.failed": "Restauracion fallida",
1220
+ "restore.failSpeak": "Restauración fallida",
1221
+ "restore.failed": "Restauración fallida",
1222
1222
  "restore.working": "Restaurando... esperando confirmacion pypilot",
1223
1223
  "restore.reason.noPy": "pypilot no confirma",
1224
1224
  "restore.reason.noEng":"AP no enganchó",
@@ -1226,16 +1226,16 @@
1226
1226
  "alert.saveOk": "Guardado.",
1227
1227
  "alert.saveFail": "Guardar fallo. Estas logueado como admin en Signal K?",
1228
1228
  "alert.configApplied": "Config guardada. Plugin reiniciando.",
1229
- "alert.configFail": "Config fallo. Inicia sesion como admin en Signal K primero.",
1229
+ "alert.configFail": "Config fallo. Inicia sesión como admin en Signal K primero.",
1230
1230
  "alert.absorb.on": "Habilitado el AutopilotProvider. IMPORTANTE: ve a SK Admin y DESACTIVA el plugin 'pypilot-autopilot-provider' para que no se peleen.",
1231
1231
  "alert.absorb.off": "Deshabilitado el AutopilotProvider. Vuelve a activar 'pypilot-autopilot-provider' en SK Admin si quieres que WilhelmSK / freeboard sigan funcionando.",
1232
1232
  "alert.hostRequired": "Falta host",
1233
1233
  "alert.nudgeSaved": "Guardado. Valores de nudge actualizados.",
1234
1234
  "confirm.removeProfile": "Borrar el perfil actual?",
1235
- "confirm.restartPypilot": "Reiniciar pypilot en la TinyPilot? La conexion se cortara ~10 s mientras vuelve.",
1236
- "confirm.resetCfg": "Borrar toda la configuracion del visor (esquinas, flechas, polares, custom paths)? Los ajustes del piloto en la TinyPilot NO se tocan.",
1235
+ "confirm.restartPypilot": "Reiniciar pypilot en la TinyPilot? La conexión se cortara ~10 s mientras vuelve.",
1236
+ "confirm.resetCfg": "Borrar toda la configuración del visor (esquinas, flechas, polares, custom paths)? Los ajustes del piloto en la TinyPilot NO se tocan.",
1237
1237
  "prompt.profileName": "Nombre del perfil",
1238
- "prompt.pasteCfg": "Pega el JSON de configuracion exportado:",
1238
+ "prompt.pasteCfg": "Pega el JSON de configuración exportado:",
1239
1239
  // Setup SSH + restart status
1240
1240
  "setup.ssh.status.emptyPwd": "Password vacio. Escribelo antes de Save (aunque no lo cambies, hay que retypearlo cada vez por seguridad).",
1241
1241
  "setup.ssh.status.saving": "Guardando...",
@@ -1273,14 +1273,14 @@
1273
1273
  "setup.restart.pypilot.sub": "~10-15 s · el AP suelta el rumbo",
1274
1274
  "setup.restart.reboot.title": "reboot de la Pi",
1275
1275
  "setup.restart.reboot.sub": "~35-60 s · corte total",
1276
- "setup.restart.hint": "Los dos botones usan el usuario+password SSH de arriba. RESTART pypilot suelta brevemente el pilotaje; reboot de la Pi es corte total. Se muestra una confirmacion pidiendo que haya alguien al timon antes de ejecutar. El restart de pypilot_web (sin interrumpir pilotaje) esta como preset en la consola de Debug de abajo.",
1276
+ "setup.restart.hint": "Los dos botones usan el usuario+password SSH de arriba. RESTART pypilot suelta brevemente el pilotaje; reboot de la Pi es corte total. Se muestra una confirmacion pidiendo que haya alguien al timón antes de ejecutar. El restart de pypilot_web (sin interrumpir pilotaje) esta como preset en la consola de Debug de abajo.",
1277
1277
  "setup.restart.outage.web": "Se reinicia solo el servidor web de pypilot. El core sigue pilotando durante esos segundos.",
1278
1278
  "setup.restart.outage.pypilot": "Se reinician el core pypilot y su servidor web. El AP suelta el rumbo brevemente y se reengancha tras reconectar.",
1279
1279
  "setup.restart.outage.reboot": "Se reinicia la Raspberry Pi entera (kernel, servicios, red). NO hay autopiloto durante ~35-60 segundos. Arranque en frio.",
1280
1280
  "helm.outage": "Corte del piloto:",
1281
1281
  "helm.warn": "ASEGURATE DE QUE ALGUIEN ESTA AL TIMON antes de continuar. No es el momento de estar bajo cubierta.",
1282
1282
  "helm.cancel": "Cancelar",
1283
- "helm.confirm": "Confirmo - hay alguien al timon",
1283
+ "helm.confirm": "Confirmo - hay alguien al timón",
1284
1284
  "helm.op.engage.title": "Enganchar piloto",
1285
1285
  "helm.op.engage.msg": "Enganchar el piloto? Confirma que alguien vigila el rumbo.",
1286
1286
  "helm.op.modeChange.title": "Cambiar modo AP",
@@ -1316,7 +1316,7 @@
1316
1316
  "ssh.p.iw": "WiFi",
1317
1317
  "ssh.p.temp": "Temperatura",
1318
1318
  "ssh.p.who": "Quien esta conectado",
1319
- "ssh.p.ver": "Version pypilot",
1319
+ "ssh.p.ver": "Versión pypilot",
1320
1320
  "ssh.p.restartWeb": "Reiniciar web pypilot",
1321
1321
  // Rev88 / Rev89 / Rev90: Aproado (subir velas al viento) pseudo-modo
1322
1322
  "aproado.modal.title": "Aproarse: subir vela",
@@ -1333,7 +1333,7 @@
1333
1333
  "aproado.transit.title.bow": "APROANDOSE POR PROA",
1334
1334
  "aproado.transit.title.stern":"APROANDOSE POR POPA",
1335
1335
  "aproado.transit.sub": "Girando al viento...",
1336
- "aproado.transit.remaining": "aun para estar aproado",
1336
+ "aproado.transit.remaining": "aún para estar aproado",
1337
1337
  "aproado.hud.title": "APROADO",
1338
1338
  "aproado.hud.summary": "MANIOBRA COMPLETADA",
1339
1339
  "aproado.hud.dist": "Dist",
package/public/index.html CHANGED
@@ -1109,13 +1109,13 @@
1109
1109
  an off-boat analysis produces an "advice" JSON that lands
1110
1110
  back here as a "Consejos recibidos" card. -->
1111
1111
  <div class="session-recorder-panel" style="margin-top:16px;padding-top:12px;border-top:1px solid var(--border)">
1112
- <div class="section-title" style="font-size:14px;margin-bottom:4px" data-i18n="sess.title">Grabador de sesiones de navegacion</div>
1113
- <div class="hint" style="font-size:11px" data-i18n="sess.hint">Cada vez que el AP se engancha, el plugin graba un JSONL con la telemetria. Al desenganchar cierra la sesion. Compartelo para recibir consejos de ajuste personalizados.</div>
1112
+ <div class="section-title" style="font-size:14px;margin-bottom:4px" data-i18n="sess.title">Grabador de sesiones de navegación</div>
1113
+ <div class="hint" style="font-size:11px" data-i18n="sess.hint">Cada vez que el AP se engancha, el plugin graba un JSONL con la telemetría. Al desenganchar cierra la sesión. Compártelo para recibir consejos de ajuste personalizados.</div>
1114
1114
  <div class="row" style="gap:10px;flex-wrap:wrap;align-items:center;margin-top:6px">
1115
1115
  <span id="sess-status" class="hint" style="font-size:12px;font-family:ui-monospace,monospace"></span>
1116
1116
  </div>
1117
1117
  <div class="row" style="gap:8px;flex-wrap:wrap;margin-top:6px">
1118
- <button id="sess-tag-btn" class="ghost" data-i18n="sess.tag">Etiquetar sesion actual</button>
1118
+ <button id="sess-tag-btn" class="ghost" data-i18n="sess.tag">Etiquetar sesión actual</button>
1119
1119
  <button id="sess-list-btn" class="ghost" data-i18n="sess.list">Ver sesiones grabadas</button>
1120
1120
  <button id="sess-advice-btn" class="ghost" data-i18n="sess.advice">Consejos recibidos</button>
1121
1121
  </div>
@@ -1328,7 +1328,7 @@
1328
1328
  <button class="ssh-preset debug-preset" data-preset="iwconfig" title="iwconfig / iw dev" data-i18n="ssh.p.iw">WiFi</button>
1329
1329
  <button class="ssh-preset debug-preset" data-preset="temp" title="/sys/.../thermal" data-i18n="ssh.p.temp">Temperatura</button>
1330
1330
  <button class="ssh-preset debug-preset" data-preset="who" title="who / last" data-i18n="ssh.p.who">Quien esta conectado</button>
1331
- <button class="ssh-preset debug-preset" data-preset="pypilot.version" title="python3 -c import pypilot" data-i18n="ssh.p.ver">Version pypilot</button>
1331
+ <button class="ssh-preset debug-preset" data-preset="pypilot.version" title="python3 -c import pypilot" data-i18n="ssh.p.ver">Versión pypilot</button>
1332
1332
  <button class="ssh-preset debug-preset" data-preset="restart.web" title="sv restart pypilot_web" data-i18n="ssh.p.restartWeb">Reiniciar web pypilot</button>
1333
1333
  </div>
1334
1334
 
@@ -2097,6 +2097,6 @@
2097
2097
  </div>
2098
2098
  </div>
2099
2099
 
2100
- <script src="app.js?v=Rev277"></script>
2100
+ <script src="app.js?v=Rev278"></script>
2101
2101
  </body>
2102
2102
  </html>