feat(i18n): add English localization with per-user language preference and navbar toggle
This commit is contained in:
@@ -1,21 +1,22 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}{{ profile_user.username }} 的明信片{% endblock %}
|
||||
{% set lang = lang if lang is defined else 'zh' %}
|
||||
{% block title %}{{ profile_user.username }} {{ 'showcase.title'|t(lang) }}{% endblock %}
|
||||
{% block nav %}{% endblock %}
|
||||
{% block content %}
|
||||
<div class="section-header">
|
||||
<h1>📮 {{ profile_user.username }} 的明信片</h1>
|
||||
<h1>📮 {{ profile_user.username }} {{ 'showcase.title'|t(lang) }}</h1>
|
||||
</div>
|
||||
|
||||
{% set has_content = (sent_all|length + received_all|length) > 0 %}
|
||||
{% if not has_content %}
|
||||
<div class="empty-state">
|
||||
<p>暂无展示内容</p>
|
||||
<p>{{ 'showcase.empty'|t(lang) }}</p>
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
<div class="tabs" id="tabs">
|
||||
<button class="tab active" onclick="switchTab('sent')">发出 ({{ sent_all|length }})</button>
|
||||
<button class="tab" onclick="switchTab('received')">收到 ({{ received_all|length }})</button>
|
||||
<button class="tab active" onclick="switchTab('sent')">{{ 'showcase.tab_sent'|t(lang) }} ({{ sent_all|length }})</button>
|
||||
<button class="tab" onclick="switchTab('received')">{{ 'showcase.tab_received'|t(lang) }} ({{ received_all|length }})</button>
|
||||
</div>
|
||||
|
||||
<div id="tab-sent" class="tab-panel">
|
||||
@@ -113,76 +114,47 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="lightbox" class="lightbox" onclick="closeLightbox(event)">
|
||||
<button class="lightbox-close" onclick="closeLightbox(event)">×</button>
|
||||
<button class="lightbox-prev" onclick="navLightbox(-1,event)">❮</button>
|
||||
<button class="lightbox-next" onclick="navLightbox(1,event)">❯</button>
|
||||
<!-- Lightbox -->
|
||||
<div id="lightbox" class="lightbox" onclick="closeLightbox()">
|
||||
<button class="lightbox-close" onclick="closeLightbox()">✕</button>
|
||||
<button class="lightbox-prev" onclick="event.stopPropagation();navLightbox(-1)">‹</button>
|
||||
<button class="lightbox-next" onclick="event.stopPropagation();navLightbox(1)">›</button>
|
||||
<div class="lightbox-content" onclick="event.stopPropagation()">
|
||||
<img id="lightbox-img" src="" alt="">
|
||||
<div id="lightbox-caption" class="lightbox-caption"></div>
|
||||
<div id="lightbox-number" class="lightbox-number"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var cards = [];
|
||||
document.querySelectorAll('.showcase-card').forEach(function(el) {
|
||||
cards.push({ front: el.dataset.front, number: el.dataset.number });
|
||||
});
|
||||
var currentIndex = 0;
|
||||
|
||||
function openLightbox(el) {
|
||||
currentIndex = cards.findIndex(function(c) { return c.number === el.dataset.number; });
|
||||
showLightbox();
|
||||
document.getElementById('lightbox').style.display = 'flex';
|
||||
}
|
||||
function showLightbox() {
|
||||
var c = cards[currentIndex];
|
||||
document.getElementById('lightbox-img').src = c.front;
|
||||
document.getElementById('lightbox-number').textContent = c.number;
|
||||
}
|
||||
function closeLightbox() { document.getElementById('lightbox').style.display = 'none'; }
|
||||
function navLightbox(dir) { currentIndex = (currentIndex + dir + cards.length) % cards.length; showLightbox(); }
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (document.getElementById('lightbox').style.display !== 'flex') return;
|
||||
if (e.key === 'Escape') closeLightbox();
|
||||
if (e.key === 'ArrowLeft') navLightbox(-1);
|
||||
if (e.key === 'ArrowRight') navLightbox(1);
|
||||
});
|
||||
function switchTab(name) {
|
||||
document.querySelectorAll('.tab').forEach(function(t) { t.classList.remove('active'); });
|
||||
document.querySelectorAll('.tab-panel').forEach(function(p) { p.style.display = 'none'; });
|
||||
event.currentTarget.classList.add('active');
|
||||
document.getElementById('tab-' + name).style.display = '';
|
||||
}
|
||||
|
||||
var lightboxItems = [];
|
||||
var lightboxIdx = 0;
|
||||
|
||||
function buildLightboxItems() {
|
||||
lightboxItems = [];
|
||||
var visible = document.querySelectorAll('.tab-panel:not([style*="display:none"]) .showcase-card[data-front]');
|
||||
visible.forEach(function(card) {
|
||||
var front = card.getAttribute('data-front');
|
||||
var number = card.getAttribute('data-number');
|
||||
if (front) lightboxItems.push({src: front, number: number});
|
||||
});
|
||||
}
|
||||
|
||||
function openLightbox(el) {
|
||||
buildLightboxItems();
|
||||
var front = el.getAttribute('data-front');
|
||||
if (!front) return;
|
||||
var number = el.getAttribute('data-number');
|
||||
for (var i = 0; i < lightboxItems.length; i++) {
|
||||
if (lightboxItems[i].number === number) { lightboxIdx = i; break; }
|
||||
}
|
||||
showLightboxItem();
|
||||
document.getElementById('lightbox').classList.add('active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function showLightboxItem() {
|
||||
if (!lightboxItems.length) return;
|
||||
var item = lightboxItems[lightboxIdx];
|
||||
document.getElementById('lightbox-img').src = item.src;
|
||||
document.getElementById('lightbox-caption').textContent = item.number + ' (' + (lightboxIdx+1) + '/' + lightboxItems.length + ')';
|
||||
}
|
||||
|
||||
function closeLightbox(e) {
|
||||
if (e) e.stopPropagation();
|
||||
document.getElementById('lightbox').classList.remove('active');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
|
||||
function navLightbox(dir, e) {
|
||||
if (e) e.stopPropagation();
|
||||
if (!lightboxItems.length) return;
|
||||
lightboxIdx = (lightboxIdx + dir + lightboxItems.length) % lightboxItems.length;
|
||||
showLightboxItem();
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
var lb = document.getElementById('lightbox');
|
||||
if (!lb || !lb.classList.contains('active')) return;
|
||||
if (e.key === 'Escape') closeLightbox();
|
||||
else if (e.key === 'ArrowLeft') navLightbox(-1);
|
||||
else if (e.key === 'ArrowRight') navLightbox(1);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user