mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
a876fb2634
* feat(auth): passkey (WebAuthn) login — server endpoints, schema + admin toggle Add @simplewebauthn/server registration and primary (discoverable) login ceremonies under /api/auth/passkey, a webauthn_credentials + single-use webauthn_challenges schema (migration), the instance-wide passkey_login toggle (default off) enforced before auth by a guard, and require_mfa satisfaction via a verified passkey. RP ID/origin come only from server config (webauthn_rp_id/origins -> APP_URL), never request headers. * feat(auth): passkey enrolment, login button + admin settings UI PasskeysSection in account settings (add/rename/remove with a current-password step-up), a 'Sign in with a passkey' button on the login page, the admin enable + RP-ID/origins controls, and a per-user admin reset action. * i18n(auth): passkey strings across all locales Add login/settings/admin passkey keys to en and all 19 translated locales.
311 lines
18 KiB
TypeScript
311 lines
18 KiB
TypeScript
import type { TranslationStrings } from '../types';
|
||
|
||
const settings: TranslationStrings = {
|
||
'settings.title': '设置',
|
||
'settings.subtitle': '配置你的个人设置',
|
||
'settings.tabs.display': '显示',
|
||
'settings.tabs.map': '地图',
|
||
'settings.tabs.notifications': '通知',
|
||
'settings.tabs.integrations': '集成',
|
||
'settings.tabs.account': '账户',
|
||
'settings.tabs.offline': 'Offline',
|
||
'settings.tabs.about': '关于',
|
||
'settings.map': '地图',
|
||
'settings.mapTemplate': '地图模板',
|
||
'settings.mapTemplatePlaceholder.select': '选择模板...',
|
||
'settings.mapDefaultHint': '留空则使用 OpenStreetMap(默认)',
|
||
'settings.mapTemplatePlaceholder':
|
||
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||
'settings.mapHint': '地图瓦片 URL 模板',
|
||
'settings.mapProvider': '地图提供商',
|
||
'settings.mapProviderHint':
|
||
'影响行程规划和旅程地图。Atlas 始终使用 Leaflet。',
|
||
'settings.mapLeafletSubtitle': '经典 2D,任何栅格瓦片',
|
||
'settings.mapMapboxSubtitle': '矢量瓦片、3D 建筑和地形',
|
||
'settings.mapExperimental': '实验性',
|
||
'settings.mapMapboxToken': 'Mapbox 访问令牌',
|
||
'settings.mapMapboxTokenHint': '公共令牌 (pk.*) 来自',
|
||
'settings.mapMapboxTokenLink': 'mapbox.com → 访问令牌',
|
||
'settings.mapStyle': '地图样式',
|
||
'settings.mapStylePlaceholder': '选择 Mapbox 样式',
|
||
'settings.mapStyleHint': '预设或您自己的 mapbox://styles/USER/ID URL',
|
||
'settings.map3dBuildings': '3D 建筑和地形',
|
||
'settings.map3dHint': '倾斜 + 真实 3D 建筑拉伸 — 适用于所有样式,包括卫星。',
|
||
'settings.mapHighQuality': '高画质模式',
|
||
'settings.mapHighQualityHint':
|
||
'抗锯齿 + 地球投影,带来更清晰的边缘和更真实的世界视图。',
|
||
'settings.mapHighQualityWarning': '可能影响低端设备的性能。',
|
||
'settings.mapTipLabel': '提示:',
|
||
'settings.mapTip':
|
||
'右键点击并拖动以旋转/倾斜地图。中键点击添加地点(右键用于旋转)。',
|
||
'settings.latitude': '纬度',
|
||
'settings.longitude': '经度',
|
||
'settings.saveMap': '保存地图',
|
||
'settings.apiKeys': 'API 密钥',
|
||
'settings.mapsKey': 'Google Maps API 密钥',
|
||
'settings.mapsKeyHint':
|
||
'用于地点搜索。需要 Places API (New)。在 console.cloud.google.com 获取',
|
||
'settings.weatherKey': 'OpenWeatherMap API 密钥',
|
||
'settings.weatherKeyHint': '用于天气数据。在 openweathermap.org/api 免费获取',
|
||
'settings.keyPlaceholder': '输入密钥...',
|
||
'settings.configured': '已配置',
|
||
'settings.saveKeys': '保存密钥',
|
||
'settings.display': '显示',
|
||
'settings.colorMode': '颜色模式',
|
||
'settings.light': '浅色',
|
||
'settings.dark': '深色',
|
||
'settings.auto': '自动',
|
||
'settings.language': '语言',
|
||
'settings.temperature': '温度单位',
|
||
'settings.timeFormat': '时间格式',
|
||
'settings.blurBookingCodes': '模糊预订代码',
|
||
'settings.notifications': '通知',
|
||
'settings.notifyTripInvite': '旅行邀请',
|
||
'settings.notifyBookingChange': '预订变更',
|
||
'settings.notifyTripReminder': '旅行提醒',
|
||
'settings.notifyTodoDue': '待办事项即将到期',
|
||
'settings.notifyVacayInvite': 'Vacay 融合邀请',
|
||
'settings.notifyPhotosShared': '共享照片 (Immich)',
|
||
'settings.notifyCollabMessage': '聊天消息 (Collab)',
|
||
'settings.notifyPackingTagged': '行李清单:分配',
|
||
'settings.notifyWebhook': 'Webhook 通知',
|
||
'settings.notificationsDisabled':
|
||
'通知尚未配置。请联系管理员启用电子邮件或 Webhook 通知。',
|
||
'settings.notificationsActive': '活跃频道',
|
||
'settings.notificationsManagedByAdmin': '通知事件由管理员配置。',
|
||
'settings.on': '开',
|
||
'settings.off': '关',
|
||
'settings.mcp.title': 'MCP 配置',
|
||
'settings.mcp.endpoint': 'MCP 端点',
|
||
'settings.mcp.clientConfig': '客户端配置',
|
||
'settings.mcp.clientConfigHint':
|
||
'将 <your_token> 替换为下方列表中的 API 令牌。npx 的路径可能需要根据您的系统进行调整(例如 Windows 上为 C:\\PROGRA~1\\nodejs\\npx.cmd)。',
|
||
'settings.mcp.clientConfigHintOAuth':
|
||
'将 <your_client_id> 和 <your_client_secret> 替换为上方创建的 OAuth 2.1 客户端凭据。首次连接时,mcp-remote 将打开浏览器完成授权。npx 的路径可能需要根据您的系统进行调整(例如 Windows 上为 C:\\PROGRA~1\\nodejs\\npx.cmd)。',
|
||
'settings.mcp.copy': '复制',
|
||
'settings.mcp.copied': '已复制!',
|
||
'settings.mcp.apiTokens': 'API 令牌',
|
||
'settings.mcp.createToken': '创建新令牌',
|
||
'settings.mcp.noTokens': '暂无令牌,请创建一个以连接 MCP 客户端。',
|
||
'settings.mcp.tokenCreatedAt': '创建于',
|
||
'settings.mcp.tokenUsedAt': '使用于',
|
||
'settings.mcp.deleteTokenTitle': '删除令牌',
|
||
'settings.mcp.deleteTokenMessage':
|
||
'此令牌将立即失效,使用它的所有 MCP 客户端将失去访问权限。',
|
||
'settings.mcp.modal.createTitle': '创建 API 令牌',
|
||
'settings.mcp.modal.tokenName': '令牌名称',
|
||
'settings.mcp.modal.tokenNamePlaceholder': '例如:Claude Desktop、工作电脑',
|
||
'settings.mcp.modal.creating': '创建中…',
|
||
'settings.mcp.modal.create': '创建令牌',
|
||
'settings.mcp.modal.createdTitle': '令牌已创建',
|
||
'settings.mcp.modal.createdWarning':
|
||
'此令牌只会显示一次,请立即复制并妥善保存——无法找回。',
|
||
'settings.mcp.modal.done': '完成',
|
||
'settings.mcp.toast.created': '令牌已创建',
|
||
'settings.mcp.toast.createError': '创建令牌失败',
|
||
'settings.mcp.toast.deleted': '令牌已删除',
|
||
'settings.mcp.toast.deleteError': '删除令牌失败',
|
||
'settings.mcp.apiTokensDeprecated':
|
||
'API 令牌已弃用,将在未来版本中移除。请改用 OAuth 2.1 客户端。',
|
||
'settings.oauth.clients': 'OAuth 2.1 客户端',
|
||
'settings.oauth.clientsHint':
|
||
'注册 OAuth 2.1 客户端,让第三方 MCP 应用程序(Claude Web、Cursor 等)无需静态令牌即可连接。',
|
||
'settings.oauth.createClient': '新建客户端',
|
||
'settings.oauth.noClients': '没有已注册的 OAuth 客户端。',
|
||
'settings.oauth.clientId': '客户端 ID',
|
||
'settings.oauth.clientSecret': '客户端密钥',
|
||
'settings.oauth.deleteClient': '删除客户端',
|
||
'settings.oauth.deleteClientMessage':
|
||
'此客户端及所有活跃会话将被永久删除。使用此客户端的任何应用程序将立即失去访问权限。',
|
||
'settings.oauth.rotateSecret': '轮换密钥',
|
||
'settings.oauth.rotateSecretMessage':
|
||
'将生成新的客户端密钥,所有现有会话将立即失效。在关闭此对话框之前,请更新您的应用程序。',
|
||
'settings.oauth.rotateSecretConfirm': '轮换',
|
||
'settings.oauth.rotateSecretConfirming': '轮换中…',
|
||
'settings.oauth.rotateSecretDoneTitle': '已生成新密钥',
|
||
'settings.oauth.rotateSecretDoneWarning':
|
||
'此密钥仅显示一次。请立即复制并更新您的应用程序——所有之前的会话已失效。',
|
||
'settings.oauth.activeSessions': '活跃的 OAuth 会话',
|
||
'settings.oauth.sessionScopes': '权限范围',
|
||
'settings.oauth.sessionExpires': '过期时间',
|
||
'settings.oauth.revoke': '撤销',
|
||
'settings.oauth.revokeSession': '撤销会话',
|
||
'settings.oauth.revokeSessionMessage':
|
||
'这将立即撤销此 OAuth 会话的访问权限。',
|
||
'settings.oauth.modal.createTitle': '注册 OAuth 客户端',
|
||
'settings.oauth.modal.presets': '快速预设',
|
||
'settings.oauth.modal.clientName': '应用程序名称',
|
||
'settings.oauth.modal.clientNamePlaceholder':
|
||
'例如 Claude Web、我的 MCP 应用',
|
||
'settings.oauth.modal.redirectUris': '重定向 URI',
|
||
'settings.oauth.modal.redirectUrisPlaceholder':
|
||
'https://your-app.com/callback\nhttps://your-app.com/auth',
|
||
'settings.oauth.modal.redirectUrisHint':
|
||
'每行一个 URI。需要 HTTPS(localhost 除外)。要求精确匹配。',
|
||
'settings.oauth.modal.scopes': '允许的权限范围',
|
||
'settings.oauth.modal.scopesHint':
|
||
'list_trips 和 get_trip_summary 始终可用——无需权限范围。它们帮助 AI 发现所需的行程 ID。',
|
||
'settings.oauth.modal.selectAll': '全选',
|
||
'settings.oauth.modal.deselectAll': '取消全选',
|
||
'settings.oauth.modal.creating': '注册中…',
|
||
'settings.oauth.modal.create': '注册客户端',
|
||
'settings.oauth.modal.createdTitle': '客户端已注册',
|
||
'settings.oauth.modal.createdWarning':
|
||
'客户端密钥仅显示一次。请立即复制——无法恢复。',
|
||
'settings.oauth.toast.createError': '注册 OAuth 客户端失败',
|
||
'settings.oauth.toast.deleted': 'OAuth 客户端已删除',
|
||
'settings.oauth.toast.deleteError': '删除 OAuth 客户端失败',
|
||
'settings.oauth.toast.revoked': '会话已撤销',
|
||
'settings.oauth.toast.revokeError': '撤销会话失败',
|
||
'settings.oauth.toast.rotateError': '轮换客户端密钥失败',
|
||
'settings.oauth.modal.machineClient': '机器客户端(无需浏览器登录)',
|
||
'settings.oauth.modal.machineClientHint':
|
||
'使用 client_credentials 授权——无需重定向 URI。令牌通过 client_id + client_secret 直接颁发,并在所选范围内以您的身份运行。',
|
||
'settings.oauth.modal.machineClientUsage':
|
||
'获取令牌:向 /oauth/token 发送 POST 请求,携带 grant_type=client_credentials、client_id 和 client_secret。无需浏览器,无刷新令牌。',
|
||
'settings.oauth.badge.machine': '机器',
|
||
'settings.account': '账户',
|
||
'settings.about': '关于',
|
||
'settings.about.reportBug': '报告错误',
|
||
'settings.about.reportBugHint': '发现问题?告诉我们',
|
||
'settings.about.featureRequest': '功能建议',
|
||
'settings.about.featureRequestHint': '建议一个新功能',
|
||
'settings.about.wikiHint': '文档和指南',
|
||
'settings.about.supporters.badge': '月度支持者',
|
||
'settings.about.supporters.title': '与 TREK 同行的伙伴',
|
||
'settings.about.supporters.subtitle':
|
||
'当你在规划下一段路线时,这些人也在一起规划 TREK 的未来。他们每月的支持直接用于开发与真实投入的时间——让 TREK 保持开源。',
|
||
'settings.about.supporters.since': '{date} 起的支持者',
|
||
'settings.about.supporters.tierEmpty': '成为第一个',
|
||
'settings.about.supporter.tier.noReturnTicket': 'No Return Ticket',
|
||
'settings.about.supporter.tier.lostLuggageVip': 'Lost Luggage VIP',
|
||
'settings.about.supporter.tier.businessClassDreamer':
|
||
'Business Class Dreamer',
|
||
'settings.about.supporter.tier.budgetTraveller': 'Budget Traveller',
|
||
'settings.about.supporter.tier.hostelBunkmate': 'Hostel Bunkmate',
|
||
'settings.about.description':
|
||
'TREK 是一个自托管的旅行规划工具,帮助你从最初的想法到最后的回忆,全程组织你的旅行。日程规划、预算、行李清单、照片等——一切尽在一处,在你自己的服务器上。',
|
||
'settings.about.madeWith': '用',
|
||
'settings.about.madeBy': '由 Maurice 和不断壮大的开源社区打造。',
|
||
'settings.username': '用户名',
|
||
'settings.email': '邮箱',
|
||
'settings.role': '角色',
|
||
'settings.roleAdmin': '管理员',
|
||
'settings.oidcLinked': '已关联',
|
||
'settings.changePassword': '修改密码',
|
||
'settings.mustChangePassword': '您必须更改密码才能继续。请在下方设置新密码。',
|
||
'settings.currentPassword': '当前密码',
|
||
'settings.currentPasswordRequired': '请输入当前密码',
|
||
'settings.newPassword': '新密码',
|
||
'settings.confirmPassword': '确认新密码',
|
||
'settings.updatePassword': '更新密码',
|
||
'settings.passwordRequired': '请输入当前密码和新密码',
|
||
'settings.passwordTooShort': '密码至少需要 8 个字符',
|
||
'settings.passwordMismatch': '两次输入的密码不一致',
|
||
'settings.passwordWeak': '密码必须包含大写字母、小写字母、数字和特殊字符',
|
||
'settings.passwordChanged': '密码修改成功',
|
||
'settings.deleteAccount': '删除账户',
|
||
'settings.deleteAccountTitle': '确定删除账户?',
|
||
'settings.deleteAccountWarning':
|
||
'你的账户以及所有旅行、地点和文件将被永久删除。此操作无法撤销。',
|
||
'settings.deleteAccountConfirm': '永久删除',
|
||
'settings.deleteBlockedTitle': '无法删除',
|
||
'settings.deleteBlockedMessage':
|
||
'你是唯一的管理员。请先将其他用户提升为管理员,然后再删除账户。',
|
||
'settings.roleUser': '用户',
|
||
'settings.saveProfile': '保存资料',
|
||
'settings.mfa.title': '双因素认证 (2FA)',
|
||
'settings.mfa.description':
|
||
'登录时添加第二步验证。使用身份验证器应用(Google Authenticator、Authy 等)。',
|
||
'settings.mfa.requiredByPolicy':
|
||
'管理员要求双因素身份验证。请先完成下方的身份验证器设置后再继续。',
|
||
'settings.mfa.backupTitle': '备用代码',
|
||
'settings.mfa.backupDescription':
|
||
'如果你无法使用身份验证器应用,可使用这些一次性备用代码登录。',
|
||
'settings.mfa.backupWarning': '请立即保存这些代码。每个代码只能使用一次。',
|
||
'settings.mfa.backupCopy': '复制代码',
|
||
'settings.mfa.backupDownload': '下载 TXT',
|
||
'settings.mfa.backupPrint': '打印 / PDF',
|
||
'settings.mfa.backupCopied': '备用代码已复制',
|
||
'settings.mfa.enabled': '您的账户已启用 2FA。',
|
||
'settings.mfa.disabled': '2FA 未启用。',
|
||
'settings.mfa.setup': '设置身份验证器',
|
||
'settings.mfa.scanQr': '使用应用扫描此二维码,或手动输入密钥。',
|
||
'settings.mfa.secretLabel': '密钥(手动输入)',
|
||
'settings.mfa.codePlaceholder': '6 位验证码',
|
||
'settings.mfa.enable': '启用 2FA',
|
||
'settings.mfa.cancelSetup': '取消',
|
||
'settings.mfa.disableTitle': '停用 2FA',
|
||
'settings.mfa.disableHint': '输入您的账户密码和身份验证器中的当前验证码。',
|
||
'settings.mfa.disable': '停用 2FA',
|
||
'settings.mfa.toastEnabled': '双因素认证已启用',
|
||
'settings.mfa.toastDisabled': '双因素认证已停用',
|
||
'settings.mfa.demoBlocked': '演示模式下不可用',
|
||
'settings.toast.mapSaved': '地图设置已保存',
|
||
'settings.toast.keysSaved': 'API 密钥已保存',
|
||
'settings.toast.displaySaved': '显示设置已保存',
|
||
'settings.toast.profileSaved': '资料已保存',
|
||
'settings.uploadAvatar': '上传头像',
|
||
'settings.removeAvatar': '移除头像',
|
||
'settings.avatarUploaded': '头像已更新',
|
||
'settings.avatarRemoved': '头像已移除',
|
||
'settings.avatarError': '上传失败',
|
||
'settings.bookingLabels': '预订路线标签',
|
||
'settings.bookingLabelsHint':
|
||
'在地图上显示车站 / 机场名称。关闭时仅显示图标。',
|
||
'settings.notifyVersionAvailable': '有新版本可用',
|
||
'settings.notificationPreferences.noChannels':
|
||
'未配置通知渠道。请联系管理员设置电子邮件或 Webhook 通知。',
|
||
'settings.webhookUrl.label': 'Webhook URL',
|
||
'settings.webhookUrl.placeholder': 'https://discord.com/api/webhooks/...',
|
||
'settings.webhookUrl.hint':
|
||
'输入您的 Discord、Slack 或自定义 Webhook URL 以接收通知。',
|
||
'settings.webhookUrl.saved': 'Webhook URL 已保存',
|
||
'settings.webhookUrl.test': '测试',
|
||
'settings.webhookUrl.testSuccess': '测试 Webhook 发送成功',
|
||
'settings.webhookUrl.testFailed': '测试 Webhook 失败',
|
||
'settings.ntfyUrl.topicLabel': 'Ntfy 主题',
|
||
'settings.ntfyUrl.topicPlaceholder': 'my-trek-alerts',
|
||
'settings.ntfyUrl.serverLabel': 'Ntfy 服务器 URL(可选)',
|
||
'settings.ntfyUrl.serverPlaceholder': 'https://ntfy.sh',
|
||
'settings.ntfyUrl.hint':
|
||
'输入您的 Ntfy 主题以接收推送通知。将服务器留空以使用管理员配置的默认值。',
|
||
'settings.ntfyUrl.tokenLabel': '访问令牌(可选)',
|
||
'settings.ntfyUrl.tokenHint': '受密码保护的主题需要此项。',
|
||
'settings.ntfyUrl.saved': 'Ntfy 设置已保存',
|
||
'settings.ntfyUrl.test': '测试',
|
||
'settings.ntfyUrl.testSuccess': '测试 Ntfy 通知发送成功',
|
||
'settings.ntfyUrl.testFailed': '测试 Ntfy 通知失败',
|
||
'settings.ntfyUrl.tokenCleared': '访问令牌已清除',
|
||
'settings.notificationPreferences.inapp': 'In-App',
|
||
'settings.notificationPreferences.webhook': 'Webhook',
|
||
'settings.notificationPreferences.email': 'Email',
|
||
'settings.notificationPreferences.ntfy': 'Ntfy',
|
||
"settings.currency": "Currency",
|
||
"settings.currencyHint": "All amounts in Costs are converted to and shown in this currency.",
|
||
'settings.passkey.title': '通行密钥',
|
||
'settings.passkey.description':
|
||
'使用通行密钥更快登录,并能抵御钓鱼攻击——通过指纹、面容、PIN 或硬件密钥验证。你的密码仍可作为备用方式。',
|
||
'settings.passkey.notConfigured':
|
||
'通行密钥已启用,但此服务器尚未完成完整配置。请联系管理员设置 WebAuthn 域名。',
|
||
'settings.passkey.add': '添加通行密钥',
|
||
'settings.passkey.addTitle': '添加通行密钥',
|
||
'settings.passkey.passwordPrompt': '确认你的当前密码,然后按照设备提示操作。',
|
||
'settings.passkey.passwordRequired': '需要输入你的当前密码。',
|
||
'settings.passkey.namePlaceholder': '名称(可选,如 "iPhone")',
|
||
'settings.passkey.addedToast': '通行密钥已添加',
|
||
'settings.passkey.added': '已添加',
|
||
'settings.passkey.addError': '无法添加通行密钥',
|
||
'settings.passkey.cancelled': '已取消通行密钥设置',
|
||
'settings.passkey.deleted': '通行密钥已移除',
|
||
'settings.passkey.deleteConfirm': '移除此通行密钥?请输入密码确认。',
|
||
'settings.passkey.rename': '重命名',
|
||
'settings.passkey.defaultName': '通行密钥',
|
||
'settings.passkey.synced': '已同步',
|
||
'settings.passkey.deviceBound': '此设备',
|
||
'settings.passkey.lastUsed': '上次使用',
|
||
'settings.passkey.neverUsed': '从未使用',
|
||
};
|
||
|
||
export default settings;
|