Files
siftlode/frontend/src/i18n/locales/en/header.json
T
peter bc9e34d0ae fix(auth): close the three leftovers E9.5 logged but kept out of its diff
DX-17, three one-liners the epic's canonical sweep did not reach:

`routes/setup.py::setup_admin` still resolved the wizard's admin by
literal `User.email ==`. The wizard can be re-run, and E9.5's premise is
that two spellings of one Gmail mailbox are one person — so a second run
under the other spelling would have created exactly the duplicate admin
row the epic exists to prevent.

`routes/admin.py::_decide` hand-rolled `db.get` + 404 where the file's
newer endpoints use `get_or_404`. There were TWO such sites, not the one
the review named; both are converted, per the house rule that a
principle gets fixed everywhere in one sweep.

`useVerifyEntry`'s `hashchange` listener recognised `#verify=` but not
`#reset=`, so pasting a reset link into a tab already running the app
was silently ignored — the same silence that made the verify half a bug.
It now notices, and says out loud that reset links need a signed-out
window; the fragment is still deliberately left in the address bar
(review round 4), so signing out from that tab recovers it.

DX-16: `.catch(() => setOutcome("invalid"))` could not tell a spent
token from a 502 mid-deploy or a dropped connection, and by then the
fragment is cleared — so a network blip was reported as "that link is no
longer valid", pushing the user to request a fresh one on the strength
of a false statement. Only a 400 carrying {code:"verify"} is the
server's verdict now; everything else gets its own outcome, with no
resend CTA, because the token is untouched and retrying it works. The
rule was already written one file away for the reset-link probe: "a
network blip must never be cached as 'this link is dead'".

Two existing tests asserted the old conflation by rejecting with a bare
Error("400"); they now reject with the real HttpError. The errors are
built inside the rejection, not hoisted: mountAt calls vi.resetModules(),
so an HttpError imported earlier is a different class identity and
`instanceof` would quietly miss.

Gate: vitest 671 -> 676, pytest 924 -> 925.
2026-09-05 01:35:09 +02:00

69 lines
2.4 KiB
JSON

{
"feed": "Feed",
"searchPlaceholder": "Search your subscriptions…",
"clearSearch": "Clear search",
"searchYoutube": "Search YouTube",
"searchYoutubeTip": "Search live on YouTube for this term (uses shared API quota). You can also press Enter.",
"go": "Go",
"goTip": "Search (or press Enter)",
"prevModule": "Previous module",
"nextModule": "Next module",
"channelManager": "Channel manager",
"usageStats": "Usage & stats",
"scheduler": "Scheduler",
"configuration": "Configuration",
"users": "Users",
"scope": {
"label": "Feed source",
"my": "Mine",
"myTip": "Only videos from your own subscriptions",
"all": "Library",
"allTip": "Every video in the shared catalog"
},
"account": {
"admin": "Admin",
"feed": "Feed",
"channels": "Channels",
"playlists": "Playlists",
"stats": "Stats",
"scheduler": "Scheduler",
"config": "Configuration",
"users": "Users",
"settings": "Settings",
"about": "About",
"signOut": "Sign out",
"addAccount": "Add another account",
"switchTo": "Switch to {{name}}",
"audit": "Audit log",
"googleAddress": "Google account: {{email}}"
},
"sync": {
"yours": "yours",
"total": "total",
"countTooltip": "Your subscriptions vs. the whole shared catalog.",
"paused": "paused",
"syncing": "{{count}} syncing",
"backfillingHistory": "fetching history",
"working": "syncing…",
"recentQueued": "{{count}} queued",
"allSynced": "all synced",
"withoutFullHistory": "{{count}} without full history",
"fullHistoryTooltip": "Recent uploads only — click to fetch the rest.",
"pause": "Pause sync",
"resume": "Resume sync"
},
"banner": {
"updated": "Updated to v{{version}} — see what's changed.",
"releaseNotes": "Release notes",
"dismiss": "Dismiss"
},
"verify": {
"confirmed": "Email address confirmed.",
"confirmedNamed": "Email address confirmed — {{email}}.",
"invalid": "That verification link is no longer valid — it has expired or was already used.",
"unreachable": "Couldn't reach the server to confirm that link, so it hasn't been used up. Try opening it again in a moment.",
"resetSignedOut": "Password-reset links open in a signed-out window. Sign out here, or open the link in a private window, and it will pick up where it left off.",
"reset": "The password this account registered with was cleared for security; set a new one before signing in."
}
}