Files
TimeTracker/app/templates/_components.html
Dries Peeters 69f9f1140d feat(i18n): add translations, locale switcher, and user language preference
- Integrate Flask-Babel and i18n utilities; initialize in app factory
- Add `preferred_language` to `User` with Alembic migration (011_add_user_preferred_language)
- Add `babel.cfg` and `scripts/extract_translations.py`
- Add `translations/` for en, de, fr, it, nl, fi
- Update templates to use `_()` and add language picker in navbar/profile
- Respect locale in routes and context processors; persist user preference
- Update requirements and Docker/Docker entrypoint for Babel/gettext support
- Minor copy and style adjustments across pages

Migration: run `alembic upgrade head`
2025-09-11 23:08:41 +02:00

50 lines
1.9 KiB
HTML

{% macro page_header(icon_class, title_text, subtitle_text=None, actions_html=None) %}
<div class="card stats-card hover-lift mb-4">
<div class="card-body d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center">
<div class="mb-3 mb-md-0">
<h1 class="h3 mb-1">{% if icon_class %}<i class="{{ icon_class }} me-2"></i>{% endif %}{{ _(title_text) }}</h1>
{% if subtitle_text %}
<p class="mb-0 text-muted">{{ _(subtitle_text) }}</p>
{% endif %}
</div>
<div class="d-flex flex-wrap gap-2 align-items-center">
{{ actions_html|safe if actions_html }}
</div>
</div>
</div>
{% endmacro %}
{% macro summary_card(icon_class, icon_color, label, value) %}
<div class="card border-0 shadow-sm h-100 summary-card">
<div class="card-body p-3">
<div class="d-flex align-items-center">
<div class="flex-shrink-0">
<div class="summary-icon bg-{{ icon_color }} bg-opacity-10 text-{{ icon_color }}">
<i class="{{ icon_class }}"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<div class="summary-label">{{ _(label) }}</div>
<div class="summary-value">{{ value }}</div>
</div>
</div>
</div>
</div>
{% endmacro %}
{% macro empty_state(icon_class, title, message, actions_html=None) %}
<div class="text-center py-5">
<div class="bg-light rounded-circle d-flex align-items-center justify-content-center mx-auto mb-4" style="width: 80px; height: 80px;">
<i class="{{ icon_class }} fa-2x text-muted"></i>
</div>
<h4 class="text-muted mb-2">{{ _(title) }}</h4>
<p class="text-muted mb-4">{{ _(message) }}</p>
{% if actions_html %}
<div class="d-flex flex-column flex-sm-row gap-2 justify-content-center">
{{ actions_html|safe }}
</div>
{% endif %}
</div>
{% endmacro %}