Преглед изворни кода

fix(archives): report a refused FTPS handshake as the printer, not the slicer (issue #2780)

The Archives banner picks its wording from a priority list of the causes it
knows. REASON_FTPS_COOLOFF was added by #2957 and never put in that list, so an
install whose empty archives all came from a printer refusing the TLS handshake
matched nothing, got reason: null, and fell to the original wording: the slicer
did not leave the .gcode.3mf on the card, switch on "Store sent files on
external storage", here is installation step 4.

Every clause of that is wrong for this cause. The slicer did write the file --
reason he read the whole thing as Bambuddy being broken. The setting was
already on. And there is nothing on his side to change: the printer's file
service answered port 990 with something that is not TLS, so no lookup ever
ran and where the file went was never tested. It is #2899's mistake -- an
error message describing a cause that was ruled out before it was printed --
in a surface that did not get that pass.

The slug now leads the list rather than joining the end of it. The other three
describe an install working as configured and each ends in something the
operator can change; this one reports a fault nobody can yet explain, which is
both the more urgent thing to say and the thing that produces a useful report.
The banner also dismisses one-shot into localStorage, so a reason ranked below
another is not deferred to next time -- it is never shown to that user again.
Ranking it first cannot bury a permanent cause in exchange: a successful
recovery clears the row's markers (#2957), so a row still carrying this slug is
one whose retry failed too, days after the print.

New wording in all fourteen languages says the printer refused the connection,
that this is not a slicer setting and not something the operator did, that
Bambuddy comes back for the file when the five-minute pause clears so a brief
episode fills itself in, and that a card still empty means the refusal outlasted
the retry. It links to the handshake entry in the troubleshooting guide instead
of to the installation guide.

The client's getNo3MFWarning type still declared the old three-slug union, which
made all three new comparisons provably dead -- caught by tsc, not by any test.

Four tests. One pins the slug reaching the banner, one pins it outranking the
three settled causes, one pins those three keeping their order behind it, and
one asserts the rendered wording carries no slicer advice at all.

Also corrects the wiki page these reports are pointed at. It said to power-cycle
the printer; the reporter who prompted that advice power-cycled both of his and
the failure continued unchanged, and bambu_ftp.py has carried the retraction in
a comment since. The page now states what was actually measured -- that a
version mismatch reports itself differently, that every printer probed refuses
TLS 1.3 and completes on 1.2 so there is no version to fall back from, and that
three P2S units failed while three more on the same switch never did -- says
plainly that the trigger is unknown, and names the one cleartext-probe line
worth collecting.
maziggy пре 13 часа
родитељ
комит
6564c74071

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
CHANGELOG.md


+ 23 - 1
backend/app/api/routes/archives.py

@@ -40,6 +40,7 @@ from backend.app.services.bambu_ftp import ftps_handshake_blocked, list_files_re
 from backend.app.services.design_settings import overrides_from_config
 from backend.app.services.design_settings import overrides_from_config
 from backend.app.services.filament_requirements import annotate_rack_groups
 from backend.app.services.filament_requirements import annotate_rack_groups
 from backend.app.services.print_storage import (
 from backend.app.services.print_storage import (
+    REASON_FTPS_COOLOFF,
     REASON_INTERNAL_HISTORY,
     REASON_INTERNAL_HISTORY,
     REASON_INTERNAL_STORAGE,
     REASON_INTERNAL_STORAGE,
     REASON_NO_EXTERNAL_STORAGE,
     REASON_NO_EXTERNAL_STORAGE,
@@ -581,12 +582,33 @@ async def no_3mf_warning(
     # all, so an install with one H2C and three older printers still gets the
     # all, so an install with one H2C and three older printers still gets the
     # H2C explanation rather than the generic one.
     # H2C explanation rather than the generic one.
     #
     #
+    # REASON_FTPS_COOLOFF leads, and it is the only one of these that reports a
+    # fault rather than a choice: the printer's file service refused a TLS
+    # handshake, so the sweep never ran and nothing about where the file went
+    # was ever tested. The other three describe an install working as
+    # configured, and each ends in something the operator can change. This one
+    # ends in "your printer is doing something we cannot yet explain", which is
+    # both the more urgent thing to say and the thing that produces a useful
+    # report. It also has to outrank them because the banner dismisses one-shot
+    # into localStorage: a reason ranked below another is not merely deferred,
+    # it is never shown to that user again (#2780).
+    #
+    # Ranking it first cannot mask a permanent cause, because a cool-off row is
+    # not permanent. The retry #2957 schedules clears the row's markers when it
+    # lands, so a row still carrying this slug is one where the retry failed too
+    # -- a printer whose file service is still refusing, days later.
+    #
     # REASON_INTERNAL_HISTORY comes last on purpose, even though it is the
     # REASON_INTERNAL_HISTORY comes last on purpose, even though it is the
     # narrowest: it is the one cause with no remedy at all -- the file was
     # narrowest: it is the one cause with no remedy at all -- the file was
     # already on the printer, in an area port 990 does not serve. The two ahead
     # already on the printer, in an area port 990 does not serve. The two ahead
     # of it each end in something the operator can do, so when an install has
     # of it each end in something the operator can do, so when an install has
     # both, the actionable explanation is the one worth the banner (#1820).
     # both, the actionable explanation is the one worth the banner (#1820).
-    for candidate in (REASON_INTERNAL_STORAGE, REASON_NO_EXTERNAL_STORAGE, REASON_INTERNAL_HISTORY):
+    for candidate in (
+        REASON_FTPS_COOLOFF,
+        REASON_INTERNAL_STORAGE,
+        REASON_NO_EXTERNAL_STORAGE,
+        REASON_INTERNAL_HISTORY,
+    ):
         if candidate in reasons:
         if candidate in reasons:
             return {"has_fallback": True, "reason": candidate}
             return {"has_fallback": True, "reason": candidate}
     return {"has_fallback": True, "reason": None}
     return {"has_fallback": True, "reason": None}

+ 57 - 0
backend/tests/integration/test_archives_api.py

@@ -1505,6 +1505,63 @@ class TestNo3MFWarningReason:
 
 
         assert response.json() == {"has_fallback": False, "reason": None}
         assert response.json() == {"has_fallback": False, "reason": None}
 
 
+    @pytest.mark.asyncio
+    @pytest.mark.integration
+    async def test_a_refused_handshake_is_reported(
+        self, async_client: AsyncClient, archive_factory, printer_factory, db_session
+    ):
+        """#2957 stamps this slug and #2780 never taught the banner about it, so
+        an install whose only empty archives came from a printer refusing TLS on
+        port 990 was told the slicer had not written the file to the card. The
+        slicer had; nothing could read it back. The reporter could see the file
+        on the stick from his own computer, which is exactly why the advice read
+        as Bambuddy being broken.
+        """
+        printer = await printer_factory()
+        await archive_factory(
+            printer.id,
+            extra_data={"no_3mf_available": True, "no_3mf_reason": "ftps_cooloff"},
+        )
+
+        response = await async_client.get("/api/v1/archives/no-3mf-warning")
+
+        assert response.json() == {"has_fallback": True, "reason": "ftps_cooloff"}
+
+    @pytest.mark.asyncio
+    @pytest.mark.integration
+    async def test_a_refused_handshake_outranks_every_settled_cause(
+        self, async_client: AsyncClient, archive_factory, printer_factory, db_session
+    ):
+        """The other three describe an install working as configured. This one
+        reports a printer doing something we cannot yet explain, and the banner
+        dismisses one-shot into localStorage -- so a reason ranked below another
+        is not deferred, it is never shown to that user at all.
+        """
+        printer = await printer_factory()
+        for reason in ("internal_storage", "no_external_storage", "internal_history"):
+            await archive_factory(printer.id, extra_data={"no_3mf_available": True, "no_3mf_reason": reason})
+        await archive_factory(printer.id, extra_data={"no_3mf_available": True, "no_3mf_reason": "ftps_cooloff"})
+
+        response = await async_client.get("/api/v1/archives/no-3mf-warning")
+
+        assert response.json() == {"has_fallback": True, "reason": "ftps_cooloff"}
+
+    @pytest.mark.asyncio
+    @pytest.mark.integration
+    async def test_the_settled_causes_keep_their_order_behind_it(
+        self, async_client: AsyncClient, archive_factory, printer_factory, db_session
+    ):
+        """Adding a new leader must not disturb the ranking underneath it: an
+        install with no refused handshake still gets exactly what it got before.
+        """
+        printer = await printer_factory()
+        await archive_factory(printer.id, extra_data={"no_3mf_available": True, "no_3mf_reason": "internal_history"})
+        await archive_factory(printer.id, extra_data={"no_3mf_available": True, "no_3mf_reason": "no_external_storage"})
+
+        response = await async_client.get("/api/v1/archives/no-3mf-warning")
+
+        assert response.json() == {"has_fallback": True, "reason": "no_external_storage"}
+
 
 
 class TestPrintLogEntryDelete:
 class TestPrintLogEntryDelete:
     """#1687: per-row delete on the Print Log page.
     """#1687: per-row delete on the Print Log page.

+ 22 - 1
frontend/src/__tests__/pages/ArchivesNo3MFBanner.test.tsx

@@ -12,6 +12,12 @@
  * screen, where no slicer was involved at all and both of the wordings above
  * screen, where no slicer was involved at all and both of the wordings above
  * describe a step the operator never took.
  * describe a step the operator never took.
  *
  *
+ * And a fourth, which is why this file grew again: a printer whose file service
+ * refused the TLS handshake, so no lookup ever ran. #2957 recorded that cause
+ * and nothing surfaced it, so those installs fell to the generic wording and
+ * were told to switch on a setting that was already on, about a file they could
+ * see sitting on the stick.
+ *
  * So these assert the wording actually shown, not just that a banner rendered.
  * So these assert the wording actually shown, not just that a banner rendered.
  */
  */
 
 
@@ -92,6 +98,21 @@ describe('ArchivesPage no-3MF banner', () => {
     expect(screen.queryByText('Why this happens')).not.toBeInTheDocument();
     expect(screen.queryByText('Why this happens')).not.toBeInTheDocument();
   });
   });
 
 
+  it('reports a refused handshake as the printer, not as the slicer', async () => {
+    mockWarning({ has_fallback: true, reason: 'ftps_cooloff' });
+
+    render(<ArchivesPage />);
+
+    expect(
+      await screen.findByText(/refused the file connection/i),
+    ).toBeInTheDocument();
+    // The whole point: nothing here may read as a slicer setting the user
+    // should go and change, because there is nothing they can change.
+    expect(screen.queryByText('See install step 4')).not.toBeInTheDocument();
+    expect(screen.queryByText(/Store sent files on external storage/i)).not.toBeInTheDocument();
+    expect(screen.getByText('Why this happens')).toBeInTheDocument();
+  });
+
   it('shows nothing at all when no print fell back', async () => {
   it('shows nothing at all when no print fell back', async () => {
     mockWarning({ has_fallback: false, reason: null });
     mockWarning({ has_fallback: false, reason: null });
 
 
@@ -107,7 +128,7 @@ describe('ArchivesPage no-3MF banner', () => {
     // The variant suffix is built by string concatenation, so a typo in one
     // The variant suffix is built by string concatenation, so a typo in one
     // locale key surfaces as a raw "archives.no3mfBanner.titleX" on screen
     // locale key surfaces as a raw "archives.no3mfBanner.titleX" on screen
     // instead of failing anything.
     // instead of failing anything.
-    for (const reason of [null, 'internal_storage', 'no_external_storage', 'internal_history']) {
+    for (const reason of [null, 'internal_storage', 'no_external_storage', 'internal_history', 'ftps_cooloff']) {
       localStorage.clear();
       localStorage.clear();
       mockWarning({ has_fallback: true, reason });
       mockWarning({ has_fallback: true, reason });
 
 

+ 1 - 1
frontend/src/api/client.ts

@@ -5024,7 +5024,7 @@ export const api = {
   getNo3MFWarning: () =>
   getNo3MFWarning: () =>
     request<{
     request<{
       has_fallback: boolean;
       has_fallback: boolean;
-      reason: 'internal_storage' | 'no_external_storage' | 'internal_history' | null;
+      reason: 'ftps_cooloff' | 'internal_storage' | 'no_external_storage' | 'internal_history' | null;
     }>(
     }>(
       '/archives/no-3mf-warning',
       '/archives/no-3mf-warning',
     ),
     ),

+ 2 - 0
frontend/src/i18n/locales/de.ts

@@ -906,6 +906,8 @@ export default {
       bodyNoExternalStorage: 'Der Drucker meldet weder Karte noch Stick im Steckplatz, daher hatte die geslicte Datei keinen Ablageort und Bambuddy nichts zu lesen. Legen Sie einen ein, dann wird der nächste Druck vollständig archiviert.',
       bodyNoExternalStorage: 'Der Drucker meldet weder Karte noch Stick im Steckplatz, daher hatte die geslicte Datei keinen Ablageort und Bambuddy nichts zu lesen. Legen Sie einen ein, dann wird der nächste Druck vollständig archiviert.',
       titleInternalHistory: 'Einige kürzliche Drucke wurden aus einer Datei gestartet, die bereits auf dem Drucker lag',
       titleInternalHistory: 'Einige kürzliche Drucke wurden aus einer Datei gestartet, die bereits auf dem Drucker lag',
       bodyInternalHistory: 'Diese Drucke liefen aus der eigenen Bibliothek des Druckers — ein erneuter Druck über sein Display, ein Start aus Handy oder eine früher gesendete und später gedruckte Datei. Bambuddy liest Druckdateien über FTP, und das bedient nur Karte oder Stick, während der Drucker diese Bibliothek in einem Bereich ablegt, den FTP nicht erreicht — es gab also keine 3MF zu lesen. Keine Slicer-Einstellung ändert das, denn für diese Drucke wurde nichts gesendet. Sie werden weiterhin mit Namen und Zeiten archiviert, und unter "Archiv bearbeiten" lässt sich das verbrauchte Filament von Hand eintragen. Für ein vollständiges Archiv starten Sie den Druck stattdessen aus Bambuddy oder aus Ihrem Slicer.',
       bodyInternalHistory: 'Diese Drucke liefen aus der eigenen Bibliothek des Druckers — ein erneuter Druck über sein Display, ein Start aus Handy oder eine früher gesendete und später gedruckte Datei. Bambuddy liest Druckdateien über FTP, und das bedient nur Karte oder Stick, während der Drucker diese Bibliothek in einem Bereich ablegt, den FTP nicht erreicht — es gab also keine 3MF zu lesen. Keine Slicer-Einstellung ändert das, denn für diese Drucke wurde nichts gesendet. Sie werden weiterhin mit Namen und Zeiten archiviert, und unter "Archiv bearbeiten" lässt sich das verbrauchte Filament von Hand eintragen. Für ein vollständiges Archiv starten Sie den Druck stattdessen aus Bambuddy oder aus Ihrem Slicer.',
+      titleFtpsCooloff: 'Einige kürzliche Drucke konnten nicht archiviert werden — der Drucker hat die Dateiverbindung abgewiesen',
+      bodyFtpsCooloff: 'Bambuddy hat den Dateiübertragungs-Port des Druckers (FTPS 990) geöffnet, und der Drucker hat mit etwas geantwortet, das kein TLS ist. Deshalb ließ sich nichts von ihm lesen. Diese Drucke sind weiterhin mit Namen und Zeiten archiviert, nur ohne Vorschaubild und Slicer-Metadaten. Das ist keine Slicer-Einstellung und nichts, was Sie geändert haben — dieselben Modelle und Firmware-Stände laufen auf anderen Installationen normal, und ein betroffener Drucker arbeitet später meist von selbst wieder. Nach einem solchen Fehler pausiert Bambuddy die Übertragungen zu diesem Drucker fünf Minuten lang und holt die Datei nach Ablauf der Pause erneut; eine kurze Episode behebt sich damit von selbst, eine weiterhin leere Karte bedeutet, dass die Abweisung länger anhielt als der zweite Versuch. Was das auslöst, ist noch nicht bekannt. Wenn es wiederholt auftritt, aktivieren Sie auf der Seite System die Debug-Protokollierung und hängen Sie ein Support-Paket an Ihre Meldung an.',
       dismissLabel: 'Hinweis schließen',
       dismissLabel: 'Hinweis schließen',
     },
     },
     searchPlaceholder: 'Archiv durchsuchen...',
     searchPlaceholder: 'Archiv durchsuchen...',

+ 2 - 0
frontend/src/i18n/locales/en.ts

@@ -912,6 +912,8 @@ export default {
       bodyNoExternalStorage: 'The printer reports no card or stick in its slot, so the sliced file had nowhere to land and Bambuddy had nothing to read. Insert one and the next print will archive in full.',
       bodyNoExternalStorage: 'The printer reports no card or stick in its slot, so the sliced file had nowhere to land and Bambuddy had nothing to read. Insert one and the next print will archive in full.',
       titleInternalHistory: 'Some recent prints were started from a file already on the printer',
       titleInternalHistory: 'Some recent prints were started from a file already on the printer',
       bodyInternalHistory: 'Those prints ran from the printer\'s own library — a re-print from its screen, a start from Handy, or a file sent earlier and printed later. Bambuddy reads print files over FTP, which serves only the card or stick, while the printer keeps that library in an area FTP cannot reach, so there was no 3MF to read. No slicer setting changes this, because nothing was sent for these prints. They are still archived with their name and timing, and Edit Archive lets you fill in the filament used by hand. For a complete archive, start the print from Bambuddy or from your slicer instead.',
       bodyInternalHistory: 'Those prints ran from the printer\'s own library — a re-print from its screen, a start from Handy, or a file sent earlier and printed later. Bambuddy reads print files over FTP, which serves only the card or stick, while the printer keeps that library in an area FTP cannot reach, so there was no 3MF to read. No slicer setting changes this, because nothing was sent for these prints. They are still archived with their name and timing, and Edit Archive lets you fill in the filament used by hand. For a complete archive, start the print from Bambuddy or from your slicer instead.',
+      titleFtpsCooloff: 'Some recent prints couldn\'t be archived — the printer refused the file connection',
+      bodyFtpsCooloff: 'Bambuddy opened the printer\'s file-transfer port (FTPS 990) and the printer answered with something that is not TLS, so nothing could be read from it. Those prints are still archived with their name and timing, just without a thumbnail or slicer metadata. This is not a slicer setting and not something you changed — the same models and firmware run normally on other installs, and an affected printer usually works again later on its own. After such a failure Bambuddy pauses transfers to that printer for five minutes and comes back for the file once the pause clears, so a short episode fills itself in; a card still empty means the refusal outlasted the retry. What triggers it is not yet known. If it keeps happening, turn on debug logging on the System page and attach a support bundle to your report.',
     },
     },
     searchPlaceholder: 'Search archives...',
     searchPlaceholder: 'Search archives...',
     filterByPrinter: 'Filter by printer',
     filterByPrinter: 'Filter by printer',

+ 2 - 0
frontend/src/i18n/locales/es.ts

@@ -906,6 +906,8 @@ export default {
       bodyNoExternalStorage: 'La impresora no detecta ninguna tarjeta ni memoria en su ranura, así que el archivo laminado no tenía dónde aterrizar y Bambuddy nada que leer. Inserte una y la próxima impresión se archivará por completo.',
       bodyNoExternalStorage: 'La impresora no detecta ninguna tarjeta ni memoria en su ranura, así que el archivo laminado no tenía dónde aterrizar y Bambuddy nada que leer. Inserte una y la próxima impresión se archivará por completo.',
       titleInternalHistory: 'Algunas impresiones recientes se iniciaron desde un archivo que ya estaba en la impresora',
       titleInternalHistory: 'Algunas impresiones recientes se iniciaron desde un archivo que ya estaba en la impresora',
       bodyInternalHistory: 'Esas impresiones salieron de la propia biblioteca de la impresora: una reimpresión desde su pantalla, un inicio desde Handy o un archivo enviado antes e impreso después. Bambuddy lee los archivos de impresión por FTP, que solo sirve la tarjeta o la memoria, mientras que la impresora guarda esa biblioteca en una zona que FTP no alcanza, así que no había ningún 3MF que leer. Ninguna opción del laminador cambia esto, porque para estas impresiones no se envió nada. Se siguen archivando con su nombre y sus tiempos, y «Editar archivo» permite anotar a mano el filamento usado. Para un archivo completo, inicia la impresión desde Bambuddy o desde tu laminador.',
       bodyInternalHistory: 'Esas impresiones salieron de la propia biblioteca de la impresora: una reimpresión desde su pantalla, un inicio desde Handy o un archivo enviado antes e impreso después. Bambuddy lee los archivos de impresión por FTP, que solo sirve la tarjeta o la memoria, mientras que la impresora guarda esa biblioteca en una zona que FTP no alcanza, así que no había ningún 3MF que leer. Ninguna opción del laminador cambia esto, porque para estas impresiones no se envió nada. Se siguen archivando con su nombre y sus tiempos, y «Editar archivo» permite anotar a mano el filamento usado. Para un archivo completo, inicia la impresión desde Bambuddy o desde tu laminador.',
+      titleFtpsCooloff: 'Algunas impresiones recientes no se pudieron archivar — la impresora rechazó la conexión de archivos',
+      bodyFtpsCooloff: 'Bambuddy abrió el puerto de transferencia de archivos de la impresora (FTPS 990) y la impresora respondió con algo que no es TLS, así que no se pudo leer nada de ella. Esas impresiones siguen archivadas con su nombre y sus tiempos, solo que sin miniatura ni metadatos del laminador. No es un ajuste del laminador ni algo que usted haya cambiado — los mismos modelos y firmware funcionan con normalidad en otras instalaciones, y una impresora afectada suele volver a funcionar sola más tarde. Tras un fallo así, Bambuddy pausa las transferencias a esa impresora durante cinco minutos y vuelve a por el archivo cuando termina la pausa, de modo que un episodio breve se resuelve por sí solo; una ficha que sigue vacía significa que el rechazo duró más que el reintento. Todavía no se sabe qué lo provoca. Si se repite, active el registro de depuración en la página Sistema y adjunte un paquete de soporte a su informe.',
       dismissLabel: 'Descartar este aviso',
       dismissLabel: 'Descartar este aviso',
     },
     },
     searchPlaceholder: 'Buscar archivos...',
     searchPlaceholder: 'Buscar archivos...',

+ 2 - 0
frontend/src/i18n/locales/fr.ts

@@ -906,6 +906,8 @@ export default {
       bodyNoExternalStorage: 'L\'imprimante ne signale ni carte ni clé dans son emplacement, le fichier tranché n\'avait donc nulle part où atterrir et Bambuddy rien à lire. Insérez-en une et la prochaine impression sera archivée complètement.',
       bodyNoExternalStorage: 'L\'imprimante ne signale ni carte ni clé dans son emplacement, le fichier tranché n\'avait donc nulle part où atterrir et Bambuddy rien à lire. Insérez-en une et la prochaine impression sera archivée complètement.',
       titleInternalHistory: 'Certaines impressions récentes ont été lancées depuis un fichier déjà présent sur l\'imprimante',
       titleInternalHistory: 'Certaines impressions récentes ont été lancées depuis un fichier déjà présent sur l\'imprimante',
       bodyInternalHistory: 'Ces impressions sont parties de la bibliothèque de l\'imprimante elle-même : une réimpression depuis son écran, un lancement depuis Handy, ou un fichier envoyé plus tôt et imprimé ensuite. Bambuddy lit les fichiers d\'impression en FTP, qui ne dessert que la carte ou la clé, tandis que l\'imprimante conserve cette bibliothèque dans une zone que le FTP n\'atteint pas : il n\'y avait donc aucun 3MF à lire. Aucun réglage du trancheur n\'y change quoi que ce soit, puisque rien n\'a été envoyé pour ces impressions. Elles restent archivées avec leur nom et leurs durées, et « Modifier l\'archive » permet de saisir à la main le filament utilisé. Pour une archive complète, lancez plutôt l\'impression depuis Bambuddy ou depuis votre trancheur.',
       bodyInternalHistory: 'Ces impressions sont parties de la bibliothèque de l\'imprimante elle-même : une réimpression depuis son écran, un lancement depuis Handy, ou un fichier envoyé plus tôt et imprimé ensuite. Bambuddy lit les fichiers d\'impression en FTP, qui ne dessert que la carte ou la clé, tandis que l\'imprimante conserve cette bibliothèque dans une zone que le FTP n\'atteint pas : il n\'y avait donc aucun 3MF à lire. Aucun réglage du trancheur n\'y change quoi que ce soit, puisque rien n\'a été envoyé pour ces impressions. Elles restent archivées avec leur nom et leurs durées, et « Modifier l\'archive » permet de saisir à la main le filament utilisé. Pour une archive complète, lancez plutôt l\'impression depuis Bambuddy ou depuis votre trancheur.',
+      titleFtpsCooloff: 'Certaines impressions récentes n\'ont pas pu être archivées — l\'imprimante a refusé la connexion de fichiers',
+      bodyFtpsCooloff: 'Bambuddy a ouvert le port de transfert de fichiers de l\'imprimante (FTPS 990) et celle-ci a répondu par autre chose que du TLS, si bien que rien n\'a pu en être lu. Ces impressions restent archivées avec leur nom et leurs durées, simplement sans vignette ni métadonnées du trancheur. Ce n\'est pas un réglage du trancheur ni quelque chose que vous avez modifié — les mêmes modèles et les mêmes firmwares fonctionnent normalement sur d\'autres installations, et une imprimante touchée refonctionne généralement d\'elle-même plus tard. Après un tel échec, Bambuddy suspend les transferts vers cette imprimante pendant cinq minutes puis revient chercher le fichier une fois la pause terminée : un épisode bref se répare donc tout seul, tandis qu\'une fiche encore vide signifie que le refus a duré plus longtemps que la nouvelle tentative. On ignore encore ce qui le déclenche. Si cela se reproduit, activez la journalisation de débogage sur la page Système et joignez un paquet de support à votre signalement.',
       dismissLabel: 'Ignorer ce message',
       dismissLabel: 'Ignorer ce message',
     },
     },
     searchPlaceholder: 'Chercher dans les archives...',
     searchPlaceholder: 'Chercher dans les archives...',

+ 2 - 0
frontend/src/i18n/locales/it.ts

@@ -906,6 +906,8 @@ export default {
       bodyNoExternalStorage: 'La stampante non rileva né scheda né chiavetta nel suo slot, quindi il file elaborato non aveva dove finire e Bambuddy nulla da leggere. Inseriscine una e la prossima stampa verrà archiviata per intero.',
       bodyNoExternalStorage: 'La stampante non rileva né scheda né chiavetta nel suo slot, quindi il file elaborato non aveva dove finire e Bambuddy nulla da leggere. Inseriscine una e la prossima stampa verrà archiviata per intero.',
       titleInternalHistory: 'Alcune stampe recenti sono partite da un file già presente sulla stampante',
       titleInternalHistory: 'Alcune stampe recenti sono partite da un file già presente sulla stampante',
       bodyInternalHistory: 'Quelle stampe sono uscite dalla libreria della stampante stessa: una ristampa dal suo schermo, un avvio da Handy o un file inviato prima e stampato dopo. Bambuddy legge i file di stampa via FTP, che serve solo la scheda o la chiavetta, mentre la stampante tiene quella libreria in un\'area che l\'FTP non raggiunge, quindi non c\'era alcun 3MF da leggere. Nessuna impostazione dello slicer cambia questo, perché per queste stampe non è stato inviato nulla. Restano archiviate con nome e tempi, e «Modifica archivio» consente di inserire a mano il filamento usato. Per un archivio completo, avvia la stampa da Bambuddy o dal tuo slicer.',
       bodyInternalHistory: 'Quelle stampe sono uscite dalla libreria della stampante stessa: una ristampa dal suo schermo, un avvio da Handy o un file inviato prima e stampato dopo. Bambuddy legge i file di stampa via FTP, che serve solo la scheda o la chiavetta, mentre la stampante tiene quella libreria in un\'area che l\'FTP non raggiunge, quindi non c\'era alcun 3MF da leggere. Nessuna impostazione dello slicer cambia questo, perché per queste stampe non è stato inviato nulla. Restano archiviate con nome e tempi, e «Modifica archivio» consente di inserire a mano il filamento usato. Per un archivio completo, avvia la stampa da Bambuddy o dal tuo slicer.',
+      titleFtpsCooloff: 'Alcune stampe recenti non sono state archiviate — la stampante ha rifiutato la connessione dei file',
+      bodyFtpsCooloff: 'Bambuddy ha aperto la porta di trasferimento file della stampante (FTPS 990) e la stampante ha risposto con qualcosa che non è TLS, quindi non è stato possibile leggere nulla. Quelle stampe restano archiviate con nome e tempi, solo senza miniatura né metadati dello slicer. Non è un\'impostazione dello slicer né qualcosa che hai cambiato tu — gli stessi modelli e firmware funzionano normalmente su altre installazioni, e una stampante colpita di solito torna a funzionare da sola più tardi. Dopo un errore simile Bambuddy sospende i trasferimenti verso quella stampante per cinque minuti e ritorna a prendere il file al termine della pausa, così un episodio breve si risolve da sé; una scheda ancora vuota significa che il rifiuto è durato più del secondo tentativo. Non si sa ancora che cosa lo scateni. Se continua a capitare, attiva la registrazione di debug nella pagina Sistema e allega un pacchetto di supporto alla tua segnalazione.',
       dismissLabel: 'Chiudi questo avviso',
       dismissLabel: 'Chiudi questo avviso',
     },
     },
     searchPlaceholder: 'Cerca archivi...',
     searchPlaceholder: 'Cerca archivi...',

+ 2 - 0
frontend/src/i18n/locales/ja.ts

@@ -905,6 +905,8 @@ export default {
       bodyNoExternalStorage: 'プリンターのスロットにカードもUSBメモリも検出されないため、スライス済みファイルの保存先がなく、Bambuddyが読み取るものもありませんでした。挿入すれば次の印刷は完全にアーカイブされます。',
       bodyNoExternalStorage: 'プリンターのスロットにカードもUSBメモリも検出されないため、スライス済みファイルの保存先がなく、Bambuddyが読み取るものもありませんでした。挿入すれば次の印刷は完全にアーカイブされます。',
       titleInternalHistory: '最近の一部の印刷は、すでにプリンター内にあるファイルから開始されました',
       titleInternalHistory: '最近の一部の印刷は、すでにプリンター内にあるファイルから開始されました',
       bodyInternalHistory: 'これらの印刷はプリンター自身のライブラリから実行されました — 画面からの再印刷、Handy からの開始、または以前に送信して後から印刷したファイルです。Bambuddy は印刷ファイルを FTP で読み取りますが、FTP が扱えるのはカードまたは USB メモリだけで、プリンターはそのライブラリを FTP の届かない領域に保存するため、読み取れる 3MF がありませんでした。これらの印刷では何も送信されていないので、スライサーの設定を変えても解決しません。名前と時間付きでのアーカイブは続き、「アーカイブを編集」で使用フィラメントを手入力できます。完全なアーカイブにするには、Bambuddy またはスライサーから印刷を開始してください。',
       bodyInternalHistory: 'これらの印刷はプリンター自身のライブラリから実行されました — 画面からの再印刷、Handy からの開始、または以前に送信して後から印刷したファイルです。Bambuddy は印刷ファイルを FTP で読み取りますが、FTP が扱えるのはカードまたは USB メモリだけで、プリンターはそのライブラリを FTP の届かない領域に保存するため、読み取れる 3MF がありませんでした。これらの印刷では何も送信されていないので、スライサーの設定を変えても解決しません。名前と時間付きでのアーカイブは続き、「アーカイブを編集」で使用フィラメントを手入力できます。完全なアーカイブにするには、Bambuddy またはスライサーから印刷を開始してください。',
+      titleFtpsCooloff: '最近の一部の印刷を保存できませんでした — プリンターがファイル接続を拒否しました',
+      bodyFtpsCooloff: 'Bambuddy がプリンターのファイル転送ポート (FTPS 990) を開いたところ、プリンターは TLS ではないもので応答したため、何も読み取れませんでした。これらの印刷は名前と時間付きでアーカイブされていますが、サムネイルとスライサーのメタデータはありません。これはスライサーの設定でも、お客様が変更したことでもありません。同じ機種・同じファームウェアが他の環境では正常に動作しており、影響を受けたプリンターも通常はしばらくすると自然に復帰します。この失敗のあと Bambuddy はそのプリンターへの転送を 5 分間停止し、停止が明けてからファイルを取りに戻ります。短時間の事象であれば自動的に埋まり、カードが空のままであれば拒否が再試行より長く続いたことを意味します。原因はまだ分かっていません。繰り返す場合は、システムページでデバッグログを有効にし、サポートバンドルを報告に添付してください。',
       dismissLabel: 'この通知を閉じる',
       dismissLabel: 'この通知を閉じる',
     },
     },
     searchPlaceholder: 'アーカイブを検索...',
     searchPlaceholder: 'アーカイブを検索...',

+ 2 - 0
frontend/src/i18n/locales/ko.ts

@@ -862,6 +862,8 @@ export default {
       bodyNoExternalStorage: '프린터 슬롯에 카드도 USB도 감지되지 않아 슬라이싱된 파일이 저장될 곳이 없었고 Bambuddy가 읽을 것도 없었습니다. 하나 넣으면 다음 출력물은 온전히 보관됩니다.',
       bodyNoExternalStorage: '프린터 슬롯에 카드도 USB도 감지되지 않아 슬라이싱된 파일이 저장될 곳이 없었고 Bambuddy가 읽을 것도 없었습니다. 하나 넣으면 다음 출력물은 온전히 보관됩니다.',
       titleInternalHistory: '최근 일부 출력물은 이미 프린터에 있던 파일에서 시작되었습니다',
       titleInternalHistory: '최근 일부 출력물은 이미 프린터에 있던 파일에서 시작되었습니다',
       bodyInternalHistory: '해당 출력물은 프린터 자체 라이브러리에서 실행되었습니다 — 화면에서의 재출력, Handy에서의 시작, 또는 이전에 보내 두고 나중에 출력한 파일입니다. Bambuddy는 출력 파일을 FTP로 읽는데 FTP는 카드나 USB만 제공하고, 프린터는 그 라이브러리를 FTP가 닿지 않는 영역에 보관하므로 읽을 3MF가 없었습니다. 이 출력물들은 아무것도 전송되지 않았으므로 슬라이서 설정으로는 해결되지 않습니다. 이름과 시간과 함께 계속 보관되며, "아카이브 편집"에서 사용된 필라멘트를 직접 입력할 수 있습니다. 온전한 보관을 원하면 Bambuddy나 슬라이서에서 출력을 시작하세요.',
       bodyInternalHistory: '해당 출력물은 프린터 자체 라이브러리에서 실행되었습니다 — 화면에서의 재출력, Handy에서의 시작, 또는 이전에 보내 두고 나중에 출력한 파일입니다. Bambuddy는 출력 파일을 FTP로 읽는데 FTP는 카드나 USB만 제공하고, 프린터는 그 라이브러리를 FTP가 닿지 않는 영역에 보관하므로 읽을 3MF가 없었습니다. 이 출력물들은 아무것도 전송되지 않았으므로 슬라이서 설정으로는 해결되지 않습니다. 이름과 시간과 함께 계속 보관되며, "아카이브 편집"에서 사용된 필라멘트를 직접 입력할 수 있습니다. 온전한 보관을 원하면 Bambuddy나 슬라이서에서 출력을 시작하세요.',
+      titleFtpsCooloff: '최근 일부 출력물을 보관하지 못했습니다 — 프린터가 파일 연결을 거부했습니다',
+      bodyFtpsCooloff: 'Bambuddy가 프린터의 파일 전송 포트(FTPS 990)를 열었으나 프린터가 TLS가 아닌 것으로 응답해 아무것도 읽을 수 없었습니다. 해당 출력물은 이름과 시간과 함께 보관되지만 미리보기와 슬라이서 메타데이터는 없습니다. 이는 슬라이서 설정 문제도, 사용자가 바꾼 것도 아닙니다. 같은 모델과 같은 펌웨어가 다른 설치 환경에서는 정상 동작하며, 문제가 생긴 프린터도 대개 나중에 저절로 다시 동작합니다. 이런 실패 후 Bambuddy는 해당 프린터로의 전송을 5분간 멈추고, 그 후 파일을 다시 가지러 갑니다. 짧은 문제라면 스스로 채워지고, 카드가 계속 비어 있다면 거부가 재시도보다 오래 지속되었다는 뜻입니다. 무엇이 원인인지는 아직 밝혀지지 않았습니다. 반복된다면 시스템 페이지에서 디버그 로깅을 켠 뒤 지원 번들을 보고에 첨부해 주세요.',
       dismissLabel: '이 알림 닫기'
       dismissLabel: '이 알림 닫기'
     },
     },
     searchPlaceholder: '아카이브 검색...',
     searchPlaceholder: '아카이브 검색...',

+ 2 - 0
frontend/src/i18n/locales/nl.ts

@@ -912,6 +912,8 @@ export default {
       bodyNoExternalStorage: 'De printer meldt dat er geen kaart of USB-stick in de sleuf zit, waardoor het geslicede bestand nergens kon worden opgeslagen en Bambuddy niets kon uitlezen. Plaats er een en de volgende afdruk wordt volledig gearchiveerd.',
       bodyNoExternalStorage: 'De printer meldt dat er geen kaart of USB-stick in de sleuf zit, waardoor het geslicede bestand nergens kon worden opgeslagen en Bambuddy niets kon uitlezen. Plaats er een en de volgende afdruk wordt volledig gearchiveerd.',
       titleInternalHistory: 'Sommige recente prints zijn gestart vanaf een bestand dat al op de printer stond',
       titleInternalHistory: 'Sommige recente prints zijn gestart vanaf een bestand dat al op de printer stond',
       bodyInternalHistory: 'Die prints liepen vanuit de eigen bibliotheek van de printer — opnieuw afdrukken via het scherm, starten vanuit Handy, of een bestand dat eerder is verstuurd en later is afgedrukt. Bambuddy leest printbestanden via FTP, dat alleen de kaart of stick aanbiedt, terwijl de printer die bibliotheek bewaart op een plek die FTP niet kan bereiken. Er was dus geen 3MF om te lezen. Geen enkele slicer-instelling verandert dit, omdat er voor deze prints niets is verstuurd. Ze worden nog steeds gearchiveerd met naam en tijden, en via Archief bewerken kun je het gebruikte filament handmatig invullen. Start de print vanuit Bambuddy of vanuit je slicer voor een volledig archief.',
       bodyInternalHistory: 'Die prints liepen vanuit de eigen bibliotheek van de printer — opnieuw afdrukken via het scherm, starten vanuit Handy, of een bestand dat eerder is verstuurd en later is afgedrukt. Bambuddy leest printbestanden via FTP, dat alleen de kaart of stick aanbiedt, terwijl de printer die bibliotheek bewaart op een plek die FTP niet kan bereiken. Er was dus geen 3MF om te lezen. Geen enkele slicer-instelling verandert dit, omdat er voor deze prints niets is verstuurd. Ze worden nog steeds gearchiveerd met naam en tijden, en via Archief bewerken kun je het gebruikte filament handmatig invullen. Start de print vanuit Bambuddy of vanuit je slicer voor een volledig archief.',
+      titleFtpsCooloff: 'Sommige recente prints konden niet worden gearchiveerd — de printer weigerde de bestandsverbinding',
+      bodyFtpsCooloff: 'Bambuddy opende de bestandsoverdrachtspoort van de printer (FTPS 990) en de printer antwoordde met iets dat geen TLS is, waardoor er niets van te lezen viel. Die prints staan nog wel in het archief met hun naam en tijden, alleen zonder miniatuur of slicer-metadata. Dit is geen slicer-instelling en niets wat u hebt gewijzigd — dezelfde modellen en firmware draaien normaal op andere installaties, en een getroffen printer werkt later meestal vanzelf weer. Na zo\'n fout pauzeert Bambuddy de overdrachten naar die printer vijf minuten en haalt het bestand daarna alsnog op, dus een korte episode herstelt zichzelf; een kaart die leeg blijft betekent dat de weigering langer duurde dan de herhaalpoging. Wat het veroorzaakt is nog niet bekend. Blijft het gebeuren, zet dan debug-logging aan op de pagina Systeem en voeg een supportpakket bij uw melding.',
     },
     },
     searchPlaceholder: 'Archieven zoeken...',
     searchPlaceholder: 'Archieven zoeken...',
     filterByPrinter: 'Filteren op printer',
     filterByPrinter: 'Filteren op printer',

+ 2 - 0
frontend/src/i18n/locales/pt-BR.ts

@@ -906,6 +906,8 @@ export default {
       bodyNoExternalStorage: 'A impressora não detecta cartão nem pendrive no slot, então o arquivo fatiado não tinha onde ficar e o Bambuddy nada para ler. Insira um e a próxima impressão será arquivada por completo.',
       bodyNoExternalStorage: 'A impressora não detecta cartão nem pendrive no slot, então o arquivo fatiado não tinha onde ficar e o Bambuddy nada para ler. Insira um e a próxima impressão será arquivada por completo.',
       titleInternalHistory: 'Algumas impressões recentes começaram a partir de um arquivo que já estava na impressora',
       titleInternalHistory: 'Algumas impressões recentes começaram a partir de um arquivo que já estava na impressora',
       bodyInternalHistory: 'Essas impressões saíram da própria biblioteca da impressora: uma reimpressão pela tela dela, um início pelo Handy ou um arquivo enviado antes e impresso depois. O Bambuddy lê os arquivos de impressão por FTP, que só serve o cartão ou o pendrive, enquanto a impressora guarda essa biblioteca em uma área que o FTP não alcança, então não havia nenhum 3MF para ler. Nenhuma opção do fatiador muda isso, porque nada foi enviado para essas impressões. Elas continuam arquivadas com nome e tempos, e «Editar Arquivo» permite preencher à mão o filamento usado. Para um arquivo completo, inicie a impressão pelo Bambuddy ou pelo seu fatiador.',
       bodyInternalHistory: 'Essas impressões saíram da própria biblioteca da impressora: uma reimpressão pela tela dela, um início pelo Handy ou um arquivo enviado antes e impresso depois. O Bambuddy lê os arquivos de impressão por FTP, que só serve o cartão ou o pendrive, enquanto a impressora guarda essa biblioteca em uma área que o FTP não alcança, então não havia nenhum 3MF para ler. Nenhuma opção do fatiador muda isso, porque nada foi enviado para essas impressões. Elas continuam arquivadas com nome e tempos, e «Editar Arquivo» permite preencher à mão o filamento usado. Para um arquivo completo, inicie a impressão pelo Bambuddy ou pelo seu fatiador.',
+      titleFtpsCooloff: 'Algumas impressões recentes não puderam ser arquivadas — a impressora recusou a conexão de arquivos',
+      bodyFtpsCooloff: 'O Bambuddy abriu a porta de transferência de arquivos da impressora (FTPS 990) e a impressora respondeu com algo que não é TLS, então nada pôde ser lido dela. Essas impressões continuam arquivadas com nome e tempos, apenas sem miniatura nem metadados do fatiador. Não é uma configuração do fatiador nem algo que você mudou — os mesmos modelos e firmwares funcionam normalmente em outras instalações, e uma impressora afetada costuma voltar a funcionar sozinha depois. Após uma falha dessas, o Bambuddy pausa as transferências para essa impressora por cinco minutos e volta a buscar o arquivo quando a pausa termina, de modo que um episódio curto se resolve sozinho; um cartão ainda vazio significa que a recusa durou mais que a nova tentativa. Ainda não se sabe o que provoca isso. Se continuar acontecendo, ative o registro de depuração na página Sistema e anexe um pacote de suporte ao seu relato.',
       dismissLabel: 'Dispensar este aviso',
       dismissLabel: 'Dispensar este aviso',
     },
     },
     searchPlaceholder: 'Pesquisar arquivos...',
     searchPlaceholder: 'Pesquisar arquivos...',

+ 2 - 0
frontend/src/i18n/locales/ru.ts

@@ -861,6 +861,8 @@ export default {
       bodyNoExternalStorage: 'Принтер не видит ни карты, ни флешки в слоте, поэтому нарезанному файлу некуда было попасть, а Bambuddy нечего читать. Вставьте накопитель, и следующая печать будет заархивирована полностью.',
       bodyNoExternalStorage: 'Принтер не видит ни карты, ни флешки в слоте, поэтому нарезанному файлу некуда было попасть, а Bambuddy нечего читать. Вставьте накопитель, и следующая печать будет заархивирована полностью.',
       titleInternalHistory: 'Некоторые недавние печати запущены из файла, который уже был на принтере',
       titleInternalHistory: 'Некоторые недавние печати запущены из файла, который уже был на принтере',
       bodyInternalHistory: 'Эти печати шли из собственной библиотеки принтера — повторная печать с его экрана, запуск из Handy или файл, отправленный раньше и напечатанный позже. Bambuddy читает файлы печати по FTP, а он отдаёт только карту или флешку, тогда как принтер держит эту библиотеку в области, куда FTP не достаёт, — читать 3MF было негде. Настройки слайсера тут ничего не меняют: для этих печатей ничего не отправлялось. Они по-прежнему архивируются с именем и временем, а в «Редактировании архива» израсходованный филамент можно указать вручную. Чтобы архив был полным, запускайте печать из Bambuddy или из своего слайсера.',
       bodyInternalHistory: 'Эти печати шли из собственной библиотеки принтера — повторная печать с его экрана, запуск из Handy или файл, отправленный раньше и напечатанный позже. Bambuddy читает файлы печати по FTP, а он отдаёт только карту или флешку, тогда как принтер держит эту библиотеку в области, куда FTP не достаёт, — читать 3MF было негде. Настройки слайсера тут ничего не меняют: для этих печатей ничего не отправлялось. Они по-прежнему архивируются с именем и временем, а в «Редактировании архива» израсходованный филамент можно указать вручную. Чтобы архив был полным, запускайте печать из Bambuddy или из своего слайсера.',
+      titleFtpsCooloff: 'Некоторые недавние печати не удалось заархивировать — принтер отклонил файловое соединение',
+      bodyFtpsCooloff: 'Bambuddy открыл порт передачи файлов принтера (FTPS 990), и принтер ответил чем-то, что не является TLS, поэтому прочитать с него ничего не удалось. Эти печати всё равно сохранены в архиве с названием и временем, только без миниатюры и метаданных слайсера. Это не настройка слайсера и не то, что вы меняли: те же модели и прошивки нормально работают на других установках, а затронутый принтер обычно позже начинает работать сам. После такой ошибки Bambuddy приостанавливает передачи к этому принтеру на пять минут и возвращается за файлом, когда пауза заканчивается, поэтому короткий эпизод исправляется сам; если карточка так и осталась пустой, значит отказ продлился дольше повторной попытки. Что именно это вызывает, пока неизвестно. Если повторяется, включите отладочное журналирование на странице Система и приложите пакет поддержки к своему сообщению.',
       dismissLabel: "Закрыть это уведомление",
       dismissLabel: "Закрыть это уведомление",
     },
     },
     searchPlaceholder: "Поиск в архиве...",
     searchPlaceholder: "Поиск в архиве...",

+ 2 - 0
frontend/src/i18n/locales/tr.ts

@@ -906,6 +906,8 @@ export default {
       bodyNoExternalStorage: 'Yazıcı yuvasında kart veya bellek bildirmiyor, bu yüzden dilimlenmiş dosyanın ineceği bir yer ve Bambuddy\'nin okuyacağı bir şey yoktu. Bir tane takın, sonraki baskı eksiksiz arşivlenecek.',
       bodyNoExternalStorage: 'Yazıcı yuvasında kart veya bellek bildirmiyor, bu yüzden dilimlenmiş dosyanın ineceği bir yer ve Bambuddy\'nin okuyacağı bir şey yoktu. Bir tane takın, sonraki baskı eksiksiz arşivlenecek.',
       titleInternalHistory: 'Bazı son baskılar yazıcıda zaten bulunan bir dosyadan başlatıldı',
       titleInternalHistory: 'Bazı son baskılar yazıcıda zaten bulunan bir dosyadan başlatıldı',
       bodyInternalHistory: 'Bu baskılar yazıcının kendi kitaplığından çalıştı — ekranından yeniden baskı, Handy üzerinden başlatma ya da daha önce gönderilip sonra basılan bir dosya. Bambuddy baskı dosyalarını FTP üzerinden okur, FTP ise yalnızca kartı veya belleği sunar; yazıcı bu kitaplığı FTP\'nin ulaşamadığı bir alanda tutar, dolayısıyla okunacak bir 3MF yoktu. Hiçbir dilimleyici ayarı bunu değiştirmez, çünkü bu baskılar için hiçbir şey gönderilmedi. Adları ve süreleriyle arşivlenmeye devam ederler ve "Arşivi Düzenle" ile kullanılan filamenti elle girebilirsiniz. Eksiksiz bir arşiv için baskıyı Bambuddy\'den ya da dilimleyicinizden başlatın.',
       bodyInternalHistory: 'Bu baskılar yazıcının kendi kitaplığından çalıştı — ekranından yeniden baskı, Handy üzerinden başlatma ya da daha önce gönderilip sonra basılan bir dosya. Bambuddy baskı dosyalarını FTP üzerinden okur, FTP ise yalnızca kartı veya belleği sunar; yazıcı bu kitaplığı FTP\'nin ulaşamadığı bir alanda tutar, dolayısıyla okunacak bir 3MF yoktu. Hiçbir dilimleyici ayarı bunu değiştirmez, çünkü bu baskılar için hiçbir şey gönderilmedi. Adları ve süreleriyle arşivlenmeye devam ederler ve "Arşivi Düzenle" ile kullanılan filamenti elle girebilirsiniz. Eksiksiz bir arşiv için baskıyı Bambuddy\'den ya da dilimleyicinizden başlatın.',
+      titleFtpsCooloff: 'Bazı son baskılar arşivlenemedi — yazıcı dosya bağlantısını reddetti',
+      bodyFtpsCooloff: 'Bambuddy yazıcının dosya aktarım portunu (FTPS 990) açtı ve yazıcı TLS olmayan bir şeyle yanıt verdi, bu yüzden ondan hiçbir şey okunamadı. O baskılar adları ve süreleriyle yine arşivlenir, yalnızca küçük resim ve dilimleyici meta verileri olmadan. Bu bir dilimleyici ayarı değil ve sizin değiştirdiğiniz bir şey de değil — aynı modeller ve aynı ürün yazılımları başka kurulumlarda sorunsuz çalışıyor ve etkilenen bir yazıcı genellikle bir süre sonra kendiliğinden yeniden çalışıyor. Böyle bir hatadan sonra Bambuddy o yazıcıya yapılan aktarımları beş dakika duraklatır ve duraklama bitince dosyayı yeniden almaya gelir; kısa bir kesinti böylece kendiliğinden düzelir, hâlâ boş duran bir kart ise reddin yeniden denemeden daha uzun sürdüğü anlamına gelir. Buna neyin yol açtığı henüz bilinmiyor. Tekrarlıyorsa Sistem sayfasından hata ayıklama günlüğünü açın ve bildiriminize bir destek paketi ekleyin.',
       dismissLabel: 'Bu bildirimi kapat',
       dismissLabel: 'Bu bildirimi kapat',
     },
     },
     searchPlaceholder: 'Arşivlerde ara...',
     searchPlaceholder: 'Arşivlerde ara...',

