# Translation keys for zh (Chinese) and en (English) _translations: dict[str, dict[str, str]] = { # ── Brand / Nav ── "brand": {"zh": "📮 星笺", "en": "📮 Mailova"}, "nav.profiles": {"zh": "Profile", "en": "Profiles"}, "nav.settings": {"zh": "设置", "en": "Settings"}, "nav.invites": {"zh": "邀请码管理", "en": "Invites"}, "nav.logout": {"zh": "退出", "en": "Logout"}, "nav.api_docs": {"zh": "API 文档", "en": "API Docs"}, # ── Auth ── "login.title": {"zh": "登录", "en": "Login"}, "login.username": {"zh": "用户名", "en": "Username"}, "login.password": {"zh": "密码", "en": "Password"}, "login.remember": {"zh": "记住我", "en": "Remember me"}, "login.no_account": {"zh": "没有账号?", "en": "No account?"}, "login.go_register": {"zh": "去注册", "en": "Sign up"}, "register.title": {"zh": "注册", "en": "Register"}, "register.hint": {"zh": "邀请码由已有用户或管理员提供", "en": "Invite code provided by an existing user or admin"}, "register.invite_code": {"zh": "邀请码", "en": "Invite code"}, "register.invite_ph": {"zh": "8位字母数字", "en": "8-char code"}, "register.username": {"zh": "用户名", "en": "Username"}, "register.password": {"zh": "密码", "en": "Password"}, "register.confirm_password": {"zh": "确认密码", "en": "Confirm password"}, "register.has_account": {"zh": "已有账号?", "en": "Already have an account?"}, "register.go_login": {"zh": "去登录", "en": "Log in"}, # ── Dashboard ── "dash.welcome": {"zh": "👋 欢迎,", "en": "👋 Welcome, "}, "dash.total_cards": {"zh": "全部明信片", "en": "Total postcards"}, "dash.sent": {"zh": "已寄出", "en": "Sent"}, "dash.delivered": {"zh": "已送达", "en": "Delivered"}, "dash.received": {"zh": "已收到", "en": "Received"}, "dash.countries": {"zh": "国家/地区", "en": "Countries"}, "dash.chart_sent": {"zh": "📤 寄出", "en": "📤 Sent"}, "dash.chart_received": {"zh": "📬 收到", "en": "📬 Received"}, "dash.recent": {"zh": "最近动态", "en": "Recent activity"}, "dash.empty": {"zh": "暂无明信片", "en": "No postcards yet"}, "dash.welcome_title": {"zh": "欢迎使用星笺!", "en": "Welcome to Mailova!"}, "dash.welcome_hint": {"zh": "创建一个", "en": "Create a"}, "dash.welcome_hint2": {"zh": " 开始管理你的明信片", "en": " to start managing your postcards"}, "dash.today": {"zh": "今天", "en": "Today"}, "dash.yesterday": {"zh": "昨天", "en": "Yesterday"}, "dash.days_ago": {"zh": "天前", "en": " days ago"}, # ── Profiles ── "profiles.title": {"zh": "Profile", "en": "Profiles"}, "profiles.new_ph": {"zh": "新 Profile 昵称", "en": "New profile nickname"}, "profiles.new_btn": {"zh": "+ 新建", "en": "+ New"}, "profiles.rename": {"zh": "改名", "en": "Rename"}, "profiles.total": {"zh": "总计", "en": "Total"}, "profiles.countries": {"zh": "国家", "en": "Countries"}, "profiles.notes_ph": {"zh": "备注(仅自己可见)", "en": "Notes (private)"}, "profiles.save": {"zh": "保存", "en": "Save"}, "profiles.created_at": {"zh": "创建于", "en": "Created"}, "profiles.view": {"zh": "查看", "en": "View"}, "profiles.delete": {"zh": "删除", "en": "Delete"}, "profiles.confirm_delete": {"zh": "确定删除此 Profile?", "en": "Delete this profile?"}, # ── Postcards list ── "pc_list.title": {"zh": " 的明信片", "en": "'s postcards"}, "pc_list.new": {"zh": "+ 新明信片", "en": "+ New postcard"}, "pc_list.duplicate": {"zh": "编号已存在", "en": "Card number already exists"}, "pc_list.all_countries": {"zh": "全部国家", "en": "All countries"}, "pc_list.filter": {"zh": "筛选", "en": "Filter"}, "pc_list.tab_sent": {"zh": "寄出", "en": "Sent"}, "pc_list.tab_received": {"zh": "收到", "en": "Received"}, "pc_list.mark_delivered": {"zh": "已送达", "en": "Delivered"}, "pc_list.confirm_delivered": {"zh": "确认已送达?", "en": "Mark as delivered?"}, "pc_list.empty_sent": {"zh": "没有寄出的明信片。", "en": "No sent postcards."}, "pc_list.empty_received": {"zh": "没有收到的明信片。", "en": "No received postcards."}, # ── Postcard detail ── "pc_detail.title": {"zh": "明信片详情", "en": "Postcard detail"}, "pc_detail.edit": {"zh": "编辑", "en": "Edit"}, "pc_detail.mark_delivered": {"zh": "已送达", "en": "Mark delivered"}, "pc_detail.confirm_delivered": {"zh": "确认已送达?", "en": "Mark as delivered?"}, "pc_detail.delete": {"zh": "删除", "en": "Delete"}, "pc_detail.confirm_delete": {"zh": "确定删除?", "en": "Delete this postcard?"}, "pc_detail.front": {"zh": "正面", "en": "Front"}, "pc_detail.back": {"zh": "反面", "en": "Back"}, "pc_detail.no_front": {"zh": "📷 未上传正面图片", "en": "📷 No front image"}, "pc_detail.no_back": {"zh": "📷 未上传反面图片", "en": "📷 No back image"}, "pc_detail.upload_front": {"zh": "上传正面", "en": "Upload front"}, "pc_detail.upload_back": {"zh": "上传反面", "en": "Upload back"}, "pc_detail.card_number": {"zh": "编号", "en": "Number"}, "pc_detail.status": {"zh": "状态", "en": "Status"}, "pc_detail.recipient": {"zh": "收件人", "en": "Recipient"}, "pc_detail.country": {"zh": "国家/地区", "en": "Country"}, "pc_detail.send_time": {"zh": "寄出时间", "en": "Sent date"}, "pc_detail.arrival_time": {"zh": "到达时间", "en": "Arrival date"}, "pc_detail.sender": {"zh": "发件人", "en": "Sender"}, "pc_detail.receive_time": {"zh": "收到时间", "en": "Received date"}, "pc_detail.profile": {"zh": "所属 Profile", "en": "Profile"}, "pc_detail.notes": {"zh": "备注", "en": "Notes"}, # ── Status labels ── "status.sent": {"zh": "已寄出", "en": "Sent"}, "status.delivered": {"zh": "已送达", "en": "Delivered"}, "status.received": {"zh": "已收到", "en": "Received"}, # ── Postcard form ── "pc_form.edit": {"zh": "编辑明信片", "en": "Edit postcard"}, "pc_form.new": {"zh": "新建明信片", "en": "New postcard"}, "pc_form.number": {"zh": "编号", "en": "Number"}, "pc_form.number_hint": {"zh": "格式:AB-1234567", "en": "Format: AB-1234567"}, "pc_form.status": {"zh": "状态", "en": "Status"}, "pc_form.recipient": {"zh": "收件人", "en": "Recipient"}, "pc_form.country": {"zh": "国家/地区", "en": "Country"}, "pc_form.send_time": {"zh": "寄出时间", "en": "Sent date"}, "pc_form.arrival_time": {"zh": "到达时间", "en": "Arrival date"}, "pc_form.sender": {"zh": "发件人", "en": "Sender"}, "pc_form.receive_time": {"zh": "收到时间", "en": "Received date"}, "pc_form.notes": {"zh": "备注", "en": "Notes"}, "pc_form.notes_ph": {"zh": "可选备注信息", "en": "Optional notes"}, "pc_form.save": {"zh": "保存", "en": "Save"}, "pc_form.cancel": {"zh": "取消", "en": "Cancel"}, # ── Settings ── "settings.title": {"zh": "用户设置", "en": "Settings"}, "settings.tab_account": {"zh": "账号", "en": "Account"}, "settings.tab_showcase": {"zh": "展示", "en": "Showcase"}, "settings.change_username": {"zh": "修改用户名", "en": "Change username"}, "settings.current_username": {"zh": "当前用户名", "en": "Current username"}, "settings.new_username": {"zh": "新用户名", "en": "New username"}, "settings.change_password": {"zh": "修改密码", "en": "Change password"}, "settings.current_password": {"zh": "当前密码", "en": "Current password"}, "settings.new_password": {"zh": "新密码", "en": "New password"}, "settings.confirm_password": {"zh": "确认新密码", "en": "Confirm new password"}, "settings.language": {"zh": "语言", "en": "Language"}, "settings.language_zh": {"zh": "中文", "en": "中文"}, "settings.language_en": {"zh": "English", "en": "English"}, "settings.showcase_global": {"zh": "全局展示设置", "en": "Global showcase settings"}, "settings.showcase_mode": {"zh": "展示页面模式", "en": "Showcase mode"}, "settings.mode_profile": {"zh": "按 Profile 分类", "en": "Grouped by profile"}, "settings.mode_flat": {"zh": "全部合并", "en": "All together"}, "settings.save_global": {"zh": "保存全局设置", "en": "Save global settings"}, "settings.public_url": {"zh": "公开展示页地址:", "en": "Public showcase: "}, "settings.public_url_label": {"zh": "公开展示页:", "en": "Public showcase: "}, "settings.profiles_showcase": {"zh": "各 Profile 展示设置", "en": "Per-profile showcase"}, "settings.showcase_on": {"zh": "展示中", "en": "Showing"}, "settings.showcase_off": {"zh": "未开启", "en": "Off"}, "settings.enable_showcase": {"zh": "开启展示", "en": "Enable showcase"}, "settings.showcase_content": {"zh": "展示内容", "en": "Content"}, "settings.content_both": {"zh": "发出 + 收到", "en": "Sent + Received"}, "settings.content_sent": {"zh": "仅发出", "en": "Sent only"}, "settings.content_received": {"zh": "仅收到", "en": "Received only"}, "settings.save": {"zh": "保存", "en": "Save"}, # ── Admin invites ── "invites.title": {"zh": "邀请码管理", "en": "Invite codes"}, "invites.create": {"zh": "创建邀请码", "en": "Create invite code"}, "invites.code_label": {"zh": "邀请码(留空自动生成)", "en": "Code (leave empty to auto-generate)"}, "invites.code_ph": {"zh": "自动生成", "en": "Auto-generate"}, "invites.limit_type": {"zh": "限制类型", "en": "Limit type"}, "invites.unlimited": {"zh": "无限制", "en": "Unlimited"}, "invites.uses": {"zh": "使用次数", "en": "Max uses"}, "invites.expires": {"zh": "有效期", "en": "Expiration"}, "invites.times": {"zh": "次数", "en": "Times"}, "invites.create_btn": {"zh": "创建", "en": "Create"}, "invites.creator": {"zh": "创建者", "en": "By"}, "invites.used": {"zh": "已用", "en": "Used"}, "invites.no_expire": {"zh": "永不过期", "en": "No expiration"}, "invites.expires_at": {"zh": "过期", "en": "Expires"}, "invites.edit": {"zh": "编辑", "en": "Edit"}, "invites.save": {"zh": "保存", "en": "Save"}, "invites.delete": {"zh": "删除", "en": "Delete"}, "invites.confirm_delete": {"zh": "确定删除此邀请码?", "en": "Delete this invite code?"}, "invites.max_uses": {"zh": "最大使用次数", "en": "Max uses"}, "invites.expires_time": {"zh": "过期时间", "en": "Expiration"}, "invites.registered_users": {"zh": "注册用户", "en": "Registered users"}, "invites.empty": {"zh": "暂无邀请码", "en": "No invite codes yet"}, # ── Showcase (public) ── "showcase.title": {"zh": " 的明信片", "en": "'s postcards"}, "showcase.empty": {"zh": "暂无展示内容", "en": "Nothing to show yet"}, "showcase.tab_sent": {"zh": "发出", "en": "Sent"}, "showcase.tab_received": {"zh": "收到", "en": "Received"}, # ── Showcase manage ── "showcase_manage.title": {"zh": "展示管理", "en": "Showcase manager"}, "showcase_manage.global": {"zh": "全局展示设置", "en": "Global showcase settings"}, "showcase_manage.save": {"zh": "保存全局设置", "en": "Save global settings"}, "showcase_manage.public_url": {"zh": "公开展示页地址:", "en": "Public showcase: "}, "showcase_manage.profiles": {"zh": "各 Profile 展示设置", "en": "Per-profile settings"}, "showcase_manage.on": {"zh": "展示中", "en": "Showing"}, "showcase_manage.off": {"zh": "未开启", "en": "Off"}, "showcase_manage.enable": {"zh": "开启展示", "en": "Enable"}, "showcase_manage.content": {"zh": "展示内容", "en": "Content"}, "showcase_manage.both": {"zh": "发出 + 收到", "en": "Sent + Received"}, "showcase_manage.sent_only": {"zh": "仅发出", "en": "Sent only"}, "showcase_manage.received_only": {"zh": "仅收到", "en": "Received only"}, # ── Profile showcase ── "profile_showcase.title": {"zh": " 展示设置", "en": " showcase settings"}, "profile_showcase.enable": {"zh": "开启展示", "en": "Enable showcase"}, "profile_showcase.content": {"zh": "展示内容", "en": "Content"}, "profile_showcase.both": {"zh": "发出 + 收到", "en": "Sent + Received"}, "profile_showcase.sent_only": {"zh": "仅发出", "en": "Sent only"}, "profile_showcase.received_only": {"zh": "仅收到", "en": "Received only"}, "profile_showcase.single_control": {"zh": "单张明信片展示控制", "en": "Per-card visibility"}, "profile_showcase.hidden": {"zh": "隐藏", "en": "Hidden"}, "profile_showcase.hint": {"zh": "开启展示后可控制单张明信片的可见性", "en": "Enable showcase to control per-card visibility"}, # ── Flash messages ── "flash.username_taken": {"zh": "用户名已存在", "en": "Username already taken"}, "flash.username_ok": {"zh": "用户名修改成功", "en": "Username changed"}, "flash.wrong_password": {"zh": "当前密码错误", "en": "Wrong password"}, "flash.password_mismatch": {"zh": "两次输入的新密码不一致", "en": "Passwords don't match"}, "flash.password_short": {"zh": "新密码长度至少6位", "en": "Password must be at least 6 characters"}, "flash.password_ok": {"zh": "密码修改成功", "en": "Password changed"}, # ── API Keys ── "settings.tab_apikeys": {"zh": "API Keys", "en": "API Keys"}, "apikey.title": {"zh": "API Key 管理", "en": "API Key Management"}, "apikey.hint": {"zh": "使用 API Key 通过 HTTP 请求访问星笺的公共 API。请妥善保管你的 Key,它仅在创建时显示一次。", "en": "Use API Keys to access Mailova's public API via HTTP requests. Keep your key safe — it is only shown once upon creation."}, "apikey.created": {"zh": "✅ 新 Key 已创建:", "en": "✅ New key created:"}, "apikey.copy_now": {"zh": "⚠️ 请立即复制保存,关闭后将无法再次查看完整 Key。", "en": "⚠️ Copy it now. You won't be able to see the full key again after leaving this page."}, "apikey.name_ph": {"zh": "Key 名称(可选)", "en": "Key name (optional)"}, "apikey.create": {"zh": "创建 Key", "en": "Create Key"}, "apikey.name": {"zh": "名称", "en": "Name"}, "apikey.key": {"zh": "Key", "en": "Key"}, "apikey.created_at": {"zh": "创建时间", "en": "Created"}, "apikey.last_used": {"zh": "最后使用", "en": "Last used"}, "apikey.delete": {"zh": "删除", "en": "Delete"}, "apikey.confirm_delete": {"zh": "确定删除此 API Key?", "en": "Delete this API key?"}, "apikey.empty": {"zh": "暂无 API Key", "en": "No API keys yet"}, # ── API Docs ── "api_docs.title": {"zh": "API 文档", "en": "API Documentation"}, "api_docs.intro": {"zh": "星笺提供 RESTful API,供第三方应用集成使用。所有需要鉴权的请求需在 Header 中携带 X-API-Key。", "en": "Mailova provides a RESTful API for third-party integrations. All authenticated requests must include the X-API-Key header."}, "api_docs.base_url": {"zh": "基础 URL", "en": "Base URL"}, "api_docs.auth": {"zh": "鉴权方式", "en": "Authentication"}, "api_docs.auth_desc": {"zh": "在请求头中携带你的 API Key:", "en": "Include your API Key in the request header:"}, "api_docs.profile_ops": {"zh": "Profile 操作", "en": "Profile Operations"}, "api_docs.postcard_ops": {"zh": "明信片操作", "en": "Postcard Operations"}, "api_docs.upload_op": {"zh": "图片上传", "en": "Image Upload"}, "api_docs.key_ops": {"zh": "API Key 管理", "en": "API Key Management"}, "api_docs.showcase_ops": {"zh": "公开展示(无需鉴权)", "en": "Public Showcase (no auth)"}, "api_docs.method": {"zh": "方法", "en": "Method"}, "api_docs.path": {"zh": "路径", "en": "Path"}, "api_docs.desc": {"zh": "说明", "en": "Description"}, "api_docs.params": {"zh": "参数", "en": "Parameters"}, "api_docs.body": {"zh": "请求体 (JSON)", "en": "Request Body (JSON)"}, "api_docs.response": {"zh": "响应", "en": "Response"}, "api_docs.status": {"zh": "状态码", "en": "Status"}, "api_docs.go_settings": {"zh": "去设置页创建 API Key →", "en": "Go to Settings to create an API Key →"}, "api_docs.try_it": {"zh": "试试看", "en": "Try it"}, "api_docs.api_key_ph": {"zh": "输入你的 API Key", "en": "Enter your API Key"}, "api_docs.send": {"zh": "发送", "en": "Send"}, "api_docs.response_label": {"zh": "响应结果", "en": "Response"}, "api_docs.no_auth": {"zh": "此接口无需鉴权", "en": "No authentication required"}, # ── API Docs (endpoint descriptions) ── "api_docs.ep.list_profiles": {"zh": "获取当前用户的所有 Profile 列表。", "en": "List all profiles for the current user."}, "api_docs.ep.create_profile": {"zh": "创建新 Profile。", "en": "Create a new profile."}, "api_docs.ep.get_profile": {"zh": "获取单个 Profile 详情。", "en": "Get a single profile by ID."}, "api_docs.ep.update_profile": {"zh": "更新 Profile。", "en": "Update a profile."}, "api_docs.ep.delete_profile": {"zh": "删除 Profile 及其下所有明信片。", "en": "Delete a profile and all its postcards."}, "api_docs.ep.list_postcards": {"zh": "获取指定 Profile 下的明信片列表。", "en": "List postcards under a profile."}, "api_docs.ep.create_postcard": {"zh": "创建新明信片。", "en": "Create a new postcard."}, "api_docs.ep.get_postcard": {"zh": "获取单张明信片详情。", "en": "Get a single postcard by ID."}, "api_docs.ep.update_postcard": {"zh": "更新明信片。仅传入需要修改的字段。", "en": "Update a postcard. Only send fields you want to change."}, "api_docs.ep.delete_postcard": {"zh": "删除单张明信片。", "en": "Delete a single postcard."}, "api_docs.ep.upload_image": {"zh": "上传明信片图片(正面或背面),使用", "en": "Upload a postcard image (front or back), using"}, "api_docs.ep.upload_uses": {"zh": "上传明信片图片(正面或背面),使用", "en": "Upload a postcard image (front or back), using"}, "api_docs.ep.list_keys": {"zh": "获取当前用户的所有 API Key。", "en": "List all API keys for the current user."}, "api_docs.ep.create_key": {"zh": "创建新的 API Key。创建后完整 Key 仅在响应中显示一次。", "en": "Create a new API key. The full key is only shown once in the response."}, "api_docs.ep.delete_key": {"zh": "删除指定 API Key。", "en": "Delete an API key."}, "api_docs.ep.showcase_user": {"zh": "获取用户的公开展示数据。", "en": "Get a user's public showcase data."}, "api_docs.ep.showcase_profile": {"zh": "获取单个 Profile 的展示数据。", "en": "Get showcase data for a single profile."}, "api_docs.ep.filter_hint": {"zh": "按状态筛选:sent / delivered / received", "en": "Filter by status: sent / delivered / received"}, "api_docs.ep.optional_str": {"zh": "string(可选)", "en": "string (optional)"}, "api_docs.ep.image_file": {"zh": "图片文件", "en": "image file"}, "api_docs.ep.side_hint": {"zh": "string(可选)— front 或 back,默认 front", "en": "string (optional) — front or back, defaults to front"}, "api_docs.ep.key_name_hint": {"zh": "string(可选)— Key 的备注名称", "en": "string (optional) — a label for the key"}, "api_docs.ep.country_hint": {"zh": "两个大写字母,如 JP", "en": "two uppercase letters, e.g. JP"}, "api_docs.ep.date_hint": {"zh": "格式 YYYY-MM-DD 或 YYYY-MM-DDTHH:MM", "en": "format: YYYY-MM-DD or YYYY-MM-DDTHH:MM"}, # ── Misc ── "misc.required": {"zh": " *", "en": " *"}, } def t(key: str, lang: str = "zh") -> str: """Translate a key to the given language. Falls back to zh, then key itself.""" entry = _translations.get(key) if entry is None: return key return entry.get(lang) or entry.get("zh") or key