1b94df1604
- #7 隔夜被迫重新登录:auth.ts 加 refreshInFlight 单飞刷新。根因=broker 单次轮换 refresh token + 冷启并发 401(引擎 boot 同时 startHub/refreshSessionScope/healIOSIdentity/refreshICEServers,隔夜 access 已过期全部 401)各自用同一 refresh 刷新,首个轮换、其余 replay 失效旧 token → 401 invalid → forceLogout → 清 Keychain → 重登。单飞使并发 401 共享一次轮换。 - #2 通知系统重做:删 EngineController.deviceActionStatus/clipboardStatus 两字段及设备页/设置页内联灰字(串页、不清除);改瞬时横幅 NotificationBanner(NoticeOverlay 顶部覆盖,成功绿/失败红/信息中性、4s 自动消失、可点叉清除),设备移除/改名/剪贴板结果统一走 notify。 - #5 未读红点:EngineController unreadMessages/unreadTransfers/activeTab/seenIncomingTransfers + setActiveTab(进入对应 tab 清零)+ noteIncomingTransfer;RootView Tab .badge + onChange(selection) 同步当前页。 - #1 标签栏重排:传输 / 文件 / 消息 / 设备 / 设置(文件域相邻、设备归管理区近设置)。 - #3 日志独立界面:EngineController logs 环形缓冲(cap 300)+ clearLogs;新增 LogView(最近 N 条、分级配色、可选中、可清空),设置页引擎段「查看日志」NavigationLink。 - #8 扫码登录他端:iOS 此前仅能展示自身码被扫,缺扫描方批准能力。新增 ScannerView(VisionKit DataScannerViewController + 相机权限 + /link?r=&c= 校验);engine/main.ts 导入 qr.ts 加 fetchLoginRequest/approveLogin/denyLogin(qrRequest/qrApprove(full,persist)/qrDeny)+ 回报 loginRequest/loginApproved/loginDenied/loginFailed;EngineController pendingLoginRequest + 方法 + handleNotify;设备页工具栏「扫码登录设备」入口 + 批准确认(展示对端名/类型/IP)。 - #6 主屏小组件 + 应用外反馈:除控制中心两控件外,新增 CloudClipboardWidget(交互式主屏/锁屏小组件,上传/拉取按钮复用同一 AppIntent);新增 WidgetFeedback(App 外触发弹本地通知反馈);ClipboardIntents perform 加成功/失败/空/needApp 反馈。品牌色 Color.cdropAccent 从 RootView 移入 Shared/Theme(主 app 与扩展共用)。 - 长条行交互统一:设备 / 传输历史 / 收到的文件 一致为「点按打开 + 尾部滑动删除 + 长按菜单」。设备去掉「点按即删」、加长按移除;修滑动移除时「析构按钮预演删除动画致下方设备上移又复位」的抖动(改普通按钮 + 红色,真正删除在二次确认后);传输页 ScrollView→List 以获原生滑动删除,卡片观感经 .plain + 透明行背景 + 隐藏分隔线保留。 - i18n:3 locale 新增 ios.logs./ios.scan./ios.widget./ios.settings.viewLogs 等键并重生 iOS JSON。
399 lines
23 KiB
JSON
399 lines
23 KiB
JSON
{
|
|
"app.brand": "Commilitia Drop",
|
|
"deviceType.browser": "Browser",
|
|
"deviceType.macos": "macOS client",
|
|
"deviceType.windows": "Windows client",
|
|
"deviceType.linux": "Linux client",
|
|
"deviceType.ios": "iOS client",
|
|
"deviceType.shortcut": "Shortcut",
|
|
"app.connected": "Online",
|
|
"app.connecting": "Connecting…",
|
|
"app.disconnectedTitle": "Reconnecting",
|
|
"app.disconnectedHint": "Lost connection to the server — retrying automatically. No need to refresh.",
|
|
"auth.sessionLost.title": "Signed out",
|
|
"auth.sessionLost.body": "This device's login was revoked or expired. Please sign in again.",
|
|
"nav.accountMenu": "Account menu",
|
|
"nav.thisDeviceLabel": "This device: ",
|
|
"nav.settings": "Settings",
|
|
"nav.signOut": "Sign out",
|
|
"nav.backToHome": "← Home",
|
|
"nav.language": "语言 / Language",
|
|
"nav.theme": "主题 / Theme",
|
|
"nav.theme.light": "Light",
|
|
"nav.theme.dark": "Dark",
|
|
"nav.theme.system": "Follow system",
|
|
"nav.themeToggle": "Toggle theme",
|
|
"home.greeting": "Hello, {{name}}",
|
|
"home.deviceList.title": "Devices",
|
|
"home.deviceList.onlineSuffix": "({{count}} online)",
|
|
"home.deviceList.showOffline": "Show offline ({{count}})",
|
|
"home.deviceList.hideOffline": "Hide offline",
|
|
"home.deviceList.empty": "No peer devices yet. Open the app in another tab with a different device name (Settings → Device name) to see it here.",
|
|
"home.tabs.file": "File",
|
|
"home.tabs.message": "Message",
|
|
"home.tabs.clipboard": "Clipboard",
|
|
"home.file.dropzone": "Drop a file here or click to browse",
|
|
"home.file.selectedSize": "{{name}} ({{size}})",
|
|
"home.file.rejected": "File rejected",
|
|
"home.cta.selectDeviceAndFile": "Select a device and a file",
|
|
"home.cta.selectFile": "Select a file",
|
|
"home.cta.selectDevice": "Select a device",
|
|
"home.cta.sendTo": "Send to {{name}}",
|
|
"home.message.placeholder": "Type a message to {{name}}…",
|
|
"home.message.placeholderEmpty": "Select a device first",
|
|
"home.message.hint": "Enter to send, Shift+Enter for newline. Max 4 KB.",
|
|
"home.message.title": "Messages",
|
|
"home.message.countSuffix": "({{count}})",
|
|
"home.message.clearAll": "Clear all",
|
|
"home.transfer.active": "Active",
|
|
"home.transfer.history": "Recent transfers",
|
|
"home.clipboard.cloudTitle": "Latest from cloud",
|
|
"home.clipboard.cloudFrom": "From {{name}} · {{time}}",
|
|
"home.clipboard.cloudFromSelf": "From this device · {{time}}",
|
|
"home.clipboard.cloudEmpty": "Nothing synced yet.",
|
|
"home.clipboard.copyToLocal": "Copy to local clipboard",
|
|
"home.clipboard.copyToLocalSuccess": "Copied to local clipboard",
|
|
"home.clipboard.uploadTitle": "Sync local clipboard",
|
|
"home.clipboard.uploadHint": "Plain text only, max 64 KB. Styles (bold / color) are stripped.",
|
|
"home.clipboard.uploadButton": "Upload local clipboard",
|
|
"home.clipboard.uploading": "Uploading…",
|
|
"home.clipboard.uploadEmpty": "Local clipboard is empty",
|
|
"home.clipboard.refresh": "Refresh",
|
|
"home.clipboard.clear": "Clear cloud",
|
|
"home.clipboard.clearConfirm": "Clear the cloud clipboard? All devices will see empty content.",
|
|
"home.clipboard.clearSuccess": "Cloud clipboard cleared",
|
|
"home.clipboard.hidden": "Content hidden — click Reveal to show",
|
|
"home.clipboard.reveal": "Reveal",
|
|
"home.clipboard.hide": "Hide",
|
|
"setup.title": "Name this device",
|
|
"setup.help": "The name is shown to your other devices. Avoid spaces, ≤32 chars.",
|
|
"setup.field": "Device name",
|
|
"setup.save": "Save and continue",
|
|
"login.title": "Sign in",
|
|
"login.dev.help": "Dev mode: pick any user identifier. Two tabs with the same identifier simulate two devices of one user.",
|
|
"login.dev.field": "Dev user id",
|
|
"login.dev.continue": "Continue",
|
|
"login.prod.help": "Sign in via Casdoor.",
|
|
"login.prod.button": "Sign in with Casdoor",
|
|
"oauth.failed": "Sign-in failed",
|
|
"oauth.signingIn": "Signing in…",
|
|
"oauth.missingParams": "Missing 'code' or 'state' query parameter",
|
|
"qr.entry.fromLogin": "Sign in with a QR code",
|
|
"qr.entry.scanNewDevice": "Scan to link a device",
|
|
"qr.scan.title": "Scan to link a device",
|
|
"qr.scan.subtitle": "Point the code shown on the other device at the frame. Approval stays on this signed-in device.",
|
|
"qr.scan.starting": "Starting the camera…",
|
|
"qr.scan.aiming": "Line the code up inside the frame",
|
|
"qr.scan.foreign": "That isn't a sign-in code for this site. Aim at the code from “Sign in with a QR code” on the new device.",
|
|
"qr.scan.noCamera": "This device has no camera available. Use a phone or tablet with a camera to scan instead.",
|
|
"qr.scan.denied": "Camera access was blocked. Allow the camera in your browser's site settings, then reopen this page.",
|
|
"qr.scan.error": "Couldn't open the camera. Try again, or scan from a device with a camera.",
|
|
"qr.scan.howto1": "On the new device, open “Sign in with a QR code” to show a code.",
|
|
"qr.scan.howto2": "Line that code up in the frame above — approval starts automatically.",
|
|
"qr.scan.back": "Back",
|
|
"qr.show.title": "Sign in with a QR code",
|
|
"qr.show.subtitle": "Name this device, then scan the code from a signed-in phone to let it into your account.",
|
|
"qr.show.nameHint": "Shown to your other devices. ASCII characters only.",
|
|
"qr.show.generate": "Generate code",
|
|
"qr.show.scanTitle": "Scan to approve",
|
|
"qr.show.howto1": "Open the camera or cdrop on another signed-in device.",
|
|
"qr.show.howto2": "Scan the code above and approve this device.",
|
|
"qr.show.waiting": "Waiting for approval…",
|
|
"qr.show.approved": "Approved — signing you in…",
|
|
"qr.show.expired": "This code has expired. Generate a new one and scan again.",
|
|
"qr.show.denied": "This request was declined. If that was you, generate a new code and try again.",
|
|
"qr.show.regenerate": "Generate a new code",
|
|
"qr.show.back": "Back to home",
|
|
"qr.show.backToName": "Back",
|
|
"qr.approve.title": "Approve a new device",
|
|
"qr.approve.subtitle": "Confirm this device may sign in to your account. Check the device and origin first.",
|
|
"qr.approve.loading": "Reading device details…",
|
|
"qr.approve.badLink": "This approval link is incomplete. Generate a new code on the device and scan it again.",
|
|
"qr.approve.signInFirst": "Sign in to your account first, then approve this device.",
|
|
"qr.approve.trustLabel": "Trust duration",
|
|
"qr.approve.trust.title": "Trust this device (7 days)",
|
|
"qr.approve.trust.hint": "Skip approval for 7 days, renewed on each use.",
|
|
"qr.approve.once.title": "Just this once (1 hour)",
|
|
"qr.approve.once.hint": "Signed in for 1 hour, then scan again.",
|
|
"qr.approve.scopeFull": "This device signs fully into your account for 7 days: it can send and receive files and messages, and manage your account and devices.",
|
|
"qr.approve.scopeGuest": "Signs in as a limited guest — it can send and receive files and messages, but can't change your account or approve other devices; expires after 1 hour.",
|
|
"qr.approve.nativeFull": "This is a native app device — it signs in with full access (trusted, valid for 7 days). Native apps don't support limited guest sessions.",
|
|
"qr.approve.trustContinue": "Trust & Continue",
|
|
"qr.approve.approve": "Approve sign-in",
|
|
"qr.approve.stepUp.notice": "For security, verify your identity before approving — the button below takes you through a fresh sign-in.",
|
|
"qr.approve.stepUp.button": "Verify and approve",
|
|
"qr.approve.stepUp.rejected": "Identity verification didn't pass or has expired. Verify again to confirm it's you, then approve.",
|
|
"qr.approve.deny": "Decline",
|
|
"qr.approve.doneApprovedTitle": "Approved",
|
|
"qr.approve.doneApproved": "This device is now linked to your account. You can send and receive files on it.",
|
|
"qr.approve.doneDeniedTitle": "Declined",
|
|
"qr.approve.doneDenied": "The request was declined. That device won't sign in to your account.",
|
|
"qr.approve.expiredTitle": "Code expired",
|
|
"qr.approve.expired": "This code is no longer valid. Generate a new one on the device and scan again.",
|
|
"qr.approve.errorTitle": "Something went wrong",
|
|
"qr.approve.error": "That didn't go through. Try again, or generate a new code on the device.",
|
|
"qr.approve.backHome": "Back to home",
|
|
"settings.title": "Settings",
|
|
"settings.currentDevice.title": "This device",
|
|
"settings.deviceName.field": "Device name",
|
|
"settings.deviceName.save": "Save",
|
|
"settings.deviceName.unchanged": "Name is unchanged",
|
|
"settings.deviceName.empty": "Name cannot be empty",
|
|
"settings.deviceName.asciiOnly": "Device name must use ASCII characters only (letters, numbers, symbols).",
|
|
"settings.deviceName.success": "Device name updated",
|
|
"settings.unregister.current": "Unregister this device",
|
|
"settings.unregister.currentHint": "Removes this device's registration and signs you out.",
|
|
"settings.unregister.currentConfirm": "Unregistering this device will remove its registration and sign you out. Continue?",
|
|
"settings.error.delete": "Action failed: {{message}}",
|
|
"settings.guest.badge": "Limited guest",
|
|
"settings.guest.title": "This device is a limited guest",
|
|
"settings.guest.body": "This device is signed in as a limited guest: it can send and receive files, messages, and clipboard, but cannot manage the account, remove devices, or authorize new ones. To get full access, sign in again on your main device.",
|
|
"settings.sessions.title": "Login sessions",
|
|
"settings.sessions.hint": "Every device currently signed in to this account — browser, desktop, and mobile clients; online ones are listed first. Signing a device out ends its session immediately; it must sign in again on that device to continue.",
|
|
"settings.sessions.guestNote": "Limited guests can't manage login sessions. To manage them, sign in fully on your main device.",
|
|
"settings.sessions.empty": "No other login sessions.",
|
|
"settings.sessions.loadError": "Failed to load login sessions.",
|
|
"settings.sessions.retry": "Retry",
|
|
"settings.sessions.current": "This device",
|
|
"settings.sessions.scopeFull": "Full",
|
|
"settings.sessions.scopeGuest": "Limited guest",
|
|
"settings.sessions.kind.oidc": "Account login",
|
|
"settings.sessions.kind.self": "Local account",
|
|
"settings.sessions.kind.guest": "Scanned guest",
|
|
"settings.sessions.lastUsed": "Last active {{time}}",
|
|
"settings.sessions.neverUsed": "Not active yet",
|
|
"settings.sessions.signOut": "Sign out",
|
|
"settings.sessions.signingOut": "Signing out…",
|
|
"settings.sessions.signOutCurrent": "Sign out this device",
|
|
"settings.sessions.confirmOther": "Sign out device \"{{name}}\"? Its session will be invalidated immediately and it must sign in again.",
|
|
"settings.sessions.confirmCurrent": "Signing out this device is the same as logging out. Continue?",
|
|
"settings.sessions.revoked": "Signed that device out",
|
|
"settings.sessions.stepUpRejected": "Identity verification failed or expired. Please try again.",
|
|
"settings.online": "Online",
|
|
"settings.offline": "Offline",
|
|
"settings.lastSeen": "Last seen {{time}}",
|
|
"settings.push.title": "Push notifications",
|
|
"settings.push.hint": "When this page is closed, new files, messages, and transfer results arrive as system notifications; while it's open, you'll see in-app alerts instead.",
|
|
"settings.push.enable": "Enable push",
|
|
"settings.push.enabled": "Enabled",
|
|
"settings.push.disable": "Turn off",
|
|
"settings.push.deniedHint": "Notifications are blocked by the browser. Allow them in this site's settings, then try again.",
|
|
"settings.push.denied": "Notification permission denied",
|
|
"settings.push.enableOk": "Push notifications enabled",
|
|
"settings.push.disableOk": "Push notifications turned off",
|
|
"settings.push.failed": "Couldn't enable push. Please try again.",
|
|
"notify.incoming.title": "Incoming file",
|
|
"notify.incoming.body": "{{sender}} is sending {{file}}",
|
|
"notify.transfer.doneTitle": "Transfer complete",
|
|
"notify.transfer.failedTitle": "Transfer failed",
|
|
"settings.account.title": "Account",
|
|
"settings.account.signOut": "Sign out",
|
|
"settings.desktop.title": "Desktop",
|
|
"settings.desktop.clipboardSync": "Auto-sync clipboard",
|
|
"settings.desktop.clipboardSyncHint": "Copies are uploaded to the cloud, and clipboard updates from your other devices are applied here.",
|
|
"settings.desktop.launchAtLogin": "Launch at login",
|
|
"settings.desktop.launchAtLoginHint": "Start cdrop in the background after you sign in (lives in the menu bar).",
|
|
"settings.desktop.downloadDir": "Download folder",
|
|
"settings.desktop.downloadDirHint": "Received files are saved here. Leave unset to use the system Downloads folder.",
|
|
"settings.desktop.downloadDirChoose": "Change…",
|
|
"settings.desktop.downloadDirReset": "Reset to default",
|
|
"settings.desktop.downloadDirPicker": "Choose download folder",
|
|
"settings.desktop.ttlNote": "For security, cloud clipboard content is cleared automatically after 5 minutes.",
|
|
"settings.shortcut.title": "iOS Shortcut",
|
|
"settings.shortcut.intro": "Issue a long-lived, clipboard-only, revocable token for the iOS Shortcuts app. Even if leaked it can only read/write the clipboard — nothing else.",
|
|
"settings.shortcut.labelField": "Label",
|
|
"settings.shortcut.labelPlaceholder": "e.g. My iPhone",
|
|
"settings.shortcut.issue": "Issue",
|
|
"settings.shortcut.empty": "No tokens issued yet.",
|
|
"settings.shortcut.loadError": "Failed to load tokens.",
|
|
"settings.shortcut.retry": "Retry",
|
|
"settings.shortcut.revoke": "Revoke",
|
|
"settings.shortcut.revoking": "Revoking…",
|
|
"settings.shortcut.revokeConfirm": "Revoking immediately disables any Shortcut using this token. Continue?",
|
|
"settings.shortcut.revoked": "Revoked",
|
|
"settings.shortcut.revokedToast": "Token revoked",
|
|
"settings.shortcut.expired": "Expired",
|
|
"settings.shortcut.expiresAt": "Expires {{date}}",
|
|
"settings.shortcut.lastUsed": "Last used {{time}}",
|
|
"settings.shortcut.neverUsed": "Never used",
|
|
"settings.shortcut.unavailable": "Shortcut tokens are not enabled on the server.",
|
|
"settings.shortcut.tooMany": "You have reached the active-token limit. Revoke an old one first.",
|
|
"settings.shortcut.issueError": "Failed: {{message}}",
|
|
"settings.shortcut.issuedTitle": "Token issued",
|
|
"settings.shortcut.onceWarning": "This token is shown only once. Copy it now — you won't be able to see it again after closing.",
|
|
"settings.shortcut.tokenLabel": "Token (Bearer)",
|
|
"settings.shortcut.copy": "Copy",
|
|
"settings.shortcut.copyFailed": "Copy failed — select and copy manually.",
|
|
"settings.shortcut.copied": "Copied",
|
|
"settings.shortcut.baseLabel": "Server address",
|
|
"settings.shortcut.guideTitle": "Set up on iOS (manual sync)",
|
|
"settings.shortcut.guideIntro": "Build two shortcuts in the iPhone Shortcuts app, filling in the server address and token above on first run:",
|
|
"settings.shortcut.guideDeviceName": "Add header X-Device-Name: your-device-name (ASCII only) to both shortcuts so it shows as one device in the list.",
|
|
"settings.shortcut.guidePullTitle": "Pull (cloud → local clipboard)",
|
|
"settings.shortcut.guidePull1": "'Get Contents of URL': set the URL to your-server-address + /api/clipboard, method GET, add header Authorization: Bearer your-token.",
|
|
"settings.shortcut.guidePull2": "'Get Dictionary Value': key content.",
|
|
"settings.shortcut.guidePull3": "If non-empty, 'Copy to Clipboard'; optionally add 'Show Notification'.",
|
|
"settings.shortcut.guidePushTitle": "Push (local clipboard → cloud)",
|
|
"settings.shortcut.guidePush1": "'Get Clipboard'; stop if empty.",
|
|
"settings.shortcut.guidePush2": "'Get Contents of URL': same URL, method PUT, headers Authorization: Bearer your-token and Content-Type: application/json, JSON body: {\"content\": clipboard, \"content_type\": \"text/plain\"}.",
|
|
"settings.shortcut.guidePush3": "Optionally add 'Show Notification'.",
|
|
"settings.shortcut.guideToleranceNote": "A single run may fail on a flaky network — just retry. The automatic polling version (next phase) retries silently in the background.",
|
|
"settings.shortcut.done": "Done",
|
|
"transfer.savedTo": "Saved to {{path}}",
|
|
"transfer.saveFailed": "Failed to save file: {{error}}",
|
|
"transfer.action.cancel": "Cancel",
|
|
"transfer.action.delete": "Delete",
|
|
"transfer.action.relayNow": "Relay now",
|
|
"transfer.action.details": "Details",
|
|
"transfer.state.PENDING": "Pending",
|
|
"transfer.state.ACCEPTED": "Accepted",
|
|
"transfer.state.P2P_ACTIVE": "Transferring",
|
|
"transfer.state.RELAY_ACTIVE": "Relaying",
|
|
"transfer.state.DONE": "Done",
|
|
"transfer.state.FAILED": "Failed",
|
|
"transfer.state.CANCELLED": "Cancelled",
|
|
"transfer.mode.p2p": "P2P",
|
|
"transfer.mode.relay": "Relay",
|
|
"transfer.phase.initializing": "Initializing…",
|
|
"transfer.phase.waiting_accept": "Waiting for the other side to accept…",
|
|
"transfer.phase.ice_gathering": "Gathering network candidates…",
|
|
"transfer.phase.ice_checking": "Establishing direct tunnel…",
|
|
"transfer.phase.ice_connected": "Tunnel established",
|
|
"transfer.phase.dc_open": "Channel open",
|
|
"transfer.phase.transferring": "Transferring",
|
|
"transfer.phase.completing": "Finalizing…",
|
|
"transfer.phase.fallback_pending": "Falling back to relay…",
|
|
"transfer.phase.relay_uploading": "Uploading via relay",
|
|
"transfer.phase.relay_downloading": "Downloading via relay",
|
|
"transfer.stalled": "Looks stalled ({{seconds}}s without progress)",
|
|
"transfer.bytesProgress": "{{sent}} / {{total}}",
|
|
"transfer.bytesRate": "{{rate}}/s",
|
|
"transfer.debug.toggle": "Debug",
|
|
"transfer.debug.iceGathering": "Gathering",
|
|
"transfer.debug.iceConnection": "Connection",
|
|
"transfer.debug.candidatesLocal": "Local candidates",
|
|
"transfer.debug.candidatesRemote": "Remote candidates",
|
|
"transfer.debug.selectedPair": "Selected pair",
|
|
"transfer.debug.noPair": "No nominated pair yet",
|
|
"transfer.debug.candidatesLine": "host {{host}} · mDNS {{mdns}} · srflx {{srflx}} · prflx {{prflx}} · relay {{relay}}",
|
|
"transfer.debug.dataChannel": "Data channel",
|
|
"transfer.debug.dcLine": "{{state}} · buffered {{buffered}}",
|
|
"time.justNow": "just now",
|
|
"time.secondsAgo": "{{n}}s ago",
|
|
"time.minutesAgo": "{{n}}m ago",
|
|
"time.hoursAgo": "{{n}}h ago",
|
|
"common.dismiss": "Dismiss",
|
|
"common.cancel": "Cancel",
|
|
"common.confirm": "Confirm",
|
|
"errors.messageEmpty": "Message is empty",
|
|
"errors.messageOverflow": "Message exceeds 4 KB; send a file instead",
|
|
"errors.noReceiver": "No receiver selected",
|
|
"errors.devTokenMissing": "Dev mode: VITE_CDROP_DEV_TOKEN is not set in .env.local",
|
|
"errors.noAccessToken": "No access token; user must log in",
|
|
"errors.clipboardUnavailable": "Browser clipboard API unavailable (requires HTTPS + permission)",
|
|
"errors.clipboardOverflow": "Content too large; exceeds {{max}} byte limit",
|
|
"errors.clipboardWriteFailed": "Failed to write to local clipboard: {{message}}",
|
|
"ios.tab.transfer": "Transfers",
|
|
"ios.tab.devices": "Devices",
|
|
"ios.tab.settings": "Settings",
|
|
"ios.login.generating": "Generating code…",
|
|
"ios.login.waiting": "Waiting for approval",
|
|
"ios.login.guide": "Scan to approve from another signed-in device",
|
|
"ios.login.expired": "Code expired — please try again",
|
|
"ios.login.failed": "Sign-in failed — please try again",
|
|
"ios.login.broker": "Sign In",
|
|
"ios.login.brokerStarting": "Opening sign-in…",
|
|
"ios.login.scanAlt": "Sign in by scanning from another device",
|
|
"ios.login.refresh": "Refresh QR Code",
|
|
"ios.login.needFull": "This device needs full access — choose \"Trust this device\" when approving.",
|
|
"ios.send.pickDevice": "Choose a device",
|
|
"ios.transfer.sending": "Sending",
|
|
"ios.settings.engine": "Engine",
|
|
"ios.settings.status": "Status",
|
|
"ios.settings.device": "Device",
|
|
"ios.settings.clipboard": "Clipboard",
|
|
"ios.settings.clipboardNote": "Upload pushes this device's clipboard to your others; Pull writes the latest cloud clipboard.",
|
|
"ios.clipboard.upload": "Upload Clipboard",
|
|
"ios.clipboard.pull": "Pull Clipboard",
|
|
"ios.clipboard.uploading": "Uploading…",
|
|
"ios.clipboard.pulling": "Pulling…",
|
|
"ios.clipboard.uploaded": "Uploaded to cloud clipboard",
|
|
"ios.clipboard.pulled": "Written to clipboard",
|
|
"ios.clipboard.empty": "Clipboard is empty",
|
|
"ios.clipboard.failed": "Clipboard sync failed",
|
|
"ios.devices.remove": "Remove Device",
|
|
"ios.devices.thisDevice": "This device",
|
|
"ios.devices.revoked": "Device removed",
|
|
"ios.devices.revokeFailed": "Remove failed",
|
|
"ios.devices.revokeStepUp": "Re-verify on the web to remove this device",
|
|
"ios.engine.disconnected": "Disconnected",
|
|
"ios.engine.ready": "Ready",
|
|
"ios.transfer.empty": "No transfers yet",
|
|
"ios.transfer.incoming": "Receive",
|
|
"ios.transfer.outgoing": "Send",
|
|
"ios.send.noDevices": "No online devices to send to",
|
|
"ios.devices.empty": "No devices yet",
|
|
"ios.detail.title": "Transfer Details",
|
|
"ios.detail.direction": "Direction",
|
|
"ios.detail.peer": "Peer",
|
|
"ios.detail.state": "State",
|
|
"ios.detail.phase": "Phase",
|
|
"ios.detail.channel": "Channel",
|
|
"ios.detail.size": "Size",
|
|
"ios.detail.progress": "Progress",
|
|
"ios.detail.speed": "Speed",
|
|
"ios.settings.account": "Account",
|
|
"ios.settings.user": "User",
|
|
"ios.settings.logout": "Sign Out",
|
|
"ios.settings.deviceName": "Device Name",
|
|
"ios.settings.deviceNameNote": "Renaming takes effect at once and syncs to all devices, without affecting sign-in.",
|
|
"ios.settings.deviceName.success": "Device name updated",
|
|
"ios.tab.messages": "Messages",
|
|
"ios.send.fromFiles": "From Files",
|
|
"ios.send.fromPhotos": "From Photos",
|
|
"ios.messages.empty": "No messages yet",
|
|
"ios.messages.noPeers": "No device to message",
|
|
"ios.messages.placeholder": "Type a message…",
|
|
"ios.records.clear": "Clear",
|
|
"ios.records.clearConfirm": "Clear all records? This cannot be undone.",
|
|
"ios.transfer.cancel": "Cancel transfer",
|
|
"ios.transfer.forceRelay": "Relay now",
|
|
"ios.settings.deviceCount": "Known Devices",
|
|
"ios.settings.signaling": "Signaling",
|
|
"ios.settings.presenceEvents": "Presence Events",
|
|
"ios.settings.reconnecting": "Reconnecting",
|
|
"ios.settings.lastLog": "Last Log",
|
|
"ios.tab.files": "Files",
|
|
"ios.files.title": "Received Files",
|
|
"ios.files.empty": "No files received yet",
|
|
"ios.files.share": "Share",
|
|
"ios.files.done": "Done",
|
|
"ios.detail.openFile": "Open File",
|
|
"ios.bg.title": "Transferring files",
|
|
"ios.bg.subtitle": "Continues in the background",
|
|
"ios.share.title": "Send {{n}} file(s) to a device",
|
|
"ios.control.upload": "Upload Clipboard",
|
|
"ios.control.pull": "Pull Clipboard",
|
|
"ios.control.sessionLabel": "{{name}} · Control",
|
|
"ios.settings.viewLogs": "View Logs",
|
|
"ios.logs.title": "Engine Logs",
|
|
"ios.logs.empty": "No logs yet",
|
|
"ios.logs.clear": "Clear Logs",
|
|
"ios.logs.copy": "Copy All",
|
|
"ios.scan.entry": "Scan to Sign In",
|
|
"ios.scan.title": "Scan QR Code",
|
|
"ios.scan.hint": "Point at the sign-in QR code on another device",
|
|
"ios.scan.invalid": "Unrecognized sign-in QR code",
|
|
"ios.scan.approveTitle": "Approve this device to sign in?",
|
|
"ios.scan.approve": "Approve",
|
|
"ios.scan.deny": "Deny",
|
|
"ios.scan.approved": "Device approved",
|
|
"ios.scan.denied": "Device denied",
|
|
"ios.scan.failed": "Action failed, please retry",
|
|
"ios.scan.cameraDenied": "Camera access is required to scan; enable it in Settings",
|
|
"ios.scan.requestIp": "Source IP",
|
|
"ios.widget.clipboardName": "Cloud Clipboard",
|
|
"ios.widget.clipboardDesc": "Quickly upload or pull the shared clipboard",
|
|
"ios.widget.needApp": "Open the app to sign in first"
|
|
}
|