Files
punktfunk/web/messages/en.json
T
enricobuehlerandClaude Opus 5 0985726415
android / android (push) Canceled after 36s
apple / swift (push) Canceled after 0s
apple / screenshots (push) Canceled after 0s
arch / build-publish (push) Canceled after 37s
ci / rust (push) Canceled after 37s
ci / rust-arm64 (push) Canceled after 36s
ci / web (push) Canceled after 34s
ci / docs-site (push) Canceled after 34s
deb / build-publish (push) Canceled after 19s
deb / build-publish-host (push) Canceled after 0s
deb / build-publish-client-arm64 (push) Canceled after 0s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Canceled after 0s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Canceled after 0s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Canceled after 0s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Canceled after 0s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Canceled after 0s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Canceled after 0s
docker / builders-arm64cross (push) Canceled after 0s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Canceled after 0s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 0s
docker / deploy-docs (push) Canceled after 0s
windows-host / canary-manifest (push) Canceled after 0s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 0s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 0s
windows-host / package (push) Canceled after 33s
windows-host / winget-source (push) Canceled after 0s
flatpak / build-publish (push) Successful in 5m43s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 6m59s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m9s
windows / build (aarch64-pc-windows-msvc) (push) Canceled after 2m19s
windows / build (x86_64-pc-windows-msvc) (push) Canceled after 0s
fix(host,web): an empty update channel stops looking like a broken host
A channel nobody has published to answers `manifest.json` with a 404, and the
check reported that the same way it reports a dead registry or a bad signature:
"Last check failed: feed returned HTTP 404". Every host on the stable channel
shows it today, because the stable manifest only publishes when someone
dispatches `announce` for a release tag — so the first thing an operator sees
from the new Updates card is a red failure caused by nothing being wrong.

The shared checker now distinguishes the two. `feed::fetch_manifest_blocking`
returns a typed `FeedError` instead of a string, and only a 404 on the manifest
ITSELF becomes `NotPublished` — a 404 on the detached signature still fails
loudly, because that is the half-published pair the manifest-then-signature
upload order can produce, and it must stay fail-closed.

The host carries that through as `UpdateStatus.not_published`, mutually
exclusive with `last_error`. It is benign only while no manifest has ever been
seen for the channel: once a check has succeeded, the same 404 means the feed
LOST a document it used to serve, which stays an error. The console then shows a
plain sentence naming the channel instead of the failure banner, and "None
published yet" rather than "Not checked yet".

The Linux client makes the same distinction but deliberately NOT the same
choice: `--check-update` keeps exiting 1 and keeps `error` set, because its
consumer is a shell script and an empty channel is the absence of evidence that
this build is current — not a confirmation that it is.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 00:37:56 +02:00

579 lines
35 KiB
JSON

