{ "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", "explore": "Channel explore", "downloads": "Downloads", "plex": "Plex" }, "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 . 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. \"scrape\" uses YouTube's internal endpoint and spends no API quota (recommended). \"api\" uses the official search.list (100 units/page). Switch to \"api\" if scraping 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." }, "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." }, "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_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." }, "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_sync_interval_min": { "label": "Sync interval (minutes)", "hint": "How often the catalog sync job mirrors Plex metadata." }, "plex_max_transcodes": { "label": "Max concurrent transcodes", "hint": "Cap on simultaneous CPU transcodes for incompatible files (a later fallback). Direct-playable files aren't limited." } }, "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.", "resetDone": "Reset to 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" }