feat: Implementiere mehrsprachige Unterstützung (i18n)
- Füge Flask-Babel für professionelle i18n-Implementierung hinzu - Implementiere automatische Browser-Spracherkennung - Erstelle datenschutzfreundliche Sprachauswahl ohne Cookies - Verwende URL-Parameter und localStorage für Sprachauswahl - Füge vollständige Übersetzungen für Deutsch und Englisch hinzu - Implementiere responsive Dropdown-Sprachauswahl mit Landesflaggen - Verbessere Barrierefreiheit mit ARIA-Attributen und Screenreader-Support - Aktualisiere README mit i18n-Dokumentation - Version 1.4.0
This commit is contained in:
@@ -9,11 +9,11 @@
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Elpatrons Datumsrechner – Open Source Kalender- und Datumsberechnungen</title>
|
||||
<meta name="description" content="Elpatrons Datumsrechner: Open Source Web-App für Kalender- und Datumsberechnungen. Tage, Werktage, Wochen, Monate, Kalenderwochen, Wochentage und mehr berechnen – barrierefrei, werbefrei, trackingfrei, kostenlos.">
|
||||
<meta name="keywords" content="Datum, Kalender, Datumsrechner, Werktage, Tage zählen, Kalenderwoche, Wochentag, Open Source, Python, Flask, barrierefreiheit, barrierefrei, kostenlos, werbefrei, trackingfrei, cookiefrei">
|
||||
<meta property="og:title" content="Elpatrons Datumsrechner – Open Source Kalender- und Datumsberechnungen">
|
||||
<meta property="og:description" content="Open Source Web-App für Kalender- und Datumsberechnungen. Werbefrei, trackingfrei, kostenlos.">
|
||||
<title>{{ _('Elpatrons Datumsrechner – Open Source Kalender- und Datumsberechnungen') }}</title>
|
||||
<meta name="description" content="{{ _('Elpatrons Datumsrechner: Open Source Web-App für Kalender- und Datumsberechnungen. Tage, Werktage, Wochen, Monate, Kalenderwochen, Wochentage und mehr berechnen – barrierefrei, werbefrei, trackingfrei, kostenlos.') }}">
|
||||
<meta name="keywords" content="{{ _('Datum, Kalender, Datumsrechner, Werktage, Tage zählen, Kalenderwoche, Wochentag, Open Source, Python, Flask, barrierefreiheit, barrierefrei, kostenlos, werbefrei, trackingfrei, cookiefrei') }}">
|
||||
<meta property="og:title" content="{{ _('Elpatrons Datumsrechner – Open Source Kalender- und Datumsberechnungen') }}">
|
||||
<meta property="og:description" content="{{ _('Open Source Web-App für Kalender- und Datumsberechnungen. Werbefrei, trackingfrei, kostenlos.') }}">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://codeberg.org/elpatron/datecalc">
|
||||
<meta property="og:image" content="/static/logo.svg">
|
||||
@@ -63,7 +63,7 @@ body {
|
||||
}
|
||||
.help-button-container {
|
||||
position: absolute;
|
||||
top: 2.5em;
|
||||
top: 1.5em;
|
||||
right: 2em;
|
||||
z-index: 10;
|
||||
}
|
||||
@@ -464,7 +464,7 @@ button:focus, .accordion-header:focus {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
.help-button-container {
|
||||
top: 1.5em;
|
||||
top: 1em;
|
||||
right: 1.2em;
|
||||
}
|
||||
.help-button {
|
||||
@@ -474,6 +474,17 @@ button:focus, .accordion-header:focus {
|
||||
min-width: 48px;
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
.language-selector {
|
||||
top: 1em;
|
||||
left: 1.2em;
|
||||
}
|
||||
|
||||
#language-dropdown {
|
||||
min-width: 100px;
|
||||
font-size: 0.85em;
|
||||
padding: 0.4em 0.6em;
|
||||
}
|
||||
.help-tooltip {
|
||||
font-size: 0.8em;
|
||||
padding: 0.4em 0.6em;
|
||||
@@ -488,6 +499,58 @@ button:focus, .accordion-header:focus {
|
||||
}
|
||||
}
|
||||
|
||||
/* Sprachauswahl */
|
||||
.language-selector {
|
||||
position: absolute;
|
||||
top: 1.5em;
|
||||
left: 2em;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#language-dropdown {
|
||||
padding: 0.5em 0.8em;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--surface);
|
||||
color: var(--text);
|
||||
font-size: 0.9em;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
min-width: 120px;
|
||||
min-height: 44px;
|
||||
transition: all 0.2s;
|
||||
box-shadow: 0 1px 3px rgba(30,41,59,0.05);
|
||||
}
|
||||
|
||||
#language-dropdown:hover {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 2px 6px rgba(30,41,59,0.1);
|
||||
}
|
||||
|
||||
#language-dropdown:focus {
|
||||
outline: 3px solid #facc15;
|
||||
outline-offset: 2px;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
#language-dropdown option {
|
||||
padding: 0.5em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
/* Screen Reader Only */
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* Touch-Target Optimierungen für Footer-Links */
|
||||
footer a {
|
||||
display: inline-block;
|
||||
@@ -535,6 +598,12 @@ footer br + a {
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
document.getElementById(id).value = today;
|
||||
}
|
||||
|
||||
function changeLanguage(language) {
|
||||
// Speichere Sprache in localStorage (datenschutzfreundlich)
|
||||
localStorage.setItem('preferred_language', language);
|
||||
window.location.href = '/set_language/' + language;
|
||||
}
|
||||
function openAccordion(idx) {
|
||||
const headers = document.querySelectorAll('.accordion-header');
|
||||
const panels = document.querySelectorAll('.accordion-content');
|
||||
@@ -632,6 +701,14 @@ footer br + a {
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Prüfe localStorage für gespeicherte Sprachauswahl
|
||||
const savedLanguage = localStorage.getItem('preferred_language');
|
||||
if (savedLanguage && !window.location.search.includes('lang=')) {
|
||||
// Wenn Sprache in localStorage gespeichert ist, aber nicht in URL
|
||||
window.location.href = window.location.pathname + '?lang=' + savedLanguage;
|
||||
return;
|
||||
}
|
||||
|
||||
// Sofortige Aktivierung der ersten Accordion-Sektion um Layout-Shifts zu vermeiden
|
||||
const activeIdx = parseInt("{{ active_idx|default(0) }}");
|
||||
const headers = document.querySelectorAll('.accordion-header');
|
||||
@@ -690,14 +767,20 @@ footer br + a {
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="help-button-container">
|
||||
<button type="button" class="help-button" onclick="showHelp()" aria-label="Hilfe anzeigen" title="Hilfe anzeigen" aria-describedby="help-tooltip">?</button>
|
||||
<div id="help-tooltip" class="help-tooltip" role="tooltip">Öffnet ein Hilfefenster mit Informationen über den Datumsrechner</div>
|
||||
<button type="button" class="help-button" onclick="showHelp()" aria-label="{{ _('Hilfe anzeigen') }}" title="{{ _('Hilfe anzeigen') }}" aria-describedby="help-tooltip">?</button>
|
||||
<div id="help-tooltip" class="help-tooltip" role="tooltip">{{ _('Öffnet ein Hilfefenster mit Informationen über den Datumsrechner') }}</div>
|
||||
</div>
|
||||
<div class="language-selector">
|
||||
<select id="language-dropdown" onchange="changeLanguage(this.value)" aria-label="{{ _('Sprache auswählen') }}" title="{{ _('Sprache auswählen') }}">
|
||||
<option value="de" {% if get_locale() == 'de' %}selected{% endif %}>{{ _('Deutsch') }}</option>
|
||||
<option value="en" {% if get_locale() == 'en' %}selected{% endif %}>{{ _('English') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="text-align:center; margin-bottom:1.2em;">
|
||||
<div style="font-size:1.1em; font-style:italic; color:#475569;">Elpatrons</div>
|
||||
<h1 style="margin:0;">Datumsrechner</h1>
|
||||
<div style="font-size:1.1em; font-style:italic; color:#475569;">{{ _('Elpatrons') }}</div>
|
||||
<h1 style="margin:0;">{{ _('Datumsrechner') }}</h1>
|
||||
<div style="font-size:0.9em; color:#1e293b; margin-top:0.3em;">
|
||||
Eine <em>freie</em> Web-App: barriere<em>frei</em>, werbe<em>frei</em>, tracking<em>frei</em>, lizenz<em>frei</em> und kosten<em>frei</em>.
|
||||
{{ _('Eine <em>freie</em> Web-App: barriere<em>frei</em>, werbe<em>frei</em>, tracking<em>frei</em>, lizenz<em>frei</em> und kosten<em>frei</em>.') | safe }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion">
|
||||
@@ -707,45 +790,45 @@ footer br + a {
|
||||
<!-- Kalender mit Doppelpfeil -->
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="5" width="18" height="16" rx="4" fill="#fff" stroke="#2563eb" stroke-width="2"/><rect x="3" y="5" width="18" height="4" rx="2" fill="#2563eb"/><rect x="6" y="2" width="2" height="4" rx="1" fill="#2563eb"/><rect x="16" y="2" width="2" height="4" rx="1" fill="#2563eb"/><path d="M8 15h8M8 15l2-2M8 15l2 2M16 15l-2-2M16 15l-2 2" stroke="#2563eb" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
</span>
|
||||
Anzahl der Tage/Werktage zwischen zwei Daten
|
||||
{{ _('Anzahl der Tage/Werktage zwischen zwei Daten') }}
|
||||
</button>
|
||||
<div class="accordion-content active" id="accordion-panel-0" role="region" aria-labelledby="accordion-header-0">
|
||||
<form method="post">
|
||||
<label for="start1">Startdatum:<br>
|
||||
<label for="start1">{{ _('Startdatum:') }}<br>
|
||||
<span class="date-row">
|
||||
<input type="date" name="start1" id="start1">
|
||||
<button type="button" class="today-btn" onclick="setToday('start1')">Heute</button>
|
||||
<button type="button" class="today-btn" onclick="setToday('start1')">{{ _('Heute') }}</button>
|
||||
</span>
|
||||
</label>
|
||||
<label for="end1">Enddatum:<br>
|
||||
<label for="end1">{{ _('Enddatum:') }}<br>
|
||||
<span class="date-row">
|
||||
<input type="date" name="end1" id="end1">
|
||||
<button type="button" class="today-btn" onclick="setToday('end1')">Heute</button>
|
||||
<button type="button" class="today-btn" onclick="setToday('end1')">{{ _('Heute') }}</button>
|
||||
</span>
|
||||
</label>
|
||||
<fieldset style="display:flex;align-items:center;gap:0.5em;margin-top:0.7em; border:none; padding:0;">
|
||||
<legend class="sr-only">Optionen</legend>
|
||||
<input type="checkbox" name="werktage" id="werktage" {% if request.form.get('werktage') %}checked{% endif %} aria-checked="{{ 'true' if request.form.get('werktage') else 'false' }}">
|
||||
<label for="werktage" style="margin:0;">Nur Werktage</label>
|
||||
<label for="bundesland" style="margin-left:1em;">Feiertage berücksichtigen für:
|
||||
<label for="werktage" style="margin:0;">{{ _('Nur Werktage') }}</label>
|
||||
<label for="bundesland" style="margin-left:1em;">{{ _('Feiertage berücksichtigen für:') }}
|
||||
<select name="bundesland" id="bundesland" {% if not request.form.get('werktage') %}disabled{% endif %}>
|
||||
<option value="">(kein Bundesland)</option>
|
||||
<option value="BW" {% if request.form.get('bundesland') == 'BW' %}selected{% endif %}>Baden-Württemberg</option>
|
||||
<option value="BY" {% if request.form.get('bundesland') == 'BY' %}selected{% endif %}>Bayern</option>
|
||||
<option value="BE" {% if request.form.get('bundesland') == 'BE' %}selected{% endif %}>Berlin</option>
|
||||
<option value="BB" {% if request.form.get('bundesland') == 'BB' %}selected{% endif %}>Brandenburg</option>
|
||||
<option value="HB" {% if request.form.get('bundesland') == 'HB' %}selected{% endif %}>Bremen</option>
|
||||
<option value="HH" {% if request.form.get('bundesland') == 'HH' %}selected{% endif %}>Hamburg</option>
|
||||
<option value="HE" {% if request.form.get('bundesland') == 'HE' %}selected{% endif %}>Hessen</option>
|
||||
<option value="MV" {% if request.form.get('bundesland') == 'MV' %}selected{% endif %}>Mecklenburg-Vorpommern</option>
|
||||
<option value="NI" {% if request.form.get('bundesland') == 'NI' %}selected{% endif %}>Niedersachsen</option>
|
||||
<option value="NW" {% if request.form.get('bundesland') == 'NW' %}selected{% endif %}>Nordrhein-Westfalen</option>
|
||||
<option value="RP" {% if request.form.get('bundesland') == 'RP' %}selected{% endif %}>Rheinland-Pfalz</option>
|
||||
<option value="SL" {% if request.form.get('bundesland') == 'SL' %}selected{% endif %}>Saarland</option>
|
||||
<option value="SN" {% if request.form.get('bundesland') == 'SN' %}selected{% endif %}>Sachsen</option>
|
||||
<option value="ST" {% if request.form.get('bundesland') == 'ST' %}selected{% endif %}>Sachsen-Anhalt</option>
|
||||
<option value="SH" {% if request.form.get('bundesland') == 'SH' %}selected{% endif %}>Schleswig-Holstein</option>
|
||||
<option value="TH" {% if request.form.get('bundesland') == 'TH' %}selected{% endif %}>Thüringen</option>
|
||||
<option value="">{{ _('(kein Bundesland)') }}</option>
|
||||
<option value="BW" {% if request.form.get('bundesland') == 'BW' %}selected{% endif %}>{{ _('Baden-Württemberg') }}</option>
|
||||
<option value="BY" {% if request.form.get('bundesland') == 'BY' %}selected{% endif %}>{{ _('Bayern') }}</option>
|
||||
<option value="BE" {% if request.form.get('bundesland') == 'BE' %}selected{% endif %}>{{ _('Berlin') }}</option>
|
||||
<option value="BB" {% if request.form.get('bundesland') == 'BB' %}selected{% endif %}>{{ _('Brandenburg') }}</option>
|
||||
<option value="HB" {% if request.form.get('bundesland') == 'HB' %}selected{% endif %}>{{ _('Bremen') }}</option>
|
||||
<option value="HH" {% if request.form.get('bundesland') == 'HH' %}selected{% endif %}>{{ _('Hamburg') }}</option>
|
||||
<option value="HE" {% if request.form.get('bundesland') == 'HE' %}selected{% endif %}>{{ _('Hessen') }}</option>
|
||||
<option value="MV" {% if request.form.get('bundesland') == 'MV' %}selected{% endif %}>{{ _('Mecklenburg-Vorpommern') }}</option>
|
||||
<option value="NI" {% if request.form.get('bundesland') == 'NI' %}selected{% endif %}>{{ _('Niedersachsen') }}</option>
|
||||
<option value="NW" {% if request.form.get('bundesland') == 'NW' %}selected{% endif %}>{{ _('Nordrhein-Westfalen') }}</option>
|
||||
<option value="RP" {% if request.form.get('bundesland') == 'RP' %}selected{% endif %}>{{ _('Rheinland-Pfalz') }}</option>
|
||||
<option value="SL" {% if request.form.get('bundesland') == 'SL' %}selected{% endif %}>{{ _('Saarland') }}</option>
|
||||
<option value="SN" {% if request.form.get('bundesland') == 'SN' %}selected{% endif %}>{{ _('Sachsen') }}</option>
|
||||
<option value="ST" {% if request.form.get('bundesland') == 'ST' %}selected{% endif %}>{{ _('Sachsen-Anhalt') }}</option>
|
||||
<option value="SH" {% if request.form.get('bundesland') == 'SH' %}selected{% endif %}>{{ _('Schleswig-Holstein') }}</option>
|
||||
<option value="TH" {% if request.form.get('bundesland') == 'TH' %}selected{% endif %}>{{ _('Thüringen') }}</option>
|
||||
</select>
|
||||
</label>
|
||||
</fieldset>
|
||||
@@ -755,19 +838,19 @@ footer br + a {
|
||||
<div class="result" aria-live="polite">
|
||||
<button type="button" class="read-aloud-btn" onclick="readAloudFromElement(this)" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); readAloudFromElement(this); }" aria-label="Ergebnis vorlesen" title="Ergebnis vorlesen" tabindex="0">🔊</button>
|
||||
{% if request.form.get('werktage') %}
|
||||
Anzahl der Werktage zwischen <b>{{ format_date(request.form.get('start1', '')) }}</b> und <b>{{ format_date(request.form.get('end1', '')) }}:</b>{% if request.form.get('bundesland') %} (Feiertage: {{ request.form.get('bundesland') }}){% endif %}: {{ tage }}
|
||||
{{ _('Anzahl der Werktage zwischen') }} <b>{{ format_date(request.form.get('start1', '')) }}</b> {{ _('und') }} <b>{{ format_date(request.form.get('end1', '')) }}:</b>{% if request.form.get('bundesland') %} {{ _('(Feiertage:') }} {{ request.form.get('bundesland') }}){% endif %}: {{ tage }}
|
||||
{% else %}
|
||||
Anzahl der Tage zwischen <b>{{ format_date(request.form.get('start1', '')) }}</b> und <b>{{ format_date(request.form.get('end1', '')) }}</b>: {{ tage }}.
|
||||
{{ _('Anzahl der Tage zwischen') }} <b>{{ format_date(request.form.get('start1', '')) }}</b> {{ _('und') }} <b>{{ format_date(request.form.get('end1', '')) }}</b>: {{ tage }}.
|
||||
{% endif %}
|
||||
{% if wochenendtage_anzahl is not none or (feiertage_anzahl is not none and request.form.get('bundesland')) %}
|
||||
<br>
|
||||
<span style="font-size:0.98em; color:#1e293b;">
|
||||
{% if wochenendtage_anzahl is not none %}
|
||||
<b>Davon sind {{ wochenendtage_anzahl }}</b> Tage Wochenendtage.
|
||||
<b>{{ _('Davon sind') }} {{ wochenendtage_anzahl }}</b> {{ _('Tage Wochenendtage.') }}
|
||||
{% endif %}
|
||||
{% if feiertage_anzahl is not none and request.form.get('bundesland') %}
|
||||
{% if wochenendtage_anzahl is not none %}, {% endif %}
|
||||
<b>{{ feiertage_anzahl }}</b> Feiertage (Mo-Fr, {{ request.form.get('bundesland') }})
|
||||
<b>{{ feiertage_anzahl }}</b> {{ _('Feiertage (Mo-Fr,') }} {{ request.form.get('bundesland') }})
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
@@ -781,22 +864,22 @@ footer br + a {
|
||||
<!-- Kalender mit W -->
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="5" width="18" height="16" rx="4" fill="#fff" stroke="#2563eb" stroke-width="2"/><rect x="3" y="5" width="18" height="4" rx="2" fill="#2563eb"/><rect x="6" y="2" width="2" height="4" rx="1" fill="#2563eb"/><rect x="16" y="2" width="2" height="4" rx="1" fill="#2563eb"/><text x="12" y="17" text-anchor="middle" font-size="12" font-family="Segoe UI, Arial, sans-serif" fill="#2563eb" font-weight="bold">W</text></svg>
|
||||
</span>
|
||||
Wochentag eines Datums
|
||||
{{ _('Wochentag eines Datums') }}
|
||||
</button>
|
||||
<div class="accordion-content" id="accordion-panel-1" role="region" aria-labelledby="accordion-header-1">
|
||||
<form method="post">
|
||||
<label for="datum3">Datum:<br>
|
||||
<label for="datum3">{{ _('Datum:') }}<br>
|
||||
<span class="date-row">
|
||||
<input type="date" name="datum3" id="datum3">
|
||||
<button type="button" class="today-btn" onclick="setToday('datum3')">Heute</button>
|
||||
<button type="button" class="today-btn" onclick="setToday('datum3')">{{ _('Heute') }}</button>
|
||||
</span>
|
||||
</label>
|
||||
<button name="action" value="wochentag" type="submit">Anzeigen</button>
|
||||
<button name="action" value="wochentag" type="submit">{{ _('Anzeigen') }}</button>
|
||||
</form>
|
||||
{% if wochentag is not none %}
|
||||
<div class="result" aria-live="polite">
|
||||
<button type="button" class="read-aloud-btn" onclick="readAloudFromElement(this)" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); readAloudFromElement(this); }" aria-label="Ergebnis vorlesen" title="Ergebnis vorlesen" tabindex="0">🔊</button>
|
||||
Wochentag von <b>{{ format_date(request.form.get('datum3', '')) }}</b>: {{ wochentag }}
|
||||
{{ _('Wochentag von') }} <b>{{ format_date(request.form.get('datum3', '')) }}</b>: {{ wochentag }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -807,22 +890,22 @@ footer br + a {
|
||||
<!-- Kalender mit # -->
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="5" width="18" height="16" rx="4" fill="#fff" stroke="#2563eb" stroke-width="2"/><rect x="3" y="5" width="18" height="4" rx="2" fill="#2563eb"/><rect x="6" y="2" width="2" height="4" rx="1" fill="#2563eb"/><rect x="16" y="2" width="2" height="4" rx="1" fill="#2563eb"/><text x="12" y="17" text-anchor="middle" font-size="13" font-family="Segoe UI, Arial, sans-serif" fill="#2563eb" font-weight="bold">#</text></svg>
|
||||
</span>
|
||||
Kalenderwoche eines Datums
|
||||
{{ _('Kalenderwoche eines Datums') }}
|
||||
</button>
|
||||
<div class="accordion-content" id="accordion-panel-2" role="region" aria-labelledby="accordion-header-2">
|
||||
<form method="post">
|
||||
<label for="datum6">Datum:<br>
|
||||
<label for="datum6">{{ _('Datum:') }}<br>
|
||||
<span class="date-row">
|
||||
<input type="date" name="datum6" id="datum6">
|
||||
<button type="button" class="today-btn" onclick="setToday('datum6')">Heute</button>
|
||||
<button type="button" class="today-btn" onclick="setToday('datum6')">{{ _('Heute') }}</button>
|
||||
</span>
|
||||
</label>
|
||||
<button name="action" value="kw_berechnen" type="submit">Kalenderwoche berechnen</button>
|
||||
<button name="action" value="kw_berechnen" type="submit">{{ _('Kalenderwoche berechnen') }}</button>
|
||||
</form>
|
||||
{% if kw_berechnen is not none %}
|
||||
<div class="result" aria-live="polite">
|
||||
<button type="button" class="read-aloud-btn" onclick="readAloudFromElement(this)" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); readAloudFromElement(this); }" aria-label="Ergebnis vorlesen" title="Ergebnis vorlesen" tabindex="0">🔊</button>
|
||||
Kalenderwoche von <b>{{ format_date(request.form.get('datum6', '')) }}</b>: {{ kw_berechnen }}
|
||||
{{ _('Kalenderwoche von') }} <b>{{ format_date(request.form.get('datum6', '')) }}</b>: {{ kw_berechnen }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -833,22 +916,22 @@ footer br + a {
|
||||
<!-- Kalender mit Pfeil nach außen -->
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="5" width="18" height="16" rx="4" fill="#fff" stroke="#2563eb" stroke-width="2"/><rect x="3" y="5" width="18" height="4" rx="2" fill="#2563eb"/><rect x="6" y="2" width="2" height="4" rx="1" fill="#2563eb"/><rect x="16" y="2" width="2" height="4" rx="1" fill="#2563eb"/><path d="M7 17l5-5 5 5" stroke="#2563eb" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><text x="12" y="12" text-anchor="middle" font-size="8" font-family="Segoe UI, Arial, sans-serif" fill="#2563eb" font-weight="bold">KW</text></svg>
|
||||
</span>
|
||||
Start-/Enddatum zu Kalenderwoche
|
||||
{{ _('Start-/Enddatum zu Kalenderwoche') }}
|
||||
</button>
|
||||
<div class="accordion-content" id="accordion-panel-3" role="region" aria-labelledby="accordion-header-3">
|
||||
<form method="post">
|
||||
<label for="jahr7">Jahr:<br>
|
||||
<label for="jahr7">{{ _('Jahr:') }}<br>
|
||||
<input type="number" name="jahr7" id="jahr7" min="1900" max="2100" style="width: 7em;">
|
||||
</label>
|
||||
<label for="kw7">Kalenderwoche:<br>
|
||||
<label for="kw7">{{ _('Kalenderwoche:') }}<br>
|
||||
<input type="number" name="kw7" id="kw7" min="1" max="53" style="width: 5em;">
|
||||
</label>
|
||||
<button name="action" value="kw_datum" type="submit">Start-/Enddatum berechnen</button>
|
||||
<button name="action" value="kw_datum" type="submit">{{ _('Start-/Enddatum berechnen') }}</button>
|
||||
</form>
|
||||
{% if kw_datum is not none %}
|
||||
<div class="result" aria-live="polite">
|
||||
<button type="button" class="read-aloud-btn" onclick="readAloudFromElement(this)" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); readAloudFromElement(this); }" aria-label="Ergebnis vorlesen" title="Ergebnis vorlesen" tabindex="0">🔊</button>
|
||||
Start-/Enddatum der KW <b>{{ request.form.get('kw7', '') }}</b> im Jahr <b>{{ request.form.get('jahr7', '') }}</b>: {{ kw_datum }}
|
||||
{{ _('Start-/Enddatum der KW') }} <b>{{ request.form.get('kw7', '') }}</b> {{ _('im Jahr') }} <b>{{ request.form.get('jahr7', '') }}</b>: {{ kw_datum }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -859,37 +942,37 @@ footer br + a {
|
||||
<!-- Kalender mit ± -->
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="5" width="18" height="16" rx="4" fill="#fff" stroke="#2563eb" stroke-width="2"/><rect x="3" y="5" width="18" height="4" rx="2" fill="#2563eb"/><rect x="6" y="2" width="2" height="4" rx="1" fill="#2563eb"/><rect x="16" y="2" width="2" height="4" rx="1" fill="#2563eb"/><text x="12" y="17" text-anchor="middle" font-size="16" font-family="Segoe UI, Arial, sans-serif" fill="#2563eb" font-weight="bold">±</text></svg>
|
||||
</span>
|
||||
Datum plus/minus X Tage/Wochen/Monate
|
||||
{{ _('Datum plus/minus X Tage/Wochen/Monate') }}
|
||||
</button>
|
||||
<div class="accordion-content" id="accordion-panel-4" role="region" aria-labelledby="accordion-header-4">
|
||||
<form method="post">
|
||||
<label for="datum_pm">Datum:<br>
|
||||
<label for="datum_pm">{{ _('Datum:') }}<br>
|
||||
<span class="date-row">
|
||||
<input type="date" name="datum_pm" id="datum_pm">
|
||||
<button type="button" class="today-btn" onclick="setToday('datum_pm')">Heute</button>
|
||||
<button type="button" class="today-btn" onclick="setToday('datum_pm')">{{ _('Heute') }}</button>
|
||||
</span>
|
||||
</label>
|
||||
<label for="anzahl_pm">Anzahl:<br>
|
||||
<label for="anzahl_pm">{{ _('Anzahl:') }}<br>
|
||||
<input type="number" name="anzahl_pm" id="anzahl_pm" style="width: 6em;">
|
||||
</label>
|
||||
<fieldset class="date-calc-row" style="border:none; padding:0;">
|
||||
<legend class="sr-only">Rechenrichtung</legend>
|
||||
<label for="richtung_pm_add"><input type="radio" name="richtung_pm" id="richtung_pm_add" value="add" checked> addieren</label>
|
||||
<label for="richtung_pm_sub"><input type="radio" name="richtung_pm" id="richtung_pm_sub" value="sub"> subtrahieren</label>
|
||||
<legend class="sr-only">{{ _('Rechenrichtung') }}</legend>
|
||||
<label for="richtung_pm_add"><input type="radio" name="richtung_pm" id="richtung_pm_add" value="add" checked> {{ _('addieren') }}</label>
|
||||
<label for="richtung_pm_sub"><input type="radio" name="richtung_pm" id="richtung_pm_sub" value="sub"> {{ _('subtrahieren') }}</label>
|
||||
</fieldset>
|
||||
<fieldset style="display:flex; align-items:center; gap:0.5em; margin-top:0.7em; border:none; padding:0;">
|
||||
<legend class="sr-only">Einheit und Werktage</legend>
|
||||
<label for="einheit_pm" style="margin:0;">Einheit:
|
||||
<legend class="sr-only">{{ _('Einheit und Werktage') }}</legend>
|
||||
<label for="einheit_pm" style="margin:0;">{{ _('Einheit:') }}
|
||||
<select name="einheit_pm" id="einheit_pm">
|
||||
<option value="tage">Tage</option>
|
||||
<option value="wochen">Wochen</option>
|
||||
<option value="monate">Monate</option>
|
||||
<option value="tage">{{ _('Tage') }}</option>
|
||||
<option value="wochen">{{ _('Wochen') }}</option>
|
||||
<option value="monate">{{ _('Monate') }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<input type="checkbox" name="werktage_pm" id="werktage_pm">
|
||||
<label for="werktage_pm" style="margin:0;">Nur Werktage</label>
|
||||
<label for="werktage_pm" style="margin:0;">{{ _('Nur Werktage') }}</label>
|
||||
</fieldset>
|
||||
<button name="action" value="plusminus" type="submit">Berechnen</button>
|
||||
<button name="action" value="plusminus" type="submit">{{ _('Berechnen') }}</button>
|
||||
</form>
|
||||
{% if plusminus_result is not none %}
|
||||
<div class="result" aria-live="polite">
|
||||
@@ -906,19 +989,19 @@ footer br + a {
|
||||
<div id="helpModal" class="modal-overlay" role="dialog" aria-labelledby="help-title" aria-describedby="help-content">
|
||||
<div class="modal-content">
|
||||
<button type="button" class="modal-close" onclick="hideHelp()" aria-label="Hilfe schließen">×</button>
|
||||
<h1 id="help-title">Was ist Elpatrons Datumsrechner?</h1>
|
||||
<h1 id="help-title">{{ _('Was ist Elpatrons Datumsrechner?') }}</h1>
|
||||
|
||||
<p>Der Datumsrechner kann verschiedene Datumsberechnungen durchführen:</p>
|
||||
<p>{{ _('Der Datumsrechner kann verschiedene Datumsberechnungen durchführen:') }}</p>
|
||||
|
||||
<ul>
|
||||
<li>Anzahl der Tage zwischen zwei Daten</li>
|
||||
<li>Anzahl der Werktage zwischen zwei Daten</li>
|
||||
<li>Anzeige des Wochentags eines Datums</li>
|
||||
<li>Datum plus/minus X Tage</li>
|
||||
<li>Datum plus/minus X Werktage</li>
|
||||
<li>Datum plus/minus X Wochen/Monate</li>
|
||||
<li>Kalenderwoche zu Datum</li>
|
||||
<li>Start-/Enddatum einer Kalenderwoche eines Jahres</li>
|
||||
<li>{{ _('Anzahl der Tage zwischen zwei Daten') }}</li>
|
||||
<li>{{ _('Anzahl der Werktage zwischen zwei Daten') }}</li>
|
||||
<li>{{ _('Anzeige des Wochentags eines Datums') }}</li>
|
||||
<li>{{ _('Datum plus/minus X Tage') }}</li>
|
||||
<li>{{ _('Datum plus/minus X Werktage') }}</li>
|
||||
<li>{{ _('Datum plus/minus X Wochen/Monate') }}</li>
|
||||
<li>{{ _('Kalenderwoche zu Datum') }}</li>
|
||||
<li>{{ _('Start-/Enddatum einer Kalenderwoche eines Jahres') }}</li>
|
||||
</ul>
|
||||
|
||||
<h2>Online Datumsrechner gibt es bereits in einer Vielzahl, warum also noch einer?</h2>
|
||||
|
Reference in New Issue
Block a user