+ 2 - 0
frontend/src/i18n/locales/uk.ts

@@ -910,6 +910,8 @@ export default {
       bodyNoExternalStorage: 'Принтер не бачить ані картки, ані флешки у слоті, тож нарізаному файлу не було куди потрапити, а Bambuddy — що читати. Вставте носій, і наступний друк заархівується повністю.',
       bodyNoExternalStorage: 'Принтер не бачить ані картки, ані флешки у слоті, тож нарізаному файлу не було куди потрапити, а Bambuddy — що читати. Вставте носій, і наступний друк заархівується повністю.',
       titleInternalHistory: 'Деякі нещодавні друки запущено з файлу, який уже був на принтері',
       titleInternalHistory: 'Деякі нещодавні друки запущено з файлу, який уже був на принтері',
       bodyInternalHistory: 'Ці друки йшли з власної бібліотеки принтера — повторний друк з його екрана, запуск із Handy або файл, надісланий раніше й надрукований пізніше. Bambuddy читає файли друку через FTP, а той віддає лише картку чи флешку, тоді як принтер тримає цю бібліотеку в області, куди FTP не дістає, — читати 3MF не було де. Налаштування слайсера тут нічого не змінюють: для цих друків нічого не надсилалося. Вони й далі архівуються з назвою та часом, а в «Редагувати архів» витрачений філамент можна вписати вручну. Щоб архів був повним, запускайте друк із Bambuddy або зі свого слайсера.',
       bodyInternalHistory: 'Ці друки йшли з власної бібліотеки принтера — повторний друк з його екрана, запуск із Handy або файл, надісланий раніше й надрукований пізніше. Bambuddy читає файли друку через FTP, а той віддає лише картку чи флешку, тоді як принтер тримає цю бібліотеку в області, куди FTP не дістає, — читати 3MF не було де. Налаштування слайсера тут нічого не змінюють: для цих друків нічого не надсилалося. Вони й далі архівуються з назвою та часом, а в «Редагувати архів» витрачений філамент можна вписати вручну. Щоб архів був повним, запускайте друк із Bambuddy або зі свого слайсера.',
+      titleFtpsCooloff: 'Деякі нещодавні друки не вдалося заархівувати — принтер відхилив файлове з\'єднання',
+      bodyFtpsCooloff: 'Bambuddy відкрив порт передавання файлів принтера (FTPS 990), і принтер відповів чимось, що не є TLS, тож прочитати з нього нічого не вдалося. Ці друки все одно збережені в архіві з назвою та часом, лише без мініатюри й метаданих слайсера. Це не налаштування слайсера і не те, що ви змінювали: ті самі моделі та прошивки нормально працюють на інших встановленнях, а уражений принтер зазвичай згодом починає працювати сам. Після такої помилки Bambuddy призупиняє передавання до цього принтера на п\'ять хвилин і повертається по файл, коли пауза завершується, тож короткий епізод виправляється сам; якщо картка й далі порожня, відмова тривала довше за повторну спробу. Що саме це спричиняє, поки невідомо. Якщо повторюється, увімкніть налагоджувальне журналювання на сторінці Система та додайте пакет підтримки до свого звіту.',
       dismissLabel: "Відхилити це повідомлення",
       dismissLabel: "Відхилити це повідомлення",
     },
     },
     searchPlaceholder: "Пошук в архівах...",
     searchPlaceholder: "Пошук в архівах...",

