Files
mailova/app/i18n.py

291 lines
20 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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