v0.254.0 — the saved notes follow the language, and the switch becomes a globe (R-557 slice 2 release C; SLICE 2 CLOSED)
gates / gates (push) Successful in 23s
gates / gates (push) Successful in 23s
The notes a background run SAVES — last night's backup line, the last error, the proof result, the restore outcome — are written in the BOX's language at the moment they are written. A household that switches sees the previous run's note in the old language until the next run rewrites it: the operator's §16 option 1, stated rather than hidden. EndRestoreOp no longer receives a Hungarian literal from anywhere. The language switch is a globe. Two text links wrapped in the sidebar footer and asked the reader to recognise "Magyar"/"English" as links; a globe is the one symbol every web user already reads as "language", so nobody has to read Hungarian to escape Hungarian. It is <details>/<summary> — a menu with no script, drawn inline because the icon sprite lives only in layout.html and the visitor pages have their own shell. Those visitor pages get the same globe, and a visitor's choice stays theirs: a display-only felhom_lang cookie that langFor reads ONLY when there is no session. A signed-in household can never inherit a language a previous visitor picked in the same browser. POST /lang is CSRF-exempt for a narrow reason written at the exemption — its only achievable effect is the language of the page the victim's own browser shows them — and safeBackPath refuses //evil.example as well as https://, because "starts with /" alone is not the test. §16 taken: a successful claim carries the cookie into the household's setting. TWO PARITY EXCEPTIONS, MEASURED: 106 fixtures compared with a real diff — exactly two change shapes (the dashboard footer, the globe in the shells) and 5 byte-identical, which are the three pages that must not change. I INTRODUCED A DEADLOCK AND THE SUITE CAUGHT IT BY HANGING. UpdateOffboxStatus holds the settings write lock while running its callback; boxLang() wants the read lock; sync.RWMutex is not reentrant. On a real box an off-site run would have hung forever HOLDING the settings lock. Fixed by resolving the language before the callback, and guarded by a test that names the file and line in a second instead of hanging for 25 minutes. MinAgent: 0.131.0 (unchanged). No hub release needed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -2196,5 +2196,76 @@
|
||||
"err.integrations.onlyoffice_no_subdomain": "the OnlyOffice subdomain is not known",
|
||||
"err.integrations.occ_failed": "the occ command failed (%s): %s (output: %s)",
|
||||
"err.integrations.occ_disable_failed": "occ app:disable failed: %s (output: %s)",
|
||||
"err.notify.hub_error": "hub error (%d): %s"
|
||||
"err.notify.hub_error": "hub error (%d): %s",
|
||||
"note.offsite.fail_quota": "The remote backup did not fit inside its storage limit",
|
||||
"note.offsite.fail_orphaned": "The remote store was made with an earlier key that is no longer available",
|
||||
"note.offsite.fail_no_repo": "There is no backup store at the remote target",
|
||||
"note.offsite.fail_no_units": "There was nothing to back up: none of the selected apps has a backup",
|
||||
"note.offsite.fail_transport": "The remote store cannot be reached (network or sign-in)",
|
||||
"note.offsite.fail_unknown": "The remote backup failed for an unknown reason",
|
||||
"note.offsite.fail_head": "The remote backup failed",
|
||||
"note.offsite.whole_unit_gap": "(the whole app — it has no local backup unit)",
|
||||
"note.offsite.no_local_unit": "These apps did NOT go into the remote backup, because they have no local backup unit yet: %s. The next backup usually makes one — if they are still listed after the second run, tell your operator.",
|
||||
"note.offsite.not_installed": "These apps are selected for remote backup but are not installed, so they cannot be backed up: %s. If you no longer need them, clear their selection on the Remote backup page.",
|
||||
"note.offsite.quota_partial": "Warning: because of the storage limit, %d apps got only a settings and database backup: %s.",
|
||||
"note.offsite.quota_usage": "The remote backup uses %d%% of its limit (%d/%d GB).",
|
||||
"note.tier2.reason_manual": "your own choice",
|
||||
"note.tier2.reason_other_drive": "another data drive",
|
||||
"note.tier2.label_internal_ssd": "internal SSD (system)",
|
||||
"note.tier2.reason_no_second": "no second data drive — only the database and settings fit on the internal SSD; large files need a second drive",
|
||||
"note.tier2.same_disk": "the target you picked is on the same physical disk",
|
||||
"note.tier2.ssd_partial": "Only the settings, the database and the required data fit on the internal SSD — the optional content was not copied.",
|
||||
"note.tier2.no_space_ssd": "not enough space on the internal SSD — backing large files off the drive needs a second drive (or remote storage)",
|
||||
"note.tier2.no_other_drive": "there is no second physical drive — the second backup needs one",
|
||||
"note.tier2.unit_preserved": "The data package on the main drive was incomplete, so the complete one already in the second copy was kept. The copy's data package is therefore older than this backup.",
|
||||
"note.restore.interrupted": "The restore was interrupted (the box restarted) — start it again.",
|
||||
"note.undo.present": "the earlier state is backed up: %s",
|
||||
"note.undo.partial": "the earlier state is only PARTLY backed up — present: %s; MISSING: %s",
|
||||
"note.undo.absent": "the backup of the earlier state is NOT where it should be (%s)",
|
||||
"note.undo.none": "no restorable copy of the earlier state was made",
|
||||
"note.reconstitute.copy_latest": "latest",
|
||||
"note.reconstitute.held": "restoring the data of %s stopped at %s, and the earlier state could not be put back either. The app stays stopped, for safety, so your data cannot be damaged further. Get in touch with us",
|
||||
"layout.nyelv": "Language",
|
||||
"note.restore.failed": "The restore failed: %s",
|
||||
"note.restore.full_failed": "The full restore failed: %s",
|
||||
"note.restore.recover_failed": "The recovery failed: %s",
|
||||
"note.restore.shares_failed": "Restoring the shares failed: %s",
|
||||
"note.restore.shares_recover_failed": "Recovering the shares failed: %s",
|
||||
"note.restore.unit_failed": "Restore failed: %s",
|
||||
"note.restore.file_failed": "File restore failed: %s",
|
||||
"note.restore.full_unit_failed": "Full restore failed: %s",
|
||||
"note.restore.recovered_files": "The missing files of %s are back among your live data.",
|
||||
"note.restore.shares_prepared": "The shares are restored — you can now put them back among your live data.",
|
||||
"note.restore.at_scratch": " into the check folder",
|
||||
"note.restore.at_scratch_named": " into the check folder: %s",
|
||||
"note.restore.scratch_full": "The full backup of %s is restored%s — together with your own files. Your existing data is unchanged.",
|
||||
"note.restore.scratch_state": "The settings and the database of %s are restored%s. Your own files (documents, pictures, uploads) did NOT come back — this check restore brings back only the app's settings and database. If you need your files, start “Prepare a full restore” on this page. Your existing data is unchanged.",
|
||||
"note.restore.files_count": "%d files",
|
||||
"note.restore.and_volumes": " and %d data volumes",
|
||||
"note.restore.and_database": " and the database",
|
||||
"note.restore.volumes_count": "%d data volumes",
|
||||
"note.restore.the_database": "the database",
|
||||
"note.restore.dumps_at": " (backup: %s)",
|
||||
"note.restore.reconstituted": "%s: %s restored%s — the app has restarted.",
|
||||
"note.restore.no_db_in_backup": " WARNING: this app HAS a database, but the backup held no database dump, so the database did NOT come back. The state from before the restore is backed up: %s",
|
||||
"note.restore.no_db_at_all": " This app has no database.",
|
||||
"note.restore.all_files_present": "Every file that was checked is in place.",
|
||||
"note.restore.files_from_second": "%s: %d files restored from the second copy.",
|
||||
"note.restore.scratch_incomplete": "The restore copy is incomplete — the last download did not finish. Start “Prepare a full restore” again.",
|
||||
"note.unit_restore_data": "%s: %s restored — the app has restarted.",
|
||||
"note.unit_restore_settings_only": "%s: the settings are back — the app has restarted. WARNING: this backup held only the settings, no data. The app's data did NOT come back from this backup.",
|
||||
"note.unit_restore_counts_unknown": "The restore of %s ran — the app has restarted. This backup has no backup unit, so we cannot tell you what came back from it. Check inside the app that your data is there.",
|
||||
"note.unit_restore_none_returned": "%s: WARNING — the backup lists %d data volumes and %d database dumps, but none of them came back. Your data is unchanged. Ask for help before you try again.",
|
||||
"note.tier2_no_coverage": "This app's data cannot be restored from this copy — the app was not stopped. Use the Start restore button on the Backup → Restore page.",
|
||||
"note.tier2_unit_available": "This app's data is not in files but in the app's own database and volumes — the app was not stopped. You can bring those back from the same copy with the “Full restore from the copy” button beside this one. Careful: that action OVERWRITES the current data, while this button only fills in the missing files.",
|
||||
"note.tier2_unit_not_covered": "The app's database and internal volumes are not part of this restore.",
|
||||
"note.tier2_unit_restore_source": "The restore came from the copy on the second drive (%s).",
|
||||
"note.tier2_unit_restore_source_unproven": "The restore came from the copy on the second drive (%s — that is the time of the last backup ATTEMPT; we cannot prove it succeeded).",
|
||||
"note.tier2_unit_action_label": "Full restore from the copy",
|
||||
"note.tier2_unit_confirm_base": "This action OVERWRITES the app's current data – its database and its internal volumes too – with the copy on the second drive. Anything made since the copy is lost.",
|
||||
"note.tier2_unit_confirm_date_fmt": " The copy is from: %s.",
|
||||
"note.tier2_unit_confirm_date_unproven_fmt": " The copy is from: %s – that is the time of the last backup attempt; we cannot prove it succeeded.",
|
||||
"note.tier2_unit_confirm_contrast": " The “Restore files” button beside it only fills in the missing files and overwrites nothing. The app stops while either one runs.",
|
||||
"note.tier2_unit_stale_clause": " WARNING: this copy's data package is older than the latest backup — the package on the main drive was incomplete, so the complete one was kept. The restore uses the package named above.",
|
||||
"note.tier2_unit_stale_notice_fmt": "The copy's data package is older than the latest backup (%s): the package on the main drive was incomplete, so the complete one already there was kept."
|
||||
}
|
||||
|
||||
@@ -2185,5 +2185,76 @@
|
||||
"err.integrations.onlyoffice_no_subdomain": "OnlyOffice aldomain nem ismert",
|
||||
"err.integrations.occ_failed": "occ parancs sikertelen (%s): %s (kimenet: %s)",
|
||||
"err.integrations.occ_disable_failed": "occ app:disable sikertelen: %s (kimenet: %s)",
|
||||
"err.notify.hub_error": "hub hiba (%d): %s"
|
||||
"err.notify.hub_error": "hub hiba (%d): %s",
|
||||
"note.offsite.fail_quota": "A távoli mentés nem fért el a tárhelykereten belül",
|
||||
"note.offsite.fail_orphaned": "A távoli tárhely egy korábbi, már nem elérhető kulccsal készült",
|
||||
"note.offsite.fail_no_repo": "A távoli tárhelyen nincs mentési adattár",
|
||||
"note.offsite.fail_no_units": "Nem volt mit menteni: egyetlen kijelölt alkalmazásnak sem található mentése",
|
||||
"note.offsite.fail_transport": "A távoli tárhely nem érhető el (hálózat vagy bejelentkezés)",
|
||||
"note.offsite.fail_unknown": "A távoli mentés ismeretlen okból nem sikerült",
|
||||
"note.offsite.fail_head": "A távoli mentés nem sikerült",
|
||||
"note.offsite.whole_unit_gap": "(a teljes alkalmazás — nincs helyi mentési egysége)",
|
||||
"note.offsite.no_local_unit": "Ezek az alkalmazások NEM kerültek be a távoli mentésbe, mert még nincs helyi mentési egységük: %s. A következő mentés általában már elkészíti — ha a második futás után is itt szerepelnek, szólj az üzemeltetőnek.",
|
||||
"note.offsite.not_installed": "Ezek az alkalmazások ki vannak jelölve távoli mentésre, de nincsenek telepítve, ezért nem menthetők: %s. Ha már nincs rájuk szükséged, vedd ki a kijelölésüket a Távoli mentés oldalon.",
|
||||
"note.offsite.quota_partial": "Figyelmeztetés: a tárhelykeret miatt %d alkalmazásnál csak konfiguráció- és adatbázis-mentés készült: %s.",
|
||||
"note.offsite.quota_usage": "A távoli mentés a keret %d%%-át használja (%d/%d GB).",
|
||||
"note.tier2.reason_manual": "kézi választás",
|
||||
"note.tier2.reason_other_drive": "másik adatmeghajtó",
|
||||
"note.tier2.label_internal_ssd": "belső SSD (rendszer)",
|
||||
"note.tier2.reason_no_second": "nincs 2. adatmeghajtó — csak az adatbázis/konfiguráció fér a belső SSD-re; a nagy fájlokhoz 2. meghajtó kell",
|
||||
"note.tier2.same_disk": "a kiválasztott cél ugyanazon a fizikai lemezen van",
|
||||
"note.tier2.ssd_partial": "A belső SSD-n csak a konfiguráció, adatbázis és a kötelező adatok férnek el — a választható tartalom nem került másolásra.",
|
||||
"note.tier2.no_space_ssd": "nincs elég hely a belső SSD-n — a nagy fájlok off-drive mentéséhez 2. meghajtó (vagy távoli tárhely) szükséges",
|
||||
"note.tier2.no_other_drive": "nincs másik fizikai meghajtó — a 2. mentéshez 2. meghajtó szükséges",
|
||||
"note.tier2.unit_preserved": "A fő meghajtón lévő adatcsomag hiányos volt, ezért a másodlagos másolatban meglévő, teljes csomagot megőriztük. A másolat adatcsomagja ezért régebbi, mint ez a mentés.",
|
||||
"note.restore.interrupted": "A visszaállítás megszakadt (a doboz újraindult) — indítsd el újra.",
|
||||
"note.undo.present": "a korábbi állapot mentése megvan: %s",
|
||||
"note.undo.partial": "a korábbi állapot mentése RÉSZBEN van meg — megvan: %s; HIÁNYZIK: %s",
|
||||
"note.undo.absent": "a korábbi állapot mentését NEM találjuk a helyén (%s)",
|
||||
"note.undo.none": "a korábbi állapotról nem készült menthető másolat",
|
||||
"note.reconstitute.copy_latest": "legutóbbi",
|
||||
"note.reconstitute.held": "a(z) %s adatainak visszaállítása %s-kor megszakadt, és a korábbi állapotot sem sikerült visszatölteni. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek tovább. Vedd fel velünk a kapcsolatot",
|
||||
"layout.nyelv": "Nyelv",
|
||||
"note.restore.failed": "A visszaállítás sikertelen: %s",
|
||||
"note.restore.full_failed": "A teljes visszaállítás sikertelen: %s",
|
||||
"note.restore.recover_failed": "A helyreállítás sikertelen: %s",
|
||||
"note.restore.shares_failed": "A megosztások visszaállítása sikertelen: %s",
|
||||
"note.restore.shares_recover_failed": "A megosztások helyreállítása sikertelen: %s",
|
||||
"note.restore.unit_failed": "Visszaállítás sikertelen: %s",
|
||||
"note.restore.file_failed": "Fájl-visszaállítás sikertelen: %s",
|
||||
"note.restore.full_unit_failed": "Teljes visszaállítás sikertelen: %s",
|
||||
"note.restore.recovered_files": "A(z) %s hiányzó fájljai helyreállítva az élő adatok közé.",
|
||||
"note.restore.shares_prepared": "A megosztások visszaállítása elkészült — most helyreállíthatod az élő adatok közé.",
|
||||
"note.restore.at_scratch": " ellenőrző mappába",
|
||||
"note.restore.at_scratch_named": " ellenőrző mappába: %s",
|
||||
"note.restore.scratch_full": "A(z) %s teljes mentése visszaállítva%s — a saját fájljaiddal együtt. A meglévő adatok változatlanok.",
|
||||
"note.restore.scratch_state": "A(z) %s beállításai és adatbázisa visszaállítva%s. A saját fájljaid (dokumentumok, képek, feltöltések) NEM kerültek vissza — ez az ellenőrző visszaállítás csak az alkalmazás beállításait és adatbázisát hozza vissza. Ha a fájljaidra van szükséged, indítsd el a „Teljes visszaállítás előkészítése” lépést ezen az oldalon. A meglévő adatok változatlanok.",
|
||||
"note.restore.files_count": "%d fájl",
|
||||
"note.restore.and_volumes": " és %d adatkötet",
|
||||
"note.restore.and_database": " és az adatbázis",
|
||||
"note.restore.volumes_count": "%d adatkötet",
|
||||
"note.restore.the_database": "az adatbázis",
|
||||
"note.restore.dumps_at": " (mentés: %s)",
|
||||
"note.restore.reconstituted": "A(z) %s: %s visszaállítva%s — az alkalmazás újraindult.",
|
||||
"note.restore.no_db_in_backup": " FIGYELEM: ennek az alkalmazásnak VAN adatbázisa, de a mentés nem tartalmazott adatbázis-mentést, ezért az adatbázis NEM állt vissza. A visszaállítás előtti állapot mentése megvan: %s",
|
||||
"note.restore.no_db_at_all": " Ennek az alkalmazásnak nincs adatbázisa.",
|
||||
"note.restore.all_files_present": "Minden vizsgált fájl megvan a helyén.",
|
||||
"note.restore.files_from_second": "%s: %d fájl visszaállítva a másodlagos másolatból.",
|
||||
"note.restore.scratch_incomplete": "A visszaállítási másolat nem teljes — a legutóbbi letöltés nem fejeződött be. Indítsd újra a teljes visszaállítás előkészítését.",
|
||||
"note.unit_restore_data": "A(z) %s: %s visszaállítva — az alkalmazás újraindult.",
|
||||
"note.unit_restore_settings_only": "A(z) %s: a beállítások visszaálltak — az alkalmazás újraindult. FIGYELEM: ez a mentés csak a beállításokat tartalmazta, adatot nem. Az alkalmazás adatai NEM álltak vissza ebből a mentésből.",
|
||||
"note.unit_restore_counts_unknown": "A(z) %s visszaállítása lefutott — az alkalmazás újraindult. Ehhez a mentéshez nem tartozik mentési egység, ezért nem tudjuk megmondani, mi állt vissza belőle. Ellenőrizd az alkalmazásban, hogy megvannak-e az adataid.",
|
||||
"note.unit_restore_none_returned": "A(z) %s: FIGYELEM — a mentés %d adatkötetet és %d adatbázis-mentést sorol fel, de egyik sem állt vissza. Az adataid változatlanok maradtak. Kérj segítséget, mielőtt újra próbálod.",
|
||||
"note.tier2_no_coverage": "Ennek az alkalmazásnak az adatai nem ebből a másolatból állíthatók vissza — az alkalmazás nem állt le. Használd a Visszaállítás indítása gombot a Biztonsági mentés → Visszaállítás oldalon.",
|
||||
"note.tier2_unit_available": "Ennek az alkalmazásnak az adatai nem fájlokban, hanem az alkalmazás saját adatbázisában és köteteiben vannak — az alkalmazás nem állt le. Ezeket a mellette lévő „Teljes visszaállítás a másolatból” gombbal tudod visszahozni ugyanerről a másolatról. Figyelem: az a művelet FELÜLÍRJA a jelenlegi adatokat, míg ez a gomb csak a hiányzó fájlokat pótolja.",
|
||||
"note.tier2_unit_not_covered": "Az alkalmazás adatbázisa és belső kötetei nem tartoznak ebbe a visszaállításba.",
|
||||
"note.tier2_unit_restore_source": "A visszaállítás forrása a második meghajtón lévő másolat volt (%s).",
|
||||
"note.tier2_unit_restore_source_unproven": "A visszaállítás forrása a második meghajtón lévő másolat volt (%s — ez az utolsó mentési kísérlet ideje; azt nem tudjuk igazolni, hogy az sikeres volt).",
|
||||
"note.tier2_unit_action_label": "Teljes visszaállítás a másolatból",
|
||||
"note.tier2_unit_confirm_base": "Ez a művelet FELÜLÍRJA az alkalmazás jelenlegi adatait – az adatbázisát és a belső köteteit is – a második meghajtón lévő másolattal. Ami a másolat óta keletkezett, elveszik.",
|
||||
"note.tier2_unit_confirm_date_fmt": " A másolat kelte: %s.",
|
||||
"note.tier2_unit_confirm_date_unproven_fmt": " A másolat kelte: %s – ez az utolsó mentési kísérlet ideje, azt nem tudjuk igazolni, hogy sikeres volt.",
|
||||
"note.tier2_unit_confirm_contrast": " A mellette lévő „Fájlok visszaállítása” ezzel szemben csak a hiányzó fájlokat pótolja, és semmit nem ír felül. Az alkalmazás a művelet idejére leáll.",
|
||||
"note.tier2_unit_stale_clause": " FIGYELEM: ennek a másolatnak az adatcsomagja régebbi, mint a legutóbbi mentés — a fő meghajtón lévő csomag hiányos volt, ezért a meglévő, teljes másolatot megőriztük. A visszaállítás a fent megadott csomagot használja.",
|
||||
"note.tier2_unit_stale_notice_fmt": "A másolat adatcsomagja régebbi, mint a legutóbbi mentés (%s): a fő meghajtón lévő csomag hiányos volt, ezért a meglévő, teljes másolatot megőriztük."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user