+ 2 - 0
frontend/src/i18n/locales/zh-CN.ts

@@ -906,6 +906,8 @@ export default {
       bodyNoExternalStorage: '打印机的插槽中未检测到存储卡或U盘,切片文件无处存放,Bambuddy 也无从读取。插入一个,下次打印就会完整归档。',
       bodyNoExternalStorage: '打印机的插槽中未检测到存储卡或U盘,切片文件无处存放,Bambuddy 也无从读取。插入一个,下次打印就会完整归档。',
       titleInternalHistory: '最近有些打印是从打印机里已有的文件启动的',
       titleInternalHistory: '最近有些打印是从打印机里已有的文件启动的',
       bodyInternalHistory: '这些打印来自打印机自己的文件库 — 从它的屏幕重新打印、从 Handy 启动,或是先前发送、稍后才打印的文件。Bambuddy 通过 FTP 读取打印文件,而 FTP 只提供存储卡或 U 盘,打印机却把这个文件库放在 FTP 够不到的区域,所以没有 3MF 可读。切片软件的任何设置都改变不了这一点,因为这些打印根本没有发送过文件。它们仍会带着名称和时间归档,并且可以在「编辑归档」里手动填写已用耗材。要获得完整归档,请从 Bambuddy 或你的切片软件启动打印。',
       bodyInternalHistory: '这些打印来自打印机自己的文件库 — 从它的屏幕重新打印、从 Handy 启动,或是先前发送、稍后才打印的文件。Bambuddy 通过 FTP 读取打印文件,而 FTP 只提供存储卡或 U 盘,打印机却把这个文件库放在 FTP 够不到的区域,所以没有 3MF 可读。切片软件的任何设置都改变不了这一点,因为这些打印根本没有发送过文件。它们仍会带着名称和时间归档,并且可以在「编辑归档」里手动填写已用耗材。要获得完整归档,请从 Bambuddy 或你的切片软件启动打印。',
+      titleFtpsCooloff: '最近有些打印无法归档 — 打印机拒绝了文件连接',
+      bodyFtpsCooloff: 'Bambuddy 打开了打印机的文件传输端口 (FTPS 990),而打印机回应的内容并不是 TLS,因此无法从它读取任何东西。这些打印仍会带着名称和时间归档,只是没有缩略图和切片元数据。这不是切片软件的设置,也不是你改动了什么 —— 相同型号、相同固件在别的安装上运行正常,受影响的打印机通常过一阵子会自行恢复。出现这种失败后,Bambuddy 会暂停对该打印机的传输五分钟,暂停结束后再回来取文件,所以短暂的一次会自行补全;卡片仍然是空的,说明拒绝持续得比重试更久。触发原因目前尚不清楚。如果反复出现,请在系统页面打开调试日志,并把支持包附在你的报告里。',
       dismissLabel: '关闭此通知',
       dismissLabel: '关闭此通知',
     },
     },
     searchPlaceholder: '搜索归档...',
     searchPlaceholder: '搜索归档...',

