From 87785494d62198b83e7118955c75d7fafe998675 Mon Sep 17 00:00:00 2001 From: Zichao Lin Date: Mon, 6 Jul 2026 22:41:09 +0800 Subject: [PATCH] feat(i18n): add English localization with per-user language preference --- app/i18n.py | 9 +++ app/templates/admin_invites.html | 2 +- app/templates/dashboard.html | 112 +++++++++++++++++++++-------- app/templates/postcard_form.html | 6 ++ app/templates/profiles.html | 27 ++++--- app/templates/settings.html | 91 ++++++++++++++++------- app/templates/showcase.html | 90 +++++++++++++++-------- app/templates/showcase_manage.html | 4 +- 8 files changed, 243 insertions(+), 98 deletions(-) diff --git a/app/i18n.py b/app/i18n.py index 014827d..478fd4d 100644 --- a/app/i18n.py +++ b/app/i18n.py @@ -33,6 +33,14 @@ _translations: dict[str, dict[str, str]] = { "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"}, @@ -159,6 +167,7 @@ _translations: dict[str, dict[str, str]] = { "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"}, diff --git a/app/templates/admin_invites.html b/app/templates/admin_invites.html index d0c0751..51dc860 100644 --- a/app/templates/admin_invites.html +++ b/app/templates/admin_invites.html @@ -93,7 +93,7 @@ {% else %}
🔑
-

{{ 'invites.title'|t(user.language) }}

+

{{ 'invites.empty'|t(user.language) }}

{% endif %} diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index 487c47d..d855759 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -76,45 +76,97 @@ {% endif %} {% endif %} -{% if profiles %}
- {% for p in profiles %} - -

{{ p.nickname }}

-
- {{ p.postcards|length }} {{ 'profiles.total'|t(user.language) }} +
+

{{ 'dash.recent'|t(user.language) }}

+ {% if recent %} +
- - {% endfor %} + {% else %} +

{{ 'dash.empty'|t(user.language) }}

+ {% endif %} +
+ +
+

Profile

+ +
-{% endif %} {% else %}
-

{{ 'dash.welcome'|t(user.language) }}{{ user.username }} 👋

+
📮
+

{{ 'dash.welcome_title'|t(user.language) }}

+

{{ 'dash.welcome_hint'|t(user.language) }} {{ 'nav.profiles'|t(user.language) }}

{% endif %} {% endblock %} diff --git a/app/templates/postcard_form.html b/app/templates/postcard_form.html index 2f19397..4ef821a 100644 --- a/app/templates/postcard_form.html +++ b/app/templates/postcard_form.html @@ -60,6 +60,7 @@ function toggleFields() { country.required = false; sendTime.required = false; arrival.required = false; + arrival.disabled = false; sender.required = true; receive.required = true; } else if (s === 'sent') { @@ -71,6 +72,7 @@ function toggleFields() { arrival.required = false; arrival.disabled = true; arrival.value = ''; + labelArrival.textContent = '到达时间'; sender.required = false; receive.required = false; } else { @@ -81,19 +83,23 @@ function toggleFields() { sendTime.required = true; arrival.disabled = false; arrival.required = true; + labelArrival.textContent = '到达时间 *'; sender.required = false; receive.required = false; } } toggleFields(); {% if not postcard %} +// Auto-fill date fields with today on new postcards (function() { var today = new Date().toISOString().slice(0, 10); var sendTime = document.getElementById('input-send-time'); var receiveTime = document.getElementById('input-receive'); var statusSel = document.getElementById('status-select'); + // Fill on page load if (statusSel.value === 'sent' && !sendTime.value) sendTime.value = today; if (statusSel.value === 'received' && !receiveTime.value) receiveTime.value = today; + // Fill on status change statusSel.addEventListener('change', function() { if (this.value === 'sent' && !sendTime.value) sendTime.value = today; if (this.value === 'received' && !receiveTime.value) receiveTime.value = today; diff --git a/app/templates/profiles.html b/app/templates/profiles.html index 46e6614..1f76cf2 100644 --- a/app/templates/profiles.html +++ b/app/templates/profiles.html @@ -2,7 +2,7 @@ {% block title %}{{ 'nav.profiles'|t(user.language) }} - {{ 'brand'|t(user.language) }}{% endblock %} {% block content %}
-

{{ 'nav.profiles'|t(user.language) }}

+

Profile

@@ -56,27 +56,34 @@
{% endfor %} {% else %} -

{{ 'profiles.new_ph'|t(user.language) }}

+
+
📮
+

还没有 Profile

+

{{ 'profiles.new_ph'|t(user.language) }}

+
{% endif %} - {% endblock %} diff --git a/app/templates/settings.html b/app/templates/settings.html index 29d3ca8..ee07747 100644 --- a/app/templates/settings.html +++ b/app/templates/settings.html @@ -76,37 +76,83 @@

-{% if profiles %}

{{ 'settings.profiles_showcase'|t(user.language) }}

+ {% if profiles %} {% for p in profiles %} -
-
+ {% set sent_cards = [] %} + {% set received_cards = [] %} + {% if profile_cards and p.id in profile_cards %} + {% for pc in profile_cards[p.id] %} + {% if pc.status in ('sent', 'delivered') %} + {% if sent_cards.append(pc) %}{% endif %} + {% else %} + {% if received_cards.append(pc) %}{% endif %} + {% endif %} + {% endfor %} + {% endif %} +
+
{{ p.nickname }} - {% if p.showcase_enabled %}{{ 'settings.showcase_on'|t(user.language) }}{% else %}{{ 'settings.showcase_off'|t(user.language) }}{% endif %} + {% if p.showcase_enabled %}{{ 'settings.showcase_on'|t(user.language) }}{% else %}{{ 'settings.showcase_off'|t(user.language) }}{% endif %}
-
-
- - + +
+
+ + +
+
+ + +
-
- - -
- {{ 'settings.save'|t(user.language) }} + + {% if p.showcase_enabled and (sent_cards or received_cards) %} +
+

{{ 'profile_showcase.single_control'|t(user.language) }}:

+ {% if sent_cards %} +
+ {{ 'showcase.tab_sent'|t(user.language) }} + {% for pc in sent_cards %} +
+ + {{ pc.card_number }} +
+ {% endfor %} +
+ {% endif %} + {% if received_cards %} +
+ {{ 'showcase.tab_received'|t(user.language) }} + {% for pc in received_cards %} +
+ + {{ pc.card_number }} +
+ {% endfor %} +
+ {% endif %} +
+ {% elif p.showcase_enabled %} +

{{ 'showcase.empty'|t(user.language) }}

+ {% endif %}
{% endfor %} + {% else %} +
+

{{ 'profiles.new_ph'|t(user.language) }}

+
+ {% endif %}
-{% endif %}
{% endblock %} diff --git a/app/templates/showcase.html b/app/templates/showcase.html index 6556618..ea1d786 100644 --- a/app/templates/showcase.html +++ b/app/templates/showcase.html @@ -1,5 +1,4 @@ {% extends "base.html" %} -{% set lang = lang if lang is defined else 'zh' %} {% block title %}{{ profile_user.username }} {{ 'showcase.title'|t(lang) }}{% endblock %} {% block nav %}{% endblock %} {% block content %} @@ -114,47 +113,76 @@
{% endif %} - -