{
"$schema": "https://inlang.com/schema/inlang-message-format",
"app_name": "Punktfunk",
"app_tagline": "management console",
"display_settings_saved": "Display configuration saved",
"nav_dashboard": "Dashboard",
"nav_host": "Host",
"nav_displays": "Virtual displays",
"nav_pairing": "Pairing",
"nav_library": "Library",
"nav_automation": "Automation",
"automation_title": "Automation",
"automation_subtitle": "Run a command, or call a webhook, when something happens on this host.",
"automation_hooks_title": "Event hooks",
"automation_add": "Add hook",
"automation_empty": "No hooks yet. Add one to run something when a stream starts, a client pairs, or a game exits.",
"automation_edit": "Edit hook",
"automation_delete": "Delete hook",
"automation_delete_confirm": "Delete this hook?",
"automation_unsaved": "Unsaved changes",
"automation_saved": "Automation saved",
"automation_save_failed": "Could not save the automation.",
"automation_debounce_badge": "min {ms} ms apart",
"automation_hook_title": "Hook",
"automation_hook_help": "Pick the event, then what should happen. A trailing .* matches every event in that domain.",
"automation_hook_save": "Done",
"automation_field_on": "When",
"automation_field_on_help": "The event that fires this hook — the same names the host publishes on its event stream.",
"automation_field_action": "Then",
"automation_action_run": "Run a command",
"automation_action_webhook": "Call a webhook",
"automation_action_run_help": "Runs detached, as the host user, with the event JSON on stdin and PF_EVENT_* in the environment.",
"automation_action_webhook_help": "The event JSON is POSTed to this URL.",
"automation_field_hmac": "HMAC secret file (optional)",
"automation_field_hmac_help": "A private, operator-owned file holding the signing secret. The request carries X-Punktfunk-Signature so the receiver can verify it really came from this host.",
"automation_field_filter": "Only for a specific client or game",
"automation_filter_client": "Client name",
"automation_filter_app": "Game / app id",
"automation_field_debounce": "Minimum gap (ms)",
"automation_field_timeout": "Timeout (s)",
"automation_confirm_title": "Save automation?",
"automation_confirm_body": "These commands run on this machine, as the host user, whenever their event fires. Confirm with the console password.",
"library_delete_failed": "Could not delete this entry.",
"gpu_apply_failed": "Could not change the GPU preference.",
"stats_start_failed": "Could not start the capture.",
"stats_stop_failed": "Could not stop the capture — it may not have been saved.",
"stats_delete_failed": "Could not delete this recording.",
"stats_download_failed": "Could not download this recording.",
"games_end_failed": "Could not end the game.",
"action_stop_failed": "Could not stop the session.",
"action_idr_failed": "Could not request a keyframe.",
"nav_settings": "Settings",
"nav_close_menu": "Close menu",
"nav_more": "More",
"nav_plugins": "Plugins",
"plugin_offline_title": "This plugin isn't running",
"plugin_offline_hint": "Start the scripting runner, then retry.",
"plugin_retry": "Retry",
"plugin_open_new_tab": "Open in new tab",
"status_title": "Live status",
"status_video": "Video",
"status_audio": "Audio",
"status_streaming": "Streaming",
"status_idle": "Idle",
"status_session": "Session",
"status_sessions_active": "{count} active",
"status_no_session": "No active session",
"status_paired_count": "Paired clients",
"status_pin_waiting": "Waiting",
"status_pin_none": "None",
"status_pin_pending": "Pairing PIN pending",
"stream_codec": "Codec",
"stream_resolution": "Resolution",
"stream_fps": "Frame rate",
"stream_first_frame": "First frame",
"stream_last_resize": "Last resize",
"stream_packet_size": "Packet size",
"stream_min_fec": "FEC floor",
"stream_bitrate": "Bitrate",
"activity_title": "Recent activity",
"activity_empty": "Nothing yet — events show up here as they happen on the host.",
"activity_client_connected": "Connected",
"activity_client_disconnected": "Disconnected",
"activity_session_started": "Session started",
"activity_session_ended": "Session ended",
"activity_stream_started": "Stream started",
"activity_stream_stopped": "Stream stopped",
"activity_game_running": "Game running",
"activity_game_exited": "Game exited",
"activity_pairing_pending": "Pairing requested",
"activity_pairing_completed": "Paired",
"activity_pairing_denied": "Pairing denied",
"activity_display_created": "Display created",
"activity_display_released": "Display released",
"activity_library_changed": "Library changed",
"activity_update_available": "Update available",
"activity_update_applied": "Update applied",
"activity_plugins_changed": "Plugins changed",
"activity_store_changed": "Store changed",
"activity_host_started": "Host started",
"activity_host_stopping": "Host stopping",
"action_stop_session": "Stop session",
"action_request_idr": "Request keyframe",
"action_unpair": "Unpair",
"connect_title": "Connect a device",
"connect_help": "Type the address into a punktfunk client, or open the link on a device that already has one installed — it opens straight onto this host. Pair from the Pairing page.",
"connect_address": "Host address",
"connect_link": "Deep link",
"connect_copy": "Copy",
"host_identity": "Identity",
"host_hostname": "Hostname",
"host_os": "Operating system",
"host_local_ip": "Local IP",
"host_version": "Version",
"host_abi": "ABI version",
"host_codecs": "Codecs",
"host_ports": "Ports",
"host_uniqueid": "Unique ID",
"host_compositors": "Compositors",
"host_compositors_help": "Backends the host can drive a virtual output on. Pass an id to a client's --compositor flag; the host honors it if available, else auto-detects.",
"compositor_available": "Available",
"compositor_unavailable": "Unavailable",
"compositor_default": "Default",
"compositor_none": "This host has no compositor backends — they are a Linux concept. Virtual displays here run on the bundled pf-vdisplay driver.",
"host_gpus": "GPUs",
"host_gpus_help": "The GPU the host captures and encodes on. Automatic picks the best GPU; preferring one pins capture + encode to it. A change applies to the next session.",
"gpu_automatic": "Automatic",
"gpu_prefer": "Prefer",
"gpu_preferred": "Preferred",
"gpu_in_use": "In use · {backend}",
"gpu_next_session": "Next session",
"gpu_none": "No GPUs detected.",
"gpu_missing_warning": "The preferred GPU “{name}” is not present — automatic selection is used instead.",
"gpu_env_note": "PUNKTFUNK_RENDER_ADAPTER={value} pins the GPU while in automatic mode.",
"gpu_encoder_pin_note": "PUNKTFUNK_ENCODER={value} pins the encoder backend.",
"gpu_encoder_pin_warning": "PUNKTFUNK_ENCODER={value} pins a {vendor} encoder, but the next session's GPU is “{name}” — remove the stale pin from host.env.",
"host_conflicts_title": "Another game-streaming server is running on this machine",
"host_conflicts_help": "It listens on the same ports as punktfunk, so whichever one started first answers your clients — which is usually why a working-looking host cannot be connected to. Stop or uninstall the other server, then restart punktfunk.",
"host_displays_help": "How virtual displays are created, kept alive, and arranged. Pick a preset, or choose Custom to set options directly. A change applies to the next session.",
"display_config_title": "Configuration",
"display_preset": "Preset",
"display_preset_custom": "Custom",
"display_preset_default": "Default",
"display_preset_gaming_rig": "Headless box",
"display_preset_shared_desktop": "Shared desktop",
"display_preset_hotdesk": "Hot-desk",
"display_preset_workstation": "Workstation",
"display_keep_alive": "Keep alive after disconnect",
"display_keep_alive_off": "Off",
"display_keep_alive_keep": "Keep for",
"display_keep_alive_forever": "Forever",
"display_keep_alive_seconds": "seconds",
"display_topology": "Topology",
"display_topology_auto": "Automatic",
"display_topology_extend": "Extend",
"display_topology_primary": "Primary",
"display_topology_exclusive": "Exclusive",
"display_max": "Max displays",
"display_save": "Save",
"display_effective": "In effect",
"display_pending_note": "Changes apply from the next connection — a streaming session keeps the display it opened on.",
"display_live": "Live displays",
"display_none_live": "No virtual displays right now.",
"display_state_active": "Active",
"display_state_lingering": "Lingering",
"display_state_pinned": "Pinned",
"display_release_btn": "Release",
"display_refresh_failed": "Could not refresh from the host — showing the last known settings. Your edits are safe.",
"display_release_all": "Release all kept",
"display_expires_in": "tears down in {sec}s",
"display_sessions": "{count} streaming",
"display_arrange": "Arrange displays",
"display_arrange_help": "Set where each streamed display sits on the desktop, in pixels. Saving switches to a manual layout; it applies from the next connect.",
"display_arrange_save": "Save arrangement",
"display_custom_desc": "Set every option yourself.",
"display_preset_apply_named": "Apply preset {name}",
"display_preset_current": "Active",
"display_preset_soon": "coming soon",
"display_keep_alive_help": "Off tears the display down as soon as the client disconnects. Keep it alive (and, on gamescope, its game) so a quick reconnect resumes instantly instead of rebuilding.",
"display_topology_help": "How the streamed display fits into the host's desktop. Extend: an extra screen alongside your monitors. Primary: the streamed display becomes the primary output, your monitors kept. Exclusive: the streamed display is the sole output — physical monitors are disabled while streaming and restored after. On a headless host it just sets whether the streamed display is the primary.",
"display_conflict": "When another client connects",
"display_conflict_help": "What happens if a second client connects while one is already streaming and asks for a different resolution.",
"display_conflict_separate": "Own display",
"display_conflict_steal": "Take over",
"display_conflict_join": "Share view",
"display_conflict_reject": "Busy — reject",
"display_identity": "Per-client identity",
"display_identity_help": "Whether the streamed display carries a stable per-client identity, so the host's desktop remembers that client's per-monitor settings (scaling, resolution) and reapplies them when it reconnects. Shared: one identity for everyone. Per client: each device keeps its own. Per client + resolution: a device keeps separate settings per resolution it connects at.",
"display_game_session": "Dedicated game sessions",
"display_game_session_help": "How a session that launches a game from the library is served. “Dedicated” always gives the launch its own headless gamescope at your exact resolution — the game boots straight in, no Steam Big Picture, no game mode. “Auto” uses whatever session the box is in. gamescope must be installed; otherwise Dedicated falls back to Auto.",
"display_game_session_auto": "Auto",
"display_game_session_dedicated": "Dedicated",
"display_experimental": "Experimental",
"display_ddc": "Turn monitors off while streaming (DDC/CI)",
"display_ddc_help": "Windows only, takes effect with Exclusive topology. Before disabling your physical monitors, the host also tells them to power their panel off over the DDC/CI monitor-control channel, and wakes them again when the stream ends. This can eliminate a periodic stutter some setups see when the streamed display is the only active one (the dark monitor keeps probing its inputs; a panel that was told to sleep doesn't). Monitors without DDC/CI support are skipped — if your monitor doesn't wake up afterwards, press its power button once and turn this off.",
"display_ddc_disabled": "Off",
"display_ddc_enabled": "On",
"display_ddc_badge": "Monitors off via DDC/CI",
"display_pnp": "Disable monitor devices while streaming (PnP)",
"display_pnp_help": "Windows only, takes effect with Exclusive topology. On top of removing your physical monitors from the desktop, the host disables their Windows device entries for the duration of the stream and re-enables them afterwards. A standby monitor or TV that keeps waking its connection (auto input scan, instant-on) can no longer interrupt the stream — Windows ignores its wake events entirely while the device is disabled. If the host crashes mid-stream, the monitors are re-enabled the next time it starts; until then you can re-enable them manually in Device Manager.",
"display_pnp_disabled": "Off",
"display_pnp_enabled": "On",
"display_pnp_badge": "Monitor devices disabled (PnP)",
"display_identity_shared": "Shared",
"display_identity_per_client": "Per client",
"display_identity_per_client_mode": "Per client + resolution",
"display_layout_mode": "Multi-monitor layout",
"display_layout_help": "Auto lays displays out side by side, left to right. Manual: you position each one yourself — a per-display X/Y editor appears in the Live displays section below once two or more are streaming.",
"display_layout_auto_row": "Auto (side by side)",
"display_layout_manual": "Manual",
"display_preset_custom_label": "Custom presets",
"display_preset_save_as": "Save as preset…",
"display_preset_name": "Preset name",
"display_preset_edit": "Rename",
"display_preset_update": "Update to current settings",
"display_preset_delete": "Delete",
"display_preset_delete_confirm": "Delete this custom preset?",
"display_custom_title": "Custom settings",
"display_unsaved": "Unsaved changes",
"display_unsaved_hint": "These options only take effect once you save.",
"display_all_saved": "All changes saved",
"display_revert": "Discard changes",
"display_discard_confirm": "You have unsaved custom settings. Discard them?",
"clients_name": "Name",
"clients_fingerprint": "Fingerprint",
"pairing_title": "Pairing",
"pairing_idle": "No pairing in progress. Start pairing from a Moonlight client, then enter its PIN here.",
"pairing_waiting": "A client is waiting to pair. Enter the PIN it shows:",
"pairing_pin_label": "PIN",
"pairing_submit": "Submit PIN",
"pairing_pin_sent": "PIN sent. If it's correct, the client finishes pairing and appears under Paired devices below.",
"pairing_failed": "Couldn't submit the PIN — check it's correct and that the client is still waiting to pair.",
"pairing_native_title": "Pair a device",
"pairing_native_desc": "Show a one-time PIN here, then enter it in your Punktfunk app to pair this device.",
"pairing_native_disabled": "The native host isn't running. Start it with `serve --native` to pair Punktfunk devices.",
"pairing_native_arm": "Pair a device",
"pairing_native_enter": "Enter this PIN on your device:",
"pairing_native_expires": "Expires in",
"pairing_native_cancel": "Cancel",
"pairing_native_devices": "Paired devices",
"pairing_native_empty": "No devices paired yet.",
"pairing_native_unpair_confirm": "Unpair this device? It will need to pair again to connect.",
"pairing_protocol": "Protocol",
"pairing_protocol_native": "punktfunk/1",
"pairing_protocol_moonlight": "Moonlight",
"pairing_pending_title": "Waiting for approval",
"pairing_pending_desc": "These devices tried to connect. Approving pairs a device immediately — no PIN needed.",
"pairing_pending_approve": "Approve",
"pairing_pending_deny": "Deny",
"pairing_pending_name_prompt": "Name this device:",
"pairing_pending_age_just_now": "just now",
"pairing_pending_age_secs": "{s}s ago",
"pairing_pending_age_mins": "{min} min ago",
"pairing_moonlight_title": "Moonlight (GameStream) pairing",
"library_title": "Library",
"library_empty": "No games found yet.",
"library_sources_title": "Game sources",
"library_sources_help": "Launchers this host scans for installed games. Turn one off to hide its games from every device — nothing is deleted, and turning it back on brings them right back.",
"library_sources_failed": "Could not update the game source.",
"library_store_steam": "Steam",
"library_store_custom": "Custom",
"library_add_title": "Add a custom game",
"library_edit_overwrites": "Saving replaces this entry with what's in this form. Prep/undo commands and detection hints set outside the console aren't shown here and will be cleared.",
"library_edit_title": "Edit custom game",
"library_add_button": "Add custom game",
"library_field_title": "Title",
"library_field_portrait": "Portrait art URL",
"library_field_hero": "Hero art URL",
"library_field_header": "Header art URL",
"library_field_logo": "Logo art URL",
"library_field_command": "Launch command",
"library_field_command_help": "Optional. The command the host runs to launch this title.",
"library_field_platform": "Platform",
"library_field_platform_help": "The system this title runs on, e.g. PS2, Xbox 360, SNES, PC.",
"library_field_description": "Description",
"library_field_developer": "Developer",
"library_field_publisher": "Publisher",
"library_field_release_year": "Release year",
"library_field_genres": "Genres",
"library_field_genres_help": "Comma-separated, e.g. RPG, Platformer.",
"library_field_tags": "Tags",
"library_field_tags_help": "Comma-separated labels for organizing, e.g. co-op, kids.",
"library_field_region": "Region",
"library_field_region_help": "e.g. NTSC-U, PAL, NTSC-J.",
"library_field_players": "Players",
"library_details_legend": "Details (optional)",
"library_owned_by": "via {provider}",
"library_providers_title": "Synced by plugins",
"library_providers_help": "These entries are owned by a plugin, so they can't be edited or removed one at a time — the plugin re-syncs them. If the plugin is gone, remove its entries here.",
"library_provider_count": "{count} entries",
"library_provider_filter": "Show only these",
"library_provider_show_all": "Show all",
"library_provider_purge": "Remove this provider's entries",
"library_provider_purge_confirm": "Remove all {count} entries synced by “{provider}”? This only removes them from the library.",
"library_provider_purged": "Removed the entries synced by “{provider}”.",
"library_provider_purge_failed": "Could not remove this provider's entries.",
"library_save": "Save",
"library_create": "Add",
"library_cancel": "Cancel",
"library_edit": "Edit",
"library_delete": "Delete",
"library_delete_confirm": "Delete this custom game? This can't be undone.",
"settings_title": "Settings",
"settings_language": "Language",
"common_loading": "Loading…",
"common_error": "Something went wrong.",
"common_retry": "Retry",
"common_cancel": "Cancel",
"common_unauthorized": "Session expired — redirecting to sign in…",
"login_title": "Sign in",
"login_subtitle": "Enter the management password to continue. Don't know what to do?",
"login_docs_link": "Visit the documentation",
"login_password": "Password",
"login_submit": "Sign in",
"login_error": "Wrong password.",
"login_signing_in": "Signing in…",
"action_logout": "Sign out",
"settings_logout_failed": "Sign-out failed — you're still signed in. Please try again.",
"nav_stats": "Performance",
"nav_logs": "Logs",
"logs_title": "Logs",
"logs_subtitle": "The host's recent log stream — follow live, filter by level, search.",
"logs_follow": "Follow",
"logs_pause": "Pause",
"logs_clear": "Clear",
"logs_search": "Search logs…",
"logs_empty": "No log entries match — adjust the filter or wait for host activity.",
"logs_dropped": "Some entries were evicted before they could be fetched",
"logs_download": "Download logs",
"logs_stalled": "Log polling failed — showing the last lines received.",
"logs_share": "Share logs",
"logs_copy": "Copy logs to clipboard",
"logs_copied": "Logs copied to clipboard",
"logs_share_failed": "Couldn't share the logs",
"stats_title": "Performance",
"stats_subtitle": "Record a session's pipeline timings and review them as graphs.",
"stats_capture_title": "Capture",
"stats_capture_desc": "Arm capture, run a session, then stop to save a recording. Sampling runs at the host's aggregation boundary — no per-frame overhead.",
"stats_recording": "Recording",
"stats_idle": "Idle",
"stats_start": "Start capture",
"stats_stop": "Stop & save",
"stats_elapsed": "Elapsed",
"stats_samples": "Samples",
"stats_kind": "Path",
"stats_kind_native": "Native",
"stats_kind_gamestream": "GameStream",
"stats_live_title": "Live",
"stats_live_window": "Showing the last {count} samples. The saved recording keeps everything.",
"stats_live_waiting": "Armed — waiting for the first samples. Start a session to begin recording.",
"stats_latency_title": "Latency by stage",
"stats_latency_axis": "µs",
"stats_latency_desc": "Per-stage pipeline time, stacked — the \"where does the time go\" view.",
"stats_throughput_title": "Throughput",
"stats_health_title": "Health",
"stats_fps_new": "New fps",
"stats_fps_repeat": "Repeat fps",
"stats_mbps": "Mb/s",
"stats_bitrate_target": "Target Mb/s",
"stats_health_gamestream_note": "Packet loss, send-drops, and FEC recovery are receiver-side metrics the GameStream path doesn't instrument — only frame drops are shown here.",
"stats_p99": "p99",
"stats_p50": "p50",
"stats_frames_dropped": "Frames dropped",
"stats_packets_dropped": "Packets dropped",
"stats_send_dropped": "Send drops",
"stats_fec_recovered": "FEC recovered",
"stats_recordings_title": "Recordings",
"stats_recordings_empty": "No recordings yet. Start a capture to record one.",
"stats_col_time": "Time",
"stats_col_kind": "Path",
"stats_col_resolution": "Resolution",
"stats_col_codec": "Codec",
"stats_col_duration": "Duration",
"stats_col_samples": "Samples",
"stats_view": "View",
"stats_download": "Download",
"stats_delete": "Delete",
"stats_delete_confirm": "Delete this recording? This can't be undone.",
"stats_detail_title": "Recording detail",
"stats_close": "Close",
"stats_no_samples": "This recording has no samples.",
"store_title": "Plugins",
"store_subtitle": "Browse the plugin catalog, install and remove plugins, and choose which catalogs this host trusts.",
"store_tab_browse": "Browse",
"store_tab_installed": "Installed",
"store_tab_sources": "Sources",
"store_tier_verified": "Verified",
"store_tier_verified_hint": "From the built-in unom catalog — unom reviewed this exact package.",
"store_tier_external": "External source",
"store_tier_external_hint": "Pinned and integrity-checked, but curated by someone other than unom. Nobody at unom reviewed this code.",
"store_tier_unverified": "Unverified",
"store_tier_unverified_hint": "Installed from a raw package spec. No catalog, no review — nobody checked this code.",
"store_tier_cli": "Installed via CLI",
"store_tier_cli_hint": "Installed from the command line, so the host has no record of where it came from.",
"store_from_source": "from",
"store_search_placeholder": "Search plugins…",
"store_filter_all": "All sources",
"store_all_sources_failed": "Could not fetch any catalog ({sources}). The store may not be empty — check the Sources tab.",
"store_empty": "No plugins in the catalog yet.",
"store_no_match": "No plugin matches your search.",
"store_by_author": "by {author}",
"store_homepage": "Homepage",
"store_install": "Install",
"store_installed_label": "Installed",
"store_update_to": "Update to {version}",
"store_incompatible": "Not compatible with this host.",
"store_blocked": "Blocked by the host: {reason}",
"store_spec_open": "Install from package spec…",
"store_runner_title": "Plugin runner",
"store_runner_help": "The service every plugin runs inside. Disabling it stops all plugins at once without uninstalling anything.",
"store_runner_not_installed": "The plugin runner isn't installed on this host, so plugins can't start.",
"store_runner_banner": "The plugin runner is switched off — plugins won't start until you enable it.",
"store_runner_enable": "Enable runner",
"store_runner_disable": "Disable runner",
"store_runner_state_running": "Running",
"store_runner_state_stopped": "Stopped",
"store_runner_state_disabled": "Disabled",
"store_runner_state_missing": "Not installed",
"store_runner_unit": "Service",
"store_runner_principal": "Runs as",
"store_runner_failed": "Could not change the plugin runner.",
"store_installed_title": "Installed plugins",
"store_installed_empty": "No plugins installed yet.",
"store_running": "Running",
"store_stopped": "Not running",
"store_version_unknown": "version unknown",
"store_uninstall": "Uninstall",
"store_uninstall_confirm": "Uninstall {title}? You can install it again from the catalog.",
"store_uninstall_failed": "Could not start the removal.",
"store_update_no_entry": "That plugin isn't in any catalog right now — refresh the sources and try again.",
"store_sources_title": "Catalog sources",
"store_sources_help": "Where this host looks for plugins. The built-in unom catalog is always present; every other source is one you added and vouch for yourself.",
"store_refresh_all": "Refresh all",
"store_refresh_failed": "Could not refresh the catalogs.",
"store_source_builtin": "Built in",
"store_source_signed": "Signed",
"store_source_unsigned": "Unsigned",
"store_source_stale": "Out of date",
"store_source_entries": "{count} plugins",
"store_source_fetched": "last fetched {when}",
"store_source_never": "never",
"store_source_remove": "Remove source",
"store_source_remove_confirm": "Remove the source “{name}”? Plugins already installed from it stay installed.",
"store_source_remove_failed": "Could not remove the source.",
"store_source_builtin_locked": "The built-in unom catalog can't be removed.",
"store_add_source_title": "Add a catalog source",
"store_field_source_name": "Name",
"store_field_source_url": "Index URL",
"store_field_source_key": "Public key (optional)",
"store_field_source_key_help": "An ed25519:… key. With a key set, the host only accepts a signed index from this source.",
"store_add_source": "Add source",
"store_add_source_failed": "Could not save the source — check the name and the URL.",
"store_source_trust_title": "Trust this source?",
"store_source_trust_body": "Everything you install from “{name}” is code unom has not reviewed. It runs on this host with the plugin runner's privileges. Only add a catalog whose operator you trust.",
"store_source_trust_unsigned": "Without a public key the host can't tell whether this index was tampered with in transit.",
"store_source_password": "Console password",
"store_source_trust_confirm": "I understand — add the source",
"store_install_title": "Install {title}?",
"store_install_verified_body": "Version {version} from the built-in unom catalog. unom reviewed this exact package.",
"store_install_confirm": "Install",
"store_install_external_title": "Install {title} from an external source?",
"store_install_external_body": "Version {version} comes from “{source}”, a catalog you added yourself.",
"store_install_external_note": "unom has not reviewed this code. The package is pinned and integrity-checked, but it will run on this host with the plugin runner's privileges.",
"store_install_external_confirm": "Install anyway",
"store_install_failed": "Could not start the install.",
"store_busy": "The host is already installing or removing a plugin. Try again once it's finished.",
"store_spec_title": "Install from a package spec",
"store_spec_lead": "This installs code straight from a package registry. It is in no catalog, nobody has reviewed it, and it will run on this host with the plugin runner's privileges — the same access it has to your files and your session.",
"store_spec_permanent": "A plugin installed this way stays marked Unverified for as long as it is installed.",
"store_spec_field": "Package spec",
"store_spec_field_help": "For example @scope/plugin-name@1.2.3.",
"store_spec_confirm_field": "Type the package spec again to confirm",
"store_spec_checkbox": "I understand that this runs unreviewed code with operator privileges.",
"store_spec_confirm": "Install unverified",
"store_spec_password": "Console password",
"store_spec_password_help": "Running unreviewed code needs the password again — a browser session on its own can't do this.",
"store_job_install": "Installing {target}",
"store_job_uninstall": "Removing {target}",
"store_job_done_install": "Installed.",
"store_job_done_uninstall": "Removed.",
"store_job_failed": "The job failed.",
"store_job_restarting": "The plugin runner is restarting — the sidebar catches up in a moment.",
"store_job_lost": "Lost track of this job",
"store_job_lost_hint": "The host restarted while it ran. Check the Installed tab to see whether it finished.",
"store_job_log": "Show log",
"store_job_dismiss": "Dismiss",
"store_phase_queued": "Queued",
"store_phase_verifying": "Verifying the package",
"store_phase_installing": "Installing",
"store_phase_removing": "Removing",
"store_phase_checking": "Checking the install",
"store_phase_rolling_back": "Rolling back",
"store_phase_recording": "Recording provenance",
"store_phase_restarting": "Restarting the plugin runner",
"store_phase_done": "Done",
"games_title": "Running games",
"games_state_launching": "Starting",
"games_state_running": "Running",
"games_state_exited": "Ended",
"games_state_grace": "Waiting for client",
"games_closing_in": "Its client is gone — closing in {time} unless it comes back",
"games_end_all_waiting_confirm": "This game has no id the host can single out, so ending it now ends all {count} games waiting to close. Continue?",
"action_stop_session_all_confirm": "The host has one stop, and it ends every live session — all {count} of them, not just this one. Continue?",
"games_end_now": "End now",
"session_game_title": "When a game or a session ends",
"session_game_help": "A streaming session and the game it launched can share a fate. These settings are about the game; the keep-alive above is about the display, and the two have separate timers.",
"session_game_on_exit": "When the game exits",
"session_game_on_exit_help": "Quitting the game hands the client back to its own library instead of leaving it on your desktop. Turn this off if you stream the desktop and treat the game as incidental.",
"session_game_on_exit_end": "End the session",
"session_game_on_exit_keep": "Keep streaming",
"session_game_end_game": "When the session ends",
"session_game_end_game_help": "Whether stopping (or losing) a session also closes the game it launched. Never applies to a game you started yourself — only one this host launched for the session.",
"session_game_end_keep": "Leave it running",
"session_game_end_on_quit": "Close it on Stop",
"session_game_end_always": "Always close it",
"session_game_always_warning": "Closing a game costs whatever it had not saved. The host asks it to close first and only forces the issue if it refuses — but a network drop is not someone pressing Stop, so a dropped client gets the reconnect window below before anything happens. A display kept forever stays up regardless; this setting governs the game, not the screen.",
"session_game_grace": "Reconnect window",
"session_game_grace_help": "How long a client that vanished has to come back before its game is closed. The console shows the countdown, and reconnecting cancels it.",
"session_game_saved": "Session and game settings saved",
"session_game_inert": "This host has no way to launch games, so these settings do nothing here",
"session_game_nested_note": "On a gamescope game session the game runs *inside* the streamed display, so it lives exactly as long as that display does — which is what Keep alive above decides, not this setting. A deliberate Stop tears that display down at once and takes the game with it, whichever option you pick here.",
"display_monitor_title": "Streamed screen",
"display_monitor_intro": "By default the host creates its own virtual screen for each client, sized to that client. Instead, you can stream one of the screens this computer already has — what you see on that monitor is what the client sees.",
"display_monitor_virtual": "Virtual screen (default)",
"display_monitor_virtual_hint": "Each client gets its own screen at its own resolution.",
"display_monitor_mirror_hint": "Every client sees this monitor, at its resolution.",
"display_monitor_none": "This host reports no monitors.",
"display_monitor_unavailable": "Monitors could not be listed on this host.",
"display_monitor_env_locked": "Pinned by PUNKTFUNK_CAPTURE_MONITOR on this host — unset it to choose here.",
"display_monitor_unsupported": "Streaming one of these screens isn't supported on this host yet — it's available on Linux hosts only. The screens are listed so you can see what this computer has; clients keep getting their own virtual screen.",
"display_monitor_primary": "primary",
"display_monitor_disabled": "off",
"display_monitor_saved": "Streamed screen saved",
"update_title": "Updates",
"update_available_badge": "Update available",
"update_current": "Installed",
"update_install_kind": "Install type",
"update_latest": "Latest release",
"update_notes": "Release notes",
"update_up_to_date": "You're up to date.",
"update_how": "Update this host with:",
"update_check_now": "Check now",
"update_checking": "Checking…",
"update_last_checked": "Last checked",
"update_never_checked": "Not checked yet",
"update_none_published": "None published yet",
"update_not_published": "Nothing has been published to the {channel} channel yet. The check itself is working — there's just no release to compare against.",
"update_stale": "The update feed hasn't changed in over 45 days — checks succeed but nothing new arrives. If that seems wrong, check this host's connectivity to git.unom.io.",
"update_disabled": "Update checks are disabled on this host (PUNKTFUNK_UPDATE_CHECK=0).",
"update_error": "Last check failed:",
"update_copy": "Copy",
"update_copied": "Copied",
"update_apply_ready": "Version {version} can be installed from here — the host downloads, verifies, and restarts itself.",
"update_apply_button": "Update now",
"update_apply_confirm_title": "Update the host to {version}?",
"update_apply_confirm_body": "Confirm with the console password. The host will restart at the end; this page reconnects by itself.",
"update_apply_force_warning": "A streaming session is live right now — updating will drop it (whoever is playing gets cut off). If that stream is how you're viewing this page, you'll lose it too.",
"update_apply_force_button": "Update anyway (drops the stream)",
"update_apply_password_label": "Console password",
"update_apply_wrong_password": "Wrong password.",
"update_apply_throttled": "Too many attempts — wait a moment and try again.",
"update_apply_working": "Starting…",
"update_apply_give_up": "Stop waiting",
"update_apply_timeout": "The host hasn't come back yet. It may still be installing — if this persists, check the service on the machine and the installer log under the punktfunk data directory (logs\\update-*.log).",
"update_applying_title": "Updating to {version}",
"update_stage_downloading": "Downloading the installer… {pct}%",
"update_stage_downloading_indeterminate": "Downloading the installer…",
"update_stage_verifying": "Verifying the download…",
"update_stage_applying": "Handing over to the installer…",
"update_stage_restarting": "The host is restarting…",
"update_stage_reconnecting": "Waiting for the host to come back…",
"update_result_ok": "Updated {from} → {to}.",
"update_result_staged": "Update to {to} is staged — reboot this host to finish.",
"update_result_noop": "Your package source had nothing newer yet — try again in a few minutes.",
"update_opt_in": "To enable one-click updates from here, run this once on the host (then log out and back in):",
"update_result_failed": "Update to {to} failed during {stage}.",
"update_result_log": "Installer log:"
}