+ 2 - 0
frontend/src/i18n/locales/zh-TW.ts

@@ -906,6 +906,8 @@ export default {
       bodyNoExternalStorage: '印表機的插槽中未偵測到記憶卡或隨身碟,切片檔案無處存放,Bambuddy 也無從讀取。插入一個,下次列印就會完整歸檔。',
       bodyNoExternalStorage: '印表機的插槽中未偵測到記憶卡或隨身碟,切片檔案無處存放,Bambuddy 也無從讀取。插入一個,下次列印就會完整歸檔。',
       titleInternalHistory: '最近有些列印是從印表機裡既有的檔案啟動的',
       titleInternalHistory: '最近有些列印是從印表機裡既有的檔案啟動的',
       bodyInternalHistory: '這些列印來自印表機自己的檔案庫 — 從它的螢幕重新列印、從 Handy 啟動,或是先前傳送、稍後才列印的檔案。Bambuddy 透過 FTP 讀取列印檔案,而 FTP 只提供記憶卡或隨身碟,印表機卻把這個檔案庫放在 FTP 搆不到的區域,因此沒有 3MF 可讀。切片軟體的任何設定都改變不了這一點,因為這些列印根本沒有傳送過檔案。它們仍會帶著名稱與時間歸檔,並且可以在「編輯歸檔」中手動填入已用耗材。要獲得完整歸檔,請從 Bambuddy 或你的切片軟體啟動列印。',
       bodyInternalHistory: '這些列印來自印表機自己的檔案庫 — 從它的螢幕重新列印、從 Handy 啟動,或是先前傳送、稍後才列印的檔案。Bambuddy 透過 FTP 讀取列印檔案,而 FTP 只提供記憶卡或隨身碟,印表機卻把這個檔案庫放在 FTP 搆不到的區域,因此沒有 3MF 可讀。切片軟體的任何設定都改變不了這一點,因為這些列印根本沒有傳送過檔案。它們仍會帶著名稱與時間歸檔,並且可以在「編輯歸檔」中手動填入已用耗材。要獲得完整歸檔,請從 Bambuddy 或你的切片軟體啟動列印。',
+      titleFtpsCooloff: '最近有些列印無法歸檔 — 印表機拒絕了檔案連線',
+      bodyFtpsCooloff: 'Bambuddy 開啟了印表機的檔案傳輸連接埠 (FTPS 990),而印表機回應的內容並不是 TLS,因此無法從它讀取任何東西。這些列印仍會帶著名稱和時間歸檔,只是沒有縮圖和切片中繼資料。這不是切片軟體的設定,也不是你改動了什麼 —— 相同型號、相同韌體在其他安裝上運作正常,受影響的印表機通常過一陣子會自行恢復。出現這種失敗後,Bambuddy 會暫停對該印表機的傳輸五分鐘,暫停結束後再回來取檔案,所以短暫的一次會自行補齊;卡片仍然是空的,表示拒絕持續得比重試更久。觸發原因目前尚不清楚。如果反覆出現,請在系統頁面開啟除錯記錄,並把支援套件附在你的報告裡。',
       dismissLabel: '關閉此通知',
       dismissLabel: '關閉此通知',
     },
     },
     searchPlaceholder: '搜尋歸檔...',
     searchPlaceholder: '搜尋歸檔...',

