feat(i18n): add English localization with per-user language preference

This commit is contained in:
2026-07-06 22:41:09 +08:00
parent 643f1dc35a
commit 87785494d6
8 changed files with 243 additions and 98 deletions

View File

@@ -76,37 +76,83 @@
</p>
</div>
{% if profiles %}
<div style="margin-top:1.5rem">
<h2 style="font-size:1rem;margin-bottom:1rem">{{ 'settings.profiles_showcase'|t(user.language) }}</h2>
{% if profiles %}
{% for p in profiles %}
<div class="form-card" style="margin-bottom:.75rem">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:.5rem">
{% 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 %}
<div class="showcase-profile-card" style="background:var(--card-bg);border:1px solid var(--border);border-radius:10px;padding:1rem;margin-bottom:.75rem">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem">
<strong>{{ p.nickname }}</strong>
<span class="badge">{% if p.showcase_enabled %}{{ 'settings.showcase_on'|t(user.language) }}{% else %}{{ 'settings.showcase_off'|t(user.language) }}{% endif %}</span>
<span class="badge" style="{% if p.showcase_enabled %}background:var(--sent){% else %}background:var(--text-muted){% endif %}">{% if p.showcase_enabled %}{{ 'settings.showcase_on'|t(user.language) }}{% else %}{{ 'settings.showcase_off'|t(user.language) }}{% endif %}</span>
</div>
<form method="post" action="/profiles/{{ p.id }}/showcase" style="display:flex;flex-wrap:wrap;gap:.75rem;align-items:flex-end">
<div style="display:flex;flex-direction:column;gap:.25rem">
<label style="margin:0;font-size:.78rem">{{ 'settings.enable_showcase'|t(user.language) }}</label>
<label class="toggle-switch">
<input type="checkbox" name="showcase_enabled" value="1" {% if p.showcase_enabled %}checked{% endif %} onchange="this.form.submit()">
<span class="toggle-slider"></span>
</label>
<form method="post" action="/profiles/{{ p.id }}/showcase">
<div style="display:flex;flex-wrap:wrap;gap:1rem;align-items:center">
<div style="display:flex;align-items:center;gap:.5rem">
<label style="margin:0;font-size:.85rem">{{ 'settings.enable_showcase'|t(user.language) }}</label>
<label class="toggle-switch">
<input type="checkbox" name="showcase_enabled" value="1" {% if p.showcase_enabled %}checked{% endif %} onchange="this.form.submit()">
<span class="toggle-slider"></span>
</label>
</div>
<div style="display:flex;align-items:center;gap:.5rem">
<label style="margin:0;font-size:.85rem">{{ 'settings.showcase_content'|t(user.language) }}</label>
<select name="showcase_visible" onchange="this.form.submit()" style="width:auto">
<option value="both" {% if p.showcase_visible == 'both' %}selected{% endif %}>{{ 'settings.content_both'|t(user.language) }}</option>
<option value="sent" {% if p.showcase_visible == 'sent' %}selected{% endif %}>{{ 'settings.content_sent'|t(user.language) }}</option>
<option value="received" {% if p.showcase_visible == 'received' %}selected{% endif %}>{{ 'settings.content_received'|t(user.language) }}</option>
</select>
</div>
</div>
<div style="display:flex;flex-direction:column;gap:.25rem">
<label style="margin:0;font-size:.78rem">{{ 'settings.showcase_content'|t(user.language) }}</label>
<select name="showcase_visible" onchange="this.form.submit()">
<option value="both" {% if p.showcase_visible == 'both' %}selected{% endif %}>{{ 'settings.content_both'|t(user.language) }}</option>
<option value="sent" {% if p.showcase_visible == 'sent' %}selected{% endif %}>{{ 'settings.content_sent'|t(user.language) }}</option>
<option value="received" {% if p.showcase_visible == 'received' %}selected{% endif %}>{{ 'settings.content_received'|t(user.language) }}</option>
</select>
</div>
<a href="/profiles/{{ p.id }}/showcase" class="btn btn-sm">{{ 'settings.save'|t(user.language) }}</a>
</form>
{% if p.showcase_enabled and (sent_cards or received_cards) %}
<div style="margin-top:.75rem;border-top:1px solid var(--border);padding-top:.75rem">
<p style="font-size:.8rem;color:var(--text-muted);margin-bottom:.5rem">{{ 'profile_showcase.single_control'|t(user.language) }}</p>
{% if sent_cards %}
<div style="margin-bottom:.4rem">
<span style="font-size:.78rem;color:var(--text-muted);margin-right:.5rem">{{ 'showcase.tab_sent'|t(user.language) }}</span>
{% for pc in sent_cards %}
<form method="post" action="/postcards/{{ pc.id }}/showcase-toggle" style="display:inline-flex;align-items:center;gap:.3rem;margin-right:.75rem;margin-bottom:.25rem;font-size:.85rem">
<input type="checkbox" name="showcase_visible" value="1" {% if not pc.showcase_hidden %}checked{% endif %} onchange="this.form.submit()" style="margin:0">
<span>{{ pc.card_number }}</span>
</form>
{% endfor %}
</div>
{% endif %}
{% if received_cards %}
<div>
<span style="font-size:.78rem;color:var(--text-muted);margin-right:.5rem">{{ 'showcase.tab_received'|t(user.language) }}</span>
{% for pc in received_cards %}
<form method="post" action="/postcards/{{ pc.id }}/showcase-toggle" style="display:inline-flex;align-items:center;gap:.3rem;margin-right:.75rem;margin-bottom:.25rem;font-size:.85rem">
<input type="checkbox" name="showcase_visible" value="1" {% if not pc.showcase_hidden %}checked{% endif %} onchange="this.form.submit()" style="margin:0">
<span>{{ pc.card_number }}</span>
</form>
{% endfor %}
</div>
{% endif %}
</div>
{% elif p.showcase_enabled %}
<p style="margin-top:.75rem;font-size:.8rem;color:var(--text-muted)">{{ 'showcase.empty'|t(user.language) }}</p>
{% endif %}
</div>
{% endfor %}
{% else %}
<div class="empty-state">
<p>{{ 'profiles.new_ph'|t(user.language) }}</p>
</div>
{% endif %}
</div>
{% endif %}
</div>
<script>
@@ -116,8 +162,5 @@ function switchTab(name) {
event.currentTarget.classList.add('active');
document.getElementById('tab-' + name).style.display = '';
}
{% if active_tab == 'showcase' %}
document.querySelector('[onclick*="showcase"]').click();
{% endif %}
</script>
{% endblock %}