feat: pairing v2 — one-tap trusted devices over LAN and private relay (#2103)

Reworks how devices connect to an OpenChamber server, end to end.

Pairing v2:
- One-time pairing links/QR codes (openchamber://connect?v=2) carrying a set of transport candidates (LAN/tunnel/relay) and a single-use secret redeemed server-side; no tokens embedded in links
- Add-a-device dialog written for first-time users: intent-based transport choice (Anywhere / Home network only / This computer only) with plain-language descriptions, transparent fallback checkboxes, server-authoritative LAN detection, high-res QR dialog
- Private relay folded into pairing as a transport candidate with a demand-driven lifecycle (enables when a relay device is paired, disables when none remain)

Multi-transport devices:
- A saved device holds all its transports and one token; mobile re-probes on connect, resume, and network change and hot-switches LAN<->relay seamlessly (no re-pairing, no remount, session preserved)
- Desktop can import relay pairing links, switch to relay hosts through the E2EE tunnel, and restore a relay default host after relaunch

Device management:
- Device list (web + desktop) shows live per-device connectivity with the active transport (Connected - Local network / Relay) and platform badges (iOS/Android/macOS/Windows/Linux)
- One physical device = one record: stable per-install dedupe keys across pairing and password re-login; typed pairing label names the device, paired devices name the connection by the issuing server hostname
- Trusted desktop-local client manages all devices (list, revoke, clear revoked); relay host reaps dead client sockets after 3 missed keepalives

Android:
- LAN transport unblocked (cleartext + mixed content, mirroring iOS ATS exceptions); resume re-probe retries through network flux and silently auto-reconnects from a disconnected state
This commit is contained in:
Iuliia Ivashko
2026-07-10 00:12:33 +03:00
committed by GitHub
parent a1aae30e66
commit 91a95bfdaa
53 changed files with 4589 additions and 1369 deletions
@@ -273,21 +273,43 @@ export const settingsDict = {
'settings.remoteInstances.direct.state.empty': 'No other servers added yet.',
'settings.remoteInstances.clientAuth.title': 'Connect to this server',
'settings.remoteInstances.clientAuth.description': 'Create a secure link or token so OpenChamber Desktop can connect to this server.',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': 'Device name (optional)',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': 'Device name — e.g. My iPhone',
'settings.remoteInstances.clientAuth.actions.create': 'Create Token',
'settings.remoteInstances.clientAuth.actions.pair': 'Create Link',
'settings.remoteInstances.clientAuth.actions.revoke': 'Revoke',
'settings.remoteInstances.clientAuth.actions.clearRevoked': 'Clear revoked',
'settings.remoteInstances.clientAuth.qrAlt': 'OpenChamber connection QR code',
'settings.remoteInstances.clientAuth.qrEnlarge': 'Enlarge QR code',
'settings.remoteInstances.clientAuth.qrScanHint': 'Scan this with the OpenChamber app on your other device. It is single-use and expires.',
'settings.remoteInstances.clientAuth.qrDialogTitle': 'Scan to connect',
'settings.remoteInstances.clientAuth.actions.addDevice': 'Add a device',
'settings.remoteInstances.clientAuth.actions.copied': 'Copied',
'settings.remoteInstances.clientAuth.addDevice.transportLabel': 'Where will you use this device?',
'settings.remoteInstances.clientAuth.addDevice.subtitle': 'Create a one-time QR code that connects another device to this server.',
'settings.remoteInstances.clientAuth.addDevice.transport.local': 'This computer only',
'settings.remoteInstances.clientAuth.addDevice.transport.localHint': 'For apps running on this same machine.',
'settings.remoteInstances.clientAuth.addDevice.transport.lan': 'Home network only',
'settings.remoteInstances.clientAuth.addDevice.transport.lanHint': 'Connects directly over your Wi-Fi. Does not work away from this network.',
'settings.remoteInstances.clientAuth.addDevice.transport.relay': 'Anywhere',
'settings.remoteInstances.clientAuth.addDevice.transport.relayHint': 'Works at home and away. Away traffic goes through OpenChamber Private Relay — an end-to-end encrypted tunnel. No setup needed.',
'settings.remoteInstances.clientAuth.addDevice.fallback.relay': 'Also allow the encrypted relay when away from home',
'settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal': 'Prefer the direct home connection when available',
'settings.remoteInstances.clientAuth.addDevice.create': 'Create QR code',
'settings.remoteInstances.clientAuth.addDevice.done': 'Done',
'settings.remoteInstances.clientAuth.pairingUrl': 'Connection link',
'settings.remoteInstances.clientAuth.createdToken': 'Copy this token now. For security, it will not be shown again.',
'settings.remoteInstances.clientAuth.state.loading': 'Loading tokens...',
'settings.remoteInstances.clientAuth.state.empty': 'No devices connected yet.',
'settings.remoteInstances.clientAuth.state.revoked': 'Revoked',
'settings.remoteInstances.clientAuth.state.thisDevice': 'This device',
'settings.remoteInstances.clientAuth.state.pending': 'Waiting to connect…',
'settings.remoteInstances.clientAuth.state.viaRelay': 'Relay',
'settings.remoteInstances.clientAuth.state.connectedDirect': 'Connected · Local network',
'settings.remoteInstances.clientAuth.state.connectedRelay': 'Connected · Relay',
'settings.remoteInstances.clientAuth.lastUsed': 'Last used {date}',
'settings.remoteInstances.clientAuth.neverUsed': 'Never used',
'settings.remoteInstances.relay.title': 'OpenChamber Relay',
'settings.remoteInstances.relay.autoHint': 'Turns on automatically when you pair a device over the relay.',
'settings.remoteInstances.relay.description': 'Let your other devices connect from anywhere without opening ports. Traffic is end-to-end encrypted — the relay cannot read it.',
'settings.remoteInstances.relay.enableHint': 'Nothing is shared until you enable the relay on this server.',
'settings.remoteInstances.relay.actions.enable': 'Enable Relay',
@@ -240,21 +240,43 @@ export const settingsDict = {
"settings.remoteInstances.direct.state.empty": "Todavía no se han añadido otros servidores.",
"settings.remoteInstances.clientAuth.title": "Conectarse a este servidor",
"settings.remoteInstances.clientAuth.description": "Crea un enlace o token seguro para que OpenChamber Desktop pueda conectarse a este servidor.",
"settings.remoteInstances.clientAuth.field.labelPlaceholder": "Nombre del dispositivo (opcional)",
"settings.remoteInstances.clientAuth.field.labelPlaceholder": "Nombre del dispositivo — p. ej. Mi iPhone",
"settings.remoteInstances.clientAuth.actions.create": "Crear token",
"settings.remoteInstances.clientAuth.actions.pair": "Crear enlace",
"settings.remoteInstances.clientAuth.actions.revoke": "Revocar",
"settings.remoteInstances.clientAuth.actions.clearRevoked": "Borrar revocados",
"settings.remoteInstances.clientAuth.qrAlt": "OpenChamber connection QR code",
"settings.remoteInstances.clientAuth.qrEnlarge": "Ampliar código QR",
"settings.remoteInstances.clientAuth.qrScanHint": "Escanéalo con la app de OpenChamber en tu otro dispositivo. Es de un solo uso y caduca.",
"settings.remoteInstances.clientAuth.qrDialogTitle": "Escanear para conectar",
"settings.remoteInstances.clientAuth.actions.addDevice": "Añadir un dispositivo",
"settings.remoteInstances.clientAuth.actions.copied": "Copiado",
"settings.remoteInstances.clientAuth.addDevice.transportLabel": "¿Dónde usarás este dispositivo?",
"settings.remoteInstances.clientAuth.addDevice.subtitle": "Crea un código QR de un solo uso que conecta otro dispositivo a este servidor.",
"settings.remoteInstances.clientAuth.addDevice.transport.local": "Solo este equipo",
"settings.remoteInstances.clientAuth.addDevice.transport.localHint": "Para aplicaciones en esta misma máquina.",
"settings.remoteInstances.clientAuth.addDevice.transport.lan": "Solo red doméstica",
"settings.remoteInstances.clientAuth.addDevice.transport.lanHint": "Se conecta directamente por tu Wi-Fi. No funciona fuera de esta red.",
"settings.remoteInstances.clientAuth.addDevice.transport.relay": "En cualquier lugar",
"settings.remoteInstances.clientAuth.addDevice.transport.relayHint": "Funciona en casa y fuera. Fuera de casa el tráfico pasa por OpenChamber Private Relay, un túnel cifrado de extremo a extremo. Sin configuración.",
"settings.remoteInstances.clientAuth.addDevice.fallback.relay": "Permitir también el relay cifrado fuera de casa",
"settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal": "Preferir la conexión doméstica directa cuando esté disponible",
"settings.remoteInstances.clientAuth.addDevice.create": "Crear código QR",
"settings.remoteInstances.clientAuth.addDevice.done": "Listo",
"settings.remoteInstances.clientAuth.pairingUrl": "Enlace de conexión",
"settings.remoteInstances.clientAuth.createdToken": "Copia este token ahora. Por seguridad, no se volverá a mostrar.",
"settings.remoteInstances.clientAuth.state.loading": "Cargando tokens...",
"settings.remoteInstances.clientAuth.state.empty": "Todavía no hay dispositivos conectados.",
"settings.remoteInstances.clientAuth.state.revoked": "Revocado",
"settings.remoteInstances.clientAuth.state.thisDevice": "Este dispositivo",
"settings.remoteInstances.clientAuth.state.pending": "Esperando conexión…",
"settings.remoteInstances.clientAuth.state.viaRelay": "Relay",
"settings.remoteInstances.clientAuth.state.connectedDirect": "Conectado · Red local",
"settings.remoteInstances.clientAuth.state.connectedRelay": "Conectado · Relay",
"settings.remoteInstances.clientAuth.lastUsed": "Último uso {date}",
"settings.remoteInstances.clientAuth.neverUsed": "Nunca usado",
"settings.remoteInstances.relay.title": "OpenChamber Relay",
"settings.remoteInstances.relay.autoHint": "Se activa automáticamente al vincular un dispositivo por relay.",
"settings.remoteInstances.relay.description": "Permite que tus otros dispositivos se conecten desde cualquier lugar sin abrir puertos. El tráfico está cifrado de extremo a extremo: el relay no puede leerlo.",
"settings.remoteInstances.relay.enableHint": "No se comparte nada hasta que actives el relay en este servidor.",
"settings.remoteInstances.relay.actions.enable": "Activar Relay",
@@ -1781,21 +1781,43 @@ export const settingsDict = {
'settings.remoteInstances.direct.state.empty': 'Aucun autre serveur ajouté pour le moment.',
'settings.remoteInstances.clientAuth.title': 'Se connecter à ce serveur',
'settings.remoteInstances.clientAuth.description': 'Créez un lien ou un token sécurisé pour permettre à OpenChamber Desktop de se connecter à ce serveur.',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': 'Nom de l’appareil (facultatif)',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': 'Nom du nouvel appareil — ex. Mon iPhone',
'settings.remoteInstances.clientAuth.actions.create': 'Créer un token',
'settings.remoteInstances.clientAuth.actions.pair': 'Créer un lien',
'settings.remoteInstances.clientAuth.actions.revoke': 'Révoquer',
'settings.remoteInstances.clientAuth.actions.clearRevoked': 'Effacer les révocations',
'settings.remoteInstances.clientAuth.qrAlt': 'QR code de connexion OpenChamber',
'settings.remoteInstances.clientAuth.qrEnlarge': 'Agrandir le QR code',
'settings.remoteInstances.clientAuth.qrScanHint': "Scannez-le avec l'application OpenChamber sur votre autre appareil. À usage unique et expire.",
'settings.remoteInstances.clientAuth.qrDialogTitle': 'Scanner pour se connecter',
'settings.remoteInstances.clientAuth.actions.addDevice': 'Ajouter un appareil',
'settings.remoteInstances.clientAuth.actions.copied': 'Copié',
'settings.remoteInstances.clientAuth.addDevice.transportLabel': 'Où utiliserez-vous cet appareil ?',
'settings.remoteInstances.clientAuth.addDevice.subtitle': 'Créez un code QR à usage unique qui connecte un autre appareil à ce serveur.',
'settings.remoteInstances.clientAuth.addDevice.transport.local': 'Cet ordinateur uniquement',
'settings.remoteInstances.clientAuth.addDevice.transport.localHint': 'Pour les applications sur cette même machine.',
'settings.remoteInstances.clientAuth.addDevice.transport.lan': 'Réseau domestique uniquement',
'settings.remoteInstances.clientAuth.addDevice.transport.lanHint': 'Connexion directe via votre Wi-Fi. Ne fonctionne pas hors de ce réseau.',
'settings.remoteInstances.clientAuth.addDevice.transport.relay': 'Partout',
'settings.remoteInstances.clientAuth.addDevice.transport.relayHint': 'Fonctionne à la maison et en déplacement. En déplacement, le trafic passe par OpenChamber Private Relay — un tunnel chiffré de bout en bout. Aucune configuration.',
'settings.remoteInstances.clientAuth.addDevice.fallback.relay': 'Autoriser aussi le relais chiffré en déplacement',
'settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal': 'Préférer la connexion domestique directe quand elle est disponible',
'settings.remoteInstances.clientAuth.addDevice.create': 'Créer le code QR',
'settings.remoteInstances.clientAuth.addDevice.done': 'Terminé',
'settings.remoteInstances.clientAuth.pairingUrl': 'Lien de connexion',
'settings.remoteInstances.clientAuth.createdToken': 'Copiez ce token maintenant. Pour des raisons de sécurité, il ne sera plus affiché.',
'settings.remoteInstances.clientAuth.state.loading': 'Chargement des tokens...',
'settings.remoteInstances.clientAuth.state.empty': 'Aucun appareil connecté pour le moment.',
'settings.remoteInstances.clientAuth.state.revoked': 'Révoqué',
'settings.remoteInstances.clientAuth.state.thisDevice': 'Cet appareil',
'settings.remoteInstances.clientAuth.state.pending': 'En attente de connexion…',
'settings.remoteInstances.clientAuth.state.viaRelay': 'Relay',
'settings.remoteInstances.clientAuth.state.connectedDirect': 'Connecté · Réseau local',
'settings.remoteInstances.clientAuth.state.connectedRelay': 'Connecté · Relais',
'settings.remoteInstances.clientAuth.lastUsed': 'Dernière utilisation le {date}',
'settings.remoteInstances.clientAuth.neverUsed': 'Jamais utilisé',
'settings.remoteInstances.relay.title': 'OpenChamber Relay',
'settings.remoteInstances.relay.autoHint': 'Activé automatiquement lorsque vous associez un appareil via le relais.',
'settings.remoteInstances.relay.description': 'Permettez à vos autres appareils de se connecter depuis n’importe où sans ouvrir de ports. Le trafic est chiffré de bout en bout — le relais ne peut pas le lire.',
'settings.remoteInstances.relay.enableHint': 'Rien n’est partagé tant que vous n’activez pas le relais sur ce serveur.',
'settings.remoteInstances.relay.actions.enable': 'Activer le relais',
@@ -273,21 +273,43 @@ export const settingsDict = {
'settings.remoteInstances.direct.state.empty': 'まだ他のサーバーが追加されていません。',
'settings.remoteInstances.clientAuth.title': 'このサーバーに接続',
'settings.remoteInstances.clientAuth.description': 'OpenChamber Desktop がこのサーバーに接続できるように、安全なリンクまたは Token を作成します。',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': 'デバイス名(任意)',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': 'デバイス名 — 例: My iPhone',
'settings.remoteInstances.clientAuth.actions.create': 'Token を作成',
'settings.remoteInstances.clientAuth.actions.pair': 'リンクを作成',
'settings.remoteInstances.clientAuth.actions.revoke': '無効化',
'settings.remoteInstances.clientAuth.actions.clearRevoked': '無効化済みをクリア',
'settings.remoteInstances.clientAuth.qrAlt': 'OpenChamber 接続 QR コード',
'settings.remoteInstances.clientAuth.qrEnlarge': 'QR コードを拡大',
'settings.remoteInstances.clientAuth.qrScanHint': '別のデバイスの OpenChamber アプリでスキャンしてください。1 回限りで期限切れになります。',
'settings.remoteInstances.clientAuth.qrDialogTitle': 'スキャンして接続',
'settings.remoteInstances.clientAuth.actions.addDevice': 'デバイスを追加',
'settings.remoteInstances.clientAuth.actions.copied': 'コピーしました',
'settings.remoteInstances.clientAuth.addDevice.transportLabel': 'このデバイスをどこで使いますか?',
'settings.remoteInstances.clientAuth.addDevice.subtitle': 'このサーバーに別のデバイスを接続する使い捨てQRコードを作成します。',
'settings.remoteInstances.clientAuth.addDevice.transport.local': 'このコンピュータのみ',
'settings.remoteInstances.clientAuth.addDevice.transport.localHint': '同じマシン上のアプリ用です。',
'settings.remoteInstances.clientAuth.addDevice.transport.lan': '自宅ネットワークのみ',
'settings.remoteInstances.clientAuth.addDevice.transport.lanHint': 'Wi-Fi経由で直接接続します。このネットワークの外では使えません。',
'settings.remoteInstances.clientAuth.addDevice.transport.relay': 'どこでも',
'settings.remoteInstances.clientAuth.addDevice.transport.relayHint': '自宅でも外出先でも使えます。外出先の通信は、エンドツーエンド暗号化トンネルのOpenChamber Private Relayを経由します。設定は不要です。',
'settings.remoteInstances.clientAuth.addDevice.fallback.relay': '外出先では暗号化リレー経由の接続も許可',
'settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal': '可能なときは自宅の直接接続を優先',
'settings.remoteInstances.clientAuth.addDevice.create': 'QRコードを作成',
'settings.remoteInstances.clientAuth.addDevice.done': '完了',
'settings.remoteInstances.clientAuth.pairingUrl': '接続リンク',
'settings.remoteInstances.clientAuth.createdToken': 'この Token を今すぐコピーしてください。セキュリティのため、再表示されません。',
'settings.remoteInstances.clientAuth.state.loading': 'Token を読み込み中...',
'settings.remoteInstances.clientAuth.state.empty': 'まだデバイスが接続されていません。',
'settings.remoteInstances.clientAuth.state.revoked': '無効化済み',
'settings.remoteInstances.clientAuth.state.thisDevice': 'このデバイス',
'settings.remoteInstances.clientAuth.state.pending': '接続を待機中…',
'settings.remoteInstances.clientAuth.state.viaRelay': 'Relay',
'settings.remoteInstances.clientAuth.state.connectedDirect': '接続中 · ローカルネットワーク',
'settings.remoteInstances.clientAuth.state.connectedRelay': '接続中 · リレー',
'settings.remoteInstances.clientAuth.lastUsed': '最終使用 {date}',
'settings.remoteInstances.clientAuth.neverUsed': '未使用',
'settings.remoteInstances.relay.title': 'OpenChamber Relay',
'settings.remoteInstances.relay.autoHint': 'リレー経由でデバイスをペアリングすると自動的に有効になります。',
'settings.remoteInstances.relay.description': 'ポートを開放せずに、他のデバイスからどこからでも接続できます。通信はエンドツーエンドで暗号化され、リレーは内容を読めません。',
'settings.remoteInstances.relay.enableHint': 'このサーバーでリレーを有効にするまで、何も共有されません。',
'settings.remoteInstances.relay.actions.enable': 'リレーを有効にする',
@@ -240,21 +240,43 @@ export const settingsDict = {
'settings.remoteInstances.direct.state.empty': '아직 추가된 다른 서버가 없습니다.',
'settings.remoteInstances.clientAuth.title': '이 서버에 연결',
'settings.remoteInstances.clientAuth.description': 'OpenChamber Desktop이 이 서버에 연결할 수 있도록 안전한 링크나 토큰을 만듭니다.',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': '기기 이름(선택 사항)',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': '기기 이름 — 예: My iPhone',
'settings.remoteInstances.clientAuth.actions.create': '토큰 만들기',
'settings.remoteInstances.clientAuth.actions.pair': '링크 만들기',
'settings.remoteInstances.clientAuth.actions.revoke': '해지',
'settings.remoteInstances.clientAuth.actions.clearRevoked': '해지된 항목 지우기',
'settings.remoteInstances.clientAuth.qrAlt': 'OpenChamber connection QR code',
'settings.remoteInstances.clientAuth.qrEnlarge': 'QR 코드 확대',
'settings.remoteInstances.clientAuth.qrScanHint': '다른 기기의 OpenChamber 앱으로 스캔하세요. 일회용이며 만료됩니다.',
'settings.remoteInstances.clientAuth.qrDialogTitle': '스캔하여 연결',
'settings.remoteInstances.clientAuth.actions.addDevice': '기기 추가',
'settings.remoteInstances.clientAuth.actions.copied': '복사됨',
'settings.remoteInstances.clientAuth.addDevice.transportLabel': '이 기기를 어디에서 사용하나요?',
'settings.remoteInstances.clientAuth.addDevice.subtitle': '다른 기기를 이 서버에 연결하는 일회용 QR 코드를 만듭니다.',
'settings.remoteInstances.clientAuth.addDevice.transport.local': '이 컴퓨터 전용',
'settings.remoteInstances.clientAuth.addDevice.transport.localHint': '같은 컴퓨터의 앱을 위한 옵션입니다.',
'settings.remoteInstances.clientAuth.addDevice.transport.lan': '집 네트워크 전용',
'settings.remoteInstances.clientAuth.addDevice.transport.lanHint': 'Wi-Fi로 직접 연결합니다. 이 네트워크 밖에서는 작동하지 않습니다.',
'settings.remoteInstances.clientAuth.addDevice.transport.relay': '어디서나',
'settings.remoteInstances.clientAuth.addDevice.transport.relayHint': '집과 밖 어디서나 작동합니다. 밖에서는 종단간 암호화 터널인 OpenChamber Private Relay를 통해 연결됩니다. 설정이 필요 없습니다.',
'settings.remoteInstances.clientAuth.addDevice.fallback.relay': '밖에서는 암호화 릴레이 연결도 허용',
'settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal': '가능하면 집에서는 직접 연결 우선',
'settings.remoteInstances.clientAuth.addDevice.create': 'QR 코드 만들기',
'settings.remoteInstances.clientAuth.addDevice.done': '완료',
'settings.remoteInstances.clientAuth.pairingUrl': '연결 링크',
'settings.remoteInstances.clientAuth.createdToken': '지금 이 토큰을 복사하세요. 보안을 위해 다시 표시되지 않습니다.',
'settings.remoteInstances.clientAuth.state.loading': '토큰을 불러오는 중...',
'settings.remoteInstances.clientAuth.state.empty': '아직 연결된 기기가 없습니다.',
'settings.remoteInstances.clientAuth.state.revoked': '해지됨',
'settings.remoteInstances.clientAuth.state.thisDevice': '이 기기',
'settings.remoteInstances.clientAuth.state.pending': '연결 대기 중…',
'settings.remoteInstances.clientAuth.state.viaRelay': 'Relay',
'settings.remoteInstances.clientAuth.state.connectedDirect': '연결됨 · 로컬 네트워크',
'settings.remoteInstances.clientAuth.state.connectedRelay': '연결됨 · 릴레이',
'settings.remoteInstances.clientAuth.lastUsed': '마지막 사용 {date}',
'settings.remoteInstances.clientAuth.neverUsed': '사용한 적 없음',
'settings.remoteInstances.relay.title': 'OpenChamber Relay',
'settings.remoteInstances.relay.autoHint': '릴레이로 기기를 페어링하면 자동으로 켜집니다.',
'settings.remoteInstances.relay.description': '포트를 열지 않고도 다른 기기가 어디서든 연결할 수 있습니다. 트래픽은 종단 간 암호화되어 릴레이는 내용을 읽을 수 없습니다.',
'settings.remoteInstances.relay.enableHint': '이 서버에서 릴레이를 켜기 전까지는 아무것도 공유되지 않습니다.',
'settings.remoteInstances.relay.actions.enable': '릴레이 켜기',
@@ -1469,21 +1469,43 @@ export const settingsDict = {
'settings.remoteInstances.direct.state.empty': 'Nie dodano jeszcze innych serwerów.',
'settings.remoteInstances.clientAuth.title': 'Połącz z tym serwerem',
'settings.remoteInstances.clientAuth.description': 'Utwórz bezpieczny link lub token, aby OpenChamber Desktop mógł połączyć się z tym serwerem.',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': 'Nazwa urządzenia (opcjonalnie)',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': 'Nazwa urządzenia — np. Mój iPhone',
'settings.remoteInstances.clientAuth.actions.create': 'Utwórz token',
'settings.remoteInstances.clientAuth.actions.pair': 'Utwórz link',
'settings.remoteInstances.clientAuth.actions.revoke': 'Unieważnij',
'settings.remoteInstances.clientAuth.actions.clearRevoked': 'Wyczyść unieważnione',
'settings.remoteInstances.clientAuth.qrAlt': 'Kod QR połączenia OpenChamber',
'settings.remoteInstances.clientAuth.qrEnlarge': 'Powiększ kod QR',
'settings.remoteInstances.clientAuth.qrScanHint': 'Zeskanuj to aplikacją OpenChamber na drugim urządzeniu. Jednorazowy i wygasa.',
'settings.remoteInstances.clientAuth.qrDialogTitle': 'Zeskanuj, aby połączyć',
'settings.remoteInstances.clientAuth.actions.addDevice': 'Dodaj urządzenie',
'settings.remoteInstances.clientAuth.actions.copied': 'Skopiowano',
'settings.remoteInstances.clientAuth.addDevice.transportLabel': 'Gdzie będziesz używać tego urządzenia?',
'settings.remoteInstances.clientAuth.addDevice.subtitle': 'Utwórz jednorazowy kod QR, który połączy inne urządzenie z tym serwerem.',
'settings.remoteInstances.clientAuth.addDevice.transport.local': 'Tylko ten komputer',
'settings.remoteInstances.clientAuth.addDevice.transport.localHint': 'Dla aplikacji na tej samej maszynie.',
'settings.remoteInstances.clientAuth.addDevice.transport.lan': 'Tylko sieć domowa',
'settings.remoteInstances.clientAuth.addDevice.transport.lanHint': 'Łączy się bezpośrednio przez Wi-Fi. Nie działa poza tą siecią.',
'settings.remoteInstances.clientAuth.addDevice.transport.relay': 'Wszędzie',
'settings.remoteInstances.clientAuth.addDevice.transport.relayHint': 'Działa w domu i poza nim. Poza domem ruch przechodzi przez OpenChamber Private Relay — szyfrowany end-to-end tunel. Bez konfiguracji.',
'settings.remoteInstances.clientAuth.addDevice.fallback.relay': 'Zezwól też na szyfrowany relay poza domem',
'settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal': 'Preferuj bezpośrednie połączenie domowe, gdy dostępne',
'settings.remoteInstances.clientAuth.addDevice.create': 'Utwórz kod QR',
'settings.remoteInstances.clientAuth.addDevice.done': 'Gotowe',
'settings.remoteInstances.clientAuth.pairingUrl': 'Link połączenia',
'settings.remoteInstances.clientAuth.createdToken': 'Skopiuj ten token teraz. Ze względów bezpieczeństwa nie zostanie pokazany ponownie.',
'settings.remoteInstances.clientAuth.state.loading': 'Ładowanie tokenów...',
'settings.remoteInstances.clientAuth.state.empty': 'Nie podłączono jeszcze żadnych urządzeń.',
'settings.remoteInstances.clientAuth.state.revoked': 'Unieważniony',
'settings.remoteInstances.clientAuth.state.thisDevice': 'To urządzenie',
'settings.remoteInstances.clientAuth.state.pending': 'Oczekiwanie na połączenie…',
'settings.remoteInstances.clientAuth.state.viaRelay': 'Relay',
'settings.remoteInstances.clientAuth.state.connectedDirect': 'Połączono · Sieć lokalna',
'settings.remoteInstances.clientAuth.state.connectedRelay': 'Połączono · Relay',
'settings.remoteInstances.clientAuth.lastUsed': 'Ostatnio użyto {date}',
'settings.remoteInstances.clientAuth.neverUsed': 'Nigdy nie użyto',
'settings.remoteInstances.relay.title': 'OpenChamber Relay',
'settings.remoteInstances.relay.autoHint': 'Włącza się automatycznie po sparowaniu urządzenia przez relay.',
'settings.remoteInstances.relay.description': 'Pozwól swoim innym urządzeniom łączyć się z dowolnego miejsca bez otwierania portów. Ruch jest szyfrowany od końca do końca — relay nie może go odczytać.',
'settings.remoteInstances.relay.enableHint': 'Nic nie jest udostępniane, dopóki nie włączysz relay na tym serwerze.',
'settings.remoteInstances.relay.actions.enable': 'Włącz Relay',
@@ -240,21 +240,43 @@ export const settingsDict = {
"settings.remoteInstances.direct.state.empty": "Nenhum outro servidor adicionado ainda.",
"settings.remoteInstances.clientAuth.title": "Conectar a este servidor",
"settings.remoteInstances.clientAuth.description": "Crie um link ou token seguro para que o OpenChamber Desktop possa se conectar a este servidor.",
"settings.remoteInstances.clientAuth.field.labelPlaceholder": "Nome do dispositivo (opcional)",
"settings.remoteInstances.clientAuth.field.labelPlaceholder": "Nome do dispositivo — ex.: Meu iPhone",
"settings.remoteInstances.clientAuth.actions.create": "Criar token",
"settings.remoteInstances.clientAuth.actions.pair": "Criar link",
"settings.remoteInstances.clientAuth.actions.revoke": "Revogar",
"settings.remoteInstances.clientAuth.actions.clearRevoked": "Limpar revogados",
"settings.remoteInstances.clientAuth.qrAlt": "OpenChamber connection QR code",
"settings.remoteInstances.clientAuth.qrEnlarge": "Ampliar código QR",
"settings.remoteInstances.clientAuth.qrScanHint": "Escaneie com o app OpenChamber no seu outro dispositivo. É de uso único e expira.",
"settings.remoteInstances.clientAuth.qrDialogTitle": "Escanear para conectar",
"settings.remoteInstances.clientAuth.actions.addDevice": "Adicionar um dispositivo",
"settings.remoteInstances.clientAuth.actions.copied": "Copiado",
"settings.remoteInstances.clientAuth.addDevice.transportLabel": "Onde você vai usar este dispositivo?",
"settings.remoteInstances.clientAuth.addDevice.subtitle": "Crie um código QR de uso único que conecta outro dispositivo a este servidor.",
"settings.remoteInstances.clientAuth.addDevice.transport.local": "Somente este computador",
"settings.remoteInstances.clientAuth.addDevice.transport.localHint": "Para aplicativos nesta mesma máquina.",
"settings.remoteInstances.clientAuth.addDevice.transport.lan": "Somente rede doméstica",
"settings.remoteInstances.clientAuth.addDevice.transport.lanHint": "Conecta diretamente pela sua rede Wi-Fi. Não funciona fora desta rede.",
"settings.remoteInstances.clientAuth.addDevice.transport.relay": "Em qualquer lugar",
"settings.remoteInstances.clientAuth.addDevice.transport.relayHint": "Funciona em casa e fora. Fora de casa o tráfego passa pelo OpenChamber Private Relay, um túnel criptografado de ponta a ponta. Sem configuração.",
"settings.remoteInstances.clientAuth.addDevice.fallback.relay": "Também permitir o relay criptografado fora de casa",
"settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal": "Preferir a conexão doméstica direta quando disponível",
"settings.remoteInstances.clientAuth.addDevice.create": "Criar código QR",
"settings.remoteInstances.clientAuth.addDevice.done": "Concluído",
"settings.remoteInstances.clientAuth.pairingUrl": "Link de conexão",
"settings.remoteInstances.clientAuth.createdToken": "Copie este token agora. Por segurança, ele não será mostrado novamente.",
"settings.remoteInstances.clientAuth.state.loading": "Carregando tokens...",
"settings.remoteInstances.clientAuth.state.empty": "Nenhum dispositivo conectado ainda.",
"settings.remoteInstances.clientAuth.state.revoked": "Revogado",
"settings.remoteInstances.clientAuth.state.thisDevice": "Este dispositivo",
"settings.remoteInstances.clientAuth.state.pending": "Aguardando conexão…",
"settings.remoteInstances.clientAuth.state.viaRelay": "Relay",
"settings.remoteInstances.clientAuth.state.connectedDirect": "Conectado · Rede local",
"settings.remoteInstances.clientAuth.state.connectedRelay": "Conectado · Relay",
"settings.remoteInstances.clientAuth.lastUsed": "Último uso em {date}",
"settings.remoteInstances.clientAuth.neverUsed": "Nunca usado",
"settings.remoteInstances.relay.title": "OpenChamber Relay",
"settings.remoteInstances.relay.autoHint": "Liga automaticamente ao parear um dispositivo pelo relay.",
"settings.remoteInstances.relay.description": "Permita que seus outros dispositivos se conectem de qualquer lugar sem abrir portas. O tráfego é criptografado de ponta a ponta — o relay não consegue lê-lo.",
"settings.remoteInstances.relay.enableHint": "Nada é compartilhado até você ativar o relay neste servidor.",
"settings.remoteInstances.relay.actions.enable": "Ativar Relay",
@@ -240,21 +240,43 @@ export const settingsDict = {
"settings.remoteInstances.direct.state.empty": "Інших серверів ще не додано.",
"settings.remoteInstances.clientAuth.title": "Підключення до цього сервера",
"settings.remoteInstances.clientAuth.description": "Створіть безпечне посилання або токен, щоб OpenChamber Desktop міг підключитися до цього сервера.",
"settings.remoteInstances.clientAuth.field.labelPlaceholder": "Назва пристрою (необов’язково)",
"settings.remoteInstances.clientAuth.field.labelPlaceholder": "Назва пристрою — напр. Мій iPhone",
"settings.remoteInstances.clientAuth.actions.create": "Створити токен",
"settings.remoteInstances.clientAuth.actions.pair": "Створити посилання",
"settings.remoteInstances.clientAuth.actions.revoke": "Відкликати",
"settings.remoteInstances.clientAuth.actions.clearRevoked": "Очистити відкликані",
"settings.remoteInstances.clientAuth.qrAlt": "QR-код підключення OpenChamber",
"settings.remoteInstances.clientAuth.qrEnlarge": "Збільшити QR-код",
"settings.remoteInstances.clientAuth.qrScanHint": "Скануй це застосунком OpenChamber на іншому пристрої. Одноразовий і має термін дії.",
"settings.remoteInstances.clientAuth.qrDialogTitle": "Сканувати для підключення",
"settings.remoteInstances.clientAuth.actions.addDevice": "Додати пристрій",
"settings.remoteInstances.clientAuth.actions.copied": "Скопійовано",
"settings.remoteInstances.clientAuth.addDevice.transportLabel": "Де ви будете користуватись цим пристроєм?",
"settings.remoteInstances.clientAuth.addDevice.subtitle": "Створіть одноразовий QR-код, який підключить інший пристрій до цього сервера.",
"settings.remoteInstances.clientAuth.addDevice.transport.local": "Лише цей компʼютер",
"settings.remoteInstances.clientAuth.addDevice.transport.localHint": "Для застосунків на цій самій машині.",
"settings.remoteInstances.clientAuth.addDevice.transport.lan": "Лише домашня мережа",
"settings.remoteInstances.clientAuth.addDevice.transport.lanHint": "Підключається напряму через ваш Wi-Fi. Поза цією мережею не працює.",
"settings.remoteInstances.clientAuth.addDevice.transport.relay": "Будь-де",
"settings.remoteInstances.clientAuth.addDevice.transport.relayHint": "Працює вдома і поза домом. Поза домом трафік іде через OpenChamber Private Relay — наскрізно зашифрований тунель. Нічого налаштовувати не треба.",
"settings.remoteInstances.clientAuth.addDevice.fallback.relay": "Також дозволити зашифрований relay поза домом",
"settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal": "Віддавати перевагу прямому домашньому підключенню, коли доступне",
"settings.remoteInstances.clientAuth.addDevice.create": "Створити QR-код",
"settings.remoteInstances.clientAuth.addDevice.done": "Готово",
"settings.remoteInstances.clientAuth.pairingUrl": "Посилання для підключення",
"settings.remoteInstances.clientAuth.createdToken": "Скопіюйте цей токен зараз. З міркувань безпеки він більше не показуватиметься.",
"settings.remoteInstances.clientAuth.state.loading": "Завантаження токенів...",
"settings.remoteInstances.clientAuth.state.empty": "Жоден пристрій ще не підключено.",
"settings.remoteInstances.clientAuth.state.revoked": "Відкликано",
"settings.remoteInstances.clientAuth.state.thisDevice": "Цей пристрій",
"settings.remoteInstances.clientAuth.state.pending": "Очікує підключення…",
"settings.remoteInstances.clientAuth.state.viaRelay": "Relay",
"settings.remoteInstances.clientAuth.state.connectedDirect": "Підключено · Локальна мережа",
"settings.remoteInstances.clientAuth.state.connectedRelay": "Підключено · Relay",
"settings.remoteInstances.clientAuth.lastUsed": "Останнє використання {date}",
"settings.remoteInstances.clientAuth.neverUsed": "Ще не використовувався",
"settings.remoteInstances.relay.title": "OpenChamber Relay",
"settings.remoteInstances.relay.autoHint": "Вмикається автоматично, коли ти паруєш пристрій через relay.",
"settings.remoteInstances.relay.description": "Дозволяє вашим іншим пристроям підключатися звідки завгодно без відкриття портів. Трафік шифрується наскрізно — релей не може його прочитати.",
"settings.remoteInstances.relay.enableHint": "Нічого не передається, доки ви не увімкнете релей на цьому сервері.",
"settings.remoteInstances.relay.actions.enable": "Увімкнути Relay",
@@ -240,21 +240,43 @@ export const settingsDict = {
'settings.remoteInstances.direct.state.empty': '尚未添加其他服务器。',
'settings.remoteInstances.clientAuth.title': '连接到此服务器',
'settings.remoteInstances.clientAuth.description': '创建安全链接或令牌,让 OpenChamber Desktop 可以连接到此服务器。',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': '设备名称(可选)',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': '设备名称 — 例如 My iPhone',
'settings.remoteInstances.clientAuth.actions.create': '创建令牌',
'settings.remoteInstances.clientAuth.actions.pair': '创建链接',
'settings.remoteInstances.clientAuth.actions.revoke': '撤销',
'settings.remoteInstances.clientAuth.actions.clearRevoked': '清除已撤销',
'settings.remoteInstances.clientAuth.qrAlt': 'OpenChamber connection QR code',
'settings.remoteInstances.clientAuth.qrEnlarge': '放大二维码',
'settings.remoteInstances.clientAuth.qrScanHint': '用另一台设备上的 OpenChamber 应用扫描。一次性使用且会过期。',
'settings.remoteInstances.clientAuth.qrDialogTitle': '扫码连接',
'settings.remoteInstances.clientAuth.actions.addDevice': '添加设备',
'settings.remoteInstances.clientAuth.actions.copied': '已复制',
'settings.remoteInstances.clientAuth.addDevice.transportLabel': '你会在哪里使用这台设备?',
'settings.remoteInstances.clientAuth.addDevice.subtitle': '创建一次性二维码,把另一台设备连接到此服务器。',
'settings.remoteInstances.clientAuth.addDevice.transport.local': '仅本机',
'settings.remoteInstances.clientAuth.addDevice.transport.localHint': '供同一台电脑上的应用使用。',
'settings.remoteInstances.clientAuth.addDevice.transport.lan': '仅家庭网络',
'settings.remoteInstances.clientAuth.addDevice.transport.lanHint': '通过 Wi-Fi 直接连接。离开此网络后无法使用。',
'settings.remoteInstances.clientAuth.addDevice.transport.relay': '任何地方',
'settings.remoteInstances.clientAuth.addDevice.transport.relayHint': '在家和外出都可用。外出时流量经由 OpenChamber Private Relay(端到端加密隧道)传输,无需配置。',
'settings.remoteInstances.clientAuth.addDevice.fallback.relay': '外出时也允许通过加密中继连接',
'settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal': '在家时优先使用直接连接',
'settings.remoteInstances.clientAuth.addDevice.create': '创建二维码',
'settings.remoteInstances.clientAuth.addDevice.done': '完成',
'settings.remoteInstances.clientAuth.pairingUrl': '连接链接',
'settings.remoteInstances.clientAuth.createdToken': '请立即复制此令牌。出于安全考虑,它不会再次显示。',
'settings.remoteInstances.clientAuth.state.loading': '正在加载令牌...',
'settings.remoteInstances.clientAuth.state.empty': '尚无已连接设备。',
'settings.remoteInstances.clientAuth.state.revoked': '已撤销',
'settings.remoteInstances.clientAuth.state.thisDevice': '此设备',
'settings.remoteInstances.clientAuth.state.pending': '等待连接…',
'settings.remoteInstances.clientAuth.state.viaRelay': 'Relay',
'settings.remoteInstances.clientAuth.state.connectedDirect': '已连接 · 局域网',
'settings.remoteInstances.clientAuth.state.connectedRelay': '已连接 · 中继',
'settings.remoteInstances.clientAuth.lastUsed': '上次使用 {date}',
'settings.remoteInstances.clientAuth.neverUsed': '从未使用',
'settings.remoteInstances.relay.title': 'OpenChamber Relay',
'settings.remoteInstances.relay.autoHint': '通过中继配对设备时自动开启。',
'settings.remoteInstances.relay.description': '无需开放端口,即可让你的其他设备从任何地方连接。流量端到端加密,中继无法读取内容。',
'settings.remoteInstances.relay.enableHint': '在此服务器上启用中继之前,不会共享任何内容。',
'settings.remoteInstances.relay.actions.enable': '启用中继',
@@ -246,21 +246,43 @@
'settings.remoteInstances.direct.state.empty': '尚無直接連線。',
'settings.remoteInstances.clientAuth.title': '用戶端存取 token',
'settings.remoteInstances.clientAuth.description': '建立與管理可讓桌面或遠端用戶端連線的 token。',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': '裝置或用戶端名稱',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': '裝置名稱 — 例如 My iPhone',
'settings.remoteInstances.clientAuth.actions.create': '建立 token',
'settings.remoteInstances.clientAuth.actions.pair': '配對裝置',
'settings.remoteInstances.clientAuth.actions.revoke': '撤銷',
'settings.remoteInstances.clientAuth.actions.clearRevoked': '清除已撤銷',
'settings.remoteInstances.clientAuth.qrAlt': '配對 QR code',
'settings.remoteInstances.clientAuth.qrEnlarge': '放大 QR code',
'settings.remoteInstances.clientAuth.qrScanHint': '用另一台裝置上的 OpenChamber 應用程式掃描。一次性使用且會過期。',
'settings.remoteInstances.clientAuth.qrDialogTitle': '掃碼連線',
'settings.remoteInstances.clientAuth.actions.addDevice': '新增裝置',
'settings.remoteInstances.clientAuth.actions.copied': '已複製',
'settings.remoteInstances.clientAuth.addDevice.transportLabel': '你會在哪裡使用這台裝置?',
'settings.remoteInstances.clientAuth.addDevice.subtitle': '建立一次性 QR 代碼,將另一台裝置連線到此伺服器。',
'settings.remoteInstances.clientAuth.addDevice.transport.local': '僅本機',
'settings.remoteInstances.clientAuth.addDevice.transport.localHint': '供同一台電腦上的應用程式使用。',
'settings.remoteInstances.clientAuth.addDevice.transport.lan': '僅家用網路',
'settings.remoteInstances.clientAuth.addDevice.transport.lanHint': '透過 Wi-Fi 直接連線。離開此網路後無法使用。',
'settings.remoteInstances.clientAuth.addDevice.transport.relay': '任何地方',
'settings.remoteInstances.clientAuth.addDevice.transport.relayHint': '在家與外出都可用。外出時流量經由 OpenChamber Private Relay(端對端加密隧道)傳輸,無需設定。',
'settings.remoteInstances.clientAuth.addDevice.fallback.relay': '外出時也允許透過加密中繼連線',
'settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal': '在家時優先使用直接連線',
'settings.remoteInstances.clientAuth.addDevice.create': '建立 QR 代碼',
'settings.remoteInstances.clientAuth.addDevice.done': '完成',
'settings.remoteInstances.clientAuth.pairingUrl': '配對 URL',
'settings.remoteInstances.clientAuth.createdToken': '已建立 token',
'settings.remoteInstances.clientAuth.state.loading': '正在載入用戶端 token...',
'settings.remoteInstances.clientAuth.state.empty': '尚無用戶端 token。',
'settings.remoteInstances.clientAuth.state.revoked': '已撤銷',
'settings.remoteInstances.clientAuth.state.thisDevice': '此裝置',
'settings.remoteInstances.clientAuth.state.pending': '等待連線…',
'settings.remoteInstances.clientAuth.state.viaRelay': 'Relay',
'settings.remoteInstances.clientAuth.state.connectedDirect': '已連線 · 區域網路',
'settings.remoteInstances.clientAuth.state.connectedRelay': '已連線 · 中繼',
'settings.remoteInstances.clientAuth.lastUsed': '上次使用:{date}',
'settings.remoteInstances.clientAuth.neverUsed': '從未使用',
'settings.remoteInstances.relay.title': 'OpenChamber Relay',
'settings.remoteInstances.relay.autoHint': '透過中繼配對裝置時自動開啟。',
'settings.remoteInstances.relay.description': '無需開放連接埠,即可讓你的其他裝置從任何地方連線。流量端對端加密,中繼無法讀取內容。',
'settings.remoteInstances.relay.enableHint': '在此伺服器上啟用中繼之前,不會共享任何內容。',
'settings.remoteInstances.relay.actions.enable': '啟用中繼',