+ 26 - 19
frontend/src/pages/ArchivesPage.tsx

@@ -2867,29 +2867,35 @@ export function ArchivesPage() {
     setNo3MFWarningDismissed(true);
     setNo3MFWarningDismissed(true);
   };
   };
   // Why the 3MF was missing decides what to tell the user, and the original
   // Why the 3MF was missing decides what to tell the user, and the original
-  // single wording is wrong for three of the four cases: it sends H2-series and
+  // single wording is wrong for four of the five cases: it sends H2-series and
   // P2S owners to switch on a setting that is already on and would not have
   // P2S owners to switch on a setting that is already on and would not have
   // helped, it blames the slicer when the real answer is an empty card slot
   // helped, it blames the slicer when the real answer is an empty card slot
-  // (#2780), and it blames a slicer that was never involved when the print was
-  // started from a file already on the printer (#1820). An unknown/absent
-  // reason keeps the original text.
+  // (#2780), it blames a slicer that was never involved when the print was
+  // started from a file already on the printer (#1820), and it blames the
+  // slicer again when the printer's own file service refused the TLS handshake
+  // and no lookup was ever attempted (#2957, surfaced by #2780). An
+  // unknown/absent reason keeps the original text.
   const no3MFVariant =
   const no3MFVariant =
-    no3MFWarning?.reason === 'internal_storage'
-      ? 'InternalStorage'
-      : no3MFWarning?.reason === 'no_external_storage'
-        ? 'NoExternalStorage'
-        : no3MFWarning?.reason === 'internal_history'
-          ? 'InternalHistory'
-          : '';
+    no3MFWarning?.reason === 'ftps_cooloff'
+      ? 'FtpsCooloff'
+      : no3MFWarning?.reason === 'internal_storage'
+        ? 'InternalStorage'
+        : no3MFWarning?.reason === 'no_external_storage'
+          ? 'NoExternalStorage'
+          : no3MFWarning?.reason === 'internal_history'
+            ? 'InternalHistory'
+            : '';
   // Nothing to link for the empty-slot case — "put a card in" is the whole fix.
   // Nothing to link for the empty-slot case — "put a card in" is the whole fix.
   const no3MFDocsHref =
   const no3MFDocsHref =
