The QR login page countdown timer compared the server's UTC expiration
timestamp against the client's local clock, causing the QR code to appear
immediately expired when the client clock was ahead of the server.
Changes:
- Add ttl_seconds field to CreateChallengeResponse (seconds until expiry)
- Frontend countdown now uses relative elapsed time since response was
received, eliminating clock-skew issues
- Mobile app: replace alert-only QR button with actual camera-based
QR code scanner using expo-camera
- Add QRScannerScreen with barcode scanning, permission handling, and
scan area overlay
- Update camera permission description to mention QR code scanning
- Add tests for ttl_seconds computation
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
- Add path traversal guard in reimport file copy loop
- Improve error log message context for table wipe failures
- Use conditional role=alert/status on result banner for accessibility
- Make test assertions more specific (exact status codes)
- Rename ambiguous view test
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
Merge origin/main into copilot/add-sharepoint-integration.
All four conflicts were resolved by keeping both the SharePoint
additions (from this branch) and the iCloud additions (from main):
- app/models.py: added both SHAREPOINT and ICLOUD to IntegrationType
- app/tasks/send_to_all.py: added both to service_map and services list
- app/tasks/upload_to_user_integration.py: kept both upload handlers
- frontend/templates/files.html: added both filter options
No database migration conflicts — SharePoint does not require schema changes.
Windows does not render regional indicator emoji as graphical flags,
showing raw text (DE, GB) instead. Replace all emoji flag values in
SUPPORTED_LANGUAGES with lowercase ISO 3166-1 alpha-2 country codes,
add the flag-icons@7.3.2 CSS library via CDN, and update templates to
render <span class="fi fi-{code}"> instead of emoji text.
Special cases:
- Welsh (cy): uses flag-icons region code "gb-wls"
- Catalan (ca): falls back to "es" (no dedicated ISO flag)
- Esperanto (eo): uses "un" (UN flag for international language)
<option> elements in profile.html no longer display flags since CSS
icon classes cannot be applied inside native <option> tags.
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
Replace all hardcoded English strings in the admin file manager
template with _() translation calls and add 47 new admin_files.*
keys to en.json.
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
Add 108 admin_plans.* translation keys to en.json and update
admin_plans.html to use _() for all static text and window.__i18nAdminPlans
for dynamic Alpine.js / JavaScript strings.
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
Add 119 new admin_users.* translation keys to en.json and update
admin_users.html to use _() for all static HTML strings, inline
Alpine.js x-text translations, and a window.__i18nAdminUsers block
for JavaScript alert/status messages."
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
Add 13 attribution.* keys to en.json and replace all hardcoded
English strings in attribution.html with _() helper calls.
Also adds aria-hidden to the decorative warning SVG icon.
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
Replace all hardcoded English strings in cookies.html with _() i18n
helper calls and add 35 new cookie_policy.* translation keys to
frontend/translations/en.json. Also improve table accessibility with
aria-label and scope attributes."
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
Add 25 imprint.* translation keys to en.json and update imprint.html
to use _() helpers for all user-visible strings. Static business data
(company name, address, contact details, VAT number) remain hardcoded
as proper nouns that must not be altered by translation.
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
- Use {gravatar} placeholder in profile.avatar_upload_hint for proper i18n
- Use {settings_link} placeholder in subscription.single_user_body
- Use {api_tokens_link} placeholder in integrations.webhook_step1
- Add optional chaining in common.js for window.__i18n safety
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
- Fix language dropdown in base.html by moving tojson data out of HTML
attribute into a script tag (prevents quote conflicts breaking Alpine.js)
- Fix avatar placeholder 404 by correcting filename reference from
avatar-placeholder.svg to default-avatar.svg
- Add session hydration from DB in _inject_global_context() so
detect_language() uses the stored preference on every request
- Sync session and cookie in PATCH /api/profile when language changes
- Reload page after language change in profile to reflect new locale
- Add tests for session/cookie sync and DB hydration
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
- Add get_suggested_languages() to i18n.py returning ≤6 ranked
suggestions (current locale → Accept-Language header → popular
language fallbacks); refactor _parse_accept_language to share
a common _parse_accept_language_entries() helper
- Inject suggested_languages into every template context (base.py)
- Redesign nav-bar language dropdown (base.html): button shows
current-language flag emoji; dropdown lists 5-7 suggestions with
flags and native names; Alpine.js search input filters all 77
languages live; footer shows count and Search shortcut
- Add language.search_placeholder and language.no_results keys to
all 77 translation JSON files (en values; external script
propagates translations to other locales)
- Remove test_all_languages_have_same_keys (external sync script
owns key completeness); add TestGetSuggestedLanguages (7 unit
tests); update test_language_selector_in_nav for new HTML
- Update InternationalizationGuide.md: single-step en.json-only
workflow for adding new translation keys
- Update .github/copilot-instructions.md: add i18n/l10n section
documenting the en.json-only rule for future agents
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
Translate all 927 keys from English to Catalan in frontend/translations/ca.json.
Previously the file contained only English placeholder values. All strings
have been translated to proper Catalan, preserving technical terms, product
names, and placeholder variables (e.g. {size}, {year}, {count}).
- 872 out of 927 keys now have Catalan translations
- 55 values intentionally kept unchanged (proper names, product names,
technical acronyms like IP/ID/ENV, language names in their native form,
numeric error codes, and words identical in Catalan and English)"
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>