Files
siftlode/frontend/src/i18n/locales/en/config.json
T
peter 9cf177b198 feat(diagnostics): send a bug report to a private Gitea issue tracker (E16 S4)
- admin config group "Bug reports": Gitea address, repository, token (secret),
  and "Check the connection" — the repository must answer, take issues and
  be PRIVATE (a report carries its reporter's log); checked on every send too
- POST /api/debug-sessions/{id}/issue sends the SAVED draft: create the issue,
  upload each file on its own request (the measured API), then show the
  screenshots inline; progress is kept in the draft, so a send that stops
  half-way keeps its issue and the retry sends only what is missing; 5 new
  issues an hour per user; audited as issue_create
- the composer: Create issue (only where a tracker is set up, naming the
  repository), a partial-send banner with retry, and a Preview — the tracker's
  own rendering in a sandboxed frame, or the zip's markdown without one
- the recorder's refusals answer in the localized family (debug_session_*,
  screenshot_*, issue(s)_*), not bare codes the UI could only call generic
- a tracker refusal logs the status only: its message can quote the title back
2026-09-19 22:48:20 +02:00

314 lines
15 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"intro": "Operational settings stored in the database — these override the file/env defaults and take effect without a redeploy. Leave a field empty (or reset it) to fall back to the default.",
"loading": "Loading configuration…",
"groups": {
"access": "Access",
"email": "Email / SMTP",
"youtube": "YouTube API",
"google": "Google sign-in",
"quota": "Quota",
"backfill": "Backfill",
"shorts": "Shorts probe",
"batch": "Batch sizes",
"maintenance": "Maintenance",
"explore": "Channel explore",
"downloads": "Downloads",
"plex": "Plex",
"tmdb": "TMDB",
"audit": "Audit log",
"diagnostics": "Diagnostics",
"issues": "Bug reports"
},
"fields": {
"smtp_host": {
"label": "SMTP host",
"hint": "e.g. smtp.gmail.com"
},
"smtp_port": {
"label": "SMTP port",
"hint": "Usually 587 (STARTTLS)."
},
"smtp_user": {
"label": "SMTP username",
"hint": "The sending account / login."
},
"smtp_from": {
"label": "From address",
"hint": "e.g. Siftlode <addr@gmail.com>. Defaults to the username."
},
"smtp_password": {
"label": "SMTP password",
"hint": "App password. Stored encrypted; write-only — it's never shown back."
},
"quota_daily_budget": {
"label": "Daily quota budget",
"hint": "Total YouTube Data API units to spend per day (free tier is 10,000). Default 9000 leaves headroom."
},
"backfill_quota_reserve": {
"label": "Backfill quota reserve",
"hint": "Units kept in reserve so scheduled backfill never starves interactive syncs / enrichment."
},
"search_daily_limit_per_user": {
"label": "Live search — daily limit per user",
"hint": "Max live YouTube searches per user per day. With the API source each search costs 100 units (so the shared budget affords only ~80-90/day total); with the scrape source it's a pure anti-abuse limit. Set 0 to disable live search."
},
"search_source": {
"label": "Live search source",
"hint": "Where live YouTube search results come from. \"Website\" reads YouTube's own search endpoint and spends no API quota (recommended). \"Official API\" uses search.list (100 units/page) — switch to it if the website source ever breaks or is blocked."
},
"backfill_recent_max_videos": {
"label": "Recent backfill — max videos",
"hint": "Newest videos fetched per channel on the first pass."
},
"backfill_recent_max_days": {
"label": "Recent backfill — max age (days)",
"hint": "How far back the first pass reaches per channel."
},
"rss_fallback_hours": {
"label": "Feed fallback after (hours)",
"hint": "When a channel's RSS feed has not answered for this many hours, its newest uploads are read through the API instead (1 unit), at most once per this many hours. 0 turns it off."
},
"shorts_probe_max_seconds": {
"label": "Shorts probe — max duration (s)",
"hint": "Only videos at or below this length are probed as possible Shorts."
},
"shorts_probe_batch": {
"label": "Shorts probe — batch size",
"hint": "How many videos to classify per run."
},
"enrich_batch_size": {
"label": "Enrichment batch size",
"hint": "videos.list ids per call (YouTube caps this at 50)."
},
"autotag_title_sample": {
"label": "Auto-tag title sample",
"hint": "Recent video titles sampled per channel for language detection."
},
"maintenance_revalidate_batch": {
"label": "Videos re-checked per run",
"hint": "How many least-recently-checked videos the maintenance job re-validates each run (1 API unit per 50 videos). Higher = a faster full cycle but more quota. Also adjustable on the Scheduler page."
},
"youtube_api_key": {
"label": "YouTube API key",
"hint": "Optional. Used for public reads (channels/videos) so shared backfill doesn't depend on a user's OAuth. Stored encrypted; write-only."
},
"youtube_api_proxy": {
"label": "YouTube API egress proxy",
"hint": "Optional. HTTP(S) proxy URL for outbound YouTube API calls — route them through a fixed-IP host so an IP-restricted key keeps working from a dynamic-IP server. Leave empty for direct."
},
"google_client_id": {
"label": "Google client ID",
"hint": "OAuth 2.0 client ID for Sign in with Google. Stored encrypted; write-only. Leave both Google fields empty to disable Google sign-in (email+password still works)."
},
"google_client_secret": {
"label": "Google client secret",
"hint": "OAuth 2.0 client secret. Stored encrypted; write-only."
},
"allow_registration": {
"label": "Allow registration",
"hint": "When on, anyone can submit an email+password registration. They still need to verify their email and be approved by an admin before they can sign in."
},
"explore_grace_days": {
"label": "Explore — grace period (days)",
"hint": "How long an explored-but-unsubscribed channel (and its ephemeral videos) is kept before the cleanup job removes it. Subscribing keeps it permanently."
},
"search_grace_days": {
"label": "Search results — grace period (days)",
"hint": "How long an un-kept live-search result video (nobody watched / saved / subscribed to) is kept before the discovery-cleanup job removes it."
},
"download_total_max_bytes": {
"label": "Total cache cap (bytes)",
"hint": "Max total size across all users' downloads. 0 = unlimited (disk is the limit); when exceeded, the GC evicts the least-recently-used files."
},
"download_default_max_bytes": {
"label": "Default per-user quota (bytes)",
"hint": "How much storage a user may hold before new downloads are blocked. A per-user override takes precedence. Default 5 GiB."
},
"download_default_max_concurrent": {
"label": "Default concurrent downloads / user",
"hint": "How many downloads one user may run at the same time."
},
"download_default_max_jobs": {
"label": "Default job limit / user",
"hint": "Max number of downloads a user may keep in their library."
},
"download_upload_max_bytes": {
"label": "Upload size cap per file (bytes)",
"hint": "Largest single file a user may upload to the download center. At least 1, so the cap is always on; the user's total storage is still bounded by their quota. Default 500 MiB."
},
"download_retention_days": {
"label": "Retention (days)",
"hint": "A download expires this many days after its last access; the cleanup job then removes it (once nothing references it) after the grace window."
},
"download_gc_grace_days": {
"label": "Cleanup grace (days)",
"hint": "Extra days an expired download is kept before it's deleted."
},
"download_layout": {
"label": "On-disk layout",
"hint": "\"Plex\" = a Channel/Season YYYY/… tree with .nfo + poster (Plex-indexable); \"Flat\" = a single folder."
},
"download_worker_concurrency": {
"label": "Worker concurrency",
"hint": "How many downloads the worker processes in parallel."
},
"sponsorblock_default": {
"label": "SponsorBlock by default",
"hint": "Enable SponsorBlock (skip sponsor segments) for newly created custom download profiles."
},
"audit_retention_days": {
"label": "Retention (days)",
"hint": "How long admin audit-log entries are kept before the audit-log cleanup job prunes them. 0 = keep forever. Default 180."
},
"log_level": {
"label": "Log level",
"hint": "How much the server writes to its log. INFO is the normal setting; DEBUG and TRACE are for reproducing a problem and are far more detailed. Takes effect immediately, no restart."
},
"log_retention_days": {
"label": "Log retention (days)",
"hint": "How long stored log events are kept before the log cleanup job deletes them. They include account-linked request history, so there is no \"keep forever\". Default 7."
},
"plex_enabled": {
"label": "Enable Plex",
"hint": "Expose the Plex library as a Feed source with a rich player. Requires the Plex server to be reachable from this host and its media on a local mount (see the path map)."
},
"plex_server_url": {
"label": "Plex server URL",
"hint": "Base URL reachable from this host, e.g. http://192.168.1.100:32400."
},
"plex_server_token": {
"label": "Plex server token",
"hint": "The server admin X-Plex-Token. Used server-side only (metadata + images); never sent to the browser. Stored encrypted; write-only."
},
"plex_path_map": {
"label": "Media path map",
"hint": "Maps Plex's on-disk paths to this host's local mount so Siftlode can play the physical file. Newline/comma-separated plexPrefix=localPrefix pairs, e.g. /data=/plex-media. Empty = identical on both sides."
},
"plex_libraries": {
"label": "Exposed libraries",
"hint": "Comma-separated Plex section keys to expose. Empty = all sections. Use the library picker below after testing the connection."
},
"plex_overlay_map": {
"label": "Hungarian overlay map",
"hint": "Pairs a Hungarian Plex library with its English twin so titles show Hungarian metadata: comma-separated huSectionKey:enSectionKey pairs, e.g. 3:4,5:1. The Hungarian library isn't browsable on its own; its titles are matched to the English ones by id. Empty = no overlay."
},
"plex_max_transcodes": {
"label": "Max concurrent transcodes",
"hint": "Cap on simultaneous transcode sessions for non-H.264 files. Remux (stream-copy) sessions count only toward the overall session limit; direct-play files aren't limited."
},
"plex_max_sessions": {
"label": "Max concurrent playback sessions",
"hint": "Cap on all simultaneous playback sessions, remux (stream-copy) included — each one writes a full segmented copy of the film to the scratch volume. One account can hold at most two. Direct-play files aren't sessions and aren't limited."
},
"plex_transcode_hw": {
"label": "Hardware transcode",
"hint": "GPU (VAAPI) encoding policy. Auto uses the GPU when it is available and can decode the source, otherwise software; GPU forces it; Software never uses it."
},
"plex_transcode_preset": {
"label": "Software preset",
"hint": "libx264 preset for the software fallback, fastest first. Slower presets shrink the stream but cost more CPU. Ignored on the GPU path."
},
"plex_transcode_crf": {
"label": "Software quality (CRF)",
"hint": "libx264 CRF for the software fallback (0–51; lower = better quality, larger). 20 is a good default. Ignored on the GPU path."
},
"plex_transcode_max_height": {
"label": "Software max height",
"hint": "Cap the software transcode's output height in pixels (e.g. 1080; 0 = keep source) so a tall source stays affordable to re-encode. The GPU path keeps source resolution."
},
"plex_audio_loudnorm": {
"label": "Normalize audio loudness",
"hint": "EBU R128 loudness normalization of the stereo downmix, for films whose dialogue is a whisper and whose action is deafening. Applies to remux/transcode playback only (a direct-played file is served untouched). Measured on a 5.1 film: −27.6 → −16.6 LUFS with the loud/quiet range narrowed — everything gets about 11 dB louder, so turn your volume down after switching it on. Takes effect on the next playback."
},
"tmdb_api_key": {
"label": "TMDB API key",
"hint": "Optional. A TMDB v3 API key for enriching Plex titles (keywords, crew, budget, TMDb score, recommendations, artwork). Used server-side only; the data is served from the app's own database. Empty = the enrichment job does nothing. Stored encrypted; write-only."
},
"tmdb_language": {
"label": "TMDB metadata language",
"hint": "Language of the data fetched from TMDB (keywords, overviews), as a TMDB locale code such as en-US or hu-HU. Default en-US."
},
"issues_gitea_url": {
"label": "Gitea address",
"hint": "The Gitea instance, e.g. https://git.example.com. Left empty, reports can only be downloaded as a zip."
},
"issues_gitea_repo": {
"label": "Repository",
"hint": "As owner/repository. It must be PRIVATE: a report carries its reporter's log, and nothing is sent to a public one."
},
"issues_gitea_token": {
"label": "Token",
"hint": "A Gitea access token with write:issue and read:repository. Stored encrypted; write-only."
}
},
"choices": {
"search_source": {
"scrape": "Website",
"api": "Official API"
},
"download_layout": {
"plex": "Plex",
"flat": "Flat"
},
"log_level": {
"TRACE": "TRACE",
"DEBUG": "DEBUG",
"INFO": "INFO",
"WARNING": "WARNING",
"ERROR": "ERROR"
},
"plex_transcode_hw": {
"auto": "Auto",
"on": "GPU",
"off": "Software"
},
"plex_transcode_preset": {
"ultrafast": "ultrafast",
"superfast": "superfast",
"veryfast": "veryfast",
"faster": "faster",
"fast": "fast",
"medium": "medium",
"slow": "slow",
"slower": "slower",
"veryslow": "veryslow"
}
},
"save": "Save",
"saving": "Saving…",
"saved": "Saved",
"saveFailed": "Couldn't save",
"unsaved": "Unsaved changes",
"discard": "Discard",
"willReset": "will reset to default on save",
"reset": "Reset",
"resetHint": "Remove this override and fall back to the file/env default.",
"usingDefault": "using default",
"overridden": "overridden in DB",
"secretSet": "•••••••• stored",
"secretEnv": "using env value",
"secretUnset": "not set",
"secretsDisabled": "Set TOKEN_ENCRYPTION_KEY to store secrets in the database.",
"testEmail": "Send test email",
"testEmailHint": "Send a test email to your own address using the settings above, to confirm they work.",
"testSent": "Test email sent to {{to}}",
"testFailed": "Test email failed — check the settings",
"plexTest": "Test connection",
"plexTestHint": "Verify the Plex server URL + token and load the library list. Save any edits first.",
"plexTestDirty": "Save your changes before testing the connection.",
"plexTestOk": "Connected to {{name}}",
"plexTestFailed": "Plex connection failed — check the URL and token",
"plexConnected": "Connected to {{name}} {{version}}",
"plexMediaOk": "Media mount OK — a sample file was found on disk.",
"plexMediaMissing": "Media not readable at {{path}} — check that the Plex media is bind-mounted into the container and that the path map is correct. Playback will fail until this is fixed.",
"plexPickLibraries": "Libraries to expose:",
"plexPickHint": "Unchecking all is the same as exposing every library. Remember to Save.",
"plexMovies": "Movies",
"plexShows": "TV Shows",
"emailOff": "Email sending is not configured — Siftlode silently skips every message: verification links, password resets and access-request notices. Fill in the fields above, then send a test.",
"issuesTest": "Check the connection",
"issuesTestHint": "Checks that the repository answers, is private and takes issues. Save your changes first.",
"issuesTestOk": "Works: {{repo}} (private)",
"issuesTestFailed": "The issue tracker check failed"
}