-    no3MFWarning?.reason === 'internal_storage'
-      ? 'https://wiki.bambuddy.cool/reference/troubleshooting/#archive-card-has-only-a-name'
-      : no3MFWarning?.reason === 'no_external_storage'
-        ? null
-        : no3MFWarning?.reason === 'internal_history'
-          ? 'https://wiki.bambuddy.cool/reference/troubleshooting/#print-started-on-the-printer-has-no-thumbnail'
-          : 'https://wiki.bambuddy.cool/getting-started/#step-4-enable-store-sent-files-on-external-storage';
+    no3MFWarning?.reason === 'ftps_cooloff'
+      ? 'https://wiki.bambuddy.cool/reference/troubleshooting/#ftps-tls-failure'
+      : no3MFWarning?.reason === 'internal_storage'
+        ? 'https://wiki.bambuddy.cool/reference/troubleshooting/#archive-card-has-only-a-name'
+        : no3MFWarning?.reason === 'no_external_storage'
+          ? null
+          : no3MFWarning?.reason === 'internal_history'
+            ? 'https://wiki.bambuddy.cool/reference/troubleshooting/#print-started-on-the-printer-has-no-thumbnail'
+            : 'https://wiki.bambuddy.cool/getting-started/#step-4-enable-store-sent-files-on-external-storage';
   const [isSelectionMode, setIsSelectionMode] = useState(false);
   const [isSelectionMode, setIsSelectionMode] = useState(false);
   const [showBulkDeleteConfirm, setShowBulkDeleteConfirm] = useState(false);
   const [showBulkDeleteConfirm, setShowBulkDeleteConfirm] = useState(false);
   const [showBatchTag, setShowBatchTag] = useState(false);
   const [showBatchTag, setShowBatchTag] = useState(false);
@@ -3720,7 +3726,8 @@ export function ArchivesPage() {
                   >
                   >
                     {t(
                     {t(
                       no3MFWarning?.reason === 'internal_storage' ||
                       no3MFWarning?.reason === 'internal_storage' ||
-                        no3MFWarning?.reason === 'internal_history'
+                        no3MFWarning?.reason === 'internal_history' ||
+                        no3MFWarning?.reason === 'ftps_cooloff'
                         ? 'archives.no3mfBanner.docsLinkInternalStorage'
                         ? 'archives.no3mfBanner.docsLinkInternalStorage'
                         : 'archives.no3mfBanner.docsLink',
                         : 'archives.no3mfBanner.docsLink',
                     )}
                     )}

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
static/assets/index-DOPutkkr.js


+ 1 - 1
static/index.html

@@ -26,7 +26,7 @@
 
 
     <!-- Splash screens for iOS -->
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-BMnY4ID9.js"></script>
+    <script type="module" crossorigin src="/assets/index-DOPutkkr.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-ChscM3lF.css">
     <link rel="stylesheet" crossorigin href="/assets/index-ChscM3lF.css">
   </head>
   </head>
   <body>
   <body>

Неке датотеке нису приказане због велике количине промена